diffy-3.1.0/0000755000175000017500000000000013121647246012750 5ustar abhijithabhijithdiffy-3.1.0/metadata.yml0000644000175000017500000000371613121647246015262 0ustar abhijithabhijith--- !ruby/object:Gem::Specification name: diffy version: !ruby/object:Gem::Version version: 3.1.0 platform: ruby authors: - Sam Goldstein autorequire: bindir: bin cert_chain: [] date: 2015-12-17 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '2.14' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '2.14' description: Convenient diffing in ruby email: - sgrock@gmail.org executables: [] extensions: [] extra_rdoc_files: [] files: - ".gitignore" - ".rspec" - ".travis.yml" - CHANGELOG - CONTRIBUTORS - Gemfile - LICENSE - README.md - Rakefile - diffy.gemspec - lib/diffy.rb - lib/diffy/css.rb - lib/diffy/diff.rb - lib/diffy/format.rb - lib/diffy/html_formatter.rb - lib/diffy/split_diff.rb - lib/diffy/version.rb - spec/demo_app.rb - spec/diffy_spec.rb homepage: http://github.com/samg/diffy licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.5.1 signing_key: specification_version: 4 summary: A convenient way to diff string in ruby test_files: - spec/demo_app.rb - spec/diffy_spec.rb diffy-3.1.0/diffy.gemspec0000644000175000017500000000152013121647246015414 0ustar abhijithabhijith# 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", '~> 2.14' end diffy-3.1.0/CONTRIBUTORS0000644000175000017500000000026013121647246014626 0ustar abhijithabhijith* Sam Goldstein * joelash * chaffeqa * Lincoln Ritter * Bernhard Weichel * Yuichi Tateno * Nigel Thorne * Richard Stiller * printercu * Bryan Ricker * JasonBarnabe * Skye Shaw diffy-3.1.0/lib/0000755000175000017500000000000013121647246013516 5ustar abhijithabhijithdiffy-3.1.0/lib/diffy/0000755000175000017500000000000013121647246014617 5ustar abhijithabhijithdiffy-3.1.0/lib/diffy/diff.rb0000644000175000017500000001145413121647246016061 0ustar abhijithabhijithmodule Diffy class Diff ORIGINAL_DEFAULT_OPTIONS = { :diff => '-U 10000', :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, :diff # 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 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 def each lines = case @options[:include_diff_info] when false then diff.split("\n").reject{|x| x =~ /^(---|\+\+\+|@@|\\\\)/ }.map {|line| line + "\n" } when true then 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.1.0/lib/diffy/split_diff.rb0000644000175000017500000000231613121647246017271 0ustar abhijithabhijithmodule 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.1.0/lib/diffy/css.rb0000644000175000017500000000300213121647246015727 0ustar abhijithabhijithmodule 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.1.0/lib/diffy/format.rb0000644000175000017500000000162713121647246016442 0ustar abhijithabhijithmodule 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.1.0/lib/diffy/version.rb0000644000175000017500000000004513121647246016630 0ustar abhijithabhijithmodule Diffy VERSION = '3.1.0' end diffy-3.1.0/lib/diffy/html_formatter.rb0000644000175000017500000001010213121647246020165 0ustar abhijithabhijithmodule 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
    \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.1.0/lib/diffy.rb0000644000175000017500000000074613121647246015153 0ustar abhijithabhijithrequire '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.1.0/Gemfile0000644000175000017500000000017313121647246014244 0ustar abhijithabhijithsource 'https://rubygems.org' platforms :rbx do gem 'rubysl', '~> 2.0' end group :test, :development do gemspec end diffy-3.1.0/CHANGELOG0000644000175000017500000000166013121647246014165 0ustar abhijithabhijith== 3.1.0 == Side by side diffs. Thanks Runar Skaare Tveiten! == 3.0.5 == Improve performance when generating html output (with inline highlighting) on long lines. Thanks Jason Barnabe! == 3.0.4 == handle windows vs. unix line breaks consistently in html output == 3.0.3 == explicitly unlink tempfiles to avoid occasional file handle leaks == 3.0.0 == allow_empty_diff is true by default == 2.1.0 == Windows support == 2.0.10 == Close tempfile after it's been written to to avoid too many open file handles == 2.0.9 == Memoize calls to `which diff` which should result in a minor performance improvement in high use environments. == 2.0.8 == Handle non-UTF-8 byte sequences in Ruby 1.9. Avoid non-deterministic deletion of temp files when GC runs == 2.0.7 == Added :allow_empty_diff option == Oops, need to backfill changelog == == 1.0.1 == * Compatibility with ruby 1.8.6 and 1.9 == 1.0.0 == * HTML output and better documentation diffy-3.1.0/spec/0000755000175000017500000000000013121647246013702 5ustar abhijithabhijithdiffy-3.1.0/spec/demo_app.rb0000644000175000017500000000313613121647246016016 0ustar abhijithabhijithrequire '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.1.0/spec/diffy_spec.rb0000644000175000017500000005041713121647246016351 0ustar abhijithabhijithrequire '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) d = ::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
    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
    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('