read-only-gollum 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -0
- data/HISTORY.md +102 -0
- data/Home.md +3 -0
- data/LICENSE +21 -0
- data/README.md +477 -0
- data/Rakefile +142 -0
- data/bin/read-only-gollum +126 -0
- data/docs/sanitization.md +32 -0
- data/lib/gollum.rb +41 -0
- data/lib/gollum/blob_entry.rb +78 -0
- data/lib/gollum/committer.rb +218 -0
- data/lib/gollum/file.rb +64 -0
- data/lib/gollum/frontend/app.rb +225 -0
- data/lib/gollum/frontend/public/css/dialog.css +141 -0
- data/lib/gollum/frontend/public/css/editor.css +537 -0
- data/lib/gollum/frontend/public/css/gollum.css +660 -0
- data/lib/gollum/frontend/public/css/ie7.css +69 -0
- data/lib/gollum/frontend/public/css/template.css +381 -0
- data/lib/gollum/frontend/public/images/icon-sprite.png +0 -0
- data/lib/gollum/frontend/public/javascript/editor/gollum.editor.js +1096 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/asciidoc.js +167 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/creole.js +104 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/markdown.js +211 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/org.js +173 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/pod.js +111 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/rdoc.js +74 -0
- data/lib/gollum/frontend/public/javascript/editor/langs/textile.js +175 -0
- data/lib/gollum/frontend/public/javascript/gollum.dialog.js +263 -0
- data/lib/gollum/frontend/public/javascript/gollum.js +161 -0
- data/lib/gollum/frontend/public/javascript/gollum.placeholder.js +54 -0
- data/lib/gollum/frontend/public/javascript/jquery.color.js +123 -0
- data/lib/gollum/frontend/public/javascript/jquery.js +7179 -0
- data/lib/gollum/frontend/templates/compare.mustache +38 -0
- data/lib/gollum/frontend/templates/create.mustache +17 -0
- data/lib/gollum/frontend/templates/edit.mustache +17 -0
- data/lib/gollum/frontend/templates/editor.mustache +116 -0
- data/lib/gollum/frontend/templates/error.mustache +8 -0
- data/lib/gollum/frontend/templates/history.mustache +58 -0
- data/lib/gollum/frontend/templates/layout.mustache +28 -0
- data/lib/gollum/frontend/templates/page.mustache +37 -0
- data/lib/gollum/frontend/templates/pages.mustache +35 -0
- data/lib/gollum/frontend/templates/search.mustache +36 -0
- data/lib/gollum/frontend/templates/searchbar.mustache +10 -0
- data/lib/gollum/frontend/views/compare.rb +94 -0
- data/lib/gollum/frontend/views/create.rb +48 -0
- data/lib/gollum/frontend/views/edit.rb +52 -0
- data/lib/gollum/frontend/views/editable.rb +13 -0
- data/lib/gollum/frontend/views/error.rb +7 -0
- data/lib/gollum/frontend/views/history.rb +44 -0
- data/lib/gollum/frontend/views/layout.rb +20 -0
- data/lib/gollum/frontend/views/page.rb +57 -0
- data/lib/gollum/frontend/views/pages.rb +19 -0
- data/lib/gollum/frontend/views/search.rb +20 -0
- data/lib/gollum/git_access.rb +248 -0
- data/lib/gollum/markup.rb +489 -0
- data/lib/gollum/page.rb +430 -0
- data/lib/gollum/pagination.rb +61 -0
- data/lib/gollum/sanitization.rb +174 -0
- data/lib/gollum/tex.rb +89 -0
- data/lib/gollum/web_sequence_diagram.rb +43 -0
- data/lib/gollum/wiki.rb +636 -0
- data/read-only-gollum.gemspec +224 -0
- data/templates/formatting.html +92 -0
- data/test/examples/empty.git/HEAD +1 -0
- data/test/examples/empty.git/config +5 -0
- data/test/examples/empty.git/description +1 -0
- data/test/examples/empty.git/hooks/applypatch-msg.sample +15 -0
- data/test/examples/empty.git/hooks/commit-msg.sample +24 -0
- data/test/examples/empty.git/hooks/post-commit.sample +8 -0
- data/test/examples/empty.git/hooks/post-receive.sample +15 -0
- data/test/examples/empty.git/hooks/post-update.sample +8 -0
- data/test/examples/empty.git/hooks/pre-applypatch.sample +14 -0
- data/test/examples/empty.git/hooks/pre-commit.sample +46 -0
- data/test/examples/empty.git/hooks/pre-rebase.sample +169 -0
- data/test/examples/empty.git/hooks/prepare-commit-msg.sample +36 -0
- data/test/examples/empty.git/hooks/update.sample +128 -0
- data/test/examples/empty.git/info/exclude +6 -0
- data/test/examples/empty.git/objects/info/.gitkeep +0 -0
- data/test/examples/empty.git/objects/pack/.gitkeep +0 -0
- data/test/examples/empty.git/refs/heads/.gitkeep +0 -0
- data/test/examples/lotr.git/COMMIT_EDITMSG +1 -0
- data/test/examples/lotr.git/HEAD +1 -0
- data/test/examples/lotr.git/ORIG_HEAD +1 -0
- data/test/examples/lotr.git/config +12 -0
- data/test/examples/lotr.git/description +1 -0
- data/test/examples/lotr.git/index +0 -0
- data/test/examples/lotr.git/info/exclude +6 -0
- data/test/examples/lotr.git/logs/HEAD +3 -0
- data/test/examples/lotr.git/logs/refs/heads/master +3 -0
- data/test/examples/lotr.git/objects/06/131480411710c92a82fe2d1e76932c70feb2e5 +0 -0
- data/test/examples/lotr.git/objects/0a/de1e2916346d4c1f2fb63b863fd3c16808fe44 +0 -0
- data/test/examples/lotr.git/objects/0e/d8cbe0a25235bd867e65193c7d837c66b328ef +3 -0
- data/test/examples/lotr.git/objects/12/629d666c5e3178f82f533f543d61b53dc78c0b +0 -0
- data/test/examples/lotr.git/objects/1d/b89ebba7e2c14d93b94ff98cfa3708a4f0d4e3 +2 -0
- data/test/examples/lotr.git/objects/24/49c2681badfd3c189e8ed658dacffe8ba48fe5 +0 -0
- data/test/examples/lotr.git/objects/25/4bdc1ba27d8b8a794538a8522d9a2b56ec2dd9 +0 -0
- data/test/examples/lotr.git/objects/2c/b9156ad383914561a8502fc70f5a1d887e48ad +4 -0
- data/test/examples/lotr.git/objects/5d/cac289a8603188d2c5caf481dcba2985126aaa +0 -0
- data/test/examples/lotr.git/objects/60/f12f4254f58801b9ee7db7bca5fa8aeefaa56b +0 -0
- data/test/examples/lotr.git/objects/71/4323c104239440a5c66ab12a67ed07a83c404f +0 -0
- data/test/examples/lotr.git/objects/84/0ec5b1ba1320e8ec443f28f99566f615d5af10 +0 -0
- data/test/examples/lotr.git/objects/93/6b83ee0dd8837adb82511e40d5e4ebe59bb675 +0 -0
- data/test/examples/lotr.git/objects/94/523d7ae48aeba575099dd12926420d8fd0425d +2 -0
- data/test/examples/lotr.git/objects/96/97dc65e095658bbd1b8e8678e08881e86d32f1 +0 -0
- data/test/examples/lotr.git/objects/a3/1ca2a7c352c92531a8b99815d15843b259e814 +0 -0
- data/test/examples/lotr.git/objects/a6/59b3763b822dd97544621fd0beef162ea37b14 +4 -0
- data/test/examples/lotr.git/objects/a8/ad3c09dd842a3517085bfadd37718856dee813 +0 -0
- data/test/examples/lotr.git/objects/aa/b61fe89d56f8614c0a8151da34f939dcedfa68 +0 -0
- data/test/examples/lotr.git/objects/bc/4b5fc0ce2c2ba3acef6647e4f67256ee45ab60 +0 -0
- data/test/examples/lotr.git/objects/c3/b43e9f08966b088e7a0192e436b7a884542e05 +0 -0
- data/test/examples/lotr.git/objects/dc/596d6b2dd89ab05c66f4abd7d5eb706bc17f19 +0 -0
- data/test/examples/lotr.git/objects/ec/da3205bee14520aab5a7bb307392064b938e83 +0 -0
- data/test/examples/lotr.git/objects/f4/84ebb1f40f8eb20d1bcd8d1d71934d2b8ae961 +0 -0
- data/test/examples/lotr.git/objects/fa/e7ef5344202bba4129abdc13060d9297d99465 +3 -0
- data/test/examples/lotr.git/objects/info/packs +2 -0
- data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.idx +0 -0
- data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.pack +0 -0
- data/test/examples/lotr.git/packed-refs +2 -0
- data/test/examples/lotr.git/refs/heads/master +1 -0
- data/test/examples/lotr.git/refs/remotes/origin/HEAD +1 -0
- data/test/examples/page_file_dir.git/COMMIT_EDITMSG +1 -0
- data/test/examples/page_file_dir.git/HEAD +1 -0
- data/test/examples/page_file_dir.git/config +6 -0
- data/test/examples/page_file_dir.git/description +1 -0
- data/test/examples/page_file_dir.git/index +0 -0
- data/test/examples/page_file_dir.git/info/exclude +6 -0
- data/test/examples/page_file_dir.git/logs/HEAD +1 -0
- data/test/examples/page_file_dir.git/logs/refs/heads/master +1 -0
- data/test/examples/page_file_dir.git/objects/0c/7d27db1f575263efdcab3dc650f4502a2dbcbf +0 -0
- data/test/examples/page_file_dir.git/objects/22/b404803c966dd92865614d86ff22ca12e50c1e +0 -0
- data/test/examples/page_file_dir.git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 +0 -0
- data/test/examples/page_file_dir.git/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 +0 -0
- data/test/examples/page_file_dir.git/objects/5b/43e14e0a15fb6f08feab1773d1c0991e9f71e2 +0 -0
- data/test/examples/page_file_dir.git/refs/heads/master +1 -0
- data/test/examples/revert.git/COMMIT_EDITMSG +1 -0
- data/test/examples/revert.git/HEAD +1 -0
- data/test/examples/revert.git/config +12 -0
- data/test/examples/revert.git/description +1 -0
- data/test/examples/revert.git/index +0 -0
- data/test/examples/revert.git/info/exclude +6 -0
- data/test/examples/revert.git/logs/HEAD +2 -0
- data/test/examples/revert.git/logs/refs/heads/master +2 -0
- data/test/examples/revert.git/objects/20/2ced67cea93c7b6bd2928aa1daef8d1d55a20d +0 -0
- data/test/examples/revert.git/objects/41/76394bfa11222363c66ce7e84b5f154095b6d9 +0 -0
- data/test/examples/revert.git/objects/6a/69f92020f5df77af6e8813ff1232493383b708 +0 -0
- data/test/examples/revert.git/objects/b4/785957bc986dc39c629de9fac9df46972c00fc +0 -0
- data/test/examples/revert.git/objects/f4/03b791119f8232b7cb0ba455c624ac6435f433 +0 -0
- data/test/examples/revert.git/objects/info/packs +2 -0
- data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.idx +0 -0
- data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.pack +0 -0
- data/test/examples/revert.git/packed-refs +2 -0
- data/test/examples/revert.git/refs/heads/master +1 -0
- data/test/examples/revert.git/refs/remotes/origin/HEAD +1 -0
- data/test/examples/yubiwa.git/HEAD +1 -0
- data/test/examples/yubiwa.git/config +5 -0
- data/test/examples/yubiwa.git/description +1 -0
- data/test/examples/yubiwa.git/info/exclude +6 -0
- data/test/examples/yubiwa.git/objects/10/fa2ddc4e3b4009d8a453aace10bd6148c1ad00 +0 -0
- data/test/examples/yubiwa.git/objects/52/4b82874327ea7cbf730389964ba7cb3de966de +0 -0
- data/test/examples/yubiwa.git/objects/58/3fc201cb457fb3f1480f3e1e5999b119633835 +0 -0
- data/test/examples/yubiwa.git/objects/87/bc1dd46ab3d3874d4e898d45dd512cc20a7cc8 +1 -0
- data/test/examples/yubiwa.git/objects/89/64ed1b4e21aa90e831763bbce9034bfda81b70 +0 -0
- data/test/examples/yubiwa.git/objects/9f/f6dd0660da5fba2d3374adb2b84fa653bb538b +0 -0
- data/test/examples/yubiwa.git/objects/ac/e97abf2b177815a1972d7db22f229f58c83309 +0 -0
- data/test/examples/yubiwa.git/objects/b1/f443863a4816628807fbf86141ebef055dda34 +0 -0
- data/test/examples/yubiwa.git/refs/heads/master +1 -0
- data/test/helper.rb +66 -0
- data/test/test_app.rb +169 -0
- data/test/test_committer.rb +64 -0
- data/test/test_file.rb +27 -0
- data/test/test_git_access.rb +52 -0
- data/test/test_markup.rb +628 -0
- data/test/test_page.rb +166 -0
- data/test/test_page_revert.rb +45 -0
- data/test/test_wiki.rb +462 -0
- metadata +470 -0
data/lib/gollum/page.rb
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
module Gollum
|
|
2
|
+
class Page
|
|
3
|
+
include Pagination
|
|
4
|
+
|
|
5
|
+
Wiki.page_class = self
|
|
6
|
+
|
|
7
|
+
VALID_PAGE_RE = /^(.+)\.(md|mkdn?|mdown|markdown|textile|rdoc|org|creole|re?st(\.txt)?|asciidoc|pod|(media)?wiki)$/i
|
|
8
|
+
FORMAT_NAMES = { :markdown => "Markdown",
|
|
9
|
+
:textile => "Textile",
|
|
10
|
+
:rdoc => "RDoc",
|
|
11
|
+
:org => "Org-mode",
|
|
12
|
+
:creole => "Creole",
|
|
13
|
+
:rest => "reStructuredText",
|
|
14
|
+
:asciidoc => "AsciiDoc",
|
|
15
|
+
:mediawiki => "MediaWiki",
|
|
16
|
+
:pod => "Pod" }
|
|
17
|
+
|
|
18
|
+
# Sets a Boolean determing whether this page is a historical version.
|
|
19
|
+
#
|
|
20
|
+
# Returns nothing.
|
|
21
|
+
attr_writer :historical
|
|
22
|
+
|
|
23
|
+
# Checks if a filename has a valid extension understood by GitHub::Markup.
|
|
24
|
+
#
|
|
25
|
+
# filename - String filename, like "Home.md".
|
|
26
|
+
#
|
|
27
|
+
# Returns the matching String basename of the file without the extension.
|
|
28
|
+
def self.valid_filename?(filename)
|
|
29
|
+
filename && filename.to_s =~ VALID_PAGE_RE && $1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Checks if a filename has a valid extension understood by GitHub::Markup.
|
|
33
|
+
# Also, checks if the filename has no "_" in the front (such as
|
|
34
|
+
# _Footer.md).
|
|
35
|
+
#
|
|
36
|
+
# filename - String filename, like "Home.md".
|
|
37
|
+
#
|
|
38
|
+
# Returns the matching String basename of the file without the extension.
|
|
39
|
+
def self.valid_page_name?(filename)
|
|
40
|
+
match = valid_filename?(filename)
|
|
41
|
+
filename =~ /^_/ ? false : match
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Public: The format of a given filename.
|
|
45
|
+
#
|
|
46
|
+
# filename - The String filename.
|
|
47
|
+
#
|
|
48
|
+
# Returns the Symbol format of the page. One of:
|
|
49
|
+
# [ :markdown | :textile | :rdoc | :org | :rest | :asciidoc | :pod |
|
|
50
|
+
# :roff ]
|
|
51
|
+
def self.format_for(filename)
|
|
52
|
+
case filename.to_s
|
|
53
|
+
when /\.(md|mkdn?|mdown|markdown)$/i
|
|
54
|
+
:markdown
|
|
55
|
+
when /\.(textile)$/i
|
|
56
|
+
:textile
|
|
57
|
+
when /\.(rdoc)$/i
|
|
58
|
+
:rdoc
|
|
59
|
+
when /\.(org)$/i
|
|
60
|
+
:org
|
|
61
|
+
when /\.(creole)$/i
|
|
62
|
+
:creole
|
|
63
|
+
when /\.(re?st(\.txt)?)$/i
|
|
64
|
+
:rest
|
|
65
|
+
when /\.(asciidoc)$/i
|
|
66
|
+
:asciidoc
|
|
67
|
+
when /\.(pod)$/i
|
|
68
|
+
:pod
|
|
69
|
+
when /\.(\d)$/i
|
|
70
|
+
:roff
|
|
71
|
+
when /\.(media)?wiki$/i
|
|
72
|
+
:mediawiki
|
|
73
|
+
else
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Reusable filter to turn a filename (without path) into a canonical name.
|
|
79
|
+
# Strips extension, converts dashes to spaces.
|
|
80
|
+
#
|
|
81
|
+
# Returns the filtered String.
|
|
82
|
+
def self.canonicalize_filename(filename)
|
|
83
|
+
strip_filename(filename).gsub('-', ' ')
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Reusable filter to strip extension and path from filename
|
|
87
|
+
#
|
|
88
|
+
# filename - The string path or filename to strip
|
|
89
|
+
#
|
|
90
|
+
# Returns the stripped String.
|
|
91
|
+
def self.strip_filename(filename)
|
|
92
|
+
::File.basename(filename, ::File.extname(filename))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Public: Initialize a page.
|
|
96
|
+
#
|
|
97
|
+
# wiki - The Gollum::Wiki in question.
|
|
98
|
+
#
|
|
99
|
+
# Returns a newly initialized Gollum::Page.
|
|
100
|
+
def initialize(wiki)
|
|
101
|
+
@wiki = wiki
|
|
102
|
+
@blob = @footer = @sidebar = nil
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Public: The on-disk filename of the page including extension.
|
|
106
|
+
#
|
|
107
|
+
# Returns the String name.
|
|
108
|
+
def filename
|
|
109
|
+
@blob && @blob.name
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Public: The on-disk filename of the page with extension stripped.
|
|
113
|
+
#
|
|
114
|
+
# Returns the String name.
|
|
115
|
+
def filename_stripped
|
|
116
|
+
self.class.strip_filename(filename)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Public: The canonical page name without extension, and dashes converted
|
|
120
|
+
# to spaces.
|
|
121
|
+
#
|
|
122
|
+
# Returns the String name.
|
|
123
|
+
def name
|
|
124
|
+
self.class.canonicalize_filename(filename)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Public: If the first element of a formatted page is an <h1> tag it can
|
|
128
|
+
# be considered the title of the page and used in the display. If the
|
|
129
|
+
# first element is NOT an <h1> tag, the title will be constructed from the
|
|
130
|
+
# filename by stripping the extension and replacing any dashes with
|
|
131
|
+
# spaces.
|
|
132
|
+
#
|
|
133
|
+
# Returns the fully sanitized String title.
|
|
134
|
+
def title
|
|
135
|
+
doc = Nokogiri::HTML(%{<div id="gollum-root">} + self.formatted_data + %{</div>})
|
|
136
|
+
|
|
137
|
+
header =
|
|
138
|
+
case self.format
|
|
139
|
+
when :asciidoc
|
|
140
|
+
doc.css("div#gollum-root > div#header > h1:first-child")
|
|
141
|
+
when :org
|
|
142
|
+
doc.css("div#gollum-root > p.title:first-child")
|
|
143
|
+
when :pod
|
|
144
|
+
doc.css("div#gollum-root > a.dummyTopAnchor:first-child + h1")
|
|
145
|
+
when :rest
|
|
146
|
+
doc.css("div#gollum-root > div > div > h1:first-child")
|
|
147
|
+
else
|
|
148
|
+
doc.css("div#gollum-root > h1:first-child")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
if !header.empty?
|
|
152
|
+
Sanitize.clean(header.to_html)
|
|
153
|
+
else
|
|
154
|
+
Sanitize.clean(name)
|
|
155
|
+
end.strip
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Public: The path of the page within the repo.
|
|
159
|
+
#
|
|
160
|
+
# Returns the String path.
|
|
161
|
+
attr_reader :path
|
|
162
|
+
|
|
163
|
+
# Public: The raw contents of the page.
|
|
164
|
+
#
|
|
165
|
+
# Returns the String data.
|
|
166
|
+
def raw_data
|
|
167
|
+
@blob && @blob.data
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Public: A text data encoded in specified encoding.
|
|
171
|
+
#
|
|
172
|
+
# encoding - An Encoding or nil
|
|
173
|
+
#
|
|
174
|
+
# Returns a character encoding aware String.
|
|
175
|
+
def text_data(encoding=nil)
|
|
176
|
+
if raw_data.respond_to?(:encoding)
|
|
177
|
+
raw_data.force_encoding(encoding || Encoding::UTF_8)
|
|
178
|
+
else
|
|
179
|
+
raw_data
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Public: The formatted contents of the page.
|
|
184
|
+
#
|
|
185
|
+
# encoding - Encoding Constant or String.
|
|
186
|
+
#
|
|
187
|
+
# Returns the String data.
|
|
188
|
+
def formatted_data(encoding = nil, &block)
|
|
189
|
+
@blob && markup_class.render(historical?, encoding, &block)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Public: The format of the page.
|
|
193
|
+
#
|
|
194
|
+
# Returns the Symbol format of the page. One of:
|
|
195
|
+
# [ :markdown | :textile | :rdoc | :org | :rest | :asciidoc | :pod |
|
|
196
|
+
# :roff ]
|
|
197
|
+
def format
|
|
198
|
+
self.class.format_for(@blob.name)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Gets the Gollum::Markup instance that will render this page's content.
|
|
202
|
+
#
|
|
203
|
+
# Returns a Gollum::Markup instance.
|
|
204
|
+
def markup_class
|
|
205
|
+
@markup_class ||= @wiki.markup_classes[format].new(self)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Public: The current version of the page.
|
|
209
|
+
#
|
|
210
|
+
# Returns the Grit::Commit.
|
|
211
|
+
attr_reader :version
|
|
212
|
+
|
|
213
|
+
# Public: All of the versions that have touched the Page.
|
|
214
|
+
#
|
|
215
|
+
# options - The options Hash:
|
|
216
|
+
# :page - The Integer page number (default: 1).
|
|
217
|
+
# :per_page - The Integer max count of items to return.
|
|
218
|
+
# :follow - Follow's a file across renames, but falls back
|
|
219
|
+
# to a slower Grit native call. (default: false)
|
|
220
|
+
#
|
|
221
|
+
# Returns an Array of Grit::Commit.
|
|
222
|
+
def versions(options = {})
|
|
223
|
+
if options[:follow]
|
|
224
|
+
options[:pretty] = 'raw'
|
|
225
|
+
options.delete :max_count
|
|
226
|
+
options.delete :skip
|
|
227
|
+
log = @wiki.repo.git.native "log", options, @wiki.ref, "--", @path
|
|
228
|
+
Grit::Commit.list_from_string(@wiki.repo, log)
|
|
229
|
+
else
|
|
230
|
+
@wiki.repo.log(@wiki.ref, @path, log_pagination_options(options))
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Public: The footer Page.
|
|
235
|
+
#
|
|
236
|
+
# Returns the footer Page or nil if none exists.
|
|
237
|
+
def footer
|
|
238
|
+
@footer ||= find_sub_page(:footer)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Public: The sidebar Page.
|
|
242
|
+
#
|
|
243
|
+
# Returns the sidebar Page or nil if none exists.
|
|
244
|
+
def sidebar
|
|
245
|
+
@sidebar ||= find_sub_page(:sidebar)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Gets a Boolean determining whether this page is a historical version.
|
|
249
|
+
# Historical pages are pulled using exact SHA hashes and format all links
|
|
250
|
+
# with rel="nofollow"
|
|
251
|
+
#
|
|
252
|
+
# Returns true if the page is pulled from a named branch or tag, or false.
|
|
253
|
+
def historical?
|
|
254
|
+
!!@historical
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
#########################################################################
|
|
258
|
+
#
|
|
259
|
+
# Class Methods
|
|
260
|
+
#
|
|
261
|
+
#########################################################################
|
|
262
|
+
|
|
263
|
+
# Convert a human page name into a canonical page name.
|
|
264
|
+
#
|
|
265
|
+
# name - The String human page name.
|
|
266
|
+
# char_white_sub - Substitution for whitespace
|
|
267
|
+
# char_other_sub - Substitution for other special chars
|
|
268
|
+
#
|
|
269
|
+
# Examples
|
|
270
|
+
#
|
|
271
|
+
# Page.cname("Bilbo Baggins")
|
|
272
|
+
# # => 'Bilbo-Baggins'
|
|
273
|
+
#
|
|
274
|
+
# Page.cname("Bilbo Baggins",'_')
|
|
275
|
+
# # => 'Bilbo_Baggins'
|
|
276
|
+
#
|
|
277
|
+
# Returns the String canonical name.
|
|
278
|
+
def self.cname(name, char_white_sub = '-', char_other_sub = '-')
|
|
279
|
+
name.respond_to?(:gsub) ?
|
|
280
|
+
name.gsub(%r{\s},char_white_sub).gsub(%r{[/<>+]}, char_other_sub) :
|
|
281
|
+
''
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Convert a format Symbol into an extension String.
|
|
285
|
+
#
|
|
286
|
+
# format - The format Symbol.
|
|
287
|
+
#
|
|
288
|
+
# Returns the String extension (no leading period).
|
|
289
|
+
def self.format_to_ext(format)
|
|
290
|
+
case format
|
|
291
|
+
when :markdown then 'md'
|
|
292
|
+
when :textile then 'textile'
|
|
293
|
+
when :rdoc then 'rdoc'
|
|
294
|
+
when :org then 'org'
|
|
295
|
+
when :creole then 'creole'
|
|
296
|
+
when :rest then 'rest'
|
|
297
|
+
when :asciidoc then 'asciidoc'
|
|
298
|
+
when :pod then 'pod'
|
|
299
|
+
when :mediawiki then 'mediawiki'
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
#########################################################################
|
|
304
|
+
#
|
|
305
|
+
# Internal Methods
|
|
306
|
+
#
|
|
307
|
+
#########################################################################
|
|
308
|
+
|
|
309
|
+
# The underlying wiki repo.
|
|
310
|
+
#
|
|
311
|
+
# Returns the Gollum::Wiki containing the page.
|
|
312
|
+
attr_reader :wiki
|
|
313
|
+
|
|
314
|
+
# Set the Grit::Commit version of the page.
|
|
315
|
+
#
|
|
316
|
+
# Returns nothing.
|
|
317
|
+
attr_writer :version
|
|
318
|
+
|
|
319
|
+
# Find a page in the given Gollum repo.
|
|
320
|
+
#
|
|
321
|
+
# name - The human or canonical String page name to find.
|
|
322
|
+
# version - The String version ID to find.
|
|
323
|
+
#
|
|
324
|
+
# Returns a Gollum::Page or nil if the page could not be found.
|
|
325
|
+
def find(name, version)
|
|
326
|
+
map = @wiki.tree_map_for(version.to_s)
|
|
327
|
+
if page = find_page_in_tree(map, name)
|
|
328
|
+
page.version = version.is_a?(Grit::Commit) ?
|
|
329
|
+
version : @wiki.commit_for(version)
|
|
330
|
+
page.historical = page.version.to_s == version.to_s
|
|
331
|
+
page
|
|
332
|
+
end
|
|
333
|
+
rescue Grit::GitRuby::Repository::NoSuchShaFound
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# Find a page in a given tree.
|
|
337
|
+
#
|
|
338
|
+
# map - The Array tree map from Wiki#tree_map.
|
|
339
|
+
# name - The canonical String page name.
|
|
340
|
+
# checked_dir - Optional String of the directory a matching page needs
|
|
341
|
+
# to be in. The string should
|
|
342
|
+
#
|
|
343
|
+
# Returns a Gollum::Page or nil if the page could not be found.
|
|
344
|
+
def find_page_in_tree(map, name, checked_dir = nil)
|
|
345
|
+
return nil if !map || name.to_s.empty?
|
|
346
|
+
if checked_dir = BlobEntry.normalize_dir(checked_dir)
|
|
347
|
+
checked_dir.downcase!
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
map.each do |entry|
|
|
351
|
+
next if entry.name.to_s.empty?
|
|
352
|
+
next unless checked_dir.nil? || entry.dir.downcase == checked_dir
|
|
353
|
+
next unless page_match(name, entry.name)
|
|
354
|
+
return entry.page(@wiki, @version)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
return nil # nothing was found
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Populate the Page with information from the Blob.
|
|
361
|
+
#
|
|
362
|
+
# blob - The Grit::Blob that contains the info.
|
|
363
|
+
# path - The String directory path of the page file.
|
|
364
|
+
#
|
|
365
|
+
# Returns the populated Gollum::Page.
|
|
366
|
+
def populate(blob, path=nil)
|
|
367
|
+
@blob = blob
|
|
368
|
+
@path = "#{path}/#{blob.name}"[1..-1]
|
|
369
|
+
self
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# The full directory path for the given tree.
|
|
373
|
+
#
|
|
374
|
+
# treemap - The Hash treemap containing parentage information.
|
|
375
|
+
# tree - The Grit::Tree for which to compute the path.
|
|
376
|
+
#
|
|
377
|
+
# Returns the String path.
|
|
378
|
+
def tree_path(treemap, tree)
|
|
379
|
+
if ptree = treemap[tree]
|
|
380
|
+
tree_path(treemap, ptree) + '/' + tree.name
|
|
381
|
+
else
|
|
382
|
+
''
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
# Compare the canonicalized versions of the two names.
|
|
387
|
+
#
|
|
388
|
+
# name - The human or canonical String page name.
|
|
389
|
+
# filename - the String filename on disk (including extension).
|
|
390
|
+
#
|
|
391
|
+
# Returns a Boolean.
|
|
392
|
+
def page_match(name, filename)
|
|
393
|
+
if match = self.class.valid_filename?(filename)
|
|
394
|
+
@wiki.ws_subs.each do |sub|
|
|
395
|
+
return true if Page.cname(name).downcase == Page.cname(match, sub).downcase
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
false
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
# Loads a sub page. Sub page nanes (footers) are prefixed with
|
|
402
|
+
# an underscore to distinguish them from other Pages.
|
|
403
|
+
#
|
|
404
|
+
# name - String page name.
|
|
405
|
+
#
|
|
406
|
+
# Returns the Page or nil if none exists.
|
|
407
|
+
def find_sub_page(name)
|
|
408
|
+
return nil unless self.version
|
|
409
|
+
return nil if self.filename =~ /^_/
|
|
410
|
+
name = "_#{name.to_s.capitalize}"
|
|
411
|
+
return nil if page_match(name, self.filename)
|
|
412
|
+
|
|
413
|
+
dirs = self.path.split('/')
|
|
414
|
+
dirs.pop
|
|
415
|
+
map = @wiki.tree_map_for(self.version.id)
|
|
416
|
+
while !dirs.empty?
|
|
417
|
+
if page = find_page_in_tree(map, name, dirs.join('/'))
|
|
418
|
+
return page
|
|
419
|
+
end
|
|
420
|
+
dirs.pop
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
find_page_in_tree(map, name, '')
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def inspect
|
|
427
|
+
%(#<#{self.class.name}:#{object_id} #{name} (#{format}) @wiki=#{@wiki.repo.path.inspect}>)
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Gollum
|
|
2
|
+
module Pagination
|
|
3
|
+
def self.included(klass)
|
|
4
|
+
klass.extend ClassMethods
|
|
5
|
+
class << klass
|
|
6
|
+
# Default Integer max count of items to return in git commands.
|
|
7
|
+
attr_accessor :per_page
|
|
8
|
+
end
|
|
9
|
+
klass.per_page = 30
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module ClassMethods
|
|
13
|
+
# Turns a page number into an offset number for the git skip option.
|
|
14
|
+
#
|
|
15
|
+
# page - Integer page number.
|
|
16
|
+
#
|
|
17
|
+
# Returns an Integer.
|
|
18
|
+
def page_to_skip(page)
|
|
19
|
+
([1, page.to_i].max - 1) * per_page
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Fills in git-specific options for the log command using simple
|
|
23
|
+
# pagination options.
|
|
24
|
+
#
|
|
25
|
+
# options - Hash of options:
|
|
26
|
+
# page - Optional Integer page number (default: 1)
|
|
27
|
+
# per_page - Optional Integer max count of items to return.
|
|
28
|
+
# Defaults to #per_class class method.
|
|
29
|
+
#
|
|
30
|
+
# Returns Hash with :max_count and :skip keys.
|
|
31
|
+
def log_pagination_options(options = {})
|
|
32
|
+
skip = page_to_skip(options.delete(:page))
|
|
33
|
+
options[:max_count] = [options.delete(:per_page).to_i, per_page].max
|
|
34
|
+
options[:skip] = skip if skip > 0
|
|
35
|
+
options
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Turns a page number into an offset number for the git skip option.
|
|
40
|
+
#
|
|
41
|
+
# page - Integer page number.
|
|
42
|
+
#
|
|
43
|
+
# Returns an Integer.
|
|
44
|
+
def page_to_skip(page)
|
|
45
|
+
self.class.page_to_skip(page)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Fills in git-specific options for the log command using simple
|
|
49
|
+
# pagination options.
|
|
50
|
+
#
|
|
51
|
+
# options - Hash of options:
|
|
52
|
+
# page - Optional Integer page number (default: 1)
|
|
53
|
+
# per_page - Optional Integer max count of items to return.
|
|
54
|
+
# Defaults to #per_class class method.
|
|
55
|
+
#
|
|
56
|
+
# Returns Hash with :max_count and :skip keys.
|
|
57
|
+
def log_pagination_options(options = {})
|
|
58
|
+
self.class.log_pagination_options(options)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|