diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb
index cd814c14..6e17e6c7 100644
--- a/lib/gollum/frontend/app.rb
+++ b/lib/gollum/frontend/app.rb
@@ -85,6 +85,16 @@ module Precious
mustache :history
end
+ post '/compare/:name' do
+ @name = params[:name]
+ @versions = params[:versions]
+ wiki = Gollum::Wiki.new($path)
+ @page = wiki.page(@name)
+ diffs = wiki.repo.diff(@versions[1], @versions[0], @page.path)
+ @diff = diffs.first
+ mustache :compare
+ end
+
get %r{/(.+?)/([0-9a-f]{40})} do
name = params[:captures][0]
wiki = Gollum::Wiki.new($path)
diff --git a/lib/gollum/frontend/public/css/screen.css b/lib/gollum/frontend/public/css/screen.css
index 7709b0ca..8f152b8d 100644
--- a/lib/gollum/frontend/public/css/screen.css
+++ b/lib/gollum/frontend/public/css/screen.css
@@ -563,4 +563,160 @@ table.commits {
table.commits td.date {
width: 12%;
text-align: right;
- }
\ No newline at end of file
+ }
+
+/****************************************************************************/
+/* Files
+/****************************************************************************/
+
+#files {
+
+}
+
+ #files .file {
+ border: 1px solid #ccc;
+ margin-bottom: 1em;
+ }
+
+ #files .file .syntax{
+ border:none;
+ padding:0;
+ }
+
+ #files .file .meta {
+ padding:0 5px;
+ height:33px;
+ line-height:33px;
+ font-size:12px;
+ color:#333;
+ background:url(/images/modules/commit/file_head.gif) 0 0 repeat-x #eee;
+ text-shadow:1px 1px 0 rgba(255, 255, 255, 0.5);
+ border-bottom: 1px solid #ccc;
+ overflow: hidden;
+ }
+
+ #files .file .meta .info {
+ float: left;
+ height:33px;
+ line-height:33px;
+ font-family: Monaco, "Courier New", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace;
+ }
+
+ #files .file .meta .info span{
+ padding-left:9px;
+ margin-left:5px;
+ background:url(/images/modules/commit/action_separator.png) 0 50% no-repeat;
+ }
+
+ #files .file .meta .info span:first-child, #files .file .meta .info .icon + span{
+ background:transparent;
+ margin-left:0;
+ padding-left:0;
+ }
+
+ #files .file .meta .info span.icon{
+ float:left;
+ margin:5px 5px 0 0;
+ padding:3px;
+ background:#f7f7f7;
+ border:1px solid #ccc;
+ border-right-color:#e5e5e5;
+ border-bottom-color:#e5e5e5;
+ -webkit-border-radius:3px;
+ -moz-border-radius:3px;
+ border-radius:3px;
+ line-height: 1em;
+ }
+
+ #files .file .meta .actions {
+ float: right;
+ height:33px;
+ line-height:33px;
+ }
+
+ #files .file .meta .actions li{
+ list-style-type:none;
+ float:left;
+ margin:0 0 0 7px;
+ height:33px;
+ line-height:33px;
+ padding-left:9px;
+ font-size:11px;
+ background:url(/images/modules/commit/action_separator.png) 0 50% no-repeat;
+ }
+
+ #files .file .meta .actions li:first-child{
+ background:transparent;
+ margin-left:0;
+ padding-left:0;
+ }
+
+ #files .file .meta .actions li a{
+ font-weight:bold;
+ }
+
+ #files .file .meta .actions li code{
+ font-size:11px;
+ }
+
+ #files .file .meta .actions li label input{
+ position:relative;
+ top:1px;
+ }
+
+ #files .file .data {
+ font-size: 80%;
+ overflow: auto;
+ background-color: #f8f8ff;
+ }
+
+ #files .file .data.empty {
+ font-size: 90%;
+ padding:5px 10px;
+ color:#777;
+ }
+
+ #files .image {
+ padding: 1.2em;
+ text-align: center;
+ }
+
+ #files .image img {
+ max-width: 60em;
+ }
+
+ #files .file .data pre, #files .file .line-data, #files .file .line-number {
+ font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
+ font-size: 115%;
+ }
+
+ #files .file .data .highlight {
+ padding: 1em 0;
+ }
+
+ #files .file .data .highlight div {
+ padding-left: 1em;
+ }
+
+ #files .file .data .line_numbers {
+ background-color: #ececec;
+ color: #aaa;
+ padding: 1em .5em;
+ border-right: 1px solid #ddd;
+ text-align: right;
+ }
+
+ #files .file .data td.line_numbers{
+ padding:0 0.5em;
+ font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
+ font-size: 115%;
+ -moz-user-select:none;
+ -khtml-user-select:none;
+ user-select:none;
+ }
+
+ #files .file .data .line_numbers span,
+ #files .file .data .line_numbers a {
+ color: #aaa;
+ cursor: pointer;
+ }
\ No newline at end of file
diff --git a/lib/gollum/frontend/public/css/syntax.css b/lib/gollum/frontend/public/css/syntax.css
index 2774b764..d84c0612 100644
--- a/lib/gollum/frontend/public/css/syntax.css
+++ b/lib/gollum/frontend/public/css/syntax.css
@@ -14,6 +14,7 @@
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
+.highlight .gc { color: #999; background-color: #EAF2F5 }
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
diff --git a/lib/gollum/frontend/public/images/txt.png b/lib/gollum/frontend/public/images/txt.png
new file mode 100644
index 00000000..f3638cb4
Binary files /dev/null and b/lib/gollum/frontend/public/images/txt.png differ
diff --git a/lib/gollum/frontend/templates/compare.mustache b/lib/gollum/frontend/templates/compare.mustache
new file mode 100644
index 00000000..02b42593
--- /dev/null
+++ b/lib/gollum/frontend/templates/compare.mustache
@@ -0,0 +1,33 @@
+
+
+
+
Comparison of {{human_name}}: {{before}} → {{after}}
+
+
+
+
+
+ {{#lines}}
+
+ | {{ldln}} |
+ {{rdln}} |
+
+ {{line}}
+ |
+
+ {{/lines}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/gollum/frontend/templates/history.mustache b/lib/gollum/frontend/templates/history.mustache
index 3166ae09..7a7ee653 100644
--- a/lib/gollum/frontend/templates/history.mustache
+++ b/lib/gollum/frontend/templates/history.mustache
@@ -4,27 +4,29 @@
« Back
History of {{human_name}}
-
+
\ No newline at end of file
diff --git a/lib/gollum/frontend/views/compare.rb b/lib/gollum/frontend/views/compare.rb
new file mode 100644
index 00000000..a23ec182
--- /dev/null
+++ b/lib/gollum/frontend/views/compare.rb
@@ -0,0 +1,94 @@
+module Precious
+ module Views
+ class Compare < Layout
+ attr_reader :page, :diff, :versions
+
+ def human_name
+ @page.title
+ end
+
+ def title
+ "A Page"
+ end
+
+ def path
+ @page.path
+ end
+
+ def before
+ @versions[1][0..6]
+ end
+
+ def after
+ @versions[0][0..6]
+ end
+
+ def lines
+ lines = []
+ @diff.diff.split("\n")[2..-1].each_with_index do |line, line_index|
+ lines << { :line => line,
+ :class => line_class(line),
+ :ldln => left_diff_line_number(0, line),
+ :rdln => right_diff_line_number(0, line) }
+ end
+ lines
+ end
+
+ # private
+
+ def line_class(line)
+ if line =~ /^@@/
+ 'gc'
+ elsif line =~ /^\+/
+ 'gi'
+ elsif line =~ /^\-/
+ 'gd'
+ else
+ ''
+ end
+ end
+
+ @left_diff_line_number = nil
+ def left_diff_line_number(id, line)
+ if line =~ /^@@/
+ m, li = *line.match(/\-(\d+)/)
+ @left_diff_line_number = li.to_i
+ @current_line_number = @left_diff_line_number
+ ret = '...'
+ elsif line[0] == ?-
+ ret = @left_diff_line_number.to_s
+ @left_diff_line_number += 1
+ @current_line_number = @left_diff_line_number - 1
+ elsif line[0] == ?+
+ ret = ' '
+ else
+ ret = @left_diff_line_number.to_s
+ @left_diff_line_number += 1
+ @current_line_number = @left_diff_line_number - 1
+ end
+ ret
+ end
+
+ @right_diff_line_number = nil
+ def right_diff_line_number(id, line)
+ if line =~ /^@@/
+ m, ri = *line.match(/\+(\d+)/)
+ @right_diff_line_number = ri.to_i
+ @current_line_number = @right_diff_line_number
+ ret = '...'
+ elsif line[0] == ?-
+ ret = ' '
+ elsif line[0] == ?+
+ ret = @right_diff_line_number.to_s
+ @right_diff_line_number += 1
+ @current_line_number = @right_diff_line_number - 1
+ else
+ ret = @right_diff_line_number.to_s
+ @right_diff_line_number += 1
+ @current_line_number = @right_diff_line_number - 1
+ end
+ ret
+ end
+ end
+ end
+end