diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/wiki_content.rb | 8 | ||||
-rw-r--r-- | app/models/wiki_page.rb | 45 |
2 files changed, 53 insertions, 0 deletions
diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb index d0a48467b..c307beb1d 100644 --- a/app/models/wiki_content.rb +++ b/app/models/wiki_content.rb @@ -60,6 +60,14 @@ class WikiContent < ActiveRecord::Base data end end + + # Returns the previous version or nil + def previous + @previous ||= WikiContent::Version.find(:first, + :order => 'version DESC', + :include => :author, + :conditions => ["wiki_content_id = ? AND version < ?", wiki_content_id, version]) + end end end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index cbca4fd68..8ce71cb80 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'diff' +require 'enumerator' class WikiPage < ActiveRecord::Base belongs_to :wiki @@ -87,6 +88,12 @@ class WikiPage < ActiveRecord::Base (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil end + def annotate(version=nil) + version = version ? version.to_i : self.content.version + c = content.versions.find_by_version(version) + c ? WikiAnnotate.new(c) : nil + end + def self.pretty_title(str) (str && str.is_a?(String)) ? str.tr('_', ' ') : str end @@ -113,3 +120,41 @@ class WikiDiff @diff = words_from.diff @words end end + +class WikiAnnotate + attr_reader :lines, :content + + def initialize(content) + @content = content + current = content + current_lines = current.text.split(/\r?\n/) + @lines = current_lines.collect {|t| [nil, nil, t]} + positions = [] + current_lines.size.times {|i| positions << i} + while (current.previous) + d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten + d.each_slice(3) do |s| + sign, line = s[0], s[1] + if sign == '+' && positions[line] && positions[line] != -1 + if @lines[positions[line]][0].nil? + @lines[positions[line]][0] = current.version + @lines[positions[line]][1] = current.author + end + end + end + d.each_slice(3) do |s| + sign, line = s[0], s[1] + if sign == '-' + positions.insert(line, -1) + else + positions[line] = nil + end + end + positions.compact! + # Stop if every line is annotated + break unless @lines.detect { |line| line[0].nil? } + current = current.previous + end + @lines.each { |line| line[0] ||= current.version } + end +end |