diffy-3.3.0/0000755000175000017500000000000013641136607012721 5ustar achaayanachaayandiffy-3.3.0/diffy.gemspec0000644000175000017500000000150513641136607015370 0ustar achaayanachaayan# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'diffy/version' Gem::Specification.new do |spec| spec.name = "diffy" spec.version = Diffy::VERSION spec.authors = ["Sam Goldstein"] spec.email = ["sgrock@gmail.org"] spec.description = "Convenient diffing in ruby" spec.summary = "A convenient way to diff string in ruby" spec.homepage = "http://github.com/samg/diffy" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "rake" spec.add_development_dependency "rspec" end diffy-3.3.0/README.md0000644000175000017500000002530713641136607014207 0ustar achaayanachaayanDiffy - Easy Diffing With Ruby [![Build Status](https://travis-ci.org/samg/diffy.svg?branch=master)](https://travis-ci.org/samg/diffy) ============================ Need diffs in your ruby app? Diffy has you covered. It provides a convenient way to generate a diff from two strings or files. Instead of reimplementing the LCS diff algorithm Diffy uses battle tested Unix diff to generate diffs, and focuses on providing a convenient interface, and getting out of your way. Supported Formats ----------------- It provides several built in format options which can be passed to `Diffy::Diff#to_s`. * `:text` - Plain text output * `:color` - ANSI colorized text suitable for use in a terminal * `:html` - HTML output. Since version 2.0 this format does inline highlighting of the character changes between lines. * `:html_simple` - HTML output without inline highlighting. This may be useful in situations where high performance is required or simpler output is desired. A default format can be set like so: Diffy::Diff.default_format = :html Installation ------------ ### on Unix gem install diffy ### on Windows: 1. Ensure that you have a working `diff` on your machine and in your search path. There are several options: 1. Install [Diff::LCS](https://github.com/halostatue/diff-lcs), which includes `ldiff`. [RSpec](https://www.relishapp.com/rspec/docs/gettingstarted) depends on Diff::LCS so you may already have it installed. 1. If you're using [RubyInstaller](http://rubyinstaller.org), install the [devkit](http://rubyinstaller.org/add-ons/devkit). 1. Install unxutils note that these tools contain diff 2.7 which has a different handling of whitespace in the diff results. This makes Diffy spec tests yielding one fail on Windows. 1. Install these two individually from the gnuwin32 project note that this delivers diff 2.8 which makes Diffy spec pass even on Windows. 2. Install the gem by gem install diffy Getting Started --------------- Here's an example of using Diffy to diff two strings $ irb >> string1 = <<-TXT >" Hello how are you >" I'm fine >" That's great >" TXT => "Hello how are you\nI'm fine\nThat's great\n" >> string2 = <<-TXT >" Hello how are you? >" I'm fine >" That's swell >" TXT => "Hello how are you?\nI'm fine\nThat's swell\n" >> puts Diffy::Diff.new(string1, string2) -Hello how are you +Hello how are you? I'm fine -That's great +That's swell HTML Output --------------- Outputing the diff as html is easy too. Here's an example using the `:html_simple` formatter. >> puts Diffy::Diff.new(string1, string2).to_s(:html_simple)
  • Hello how are you
  • Hello how are you?
  • I'm fine
  • That's great
  • That's swell
The `:html` formatter will give you inline highlighting a la github. >> puts Diffy::Diff.new("foo\n", "Foo\n").to_s(:html)
  • foo
  • Foo
There's some pretty nice css provided in `Diffy::CSS`. >> puts Diffy::CSS .diff{overflow:auto;} .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;} .diff del, .diff ins{display:block;text-decoration:none;} .diff li{padding:0; display:table-row;margin: 0;height:1em;} .diff li.ins{background:#dfd; color:#080} .diff li.del{background:#fee; color:#b00} .diff li:hover{background:#ffc} /* try 'whitespace:pre;' if you don't want lines to wrap */ .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;} .diff del strong{font-weight:normal;background:#fcc;} .diff ins strong{font-weight:normal;background:#9f9;} .diff li.diff-comment { display: none; } .diff li.diff-block-info { background: none repeat scroll 0 0 gray; } There's also a colorblind-safe version of the pallete provided in `Diffy::CSS_COLORBLIND_1`. Side-by-side comparisons ------------------------ Side-by-side comparisons, or split views as called by some, are supported by using the `Diffy::SplitDiff` class. This class takes a diff returned from `Diffy::Diff` and splits it in two parts (or two sides): left and right. The left side represents deletions while the right side represents insertions. The class is used as follows: ``` Diffy::SplitDiff.new(string1, string2, options = {}) ``` The optional options hash is passed along to the main `Diff::Diff` class, so all default options such as full diff output are supported. The output format may be changed by passing the format with the options hash (see below), and all default formats are supported. Unlike `Diffy::Diff`, `Diffy::SplitDiff` does not use `#to_s` to output the resulting diff. Instead, two self-explanatory methods are used to output the diff: `#left` and `#right`. Using the earlier example, this is what they look like in action: ``` >> puts Diffy::SplitDiff.new(string1, string2).left -Hello how are you I'm fine -That's great ``` ``` >> puts Diffy::SplitDiff.new(string1, string2).right +Hello how are you? I'm fine +That's swell ``` ### Changing the split view output format The output format may be changed by passing the format with the options hash: ``` Diffy::SplitDiff.new(string1, string2, :format => :html) ``` This will result in the following: ``` >> puts Diffy::SplitDiff.new(string1, string2, :format => :html).left
  • Hello how are you
  • I'm fine
  • That's great
``` ``` >> puts Diffy::SplitDiff.new(string1, string2, :format => :html).right
  • Hello how are you?
  • I'm fine
  • That's swell
``` Other Diff Options ------------------ ### Diffing files instead of strings You can diff files instead of strings by using the `:source` option. >> puts Diffy::Diff.new('/tmp/foo', '/tmp/bar', :source => 'files') ### Full Diff Output By default Diffy removes the superfluous diff output. This is because its default is to show the complete diff'ed file (`diff -U10000` is the default). Diffy does support full output, just use the `:include_diff_info => true` option when initializing: >> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n", :include_diff_info => true).to_s(:text) =>--- /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-ie27ex 2011-11-16 20:16:41.000000000 -0500 +++ /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-wzrhw5 2011-11-16 20:16:41.000000000 -0500 @@ -1,2 +1,3 @@ foo bar +baz And even deals a bit with the formatting! ### Empty Diff Behavior By default Diffy will return empty string if there are no differences in inputs. In previous versions the full text of its first input was returned in this case. To restore this behaviour simply use the `:allow_empty_diff => false` option when initializing. ### Plus and Minus symbols in HTML output By default Diffy doesn't include the `+`, `-`, and ` ` at the beginning of line for HTML output. You can use the `:include_plus_and_minus_in_html` option to include those symbols in the output. >> puts Diffy::Diff.new(string1, string2, :include_plus_and_minus_in_html => true).to_s(:html_simple)
  • -Hello how are you
  • +Hello how are you?
  • I'm fine
  • -That's great
  • +That's swell
### Number of lines of context around changes You can use the `:context` option to override the number of lines of context that are shown around each change (this defaults to 10000 to show the full file). >> puts Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1) foo -BAR +bar bang ### Overriding the command line options passed to diff. You can use the `:diff` option to override the command line options that are passed to unix diff. They default to `-U10000`. This option will noop if combined with the `:context` option. >> puts Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w") foo bar Default Diff Options -------------------- You can set the default options for new `Diffy::Diff`s using the `Diffy::Diff.default_options` and `Diffy::Diff.default_options=` methods. Options passed to `Diffy::Diff.new` will be merged into the default options. >> Diffy::Diff.default_options => {:diff=>"-U10000", :source=>"strings", :include_diff_info=>false, :include_plus_and_minus_in_html=>false} >> Diffy::Diff.default_options.merge!(:source => 'files') => {:diff=>"-U10000", :source=>"files", :include_diff_info=>false, :include_plus_and_minus_in_html=>false} Custom Formats -------------- Diffy tries to make generating your own custom formatted output easy. `Diffy::Diff` provides an enumerable interface which lets you iterate over lines in the diff. >> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each do |line| >* case line >> when /^\+/ then puts "line #{line.chomp} added" >> when /^-/ then puts "line #{line.chomp} removed" >> end >> end line +baz added => [" foo\n", " bar\n", "+baz\n"] You can also use `Diffy::Diff#each_chunk` to iterate each grouping of additions, deletions, and unchanged in a diff. >> Diffy::Diff.new("foo\nbar\nbang\nbaz\n", "foo\nbar\nbing\nbong\n").each_chunk.to_a => [" foo\n bar\n", "-bang\n-baz\n", "+bing\n+bong\n"] Use `#map`, `#inject`, or any of Enumerable's methods. Go crazy. Testing ------------ Diffy includes a full set of rspec tests. When contributing please include tests for your changes. [![Build Status](https://secure.travis-ci.org/samg/diffy.png)](http://travis-ci.org/samg/diffy) --------------------------------------------------------------------- Report bugs or request features at http://github.com/samg/diffy/issues diffy-3.3.0/.rspec0000644000175000017500000000002213641136607014030 0ustar achaayanachaayan--color --profile diffy-3.3.0/.gitignore0000644000175000017500000000004613641136607014711 0ustar achaayanachaayan*.gem *.swp Gemfile.lock tags .bundle diffy-3.3.0/lib/0000755000175000017500000000000013641136607013467 5ustar achaayanachaayandiffy-3.3.0/lib/diffy.rb0000644000175000017500000000074613641136607015124 0ustar achaayanachaayanrequire 'tempfile' require 'erb' require 'rbconfig' module Diffy WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) end require 'open3' unless Diffy::WINDOWS require File.join(File.dirname(__FILE__), 'diffy', 'format') require File.join(File.dirname(__FILE__), 'diffy', 'html_formatter') require File.join(File.dirname(__FILE__), 'diffy', 'diff') require File.join(File.dirname(__FILE__), 'diffy', 'split_diff') require File.join(File.dirname(__FILE__), 'diffy', 'css') diffy-3.3.0/lib/diffy/0000755000175000017500000000000013641136607014570 5ustar achaayanachaayandiffy-3.3.0/lib/diffy/css.rb0000644000175000017500000000300213641136607015700 0ustar achaayanachaayanmodule Diffy CSS = <<-STYLE .diff{overflow:auto;} .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;} .diff del, .diff ins{display:block;text-decoration:none;} .diff li{padding:0; display:table-row;margin: 0;height:1em;} .diff li.ins{background:#dfd; color:#080} .diff li.del{background:#fee; color:#b00} .diff li:hover{background:#ffc} /* try 'whitespace:pre;' if you don't want lines to wrap */ .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;} .diff del strong{font-weight:normal;background:#fcc;} .diff ins strong{font-weight:normal;background:#9f9;} .diff li.diff-comment { display: none; } .diff li.diff-block-info { background: none repeat scroll 0 0 gray; } STYLE CSS_COLORBLIND_1 = <<-STYLE .diff{overflow:auto;} .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;} .diff del, .diff ins{display:block;text-decoration:none;} .diff li{padding:0; display:table-row;margin: 0;height:1em;} .diff li.ins{background:#ddf; color:#008} .diff li.del{background:#fee; color:#b00} .diff li:hover{background:#ffc} /* try 'whitespace:pre;' if you don't want lines to wrap */ .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;} .diff del strong{font-weight:normal;background:#fcc;} .diff ins strong{font-weight:normal;background:#99f;} .diff li.diff-comment { display: none; } .diff li.diff-block-info { background: none repeat scroll 0 0 gray; } STYLE end diffy-3.3.0/lib/diffy/version.rb0000644000175000017500000000004513641136607016601 0ustar achaayanachaayanmodule Diffy VERSION = '3.3.0' end diffy-3.3.0/lib/diffy/format.rb0000644000175000017500000000161513641136607016410 0ustar achaayanachaayanmodule Diffy module Format # ANSI color output suitable for terminal output def color map do |line| case line when /^(---|\+\+\+|\\\\)/ "\033[90m#{line.chomp}\033[0m" when /^\+/ "\033[32m#{line.chomp}\033[0m" when /^-/ "\033[31m#{line.chomp}\033[0m" when /^@@/ "\033[36m#{line.chomp}\033[0m" else line.chomp end end.join("\n") + "\n" end # Basic text output def text to_a.join end # Basic html output which does not attempt to highlight the changes # between lines, and is more performant. def html_simple HtmlFormatter.new(self, options).to_s end # Html output which does inline highlighting of changes between two lines. def html HtmlFormatter.new(self, options.merge(:highlight_words => true)).to_s end end end diffy-3.3.0/lib/diffy/split_diff.rb0000644000175000017500000000231613641136607017242 0ustar achaayanachaayanmodule Diffy class SplitDiff def initialize(left, right, options = {}) @format = options[:format] || Diffy::Diff.default_format formats = Format.instance_methods(false).map { |x| x.to_s } unless formats.include?(@format.to_s) fail ArgumentError, "Format #{format.inspect} is not a valid format" end @diff = Diffy::Diff.new(left, right, options).to_s(@format) @left_diff, @right_diff = split end %w(left right).each do |direction| define_method direction do instance_variable_get("@#{direction}_diff") end end private def split [split_left, split_right] end def split_left case @format when :color @diff.gsub(/\033\[32m\+(.*)\033\[0m\n/, '') when :html, :html_simple @diff.gsub(%r{\s+
  • (.*)
  • }, '') when :text @diff.gsub(/^\+(.*)\n/, '') end end def split_right case @format when :color @diff.gsub(/\033\[31m\-(.*)\033\[0m\n/, '') when :html, :html_simple @diff.gsub(%r{\s+
  • (.*)
  • }, '') when :text @diff.gsub(/^-(.*)\n/, '') end end end end diffy-3.3.0/lib/diffy/diff.rb0000644000175000017500000001223513641136607016030 0ustar achaayanachaayanmodule Diffy class Diff ORIGINAL_DEFAULT_OPTIONS = { :diff => '-U10000', :source => 'strings', :include_diff_info => false, :include_plus_and_minus_in_html => false, :context => nil, :allow_empty_diff => true, } class << self attr_writer :default_format def default_format @default_format ||= :text end # default options passed to new Diff objects attr_writer :default_options def default_options @default_options ||= ORIGINAL_DEFAULT_OPTIONS.dup end end include Enumerable attr_reader :string1, :string2, :options # supported options # +:diff+:: A cli options string passed to diff # +:source+:: Either _strings_ or _files_. Determines whether string1 # and string2 should be interpreted as strings or file paths. # +:include_diff_info+:: Include diff header info # +:include_plus_and_minus_in_html+:: Show the +, -, ' ' at the # beginning of lines in html output. def initialize(string1, string2, options = {}) @options = self.class.default_options.merge(options) if ! ['strings', 'files'].include?(@options[:source]) raise ArgumentError, "Invalid :source option #{@options[:source].inspect}. Supported options are 'strings' and 'files'." end @string1, @string2 = string1, string2 end def diff @diff ||= begin @paths = case options[:source] when 'strings' [tempfile(string1), tempfile(string2)] when 'files' [string1, string2] end if WINDOWS # don't use open3 on windows cmd = sprintf '"%s" %s %s', diff_bin, diff_options.join(' '), @paths.map { |s| %("#{s}") }.join(' ') diff = `#{cmd}` else diff = Open3.popen3(diff_bin, *(diff_options + @paths)) { |i, o, e| o.read } end diff.force_encoding('ASCII-8BIT') if diff.respond_to?(:valid_encoding?) && !diff.valid_encoding? if diff =~ /\A\s*\Z/ && !options[:allow_empty_diff] diff = case options[:source] when 'strings' then string1 when 'files' then File.read(string1) end.gsub(/^/, " ") end diff end ensure # unlink the tempfiles explicitly now that the diff is generated if defined? @tempfiles # to avoid Ruby warnings about undefined ins var. Array(@tempfiles).each do |t| begin # check that the path is not nil and file still exists. # REE seems to be very agressive with when it magically removes # tempfiles t.unlink if t.path && File.exist?(t.path) rescue => e warn "#{e.class}: #{e}" warn e.backtrace.join("\n") end end end end def each lines = case @options[:include_diff_info] when false # this "primes" the diff and sets up the paths we'll reference below. diff # caching this regexp improves the performance of the loop by a # considerable amount. regexp = /^(--- "?#{@paths[0]}"?|\+\+\+ "?#{@paths[1]}"?|@@|\\\\)/ diff.split("\n").reject{|x| x =~ regexp }.map {|line| line + "\n" } when true diff.split("\n").map {|line| line + "\n" } end if block_given? lines.each{|line| yield line} else lines.to_enum end end def each_chunk old_state = nil chunks = inject([]) do |cc, line| state = line.each_char.first if state == old_state cc.last << line else cc.push line.dup end old_state = state cc end if block_given? chunks.each{|chunk| yield chunk } else chunks.to_enum end end def tempfile(string) t = Tempfile.new('diffy') # ensure tempfiles aren't unlinked when GC runs by maintaining a # reference to them. @tempfiles ||=[] @tempfiles.push(t) t.print(string) t.flush t.close t.path end def to_s(format = nil) format ||= self.class.default_format formats = Format.instance_methods(false).map{|x| x.to_s} if formats.include? format.to_s enum = self enum.extend Format enum.send format else raise ArgumentError, "Format #{format.inspect} not found in #{formats.inspect}" end end private @@bin = nil def diff_bin return @@bin if @@bin if @@bin = ENV['DIFFY_DIFF'] # system() trick from Minitest raise "Can't execute diff program '#@@bin'" unless system(@@bin, __FILE__, __FILE__) return @@bin end diffs = ['diff', 'ldiff'] diffs.first << '.exe' if WINDOWS # ldiff does not have exe extension @@bin = diffs.find { |name| system(name, __FILE__, __FILE__) } if @@bin.nil? raise "Can't find a diff executable in PATH #{ENV['PATH']}" end @@bin end # options pass to diff program def diff_options Array(options[:context] ? "-U #{options[:context]}" : options[:diff]) end end end diffy-3.3.0/lib/diffy/html_formatter.rb0000644000175000017500000001010213641136607020136 0ustar achaayanachaayanmodule Diffy class HtmlFormatter def initialize(diff, options = {}) @diff = diff @options = options end def to_s if @options[:highlight_words] wrap_lines(highlighted_words) else wrap_lines(@diff.map{|line| wrap_line(ERB::Util.h(line))}) end end private def wrap_line(line) cleaned = clean_line(line) case line when /^(---|\+\+\+|\\\\)/ '
  • ' + line.chomp + '
  • ' when /^\+/ '
  • ' + cleaned + '
  • ' when /^-/ '
  • ' + cleaned + '
  • ' when /^ / '
  • ' + cleaned + '
  • ' when /^@@/ '
  • ' + line.chomp + '
  • ' end end # remove +/- or wrap in html def clean_line(line) if @options[:include_plus_and_minus_in_html] line.sub(/^(.)/, '\1') else line.sub(/^./, '') end.chomp end def wrap_lines(lines) if lines.empty? %'
    ' else %'
    \n
      \n#{lines.join("\n")}\n
    \n
    \n' end end def highlighted_words chunks = @diff.each_chunk. reject{|c| c == '\ No newline at end of file'"\n"} processed = [] lines = chunks.each_with_index.map do |chunk1, index| next if processed.include? index processed << index chunk1 = chunk1 chunk2 = chunks[index + 1] if not chunk2 next ERB::Util.h(chunk1) end dir1 = chunk1.each_char.first dir2 = chunk2.each_char.first case [dir1, dir2] when ['-', '+'] if chunk1.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/ and chunk2.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/ ERB::Util.h(chunk1) else line_diff = Diffy::Diff.new( split_characters(chunk1), split_characters(chunk2), Diffy::Diff::ORIGINAL_DEFAULT_OPTIONS ) hi1 = reconstruct_characters(line_diff, '-') hi2 = reconstruct_characters(line_diff, '+') processed << (index + 1) [hi1, hi2] end else ERB::Util.h(chunk1) end end.flatten lines.map{|line| line.each_line.map(&:chomp).to_a if line }.flatten.compact. map{|line|wrap_line(line) }.compact end def split_characters(chunk) chunk.gsub(/^./, '').each_line.map do |line| chars = line.sub(/([\r\n]$)/, '').split('') # add escaped newlines chars << '\n' chars.map{|chr| ERB::Util.h(chr) } end.flatten.join("\n") + "\n" end def reconstruct_characters(line_diff, type) enum = line_diff.each_chunk.to_a enum.each_with_index.map do |l, i| re = /(^|\\n)#{Regexp.escape(type)}/ case l when re highlight(l) when /^ / if i > 1 and enum[i+1] and l.each_line.to_a.size < 4 highlight(l) else l.gsub(/^./, '').gsub("\n", ''). gsub('\r', "\r").gsub('\n', "\n") end end end.join('').split("\n").map do |l| type + l.gsub('' , '') end end def highlight(lines) "" + lines. # strip diff tokens (e.g. +,-,etc.) gsub(/(^|\\n)./, ''). # mark line boundaries from higher level line diff # html is all escaped so using brackets should make this safe. gsub('\n', ''). # join characters back by stripping out newlines gsub("\n", ''). # close and reopen strong tags. we don't want inline elements # spanning block elements which get added later. gsub('',"\n") + "" end end end diffy-3.3.0/.travis.yml0000644000175000017500000000027513641136607015036 0ustar achaayanachaayanlanguage: ruby sudo: false cache: bundler rvm: - 1.8.7 - 1.9.3-p551 - 2.0.0-p648 - 2.1.9 - 2.2.6 - 2.3.3 - 2.4.0 - jruby-9.1.12.0 matrix: allow_failures: - rvm: 1.8.7 diffy-3.3.0/Gemfile0000644000175000017500000000012713641136607014214 0ustar achaayanachaayansource 'https://rubygems.org' platforms :rbx do gem 'rubysl', '~> 2.0' end gemspec diffy-3.3.0/CONTRIBUTORS0000644000175000017500000000034713641136607014605 0ustar achaayanachaayan* Sam Goldstein * joelash * chaffeqa * Lincoln Ritter * Bernhard Weichel * Yuichi Tateno * Nigel Thorne * Richard Stiller * printercu * Bryan Ricker * JasonBarnabe * Skye Shaw * Abinoam P. Marques Jr. * evgen * J Smith @dark-panda diffy-3.3.0/spec/0000755000175000017500000000000013641136607013653 5ustar achaayanachaayandiffy-3.3.0/spec/demo_app.rb0000644000175000017500000000313613641136607015767 0ustar achaayanachaayanrequire 'rubygems' require 'sinatra' require 'json' require File.dirname(__FILE__) + '/../lib/diffy' blk = proc do Diffy::Diff.default_options.merge! JSON.parse(params[:options]) rescue {} haml "- d = Diffy::Diff.new(params[:one].to_s, params[:two].to_s)\n%div= d.to_s(:html)\n%pre= d.to_s" end post '/', &blk get '/', &blk __END__ @@ layout %html %head :css .diff{overflow:auto;} .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;} .diff del, .diff ins{display:block;text-decoration:none;} .diff li{padding:0; display:table-row;margin: 0;height:1em;} .diff li.ins{background:#dfd; color:#080} .diff li.del{background:#fee; color:#b00} .diff li:hover{background:#ffc} .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;} .diff del strong{font-weight:normal;background:#fcc;} .diff ins strong{font-weight:normal;background:#9f9;} .diff li.diff-comment { display: none; } .diff li.diff-block-info { background: none repeat scroll 0 0 gray; } %body = yield %form{:action => '', :method => 'post'} %label JSON diff options %textarea{:name => 'options', :style => 'width:100%;height:250px;'}= params[:options] %label One %textarea{:name => 'one', :style => 'width:100%;height:250px;'}= params[:one] %br/ %label Two %textarea{:name => 'two', :style => 'width:100%;height:250px;'}= params[:two] %br/ %input{:type => 'submit'} %br/ @@ index %div.title Hello world!!!!! diffy-3.3.0/spec/diffy_spec.rb0000644000175000017500000005132413641136607016320 0ustar achaayanachaayanrequire 'rspec' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'diffy')) describe Diffy::Diff do describe "diffing two files" do def tempfile(string, fn = 'diffy-spec') t = Tempfile.new(fn) # ensure tempfiles aren't unlinked when GC runs by maintaining a # reference to them. @tempfiles ||=[] @tempfiles.push(t) t.print(string) t.flush t.close t.path end it "should accept file paths as arguments" do string1 = "foo\nbar\nbang\n" string2 = "foo\nbang\n" path1, path2 = tempfile(string1), tempfile(string2) expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF foo -bar bang DIFF end it "should accept file paths with spaces as arguments" do string1 = "foo\nbar\nbang\n" string2 = "foo\nbang\n" path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces') expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF foo -bar bang DIFF end it "should accept file paths with spaces as arguments on windows" do begin orig_verbose, $VERBOSE = $VERBOSE, nil #silence redefine constant warnings orig_windows, Diffy::WINDOWS = Diffy::WINDOWS, true string1 = "foo\nbar\nbang\n" string2 = "foo\nbang\n" path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces') expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF foo -bar bang DIFF ensure Diffy::WINDOWS, $VERBOSE = orig_windows, orig_verbose end end describe "with no line different" do before do string1 = "foo\nbar\nbang\n" string2 = "foo\nbar\nbang\n" @path1, @path2 = tempfile(string1), tempfile(string2) end it "should show everything" do expect(Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => false). to_s).to eq <<-DIFF foo bar bang DIFF end it "should not show everything if the :allow_empty_diff option is set" do expect(Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => true).to_s).to eq('') end end describe "with lines that start with backslashes" do before do string1 = "foo\n\\\\bag\nbang\n" string2 = "foo\n\\\\bar\nbang\n" @path1, @path2 = tempfile(string1), tempfile(string2) end it "should not leave lines out" do expect(Diffy::Diff.new(@path1, @path2, :source => 'files').to_s).to eq <<-DIFF foo -\\\\bag +\\\\bar bang DIFF end end describe "with non valid UTF bytes" do before do string1 = "Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n" string2 = "Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n" @path1, @path2 = tempfile(string1), tempfile(string2) end it "should not raise invalid encoding issues" do desired = <<-DIFF -Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000 +Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000 DIFF desired.force_encoding("ASCII-8BIT") if desired.respond_to?(:force_encoding) expect(Diffy::Diff.new(@path1, @path2, :source => 'files').to_s).to eq(desired) end end end describe "handling temp files" do it "should unlink tempfiles after generating the diff" do before_tmpfiles = Dir.entries(Dir.tmpdir) ::Diffy::Diff.new("a", "b").to_s after_tmpfiles = Dir.entries(Dir.tmpdir) expect(before_tmpfiles).to match_array(after_tmpfiles) end it "should still be able to generate multiple diffs" do d = ::Diffy::Diff.new("a", "b") expect(d.to_s).to be_a String expect(d.to_s(:html)).to be_a String end end describe "options[:context]" do it "should limit context lines to 1" do diff = Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1) expect(diff.to_s).to eq <<-DIFF foo -BAR +bar bang DIFF end end describe "options[:include_plus_and_minus_in_html]" do it "defaults to false" do @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n") expect(@diffy.options[:include_plus_and_minus_in_html]).to eq(false) end it "can be set to true" do @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_plus_and_minus_in_html=> true ) expect(@diffy.options[:include_plus_and_minus_in_html]).to eq(true) end describe "formats" do it "includes symbols in html_simple" do output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_plus_and_minus_in_html => true ). to_s(:html_simple) expect(output).to eq <<-HTML
    • foo
    • -bar
    • bang
    HTML end it "includes symbols in html" do output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\naba\nbang\n", :include_plus_and_minus_in_html => true ). to_s(:html) expect(output).to eq <<-HTML
    • foo
    • -bar
    • +aba
    • bang
    HTML end end end describe "options[:include_diff_info]" do it "defaults to false" do @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n") expect(@diffy.options[:include_diff_info]).to eq(false) end it "can be set to true" do @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_diff_info => true ) expect(@diffy.options[:include_diff_info]).to eq(true) end it "includes all diff output" do output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s expect(output.to_s).to match( /@@/) expect(output).to match( /---/) expect(output).to match( /\+\+\+/) end describe "formats" do it "works for :color" do output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:color) expect(output).to match( /\e\[0m\n\e\[36m\@\@/ ) expect(output.to_s).to match( /\e\[90m---/) expect(output.to_s).to match( /\e\[0m\n\e\[90m\+\+\+/) end it "works for :html_simple" do output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:html_simple) expect(output.split("\n")).to include( "
  • @@ -1,3 +1,2 @@
  • " ) expect(output).to include( "
  • ---") expect(output).to include( "
  • +++") end end end describe "options[:diff]" do it "should accept an option to diff" do @diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w", :allow_empty_diff => false) expect(@diff.to_s).to eq <<-DIFF foo bar DIFF end it "should accept multiple arguments to diff" do @diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbaz\n", :diff => ["-w", "-U 3"]) expect(@diff.to_s).to eq <<-DIFF foo -bar +baz DIFF end end describe "#to_s" do describe "with no line different" do before do @string1 = "foo\nbar\nbang\n" @string2 = "foo\nbar\nbang\n" end it "should show everything" do expect(Diffy::Diff.new(@string1, @string2, :allow_empty_diff => false).to_s).to eq <<-DIFF foo bar bang DIFF end end describe "with one line different" do before do @string1 = "foo\nbar\nbang\n" @string2 = "foo\nbang\n" end it "should show one line removed" do expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF foo -bar bang DIFF end it "to_s should accept a format key" do expect(Diffy::Diff.new(@string1, @string2).to_s(:color)). to eq(" foo\n\e[31m-bar\e[0m\n bang\n") end it "should accept a default format option" do old_format = Diffy::Diff.default_format Diffy::Diff.default_format = :color expect(Diffy::Diff.new(@string1, @string2).to_s). to eq(" foo\n\e[31m-bar\e[0m\n bang\n") Diffy::Diff.default_format = old_format end it "should accept a default options" do old_options = Diffy::Diff.default_options Diffy::Diff.default_options = old_options.merge(:include_diff_info => true) expect(Diffy::Diff.new(@string1, @string2).to_s). to include('@@ -1,3 +1,2 @@') Diffy::Diff.default_options = old_options end it "should show one line added" do expect(Diffy::Diff.new(@string2, @string1).to_s). to eq <<-DIFF foo +bar bang DIFF end end describe "with one line changed" do before do @string1 = "foo\nbar\nbang\n" @string2 = "foo\nbong\nbang\n" end it "should show one line added and one removed" do expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF foo -bar +bong bang DIFF end end describe "with totally different strings" do before do @string1 = "foo\nbar\nbang\n" @string2 = "one\ntwo\nthree\n" end it "should show one line added and one removed" do expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF -foo -bar -bang +one +two +three DIFF end end describe "with a somewhat complicated diff" do before do @string1 = "foo\nbar\nbang\nwoot\n" @string2 = "one\ntwo\nthree\nbar\nbang\nbaz\n" @diff = Diffy::Diff.new(@string1, @string2) end it "should show one line added and one removed" do expect(@diff.to_s).to eq <<-DIFF -foo +one +two +three bar bang -woot +baz DIFF end it "should make an awesome simple html diff" do expect(@diff.to_s(:html_simple)).to eq <<-HTML
    • foo
    • one
    • two
    • three
    • bar
    • bang
    • woot
    • baz
    HTML end it "should accept overrides to diff's options" do @diff = Diffy::Diff.new(@string1, @string2, :diff => "--rcs") expect(@diff.to_s).to eq <<-DIFF d1 1 a1 3 one two three d4 1 a4 1 baz DIFF end end describe "html" do it "should not allow html injection on the last line" do @string1 = "hahaha\ntime flies like an arrow\nfoo bar\nbang baz\n", "").to_s(:html) expect(diff).to include('<script>') expect(diff).not_to include('