rtfmd 0.10301.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/HISTORY.md +93 -0
  2. data/LICENSE +21 -0
  3. data/README.md +393 -0
  4. data/bin/rtfm +0 -0
  5. data/bin/rtfmd +4 -0
  6. data/config/rtfmd.ru +33 -0
  7. data/docs/sanitization.md +32 -0
  8. data/lib/gollum.rb +39 -0
  9. data/lib/gollum/blob_entry.rb +78 -0
  10. data/lib/gollum/committer.rb +217 -0
  11. data/lib/gollum/file.rb +64 -0
  12. data/lib/gollum/frontend/app.rb +96 -0
  13. data/lib/gollum/frontend/indexapp.rb +17 -0
  14. data/lib/gollum/frontend/public/css/gollum.css +660 -0
  15. data/lib/gollum/frontend/public/css/ie7.css +69 -0
  16. data/lib/gollum/frontend/public/css/ronn.css +40 -0
  17. data/lib/gollum/frontend/public/css/template.css +381 -0
  18. data/lib/gollum/frontend/public/images/icon-sprite.png +0 -0
  19. data/lib/gollum/frontend/public/javascript/gollum.js +137 -0
  20. data/lib/gollum/frontend/public/javascript/gollum.placeholder.js +54 -0
  21. data/lib/gollum/frontend/public/javascript/jquery.color.js +123 -0
  22. data/lib/gollum/frontend/public/javascript/jquery.js +7179 -0
  23. data/lib/gollum/frontend/templates/error.mustache +8 -0
  24. data/lib/gollum/frontend/templates/index.mustache +25 -0
  25. data/lib/gollum/frontend/templates/layout.mustache +28 -0
  26. data/lib/gollum/frontend/templates/page.mustache +34 -0
  27. data/lib/gollum/frontend/templates/pages.mustache +31 -0
  28. data/lib/gollum/frontend/views/error.rb +7 -0
  29. data/lib/gollum/frontend/views/index.rb +21 -0
  30. data/lib/gollum/frontend/views/layout.rb +28 -0
  31. data/lib/gollum/frontend/views/page.rb +53 -0
  32. data/lib/gollum/frontend/views/pages.rb +19 -0
  33. data/lib/gollum/git_access.rb +248 -0
  34. data/lib/gollum/markup.rb +389 -0
  35. data/lib/gollum/page.rb +374 -0
  36. data/lib/gollum/pagination.rb +61 -0
  37. data/lib/gollum/sanitization.rb +161 -0
  38. data/lib/gollum/wiki.rb +378 -0
  39. data/rtfmd.gemspec +47 -0
  40. metadata +291 -0
@@ -0,0 +1,8 @@
1
+ <div id="wiki-wrapper" class="error">
2
+ <div id="error">
3
+ <h1>Error</h1>
4
+ <p>
5
+ {{message}}
6
+ </p>
7
+ </div>
8
+ </div>
@@ -0,0 +1,25 @@
1
+ <div id="wiki-wrapper" class="results">
2
+ <div id="head">
3
+ <h1>{{title}}</h1>
4
+ </div>
5
+ <div id="results">
6
+
7
+ {{#has_roots}}
8
+ <ul>
9
+ {{#roots}}
10
+ <li>
11
+ <a href="{{root}}">{{wiki}}</a>
12
+ </li>
13
+ {{/roots}}
14
+ </ul>
15
+ {{/has_roots}}
16
+
17
+ {{#no_roots}}
18
+ <p id="no-results">
19
+ There are no wikis.
20
+ </p>
21
+ {{/no_roots}}
22
+
23
+ </div>
24
+ </div>
25
+
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-type" content="text/html;charset=utf-8">
5
+ <link rel="stylesheet" type="text/css" href="{{base_path}}css/gollum.css" media="all">
6
+ <link rel="stylesheet" type="text/css" href="{{base_path}}css/template.css" media="all">
7
+ <link rel="stylesheet" type="text/css" href="{{base_path}}css/ronn.css" media="all">
8
+
9
+ <!--[if IE 7]>
10
+ <link rel="stylesheet" type="text/css" href="{{base_path}}css/ie7.css" media="all">
11
+ <![endif]-->
12
+
13
+ <script type="text/javascript" src="{{base_path}}javascript/jquery.js"></script>
14
+ <script type="text/javascript" src="{{base_path}}javascript/gollum.js"></script>
15
+ <script type="text/javascript" src="{{base_path}}javascript/gollum.placeholder.js"></script>
16
+ </head>
17
+ <body id='manpage'>
18
+ <div class='mp' id='man'>
19
+
20
+ <div class='man-navigation' style='display:none'>
21
+ </div>
22
+
23
+ {{{yield}}}
24
+
25
+ </div>
26
+
27
+ </body>
28
+ </html>
@@ -0,0 +1,34 @@
1
+ <div id="wiki-wrapper" class="page">
2
+ <div id="head">
3
+ <ul class="actions">
4
+ <li class="minibutton"><a href="{{base_path}}"
5
+ class="action-home-page">Home</a></li>
6
+ <li class="minibutton"><a href="{{base_path}}pages"
7
+ class="action-all-pages">All Pages</a></li>
8
+ <li class="minibutton"><a href="{{rtfm_root}}"
9
+ class="action-all-projects">All Projects</a></li>
10
+ </ul>
11
+ </div>
12
+ <div id="wiki-content">
13
+ <div class="wrap {{#has_footer}} has-footer {{/has_footer}} {{#has_sidebar}} has-rightbar{{/has_sidebar}}">
14
+ <div id="wiki-body" class="gollum-{{format}}-content">
15
+ <div id="template">
16
+ {{{content}}}
17
+ </div>
18
+ </div>
19
+ {{#has_sidebar}}
20
+ <div id="wiki-rightbar" class="gollum-{{sidebar_format}}-content">
21
+ {{{sidebar_content}}}
22
+ </div>
23
+ {{/has_sidebar}}
24
+ {{#has_footer}}
25
+ <div id="wiki-footer" class="gollum-{{footer_format}}-content">
26
+ <div id="footer-content">
27
+ {{{footer_content}}}
28
+ </div>
29
+ </div>
30
+ {{/has_footer}}
31
+ </div>
32
+
33
+ </div>
34
+ </div>
@@ -0,0 +1,31 @@
1
+ <div id="wiki-wrapper" class="results">
2
+ <div id="head">
3
+ <h1>{{title}}</h1>
4
+ <ul class="actions">
5
+ <li class="minibutton"><a href="{{base_path}}"
6
+ class="action-home-page">Home</a></li>
7
+ </ul>
8
+ </div>
9
+ <div id="results">
10
+
11
+ {{#has_results}}
12
+ <ul>
13
+ {{#results}}
14
+ <li>
15
+ <a href="{{base_path}}{{name}}">{{name}}</a>
16
+ </li>
17
+ {{/results}}
18
+ </ul>
19
+ {{/has_results}}
20
+
21
+ {{#no_results}}
22
+ <p id="no-results">
23
+ There are no pages in <strong>{{ref}}</strong>.
24
+ </p>
25
+ {{/no_results}}
26
+
27
+ </div>
28
+ <div id="footer">
29
+ </div>
30
+ </div>
31
+
@@ -0,0 +1,7 @@
1
+ module Precious
2
+ module Views
3
+ class Error < Layout
4
+ attr_reader :message
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ require 'cgi'
2
+
3
+ module Precious
4
+ module Views
5
+ class Index < Layout
6
+ attr_reader :roots
7
+
8
+ def title
9
+ "Index"
10
+ end
11
+
12
+ def has_roots
13
+ !@roots.empty?
14
+ end
15
+
16
+ def no_roots
17
+ @roots.empty?
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ require 'cgi'
2
+
3
+ module Precious
4
+ module Views
5
+ class Layout < Mustache
6
+ include Rack::Utils
7
+ alias_method :h, :escape_html
8
+
9
+ attr_reader :name
10
+
11
+ def escaped_name
12
+ CGI.escape(@name)
13
+ end
14
+
15
+ def title
16
+ "Home"
17
+ end
18
+
19
+ def base_path
20
+ @base_path
21
+ end
22
+
23
+ def rtfm_root
24
+ @rtfm_root
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ module Precious
2
+ module Views
3
+ class Page < Layout
4
+ attr_reader :content, :page, :footer
5
+ DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
6
+ DEFAULT_AUTHOR = 'you'
7
+
8
+ def title
9
+ @page.title
10
+ end
11
+
12
+ def format
13
+ @page.format.to_s
14
+ end
15
+
16
+ def author
17
+ return DEFAULT_AUTHOR unless @page.version
18
+ @page.version.author.name
19
+ end
20
+
21
+ def date
22
+ return Time.now.strftime(DATE_FORMAT) unless @page.version
23
+ @page.version.authored_date.strftime(DATE_FORMAT)
24
+ end
25
+
26
+ def has_footer
27
+ @footer = (@page.footer || false) if @footer.nil?
28
+ !!@footer
29
+ end
30
+
31
+ def footer_content
32
+ has_footer && @footer.formatted_data
33
+ end
34
+
35
+ def footer_format
36
+ has_footer && @footer.format.to_s
37
+ end
38
+
39
+ def has_sidebar
40
+ @sidebar = (@page.sidebar || false) if @sidebar.nil?
41
+ !!@sidebar
42
+ end
43
+
44
+ def sidebar_content
45
+ has_sidebar && @sidebar.formatted_data
46
+ end
47
+
48
+ def sidebar_format
49
+ has_sidebar && @sidebar.format.to_s
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ module Precious
2
+ module Views
3
+ class Pages < Layout
4
+ attr_reader :results, :ref
5
+
6
+ def title
7
+ "All pages in #{@ref}"
8
+ end
9
+
10
+ def has_results
11
+ !@results.empty?
12
+ end
13
+
14
+ def no_results
15
+ @results.empty?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,248 @@
1
+ module Gollum
2
+ # Controls all access to the Git objects from Gollum. Extend this class to
3
+ # add custom caching for special cases.
4
+ class GitAccess
5
+ # Initializes the GitAccess instance.
6
+ #
7
+ # path - The String path to the Git repository that holds the
8
+ # Gollum site.
9
+ # page_file_dir - String the directory in which all page files reside
10
+ #
11
+ # Returns this instance.
12
+ def initialize(path, page_file_dir = nil)
13
+ @page_file_dir = page_file_dir
14
+ @path = path
15
+ @repo = Grit::Repo.new(path)
16
+ clear
17
+ end
18
+
19
+ # Public: Determines whether the Git repository exists on disk.
20
+ #
21
+ # Returns true if it exists, or false.
22
+ def exist?
23
+ @repo.git.exist?
24
+ end
25
+
26
+ # Public: Converts a given Git reference to a SHA, using the cache if
27
+ # available.
28
+ #
29
+ # ref - a String Git reference (ex: "master")
30
+ #
31
+ # Returns a String, or nil if the ref isn't found.
32
+ def ref_to_sha(ref)
33
+ ref = ref.to_s
34
+ return if ref.empty?
35
+ sha =
36
+ if sha?(ref)
37
+ ref
38
+ else
39
+ get_cache(:ref, ref) { ref_to_sha!(ref) }
40
+ end.to_s
41
+ sha.empty? ? nil : sha
42
+ end
43
+
44
+ # Public: Gets a recursive list of Git blobs for the whole tree at the
45
+ # given commit.
46
+ #
47
+ # ref - A String Git reference or Git SHA to a commit.
48
+ #
49
+ # Returns an Array of BlobEntry instances.
50
+ def tree(ref)
51
+ if sha = ref_to_sha(ref)
52
+ get_cache(:tree, sha) { tree!(sha) }
53
+ else
54
+ []
55
+ end
56
+ end
57
+
58
+ # Public: Fetches the contents of the Git blob at the given SHA.
59
+ #
60
+ # sha - A String Git SHA.
61
+ #
62
+ # Returns the String content of the blob.
63
+ def blob(sha)
64
+ cat_file!(sha)
65
+ end
66
+
67
+ # Public: Looks up the Git commit using the given Git SHA or ref.
68
+ #
69
+ # ref - A String Git SHA or ref.
70
+ #
71
+ # Returns a Grit::Commit.
72
+ def commit(ref)
73
+ if sha?(ref)
74
+ get_cache(:commit, ref) { commit!(ref) }
75
+ else
76
+ if sha = get_cache(:ref, ref)
77
+ commit(sha)
78
+ else
79
+ if cm = commit!(ref)
80
+ set_cache(:ref, ref, cm.id)
81
+ set_cache(:commit, cm.id, cm)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ # Public: Clears all of the cached data that this GitAccess is tracking.
88
+ #
89
+ # Returns nothing.
90
+ def clear
91
+ @ref_map = {}
92
+ @tree_map = {}
93
+ @commit_map = {}
94
+ end
95
+
96
+ # Public: Refreshes just the cached Git reference data. This should
97
+ # be called after every Gollum update.
98
+ #
99
+ # Returns nothing.
100
+ def refresh
101
+ @ref_map.clear
102
+ end
103
+
104
+ #########################################################################
105
+ #
106
+ # Internal Methods
107
+ #
108
+ #########################################################################
109
+
110
+ # Gets the String path to the Git repository.
111
+ attr_reader :path
112
+
113
+ # Gets the Grit::Repo instance for the Git repository.
114
+ attr_reader :repo
115
+
116
+ # Gets a Hash cache of refs to commit SHAs.
117
+ #
118
+ # {"master" => "abc123", ...}
119
+ #
120
+ attr_reader :ref_map
121
+
122
+ # Gets a Hash cache of commit SHAs to a recursive tree of blobs.
123
+ #
124
+ # {"abc123" => [<BlobEntry>, <BlobEntry>]}
125
+ #
126
+ attr_reader :tree_map
127
+
128
+ # Gets a Hash cache of commit SHAs to the Grit::Commit instance.
129
+ #
130
+ # {"abcd123" => <Grit::Commit>}
131
+ #
132
+ attr_reader :commit_map
133
+
134
+ # Checks to see if the given String is a 40 character hex SHA.
135
+ #
136
+ # str - Possible String SHA.
137
+ #
138
+ # Returns true if the String is a SHA, or false.
139
+ def sha?(str)
140
+ !!(str =~ /^[0-9a-f]{40}$/)
141
+ end
142
+
143
+ # Looks up the Git SHA for the given Git ref.
144
+ #
145
+ # ref - String Git ref.
146
+ #
147
+ # Returns a String SHA.
148
+ def ref_to_sha!(ref)
149
+ @repo.git.rev_list({:max_count=>1}, ref)
150
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
151
+ end
152
+
153
+ # Looks up the Git blobs for a given commit.
154
+ #
155
+ # sha - String commit SHA.
156
+ #
157
+ # Returns an Array of BlobEntry instances.
158
+ def tree!(sha)
159
+ tree = @repo.git.native(:ls_tree,
160
+ {:r => true, :l => true, :z => true}, sha)
161
+ if tree.respond_to?(:force_encoding)
162
+ tree.force_encoding("UTF-8")
163
+ end
164
+ items = tree.split("\0").inject([]) do |memo, line|
165
+ memo << parse_tree_line(line)
166
+ end
167
+
168
+ if dir = @page_file_dir
169
+ regex = /^#{dir}\//
170
+ items.select { |i| i.path =~ regex }
171
+ else
172
+ items
173
+ end
174
+ end
175
+
176
+ # Reads the content from the Git db at the given SHA.
177
+ #
178
+ # sha - The String SHA.
179
+ #
180
+ # Returns the String content of the Git object.
181
+ def cat_file!(sha)
182
+ @repo.git.cat_file({:p => true}, sha)
183
+ end
184
+
185
+ # Reads a Git commit.
186
+ #
187
+ # sha - The string SHA of the Git commit.
188
+ #
189
+ # Returns a Grit::Commit.
190
+ def commit!(sha)
191
+ @repo.commit(sha)
192
+ end
193
+
194
+ # Attempts to get the given data from a cache. If it doesn't exist, it'll
195
+ # pass the results of the yielded block to the cache for future accesses.
196
+ #
197
+ # name - The cache prefix used in building the full cache key.
198
+ # key - The unique cache key suffix, usually a String Git SHA.
199
+ #
200
+ # Yields a block to pass to the cache.
201
+ # Returns the cached result.
202
+ def get_cache(name, key)
203
+ cache = instance_variable_get("@#{name}_map")
204
+ value = cache[key]
205
+ if value.nil? && block_given?
206
+ set_cache(name, key, value = yield)
207
+ end
208
+ value == :_nil ? nil : value
209
+ end
210
+
211
+ # Writes some data to the internal cache.
212
+ #
213
+ # name - The cache prefix used in building the full cache key.
214
+ # key - The unique cache key suffix, usually a String Git SHA.
215
+ # value - The value to write to the cache.
216
+ #
217
+ # Returns nothing.
218
+ def set_cache(name, key, value)
219
+ cache = instance_variable_get("@#{name}_map")
220
+ cache[key] = value || :_nil
221
+ end
222
+
223
+ # Parses a line of output from the `ls-tree` command.
224
+ #
225
+ # line - A String line of output:
226
+ # "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
227
+ #
228
+ # Returns an Array of BlobEntry instances.
229
+ def parse_tree_line(line)
230
+ mode, type, sha, size, *name = line.split(/\s+/)
231
+ BlobEntry.new(sha, name.join(' '), size.to_i)
232
+ end
233
+
234
+ # Decode octal sequences (\NNN) in tree path names.
235
+ #
236
+ # path - String path name.
237
+ #
238
+ # Returns a decoded String.
239
+ def decode_git_path(path)
240
+ if path[0] == ?" && path[-1] == ?"
241
+ path = path[1...-1]
242
+ path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
243
+ end
244
+ path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m.to_s}")) }
245
+ path
246
+ end
247
+ end
248
+ end