Commit d2b7f117e224639e566f57beadd551c7e8e0adc5

Authored by Rodrigo Souto
1 parent 4c5fccb6

Add diffy lib

vendor/plugins/diffy/.rspec 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +--color
  2 +--profile
... ...
vendor/plugins/diffy/.travis.yml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +language: ruby
  2 +rvm:
  3 + - 1.8.7
  4 + - 1.9.2
  5 + - 1.9.3
  6 + - 2.0.0
  7 + - 2.1.0
  8 + - 2.1.1
  9 + - rbx
... ...
vendor/plugins/diffy/CHANGELOG 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +allow_empty_diff is true by default
  2 +
  3 +== 2.1.0 ==
  4 +Windows support
  5 +
  6 +== 2.0.10 ==
  7 +Close tempfile after it's been written to to avoid too many open file handles
  8 +
  9 +== 2.0.9 ==
  10 +Memoize calls to `which diff` which should result in a minor performance
  11 +improvement in high use environments.
  12 +
  13 +== 2.0.8 ==
  14 +Handle non-UTF-8 byte sequences in Ruby 1.9.
  15 +Avoid non-deterministic deletion of temp files when GC runs
  16 +
  17 +== 2.0.7 ==
  18 +Added :allow_empty_diff option
  19 +
  20 +== Oops, need to backfill changelog ==
  21 +
  22 +== 1.0.1 ==
  23 +* Compatibility with ruby 1.8.6 and 1.9
  24 +
  25 +== 1.0.0 ==
  26 +* HTML output and better documentation
... ...
vendor/plugins/diffy/CONTRIBUTORS 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +* Sam Goldstein
  2 +* joelash
  3 +* chaffeqa
  4 +* Lincoln Ritter
  5 +* Bernhard Weichel
  6 +* Yuichi Tateno
  7 +* Nigel Thorne
  8 +* Richard Stiller
  9 +* printercu
  10 +* Bryan Ricker
... ...
vendor/plugins/diffy/Gemfile 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +source 'https://rubygems.org'
  2 +
  3 +platforms :rbx do
  4 + gem 'rubysl', '~> 2.0'
  5 +end
  6 +
  7 +
  8 +group :test, :development do
  9 + gemspec
  10 +end
... ...
vendor/plugins/diffy/LICENSE 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +Copyright (c) 2010 Sam Goldstein
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  4 +this software and associated documentation files (the "Software"), to deal in
  5 +the Software without restriction, including without limitation the rights to
  6 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  7 +of the Software, and to permit persons to whom the Software is furnished to do
  8 +so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in all
  11 +copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19 +SOFTWARE.
... ...
vendor/plugins/diffy/README.md 0 → 100644
... ... @@ -0,0 +1,260 @@
  1 +Diffy - Easy Diffing With Ruby [![Build Status](https://secure.travis-ci.org/samg/diffy.png)](http://travis-ci.org/samg/diffy)
  2 +============================
  3 +
  4 +Need diffs in your ruby app? Diffy has you covered. It provides a convenient
  5 +way to generate a diff from two strings or files. Instead of reimplementing
  6 +the LCS diff algorithm Diffy uses battle tested Unix diff to generate diffs,
  7 +and focuses on providing a convenient interface, and getting out of your way.
  8 +
  9 +Supported Formats
  10 +-----------------
  11 +
  12 +It provides several built in format options which can be passed to
  13 +`Diffy::Diff#to_s`.
  14 +
  15 +* `:text` - Plain text output
  16 +* `:color` - ANSI colorized text suitable for use in a terminal
  17 +* `:html` - HTML output. Since version 2.0 this format does inline highlighting of the character changes between lines.
  18 +* `:html_simple` - HTML output without inline highlighting. This may be useful in situations where high performance is required or simpler output is desired.
  19 +
  20 +A default format can be set like so:
  21 +
  22 + Diffy::Diff.default_format = :html
  23 +
  24 +Installation
  25 +------------
  26 +
  27 +###on Unix
  28 +
  29 + gem install diffy
  30 +
  31 +###on Windows:
  32 +
  33 +1. ensure that you have a working `which` and `diff` on your machine and on
  34 + your search path.
  35 +
  36 + There are two options:
  37 +
  38 + 1. install unxutils <http://sourceforge.net/projects/unxutils>
  39 +
  40 + note that these tools contain diff 2.7 which has a different handling
  41 + of whitespace in the diff results. This makes Diffy spec tests
  42 + yielding one fail on Windows.
  43 +
  44 + 2. install these two individually from the gnuwin32 project
  45 + <http://gnuwin32.sourceforge.net/>
  46 +
  47 + note that this delivers diff 2.8 which makes Diffy spec pass
  48 + even on Windows.
  49 +
  50 +
  51 +2. install the gem by
  52 +
  53 + gem install diffy
  54 +
  55 +
  56 +Getting Started
  57 +---------------
  58 +
  59 +Here's an example of using Diffy to diff two strings
  60 +
  61 + $ irb
  62 + >> string1 = <<-TXT
  63 + >" Hello how are you
  64 + >" I'm fine
  65 + >" That's great
  66 + >" TXT
  67 + => "Hello how are you\nI'm fine\nThat's great\n"
  68 + >> string2 = <<-TXT
  69 + >" Hello how are you?
  70 + >" I'm fine
  71 + >" That's swell
  72 + >" TXT
  73 + => "Hello how are you?\nI'm fine\nThat's swell\n"
  74 + >> puts Diffy::Diff.new(string1, string2)
  75 + -Hello how are you
  76 + +Hello how are you?
  77 + I'm fine
  78 + -That's great
  79 + +That's swell
  80 +
  81 +HTML Output
  82 +---------------
  83 +
  84 +Outputing the diff as html is easy too. Here's an example using the
  85 +`:html_simple` formatter.
  86 +
  87 + >> puts Diffy::Diff.new(string1, string2).to_s(:html_simple)
  88 + <div class="diff">
  89 + <ul>
  90 + <li class="del"><del>Hello how are you</del></li>
  91 + <li class="ins"><ins>Hello how are you?</ins></li>
  92 + <li class="unchanged"><span>I'm fine</span></li>
  93 + <li class="del"><del>That's great</del></li>
  94 + <li class="ins"><ins>That's swell</ins></li>
  95 + </ul>
  96 + </div>
  97 +
  98 +The `:html` formatter will give you inline highlighting a la github.
  99 +
  100 + >> puts Diffy::Diff.new("foo\n", "Foo\n").to_s(:html)
  101 + <div class="diff">
  102 + <ul>
  103 + <li class="del"><del><strong>f</strong>oo</del></li>
  104 + <li class="ins"><ins><strong>F</strong>oo</ins></li>
  105 + </ul>
  106 + </div>
  107 +
  108 +There's some pretty nice css provided in `Diffy::CSS`.
  109 +
  110 + >> puts Diffy::CSS
  111 + .diff{overflow:auto;}
  112 + .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
  113 + .diff del, .diff ins{display:block;text-decoration:none;}
  114 + .diff li{padding:0; display:table-row;margin: 0;height:1em;}
  115 + .diff li.ins{background:#dfd; color:#080}
  116 + .diff li.del{background:#fee; color:#b00}
  117 + .diff li:hover{background:#ffc}
  118 + /* try 'whitespace:pre;' if you don't want lines to wrap */
  119 + .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
  120 + .diff del strong{font-weight:normal;background:#fcc;}
  121 + .diff ins strong{font-weight:normal;background:#9f9;}
  122 + .diff li.diff-comment { display: none; }
  123 + .diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
  124 +
  125 +Other Diff Options
  126 +------------------
  127 +
  128 +### Diffing files instead of strings
  129 +
  130 +You can diff files instead of strings by using the `:source` option.
  131 +
  132 + >> puts Diffy::Diff.new('/tmp/foo', '/tmp/bar', :source => 'files')
  133 +
  134 +### Full Diff Output
  135 +
  136 +By default Diffy removes the superfluous diff output. This is because its
  137 +default is to show the complete diff'ed file (`diff -U 10000` is the default).
  138 +
  139 +Diffy does support full output, just use the `:include_diff_info => true`
  140 +option when initializing:
  141 +
  142 + >> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n", :include_diff_info => true).to_s(:text)
  143 + =>--- /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-ie27ex 2011-11-16 20:16:41.000000000 -0500
  144 + +++ /Users/chaffeqa/Projects/stiwiki/tmp/diffy20111116-82153-wzrhw5 2011-11-16 20:16:41.000000000 -0500
  145 + @@ -1,2 +1,3 @@
  146 + foo
  147 + bar
  148 + +baz
  149 +
  150 +And even deals a bit with the formatting!
  151 +
  152 +### Empty Diff Behavior
  153 +
  154 +By default Diffy will return empty string if there are no
  155 +differences in inputs. In previous versions the full text of its first input
  156 +was returned in this case. To restore this behaviour simply use the
  157 +`:allow_empty_diff => false` option when initializing.
  158 +
  159 +### Plus and Minus symbols in HTML output
  160 +
  161 +By default Diffy doesn't include the `+`, `-`, and ` ` at the beginning of line for
  162 +HTML output.
  163 +
  164 +You can use the `:include_plus_and_minus_in_html` option to include those
  165 +symbols in the output.
  166 +
  167 + >> puts Diffy::Diff.new(string1, string2, :include_plus_and_minus_in_html => true).to_s(:html_simple)
  168 + <div class="diff">
  169 + <ul>
  170 + <li class="del"><del><span class="symbol">-</span>Hello how are you</del></li>
  171 + <li class="ins"><ins><span class="symbol">+</span>Hello how are you?</ins></li>
  172 + <li class="unchanged"><span class="symbol"> </span><span>I'm fine</span></li>
  173 + <li class="del"><del><span class="symbol">-</span>That's great</del></li>
  174 + <li class="ins"><ins><span class="symbol">+</span>That's swell</ins></li>
  175 + </ul>
  176 + </div>
  177 +
  178 +### Number of lines of context around changes
  179 +
  180 +You can use the `:context` option to override the number of lines of context
  181 +that are shown around each change (this defaults to 10000 to show the full
  182 +file).
  183 +
  184 + >> puts Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1)
  185 + foo
  186 + -BAR
  187 + +bar
  188 + bang
  189 +
  190 +
  191 +### Overriding the command line options passed to diff.
  192 +
  193 +You can use the `:diff` option to override the command line options that are
  194 +passed to unix diff. They default to `-U 10000`. This option will noop if
  195 +combined with the `:context` option.
  196 +
  197 + >> puts Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w")
  198 + foo
  199 + bar
  200 +
  201 +Default Diff Options
  202 +--------------------
  203 +
  204 +You can set the default options for new `Diffy::Diff`s using the
  205 +`Diffy::Diff.default_options` and `Diffy::Diff.default_options=` methods.
  206 +Options passed to `Diffy::Diff.new` will be merged into the default options.
  207 +
  208 + >> Diffy::Diff.default_options
  209 + => {:diff=>"-U 10000", :source=>"strings", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}
  210 + >> Diffy::Diff.default_options.merge!(:source => 'files')
  211 + => {:diff=>"-U 10000", :source=>"files", :include_diff_info=>false, :include_plus_and_minus_in_html=>false}
  212 +
  213 +
  214 +Custom Formats
  215 +--------------
  216 +
  217 +Diffy tries to make generating your own custom formatted output easy.
  218 +`Diffy::Diff` provides an enumerable interface which lets you iterate over
  219 +lines in the diff.
  220 +
  221 + >> Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each do |line|
  222 + >* case line
  223 + >> when /^\+/ then puts "line #{line.chomp} added"
  224 + >> when /^-/ then puts "line #{line.chomp} removed"
  225 + >> end
  226 + >> end
  227 + line +baz added
  228 + => [" foo\n", " bar\n", "+baz\n"]
  229 +
  230 +You can also use `Diffy::Diff#each_chunk` to iterate each grouping of additions,
  231 +deletions, and unchanged in a diff.
  232 +
  233 + >> Diffy::Diff.new("foo\nbar\nbang\nbaz\n", "foo\nbar\nbing\nbong\n").each_chunk.to_a
  234 + => [" foo\n bar\n", "-bang\n-baz\n", "+bing\n+bong\n"]
  235 +
  236 +Use `#map`, `#inject`, or any of Enumerable's methods. Go crazy.
  237 +
  238 +
  239 +Ruby Version Compatibility
  240 +-------------------------
  241 +
  242 +Support for Ruby 1.8.6 was dropped beginning at version 2.0 in order to support
  243 +the chainable enumerators available in 1.8.7 and 1.9.
  244 +
  245 +If you want to use Diffy and Ruby 1.8.6 then:
  246 +
  247 + $ gem install diffy -v1.1.0
  248 +
  249 +Testing
  250 +------------
  251 +
  252 +Diffy includes a full set of rspec tests. When contributing please include
  253 +tests for your changes.
  254 +
  255 +[![Build Status](https://secure.travis-ci.org/samg/diffy.png)](http://travis-ci.org/samg/diffy)
  256 +
  257 +---------------------------------------------------------------------
  258 +
  259 +Report bugs or request features at http://github.com/samg/diffy/issues
  260 +
... ...
vendor/plugins/diffy/Rakefile 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +require 'rspec/core/rake_task'
  2 +
  3 +task :default => :spec
  4 +
  5 +desc "Run all specs in spec directory"
  6 +RSpec::Core::RakeTask.new(:spec) do |t|
  7 + t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
  8 +end
... ...
vendor/plugins/diffy/diffy.gemspec 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +# coding: utf-8
  2 +lib = File.expand_path('../lib', __FILE__)
  3 +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
  4 +require 'diffy/version'
  5 +
  6 +Gem::Specification.new do |spec|
  7 + spec.name = "diffy"
  8 + spec.version = Diffy::VERSION
  9 + spec.authors = ["Sam Goldstein"]
  10 + spec.email = ["sgrock@gmail.org"]
  11 + spec.description = "Convenient diffing in ruby"
  12 + spec.summary = "A convenient way to diff string in ruby"
  13 + spec.homepage = "http://github.com/samg/diffy"
  14 + spec.license = "MIT"
  15 +
  16 + spec.files = `git ls-files`.split($/)
  17 + spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
  18 + spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
  19 + spec.require_paths = ["lib"]
  20 +
  21 + spec.add_development_dependency "rake"
  22 + spec.add_development_dependency "rspec", '~> 2.0'
  23 +end
... ...
vendor/plugins/diffy/lib/diffy.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +require 'tempfile'
  2 +require 'erb'
  3 +require 'rbconfig'
  4 +
  5 +module Diffy
  6 + WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
  7 +end
  8 +require 'open3' unless Diffy::WINDOWS
  9 +require File.join(File.dirname(__FILE__), 'diffy', 'format')
  10 +require File.join(File.dirname(__FILE__), 'diffy', 'html_formatter')
  11 +require File.join(File.dirname(__FILE__), 'diffy', 'diff')
  12 +require File.join(File.dirname(__FILE__), 'diffy', 'css')
... ...
vendor/plugins/diffy/lib/diffy/css.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +module Diffy
  2 + CSS = <<-STYLE
  3 +.diff{overflow:auto;}
  4 +.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
  5 +.diff del, .diff ins{display:block;text-decoration:none;}
  6 +.diff li{padding:0; display:table-row;margin: 0;height:1em;}
  7 +.diff li.ins{background:#dfd; color:#080}
  8 +.diff li.del{background:#fee; color:#b00}
  9 +.diff li:hover{background:#ffc}
  10 +/* try 'whitespace:pre;' if you don't want lines to wrap */
  11 +.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
  12 +.diff del strong{font-weight:normal;background:#fcc;}
  13 +.diff ins strong{font-weight:normal;background:#9f9;}
  14 +.diff li.diff-comment { display: none; }
  15 +.diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
  16 + STYLE
  17 +end
... ...
vendor/plugins/diffy/lib/diffy/diff.rb 0 → 100644
... ... @@ -0,0 +1,161 @@
  1 +module Diffy
  2 + class Diff
  3 + class << self
  4 + attr_writer :default_format
  5 + def default_format
  6 + @default_format || :text
  7 + end
  8 +
  9 + attr_writer :default_options
  10 + # default options passed to new Diff objects
  11 + def default_options
  12 + @default_options ||= {
  13 + :diff => '-U 10000',
  14 + :source => 'strings',
  15 + :include_diff_info => false,
  16 + :include_plus_and_minus_in_html => false,
  17 + :context => nil,
  18 + :allow_empty_diff => true,
  19 + }
  20 + end
  21 +
  22 + end
  23 + include Enumerable
  24 + attr_reader :string1, :string2, :options, :diff
  25 +
  26 + # supported options
  27 + # +:diff+:: A cli options string passed to diff
  28 + # +:source+:: Either _strings_ or _files_. Determines whether string1
  29 + # and string2 should be interpreted as strings or file paths.
  30 + # +:include_diff_info+:: Include diff header info
  31 + # +:include_plus_and_minus_in_html+:: Show the +, -, ' ' at the
  32 + # beginning of lines in html output.
  33 + def initialize(string1, string2, options = {})
  34 + @options = self.class.default_options.merge(options)
  35 + if ! ['strings', 'files'].include?(@options[:source])
  36 + raise ArgumentError, "Invalid :source option #{@options[:source].inspect}. Supported options are 'strings' and 'files'."
  37 + end
  38 + @string1, @string2 = string1, string2
  39 + end
  40 +
  41 + def diff
  42 + @diff ||= begin
  43 + paths = case options[:source]
  44 + when 'strings'
  45 + [tempfile(string1), tempfile(string2)]
  46 + when 'files'
  47 + [string1, string2]
  48 + end
  49 +
  50 + if WINDOWS
  51 + # don't use open3 on windows
  52 + cmd = "\"#{diff_bin}\" #{diff_options.join(' ')} #{paths.map{|s| "\"#{s}\""}.join(' ')}"
  53 + diff = `#{cmd}`
  54 + else
  55 + diff = Open3.popen3(diff_bin, *(diff_options + paths)) { |i, o, e| o.read }
  56 + end
  57 + diff.force_encoding('ASCII-8BIT') if diff.respond_to?(:valid_encoding?) && !diff.valid_encoding?
  58 + if diff =~ /\A\s*\Z/ && !options[:allow_empty_diff]
  59 + diff = case options[:source]
  60 + when 'strings' then string1
  61 + when 'files' then File.read(string1)
  62 + end.gsub(/^/, " ")
  63 + end
  64 + diff
  65 + end
  66 + ensure
  67 + # unlink the tempfiles explicitly now that the diff is generated
  68 + Array(@tempfiles).each do |t|
  69 + begin
  70 + # check that the path is not nil and file still exists.
  71 + # REE seems to be very agressive with when it magically removes
  72 + # tempfiles
  73 + t.unlink if t.path && File.exist?(t.path)
  74 + rescue => e
  75 + warn "#{e.class}: #{e}"
  76 + warn e.backtrace.join("\n")
  77 + end
  78 + end
  79 + end
  80 +
  81 + def each
  82 + lines = case @options[:include_diff_info]
  83 + when false then diff.split("\n").reject{|x| x =~ /^(---|\+\+\+|@@|\\\\)/ }.map {|line| line + "\n" }
  84 + when true then diff.split("\n").map {|line| line + "\n" }
  85 + end
  86 + if block_given?
  87 + lines.each{|line| yield line}
  88 + else
  89 + lines.to_enum
  90 + end
  91 + end
  92 +
  93 + def each_chunk
  94 + old_state = nil
  95 + chunks = inject([]) do |cc, line|
  96 + state = line.each_char.first
  97 + if state == old_state
  98 + cc.last << line
  99 + else
  100 + cc.push line.dup
  101 + end
  102 + old_state = state
  103 + cc
  104 + end
  105 +
  106 + if block_given?
  107 + chunks.each{|chunk| yield chunk }
  108 + else
  109 + chunks.to_enum
  110 + end
  111 + end
  112 +
  113 + def tempfile(string)
  114 + t = Tempfile.new('diffy')
  115 + # ensure tempfiles aren't unlinked when GC runs by maintaining a
  116 + # reference to them.
  117 + @tempfiles ||=[]
  118 + @tempfiles.push(t)
  119 + t.print(string)
  120 + t.flush
  121 + t.close
  122 + t.path
  123 + end
  124 +
  125 + def to_s(format = nil)
  126 + format ||= self.class.default_format
  127 + formats = Format.instance_methods(false).map{|x| x.to_s}
  128 + if formats.include? format.to_s
  129 + enum = self
  130 + enum.extend Format
  131 + enum.send format
  132 + else
  133 + raise ArgumentError,
  134 + "Format #{format.inspect} not found in #{formats.inspect}"
  135 + end
  136 + end
  137 + private
  138 +
  139 + @@bin = nil
  140 + def diff_bin
  141 + return @@bin if @@bin
  142 +
  143 + @@bin ||= ""
  144 + if WINDOWS
  145 + @@bin = `which diff.exe`.chomp if @@bin.empty?
  146 + end
  147 + @@bin = `which diff`.chomp if @@bin.empty?
  148 +
  149 + if @@bin.empty?
  150 + raise "Can't find a diff executable in PATH #{ENV['PATH']}"
  151 + end
  152 + @@bin
  153 + end
  154 +
  155 + # options pass to diff program
  156 + def diff_options
  157 + Array(options[:context] ? "-U #{options[:context]}" : options[:diff])
  158 + end
  159 +
  160 + end
  161 +end
... ...
vendor/plugins/diffy/lib/diffy/format.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +module Diffy
  2 + module Format
  3 + # ANSI color output suitable for terminal output
  4 + def color
  5 + map do |line|
  6 + case line
  7 + when /^(---|\+\+\+|\\\\)/
  8 + "\033[90m#{line.chomp}\033[0m"
  9 + when /^\+/
  10 + "\033[32m#{line.chomp}\033[0m"
  11 + when /^-/
  12 + "\033[31m#{line.chomp}\033[0m"
  13 + when /^@@/
  14 + "\033[36m#{line.chomp}\033[0m"
  15 + else
  16 + line.chomp
  17 + end
  18 + end.join("\n") + "\n"
  19 + end
  20 +
  21 + # Basic text output
  22 + def text
  23 + to_a.join
  24 + end
  25 +
  26 + # Basic html output which does not attempt to highlight the changes
  27 + # between lines, and is more performant.
  28 + def html_simple
  29 + HtmlFormatter.new(self, options).to_s
  30 + end
  31 +
  32 + # Html output which does inline highlighting of changes between two lines.
  33 + def html
  34 + HtmlFormatter.new(self, options.merge(:highlight_words => true)).to_s
  35 + end
  36 + end
  37 +end
... ...
vendor/plugins/diffy/lib/diffy/html_formatter.rb 0 → 100644
... ... @@ -0,0 +1,133 @@
  1 +module Diffy
  2 + class HtmlFormatter
  3 + def initialize(diff, options = {})
  4 + @diff = diff
  5 + @options = options
  6 + end
  7 +
  8 + def to_s
  9 + if @options[:highlight_words]
  10 + wrap_lines(highlighted_words)
  11 + else
  12 + wrap_lines(@diff.map{|line| wrap_line(ERB::Util.h(line))})
  13 + end
  14 + end
  15 +
  16 + private
  17 + def wrap_line(line)
  18 + cleaned = clean_line(line)
  19 + case line
  20 + when /^(---|\+\+\+|\\\\)/
  21 + ' <li class="diff-comment"><span>' + line.chomp + '</span></li>'
  22 + when /^\+/
  23 + ' <li class="ins"><ins>' + cleaned + '</ins></li>'
  24 + when /^-/
  25 + ' <li class="del"><del>' + cleaned + '</del></li>'
  26 + when /^ /
  27 + ' <li class="unchanged"><span>' + cleaned + '</span></li>'
  28 + when /^@@/
  29 + ' <li class="diff-block-info"><span>' + line.chomp + '</span></li>'
  30 + end
  31 + end
  32 +
  33 + # remove +/- or wrap in html
  34 + def clean_line(line)
  35 + if @options[:include_plus_and_minus_in_html]
  36 + line.sub(/^(.)/, '<span class="symbol">\1</span>')
  37 + else
  38 + line.sub(/^./, '')
  39 + end.chomp
  40 + end
  41 +
  42 + def wrap_lines(lines)
  43 + if lines.empty?
  44 + %'<div class="diff"></div>'
  45 + else
  46 + %'<div class="diff">\n <ul>\n#{lines.join("\n")}\n </ul>\n</div>\n'
  47 + end
  48 + end
  49 +
  50 + def highlighted_words
  51 + chunks = @diff.each_chunk.
  52 + reject{|c| c == '\ No newline at end of file'"\n"}
  53 +
  54 + processed = []
  55 + lines = chunks.each_with_index.map do |chunk1, index|
  56 + next if processed.include? index
  57 + processed << index
  58 + chunk1 = chunk1
  59 + chunk2 = chunks[index + 1]
  60 + if not chunk2
  61 + next ERB::Util.h(chunk1)
  62 + end
  63 +
  64 + dir1 = chunk1.each_char.first
  65 + dir2 = chunk2.each_char.first
  66 + case [dir1, dir2]
  67 + when ['-', '+']
  68 + if chunk1.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/ and
  69 + chunk2.each_char.take(3).join("") =~ /^(---|\+\+\+|\\\\)/
  70 + ERB::Util.h(chunk1)
  71 + else
  72 + line_diff = Diffy::Diff.new(
  73 + split_characters(chunk1),
  74 + split_characters(chunk2)
  75 + )
  76 + hi1 = reconstruct_characters(line_diff, '-')
  77 + hi2 = reconstruct_characters(line_diff, '+')
  78 + processed << (index + 1)
  79 + [hi1, hi2]
  80 + end
  81 + else
  82 + ERB::Util.h(chunk1)
  83 + end
  84 + end.flatten
  85 + lines.map{|line| line.each_line.map(&:chomp).to_a if line }.flatten.compact.
  86 + map{|line|wrap_line(line) }.compact
  87 + end
  88 +
  89 + def split_characters(chunk)
  90 + chunk.gsub(/^./, '').each_line.map do |line|
  91 + chars = line.sub(/([\r\n]$)/, '').split('')
  92 + # add escaped newlines
  93 + chars += [($1 || "\n").gsub("\r", '\r').gsub("\n", '\n')]
  94 + chars.map{|chr| ERB::Util.h(chr) }
  95 + end.flatten.join("\n") + "\n"
  96 + end
  97 +
  98 + def reconstruct_characters(line_diff, type)
  99 + enum = line_diff.each_chunk
  100 + enum.each_with_index.map do |l, i|
  101 + re = /(^|\\n)#{Regexp.escape(type)}/
  102 + case l
  103 + when re
  104 + highlight(l)
  105 + when /^ /
  106 + if i > 1 and enum.to_a[i+1] and l.each_line.to_a.size < 4
  107 + highlight(l)
  108 + else
  109 + l.gsub(/^./, '').gsub("\n", '').
  110 + gsub('\r', "\r").gsub('\n', "\n")
  111 + end
  112 + end
  113 + end.join('').split("\n").map do |l|
  114 + type + l.gsub('</strong><strong>' , '')
  115 + end
  116 + end
  117 +
  118 + def highlight(lines)
  119 + "<strong>" +
  120 + lines.
  121 + # strip diff tokens (e.g. +,-,etc.)
  122 + gsub(/(^|\\n)./, '').
  123 + # mark line boundaries from higher level line diff
  124 + # html is all escaped so using brackets should make this safe.
  125 + gsub('\n', '<LINE_BOUNDARY>').
  126 + # join characters back by stripping out newlines
  127 + gsub("\n", '').
  128 + # close and reopen strong tags. we don't want inline elements
  129 + # spanning block elements which get added later.
  130 + gsub('<LINE_BOUNDARY>',"</strong>\n<strong>") + "</strong>"
  131 + end
  132 + end
  133 +end
... ...
vendor/plugins/diffy/lib/diffy/version.rb 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +module Diffy
  2 + VERSION = '3.0.3'
  3 +end
... ...
vendor/plugins/diffy/spec/demo_app.rb 0 → 100644
... ... @@ -0,0 +1,46 @@
  1 +require 'rubygems'
  2 +require 'sinatra'
  3 +require 'json'
  4 +require File.dirname(__FILE__) + '/../lib/diffy'
  5 +
  6 +blk = proc do
  7 + Diffy::Diff.default_options.merge! JSON.parse(params[:options]) rescue {}
  8 + haml "- d = Diffy::Diff.new(params[:one].to_s, params[:two].to_s)\n%div= d.to_s(:html)\n%pre= d.to_s"
  9 +end
  10 +post '/', &blk
  11 +get '/', &blk
  12 +__END__
  13 +
  14 +@@ layout
  15 +%html
  16 + %head
  17 + :css
  18 + .diff{overflow:auto;}
  19 + .diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
  20 + .diff del, .diff ins{display:block;text-decoration:none;}
  21 + .diff li{padding:0; display:table-row;margin: 0;height:1em;}
  22 + .diff li.ins{background:#dfd; color:#080}
  23 + .diff li.del{background:#fee; color:#b00}
  24 + .diff li:hover{background:#ffc}
  25 + .diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
  26 + .diff del strong{font-weight:normal;background:#fcc;}
  27 + .diff ins strong{font-weight:normal;background:#9f9;}
  28 + .diff li.diff-comment { display: none; }
  29 + .diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
  30 + %body
  31 + = yield
  32 + %form{:action => '', :method => 'post'}
  33 + %label JSON diff options
  34 + %textarea{:name => 'options', :style => 'width:100%;height:250px;'}= params[:options]
  35 + %label One
  36 + %textarea{:name => 'one', :style => 'width:100%;height:250px;'}= params[:one]
  37 + %br/
  38 + %label Two
  39 + %textarea{:name => 'two', :style => 'width:100%;height:250px;'}= params[:two]
  40 + %br/
  41 + %input{:type => 'submit'}
  42 + %br/
  43 +
  44 +@@ index
  45 +%div.title Hello world!!!!!
  46 +
... ...
vendor/plugins/diffy/spec/diffy_spec.rb 0 → 100644
... ... @@ -0,0 +1,576 @@
  1 +require 'rspec'
  2 +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'diffy'))
  3 +
  4 +describe Diffy::Diff do
  5 +
  6 + describe "diffing two files" do
  7 + def tempfile(string, fn = 'diffy-spec')
  8 + t = Tempfile.new(fn)
  9 + # ensure tempfiles aren't unlinked when GC runs by maintaining a
  10 + # reference to them.
  11 + @tempfiles ||=[]
  12 + @tempfiles.push(t)
  13 + t.print(string)
  14 + t.flush
  15 + t.close
  16 + t.path
  17 + end
  18 +
  19 + it "should accept file paths as arguments" do
  20 + string1 = "foo\nbar\nbang\n"
  21 + string2 = "foo\nbang\n"
  22 + path1, path2 = tempfile(string1), tempfile(string2)
  23 + Diffy::Diff.new(path1, path2, :source => 'files').to_s.should == <<-DIFF
  24 + foo
  25 +-bar
  26 + bang
  27 + DIFF
  28 + end
  29 +
  30 + it "should accept file paths with spaces as arguments" do
  31 + string1 = "foo\nbar\nbang\n"
  32 + string2 = "foo\nbang\n"
  33 + path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces')
  34 + Diffy::Diff.new(path1, path2, :source => 'files').to_s.should == <<-DIFF
  35 + foo
  36 +-bar
  37 + bang
  38 + DIFF
  39 + end
  40 +
  41 + it "should accept file paths with spaces as arguments on windows" do
  42 + begin
  43 +
  44 + orig_verbose, $VERBOSE = $VERBOSE, nil #silence redefine constant warnings
  45 + orig_windows, Diffy::WINDOWS = Diffy::WINDOWS, true
  46 + string1 = "foo\nbar\nbang\n"
  47 + string2 = "foo\nbang\n"
  48 + path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces')
  49 + Diffy::Diff.new(path1, path2, :source => 'files').to_s.should == <<-DIFF
  50 + foo
  51 +-bar
  52 + bang
  53 + DIFF
  54 + ensure
  55 + Diffy::WINDOWS, $VERBOSE = orig_windows, orig_verbose
  56 + end
  57 +
  58 + end
  59 +
  60 + describe "with no line different" do
  61 + before do
  62 + string1 = "foo\nbar\nbang\n"
  63 + string2 = "foo\nbar\nbang\n"
  64 + @path1, @path2 = tempfile(string1), tempfile(string2)
  65 + end
  66 +
  67 + it "should show everything" do
  68 + Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => false).
  69 + to_s.should == <<-DIFF
  70 + foo
  71 + bar
  72 + bang
  73 + DIFF
  74 + end
  75 +
  76 + it "should not show everything if the :allow_empty_diff option is set" do
  77 + Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => true).to_s.should == ''
  78 + end
  79 + end
  80 + describe "with lines that start with backslashes" do
  81 + before do
  82 + string1 = "foo\n\\\\bag\nbang\n"
  83 + string2 = "foo\n\\\\bar\nbang\n"
  84 + @path1, @path2 = tempfile(string1), tempfile(string2)
  85 + end
  86 +
  87 + it "should not leave lines out" do
  88 + Diffy::Diff.new(@path1, @path2, :source => 'files').to_s.should == <<-DIFF
  89 + foo
  90 +-\\\\bag
  91 ++\\\\bar
  92 + bang
  93 + DIFF
  94 + end
  95 + end
  96 +
  97 + describe "with non valid UTF bytes" do
  98 + before do
  99 + string1 = "Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n"
  100 + string2 = "Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n"
  101 + @path1, @path2 = tempfile(string1), tempfile(string2)
  102 + end
  103 + it "should not raise invalid encoding issues" do
  104 + desired = <<-DIFF
  105 +-Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000
  106 ++Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000
  107 + DIFF
  108 + desired.force_encoding("ASCII-8BIT") if desired.respond_to?(:force_encoding)
  109 + Diffy::Diff.new(@path1, @path2, :source => 'files').to_s.should == desired
  110 + end
  111 + end
  112 +
  113 + end
  114 +
  115 + describe "handling temp files" do
  116 + it "should unlink tempfiles after generating the diff" do
  117 + before_tmpfiles = Dir.entries(Dir.tmpdir)
  118 + d = ::Diffy::Diff.new("a", "b").to_s
  119 + after_tmpfiles = Dir.entries(Dir.tmpdir)
  120 + before_tmpfiles.should =~ after_tmpfiles
  121 + end
  122 +
  123 + it "should still be able to generate multiple diffs" do
  124 + d = ::Diffy::Diff.new("a", "b")
  125 + d.to_s.should be_a String
  126 + d.to_s(:html).should be_a String
  127 + end
  128 + end
  129 +
  130 + describe "options[:context]" do
  131 + it "should limit context lines to 1" do
  132 + diff = Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1)
  133 + diff.to_s.should == <<-DIFF
  134 + foo
  135 +-BAR
  136 ++bar
  137 + bang
  138 + DIFF
  139 + end
  140 + end
  141 +
  142 + describe "options[:include_plus_and_minus_in_html]" do
  143 + it "defaults to false" do
  144 + @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n")
  145 + @diffy.options[:include_plus_and_minus_in_html].should == false
  146 + end
  147 +
  148 + it "can be set to true" do
  149 + @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_plus_and_minus_in_html=> true )
  150 + @diffy.options[:include_plus_and_minus_in_html].should == true
  151 + end
  152 +
  153 + describe "formats" do
  154 + it "includes symbols in html_simple" do
  155 + output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_plus_and_minus_in_html => true ).
  156 + to_s(:html_simple)
  157 + output.should == <<-HTML
  158 +<div class="diff">
  159 + <ul>
  160 + <li class="unchanged"><span><span class="symbol"> </span>foo</span></li>
  161 + <li class="del"><del><span class="symbol">-</span>bar</del></li>
  162 + <li class="unchanged"><span><span class="symbol"> </span>bang</span></li>
  163 + </ul>
  164 +</div>
  165 + HTML
  166 + end
  167 +
  168 + it "includes symbols in html" do
  169 + output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\naba\nbang\n", :include_plus_and_minus_in_html => true ).
  170 + to_s(:html)
  171 + output.should == <<-HTML
  172 +<div class="diff">
  173 + <ul>
  174 + <li class="unchanged"><span><span class="symbol"> </span>foo</span></li>
  175 + <li class="del"><del><span class="symbol">-</span>ba<strong>r</strong></del></li>
  176 + <li class="ins"><ins><span class="symbol">+</span><strong>a</strong>ba</ins></li>
  177 + <li class="unchanged"><span><span class="symbol"> </span>bang</span></li>
  178 + </ul>
  179 +</div>
  180 + HTML
  181 + end
  182 +
  183 + end
  184 +
  185 + end
  186 +
  187 + describe "options[:include_diff_info]" do
  188 + it "defaults to false" do
  189 + @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n")
  190 + @diffy.options[:include_diff_info].should == false
  191 + end
  192 +
  193 + it "can be set to true" do
  194 + @diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_diff_info => true )
  195 + @diffy.options[:include_diff_info].should == true
  196 + end
  197 +
  198 + it "includes all diff output" do
  199 + output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s
  200 + output.to_s.should match( /@@/)
  201 + output.should match( /---/)
  202 + output.should match( /\+\+\+/)
  203 + end
  204 +
  205 + describe "formats" do
  206 + it "works for :color" do
  207 + output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:color)
  208 + output.should match( /\e\[0m\n\e\[36m\@\@/ )
  209 + output.to_s.should match( /\e\[90m---/)
  210 + output.to_s.should match( /\e\[0m\n\e\[90m\+\+\+/)
  211 + end
  212 +
  213 + it "works for :html_simple" do
  214 + output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:html_simple)
  215 + output.split("\n").should include( " <li class=\"diff-block-info\"><span>@@ -1,3 +1,2 @@</span></li>" )
  216 + output.should include( "<li class=\"diff-comment\"><span>---")
  217 + output.should include( "<li class=\"diff-comment\"><span>+++")
  218 + end
  219 + end
  220 + end
  221 +
  222 + describe "options[:diff]" do
  223 + it "should accept an option to diff" do
  224 + @diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w", :allow_empty_diff => false)
  225 + @diff.to_s.should == <<-DIFF
  226 + foo
  227 + bar
  228 + DIFF
  229 + end
  230 +
  231 + it "should accept multiple arguments to diff" do
  232 + @diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbaz\n", :diff => ["-w", "-U 3"])
  233 + @diff.to_s.should == <<-DIFF
  234 + foo
  235 +-bar
  236 ++baz
  237 + DIFF
  238 + end
  239 + end
  240 +
  241 + describe "#to_s" do
  242 + describe "with no line different" do
  243 + before do
  244 + @string1 = "foo\nbar\nbang\n"
  245 + @string2 = "foo\nbar\nbang\n"
  246 + end
  247 +
  248 + it "should show everything" do
  249 + Diffy::Diff.new(@string1, @string2, :allow_empty_diff => false).to_s.should == <<-DIFF
  250 + foo
  251 + bar
  252 + bang
  253 + DIFF
  254 + end
  255 + end
  256 + describe "with one line different" do
  257 + before do
  258 + @string1 = "foo\nbar\nbang\n"
  259 + @string2 = "foo\nbang\n"
  260 + end
  261 +
  262 + it "should show one line removed" do
  263 + Diffy::Diff.new(@string1, @string2).to_s.should == <<-DIFF
  264 + foo
  265 +-bar
  266 + bang
  267 + DIFF
  268 + end
  269 +
  270 + it "to_s should accept a format key" do
  271 + Diffy::Diff.new(@string1, @string2).to_s(:color).
  272 + should == " foo\n\e[31m-bar\e[0m\n bang\n"
  273 + end
  274 +
  275 + it "should accept a default format option" do
  276 + old_format = Diffy::Diff.default_format
  277 + Diffy::Diff.default_format = :color
  278 + Diffy::Diff.new(@string1, @string2).to_s.
  279 + should == " foo\n\e[31m-bar\e[0m\n bang\n"
  280 + Diffy::Diff.default_format = old_format
  281 + end
  282 +
  283 + it "should accept a default options" do
  284 + old_options = Diffy::Diff.default_options
  285 + Diffy::Diff.default_options = old_options.merge(:include_diff_info => true)
  286 + Diffy::Diff.new(@string1, @string2).to_s.
  287 + should include('@@ -1,3 +1,2 @@')
  288 + Diffy::Diff.default_options = old_options
  289 + end
  290 +
  291 + it "should show one line added" do
  292 + Diffy::Diff.new(@string2, @string1).to_s.
  293 + should == <<-DIFF
  294 + foo
  295 ++bar
  296 + bang
  297 + DIFF
  298 + end
  299 + end
  300 +
  301 + describe "with one line changed" do
  302 + before do
  303 + @string1 = "foo\nbar\nbang\n"
  304 + @string2 = "foo\nbong\nbang\n"
  305 + end
  306 + it "should show one line added and one removed" do
  307 + Diffy::Diff.new(@string1, @string2).to_s.should == <<-DIFF
  308 + foo
  309 +-bar
  310 ++bong
  311 + bang
  312 + DIFF
  313 + end
  314 + end
  315 +
  316 + describe "with totally different strings" do
  317 + before do
  318 + @string1 = "foo\nbar\nbang\n"
  319 + @string2 = "one\ntwo\nthree\n"
  320 + end
  321 + it "should show one line added and one removed" do
  322 + Diffy::Diff.new(@string1, @string2).to_s.should == <<-DIFF
  323 +-foo
  324 +-bar
  325 +-bang
  326 ++one
  327 ++two
  328 ++three
  329 + DIFF
  330 + end
  331 + end
  332 +
  333 + describe "with a somewhat complicated diff" do
  334 + before do
  335 + @string1 = "foo\nbar\nbang\nwoot\n"
  336 + @string2 = "one\ntwo\nthree\nbar\nbang\nbaz\n"
  337 + @diff = Diffy::Diff.new(@string1, @string2)
  338 + end
  339 + it "should show one line added and one removed" do
  340 + @diff.to_s.should == <<-DIFF
  341 +-foo
  342 ++one
  343 ++two
  344 ++three
  345 + bar
  346 + bang
  347 +-woot
  348 ++baz
  349 + DIFF
  350 + end
  351 +
  352 + it "should make an awesome simple html diff" do
  353 + @diff.to_s(:html_simple).should == <<-HTML
  354 +<div class="diff">
  355 + <ul>
  356 + <li class="del"><del>foo</del></li>
  357 + <li class="ins"><ins>one</ins></li>
  358 + <li class="ins"><ins>two</ins></li>
  359 + <li class="ins"><ins>three</ins></li>
  360 + <li class="unchanged"><span>bar</span></li>
  361 + <li class="unchanged"><span>bang</span></li>
  362 + <li class="del"><del>woot</del></li>
  363 + <li class="ins"><ins>baz</ins></li>
  364 + </ul>
  365 +</div>
  366 + HTML
  367 + end
  368 +
  369 + it "should accept overrides to diff's options" do
  370 + @diff = Diffy::Diff.new(@string1, @string2, :diff => "--rcs")
  371 + @diff.to_s.should == <<-DIFF
  372 +d1 1
  373 +a1 3
  374 +one
  375 +two
  376 +three
  377 +d4 1
  378 +a4 1
  379 +baz
  380 + DIFF
  381 + end
  382 + end
  383 +
  384 + describe "html" do
  385 + it "should not allow html injection on the last line" do
  386 + @string1 = "hahaha\ntime flies like an arrow\nfoo bar\nbang baz\n<script>\n"
  387 + @string2 = "hahaha\nfruit flies like a banana\nbang baz\n<script>\n"
  388 + @diff = Diffy::Diff.new(@string1, @string2)
  389 + html = <<-HTML
  390 +<div class="diff">
  391 + <ul>
  392 + <li class="unchanged"><span>hahaha</span></li>
  393 + <li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
  394 + <li class="del"><del><strong>foo bar</strong></del></li>
  395 + <li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
  396 + <li class="unchanged"><span>bang baz</span></li>
  397 + <li class="unchanged"><span>&lt;script&gt;</span></li>
  398 + </ul>
  399 +</div>
  400 + HTML
  401 + @diff.to_s(:html).should == html
  402 + end
  403 +
  404 + it "should highlight the changes within the line" do
  405 + @string1 = "hahaha\ntime flies like an arrow\nfoo bar\nbang baz\n"
  406 + @string2 = "hahaha\nfruit flies like a banana\nbang baz\n"
  407 + @diff = Diffy::Diff.new(@string1, @string2)
  408 + html = <<-HTML
  409 +<div class="diff">
  410 + <ul>
  411 + <li class="unchanged"><span>hahaha</span></li>
  412 + <li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
  413 + <li class="del"><del><strong>foo bar</strong></del></li>
  414 + <li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
  415 + <li class="unchanged"><span>bang baz</span></li>
  416 + </ul>
  417 +</div>
  418 + HTML
  419 + @diff.to_s(:html).should == html
  420 + end
  421 +
  422 + it "should not duplicate some lines" do
  423 + @string1 = "hahaha\ntime flies like an arrow\n"
  424 + @string2 = "hahaha\nfruit flies like a banana\nbang baz"
  425 + @diff = Diffy::Diff.new(@string1, @string2)
  426 + html = <<-HTML
  427 +<div class="diff">
  428 + <ul>
  429 + <li class="unchanged"><span>hahaha</span></li>
  430 + <li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
  431 + <li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
  432 + <li class="ins"><ins><strong>bang baz</strong></ins></li>
  433 + </ul>
  434 +</div>
  435 + HTML
  436 + @diff.to_s(:html).should == html
  437 + end
  438 +
  439 + it "should escape html" do
  440 + @string1 = "ha<br>haha\ntime flies like an arrow\n"
  441 + @string2 = "ha<br>haha\nfruit flies like a banana\nbang baz"
  442 + @diff = Diffy::Diff.new(@string1, @string2)
  443 + html = <<-HTML
  444 +<div class="diff">
  445 + <ul>
  446 + <li class="unchanged"><span>ha&lt;br&gt;haha</span></li>
  447 + <li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
  448 + <li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
  449 + <li class="ins"><ins><strong>bang baz</strong></ins></li>
  450 + </ul>
  451 +</div>
  452 + HTML
  453 + @diff.to_s(:html).should == html
  454 + end
  455 +
  456 + it "should not double escape html in wierd edge cases" do
  457 + @string1 = "preface = (! title .)+ title &{YYACCEPT}\n"
  458 + @string2 = "preface = << (! title .)+ title >> &{YYACCEPT}\n"
  459 + @diff = Diffy::Diff.new @string1, @string2
  460 + html = <<-HTML
  461 +<div class="diff">
  462 + <ul>
  463 + <li class="del"><del>preface = (! title .)+ title &amp;{YYACCEPT}</del></li>
  464 + <li class="ins"><ins>preface = <strong>&lt;&lt; </strong>(! title .)+ title <strong>&gt;&gt; </strong>&amp;{YYACCEPT}</ins></li>
  465 + </ul>
  466 +</div>
  467 + HTML
  468 + @diff.to_s(:html).should == html
  469 + end
  470 +
  471 + it "should highlight the changes within the line with windows style line breaks" do
  472 + @string1 = "hahaha\r\ntime flies like an arrow\r\nfoo bar\r\nbang baz\n"
  473 + @string2 = "hahaha\r\nfruit flies like a banana\r\nbang baz\n"
  474 + @diff = Diffy::Diff.new(@string1, @string2)
  475 + html = <<-HTML
  476 +<div class="diff">
  477 + <ul>
  478 + <li class="unchanged"><span>hahaha</span></li>
  479 + <li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
  480 + <li class="del"><del><strong>foo bar</strong></del></li>
  481 + <li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
  482 + <li class="unchanged"><span>bang baz</span></li>
  483 + </ul>
  484 +</div>
  485 + HTML
  486 + @diff.to_s(:html).should == html
  487 + end
  488 +
  489 + it "should treat unix vs windows newlines as differences" do
  490 + @diff = Diffy::Diff.new("one\ntwo\nthree\n", "one\r\ntwo\r\nthree\r\n")
  491 + html = <<-HTML
  492 +<div class="diff">
  493 + <ul>
  494 + <li class="del"><del>one</del></li>
  495 + <li class="del"><del>two</del></li>
  496 + <li class="del"><del>three</del></li>
  497 + <li class="ins"><ins>one<strong></strong></ins></li>
  498 + <li class="ins"><ins>two<strong></strong></ins></li>
  499 + <li class="ins"><ins>three<strong></strong></ins></li>
  500 + </ul>
  501 +</div>
  502 + HTML
  503 + @diff.to_s(:html).should == html
  504 + end
  505 +
  506 + describe 'with lines that include \n' do
  507 + before do
  508 + string1 = 'a\nb'"\n"
  509 +
  510 + string2 = 'acb'"\n"
  511 + @string1, @string2 = string1, string2
  512 + end
  513 +
  514 + it "should not leave lines out" do
  515 + Diffy::Diff.new(@string1, @string2 ).to_s(:html).should == <<-DIFF
  516 +<div class="diff">
  517 + <ul>
  518 + <li class="del"><del>a<strong>\\n</strong>b</del></li>
  519 + <li class="ins"><ins>a<strong>c</strong>b</ins></li>
  520 + </ul>
  521 +</div>
  522 + DIFF
  523 + end
  524 + end
  525 +
  526 + it "should do highlighting on the last line when there's no trailing newlines" do
  527 + s1 = "foo\nbar\nbang"
  528 + s2 = "foo\nbar\nbangleize"
  529 + Diffy::Diff.new(s1,s2).to_s(:html).should == <<-DIFF
  530 +<div class="diff">
  531 + <ul>
  532 + <li class="unchanged"><span>foo</span></li>
  533 + <li class="unchanged"><span>bar</span></li>
  534 + <li class="del"><del>bang</del></li>
  535 + <li class="ins"><ins>bang<strong>leize</strong></ins></li>
  536 + </ul>
  537 +</div>
  538 + DIFF
  539 + end
  540 + end
  541 +
  542 + it "should escape diffed html in html output" do
  543 + diff = Diffy::Diff.new("<script>alert('bar')</script>", "<script>alert('foo')</script>").to_s(:html)
  544 + diff.should include('&lt;script&gt;')
  545 + diff.should_not include('<script>')
  546 + end
  547 +
  548 + it "should be easy to generate custom format" do
  549 + Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").map do |line|
  550 + case line
  551 + when /^\+/ then "line #{line.chomp} added"
  552 + when /^-/ then "line #{line.chomp} removed"
  553 + end
  554 + end.compact.join.should == "line +baz added"
  555 + end
  556 +
  557 + it "should let you iterate over chunks instead of lines" do
  558 + Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each_chunk.map do |chunk|
  559 + chunk
  560 + end.should == [" foo\n bar\n", "+baz\n"]
  561 + end
  562 +
  563 + it "should allow chaining enumerable methods" do
  564 + Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each.map do |line|
  565 + line
  566 + end.should == [" foo\n", " bar\n", "+baz\n"]
  567 + end
  568 + end
  569 +end
  570 +
  571 +describe 'Diffy::CSS' do
  572 + it "should be some css" do
  573 + Diffy::CSS.should include 'diff{overflow:auto;}'
  574 + end
  575 +end
  576 +
... ...