RTFMd 0.10301.1

Sign up to get free protection for your applications and to get access to all the features.
data/RTFMd.gemspec ADDED
@@ -0,0 +1,78 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+ s.rubygems_version = '1.3.5'
5
+
6
+ s.name = 'RTFMd'
7
+ s.version = '0.10301.1'
8
+ s.date = '2011-12-16'
9
+
10
+ s.summary = "A simple, Markdown documentation helper."
11
+ s.description = "A simple, Markdown documentation helper with ronn, gollum, and offline-generation support"
12
+
13
+ s.authors = ["Tom Bombadil", "Tom Preston-Werner", "Rick Olson"]
14
+ s.email = 'amanibhavam@destructuring.org'
15
+ s.homepage = 'https://github.com/HeSYINUvSBZfxqA/RTFMd'
16
+
17
+ s.require_paths = %w[lib]
18
+
19
+ s.executables = []
20
+
21
+ s.rdoc_options = ["--charset=UTF-8"]
22
+ s.extra_rdoc_files = %w[README.md LICENSE]
23
+
24
+ s.add_dependency('grit', "~> 2.4.1")
25
+ s.add_dependency('github-markup', [">= 0.7.0", "< 1.0.0"])
26
+ s.add_dependency('pygments.rb', "~> 0.2.0")
27
+ s.add_dependency('posix-spawn', "~> 0.3.0")
28
+ s.add_dependency('sinatra', "~> 1.0")
29
+ s.add_dependency('mustache', [">= 0.11.2", "< 1.0.0"])
30
+ s.add_dependency('sanitize', "~> 2.0.0")
31
+ s.add_dependency('nokogiri', "~> 1.4")
32
+ s.add_dependency('redcarpet')
33
+
34
+ s.add_development_dependency('RedCloth')
35
+ s.add_development_dependency('mocha')
36
+ s.add_development_dependency('org-ruby')
37
+ s.add_development_dependency('shoulda')
38
+ s.add_development_dependency('rack-test')
39
+ s.add_development_dependency('wikicloth', '~> 0.6.3')
40
+ s.add_development_dependency('rake', '~> 0.9.2')
41
+
42
+ s.files = %w[
43
+ HISTORY.md
44
+ LICENSE
45
+ README.md
46
+ Rakefile
47
+ bin/rtfm
48
+ docs/sanitization.md
49
+ RTFMd.gemspec
50
+ lib/gollum.rb
51
+ lib/gollum/blob_entry.rb
52
+ lib/gollum/committer.rb
53
+ lib/gollum/file.rb
54
+ lib/gollum/frontend/app.rb
55
+ lib/gollum/frontend/public/css/gollum.css
56
+ lib/gollum/frontend/public/css/ie7.css
57
+ lib/gollum/frontend/public/css/template.css
58
+ lib/gollum/frontend/public/images/icon-sprite.png
59
+ lib/gollum/frontend/public/javascript/gollum.js
60
+ lib/gollum/frontend/public/javascript/gollum.placeholder.js
61
+ lib/gollum/frontend/public/javascript/jquery.color.js
62
+ lib/gollum/frontend/public/javascript/jquery.js
63
+ lib/gollum/frontend/templates/error.mustache
64
+ lib/gollum/frontend/templates/layout.mustache
65
+ lib/gollum/frontend/templates/page.mustache
66
+ lib/gollum/frontend/templates/pages.mustache
67
+ lib/gollum/frontend/views/error.rb
68
+ lib/gollum/frontend/views/layout.rb
69
+ lib/gollum/frontend/views/page.rb
70
+ lib/gollum/frontend/views/pages.rb
71
+ lib/gollum/git_access.rb
72
+ lib/gollum/markup.rb
73
+ lib/gollum/page.rb
74
+ lib/gollum/pagination.rb
75
+ lib/gollum/sanitization.rb
76
+ lib/gollum/wiki.rb
77
+ ]
78
+ end
data/Rakefile ADDED
@@ -0,0 +1,138 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:test) do |test|
50
+ test.libs << 'lib' << 'test' << '.'
51
+ test.pattern = 'test/**/test_*.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
61
+ end
62
+
63
+ desc "Open an irb session preloaded with this library"
64
+ task :console do
65
+ sh "irb -rubygems -r ./lib/#{name}.rb"
66
+ end
67
+
68
+ #############################################################################
69
+ #
70
+ # Custom tasks (add your own tasks here)
71
+ #
72
+ #############################################################################
73
+
74
+
75
+
76
+ #############################################################################
77
+ #
78
+ # Packaging tasks
79
+ #
80
+ #############################################################################
81
+
82
+ task :release => :build do
83
+ unless `git branch` =~ /^\* master$/
84
+ puts "You must be on the master branch to release!"
85
+ exit!
86
+ end
87
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
88
+ sh "git tag v#{version}"
89
+ sh "git push origin master"
90
+ sh "git push origin v#{version}"
91
+ sh "gem push pkg/#{name}-#{version}.gem"
92
+ end
93
+
94
+ task :build => :gemspec do
95
+ sh "mkdir -p pkg"
96
+ sh "gem build #{gemspec_file}"
97
+ sh "mv #{gem_file} pkg"
98
+ end
99
+
100
+ task :gemspec => :validate do
101
+ # read spec file and split out manifest section
102
+ spec = File.read(gemspec_file)
103
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
104
+
105
+ # replace name version and date
106
+ replace_header(head, :name)
107
+ replace_header(head, :version)
108
+ replace_header(head, :date)
109
+ #comment this out if your rubyforge_project has a different name
110
+ replace_header(head, :rubyforge_project)
111
+
112
+ # determine file list from git ls-files
113
+ files = `git ls-files`.
114
+ split("\n").
115
+ sort.
116
+ reject { |file| file =~ /^\./ }.
117
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
118
+ map { |file| " #{file}" }.
119
+ join("\n")
120
+
121
+ # piece file back together and write
122
+ manifest = " s.files = %w[\n#{files}\n ]\n"
123
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
124
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
125
+ puts "Updated #{gemspec_file}"
126
+ end
127
+
128
+ task :validate do
129
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
130
+ unless libfiles.empty?
131
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
132
+ exit!
133
+ end
134
+ unless Dir['VERSION*'].empty?
135
+ puts "A `VERSION` file at root level violates Gem best practices."
136
+ exit!
137
+ end
138
+ end
data/bin/rtfm ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/bash -e
2
+
3
+ if [[ -n $1 ]]; then
4
+ GOLEM_WIKI=$1; shift
5
+ else
6
+ GOLEM_WIKI=$(pwd)
7
+ fi
8
+
9
+ export GOLEM_WIKI
10
+
11
+ bundle check 2>&- || { bundle install --local && bundle check; }
12
+ exec bundle exec thin start -R config/golem.ru
@@ -0,0 +1,32 @@
1
+ Sanitization Rules
2
+ ==================
3
+
4
+ Gollum uses the [Sanitize](http://wonko.com/post/sanitize) gem for HTML
5
+ sanitization.
6
+
7
+ See `lib/gollum.rb` for actual settings.
8
+
9
+ ## ALLOWED TAGS
10
+
11
+ a, abbr, acronym, address, area, b, big, blockquote, br, button, caption,
12
+ center, cite, code, col, colgroup, dd, del, dfn, dir, div, dl, dt, em,
13
+ fieldset, font, form, h1, h2, h3, h4, h5, h6, hr, i, img, input, ins, kbd,
14
+ label, legend, li, map, menu, ol, optgroup, option, p, pre, q, s, samp,
15
+ select, small, span, strike, strong, sub, sup, table, tbody, td, textarea,
16
+ tfoot, th, thead, tr, tt, u, ul, var
17
+
18
+ ## ALLOWED ATTRIBUTES
19
+
20
+ abbr, accept, accept-charset, accesskey, action, align, alt, axis, border,
21
+ cellpadding, cellspacing, char, charoff, charset, checked, cite, class, clear,
22
+ cols, colspan, color, compact, coords, datetime, dir, disabled, enctype, for,
23
+ frame, headers, height, href, hreflang, hspace, id, ismap, label, lang,
24
+ longdesc, maxlength, media, method, multiple, name, nohref, noshade, nowrap,
25
+ prompt, readonly, rel, rev, rows, rowspan, rules, scope, selected, shape,
26
+ size, span, src, start, summary, tabindex, target, title, type, usemap,
27
+ valign, value, vspace, width
28
+
29
+ ## ALLOWED PROTOCOLS
30
+
31
+ a href: http, https, mailto
32
+ img src: http, https
data/lib/gollum.rb ADDED
@@ -0,0 +1,40 @@
1
+ # stdlib
2
+ require 'digest/md5'
3
+ require 'ostruct'
4
+
5
+ # external
6
+ require 'grit'
7
+ require 'github/markup'
8
+ require 'sanitize'
9
+
10
+ # internal
11
+ require File.expand_path('../gollum/git_access', __FILE__)
12
+ require File.expand_path('../gollum/committer', __FILE__)
13
+ require File.expand_path('../gollum/pagination', __FILE__)
14
+ require File.expand_path('../gollum/blob_entry', __FILE__)
15
+ require File.expand_path('../gollum/wiki', __FILE__)
16
+ require File.expand_path('../gollum/page', __FILE__)
17
+ require File.expand_path('../gollum/file', __FILE__)
18
+ require File.expand_path('../gollum/markup', __FILE__)
19
+ require File.expand_path('../gollum/sanitization', __FILE__)
20
+ require File.expand_path('../gollum/tex', __FILE__)
21
+
22
+ module Gollum
23
+ VERSION = '1.3.1'
24
+
25
+ class Error < StandardError; end
26
+
27
+ class DuplicatePageError < Error
28
+ attr_accessor :dir
29
+ attr_accessor :existing_path
30
+ attr_accessor :attempted_path
31
+
32
+ def initialize(dir, existing, attempted, message = nil)
33
+ @dir = dir
34
+ @existing_path = existing
35
+ @attempted_path = attempted
36
+ super(message || "Cannot write #{@dir}/#{@attempted_path}, found #{@dir}/#{@existing_path}.")
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,78 @@
1
+ module Gollum
2
+ class BlobEntry
3
+ # Gets the String SHA for this blob.
4
+ attr_reader :sha
5
+
6
+ # Gets the full path String for this blob.
7
+ attr_reader :path
8
+
9
+ # Gets the Fixnum size of this blob.
10
+ attr_reader :size
11
+
12
+ def initialize(sha, path, size = nil)
13
+ @sha = sha
14
+ @path = path
15
+ @size = size
16
+ @dir = @name = @blob = nil
17
+ end
18
+
19
+ # Gets the normalized directory path String for this blob.
20
+ def dir
21
+ @dir ||= self.class.normalize_dir(::File.dirname(@path))
22
+ end
23
+
24
+ # Gets the file base name String for this blob.
25
+ def name
26
+ @name ||= ::File.basename(@path)
27
+ end
28
+
29
+ # Gets a Grit::Blob instance for this blob.
30
+ #
31
+ # repo - Grit::Repo instance for the Grit::Blob.
32
+ #
33
+ # Returns an unbaked Grit::Blob instance.
34
+ def blob(repo)
35
+ @blob ||= Grit::Blob.create(repo,
36
+ :id => @sha, :name => name, :size => @size)
37
+ end
38
+
39
+ # Gets a Page instance for this blob.
40
+ #
41
+ # wiki - Gollum::Wiki instance for the Gollum::Page
42
+ #
43
+ # Returns a Gollum::Page instance.
44
+ def page(wiki, commit)
45
+ blob = self.blob(wiki.repo)
46
+ page = wiki.page_class.new(wiki).populate(blob, self.dir)
47
+ page.version = commit
48
+ page
49
+ end
50
+
51
+ def inspect
52
+ %(#<Gollum::BlobEntry #{@sha} #{@path}>)
53
+ end
54
+
55
+ # Normalizes a given directory name for searching through tree paths.
56
+ # Ensures that a directory begins with a slash, or
57
+ #
58
+ # normalize_dir("") # => ""
59
+ # normalize_dir(".") # => ""
60
+ # normalize_dir("foo") # => "/foo"
61
+ # normalize_dir("/foo/") # => "/foo"
62
+ # normalize_dir("/") # => ""
63
+ # normalize_dir("c:/") # => ""
64
+ #
65
+ # dir - String directory name.
66
+ #
67
+ # Returns a normalized String directory name, or nil if no directory
68
+ # is given.
69
+ def self.normalize_dir(dir)
70
+ return '' if dir =~ /^.:\/$/
71
+ if dir
72
+ dir = ::File.expand_path(dir, '/')
73
+ dir = '' if dir == '/'
74
+ end
75
+ dir
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,217 @@
1
+ module Gollum
2
+ # Responsible for handling the commit process for a Wiki. It sets up the
3
+ # Git index, provides methods for modifying the tree, and stores callbacks
4
+ # to be fired after the commit has been made. This is specifically
5
+ # designed to handle multiple updated pages in a single commit.
6
+ class Committer
7
+ # Gets the instance of the Gollum::Wiki that is being updated.
8
+ attr_reader :wiki
9
+
10
+ # Gets a Hash of commit options.
11
+ attr_reader :options
12
+
13
+ # Initializes the Committer.
14
+ #
15
+ # wiki - The Gollum::Wiki instance that is being updated.
16
+ # options - The commit Hash details:
17
+ # :message - The String commit message.
18
+ # :name - The String author full name.
19
+ # :email - The String email address.
20
+ # :parent - Optional Grit::Commit parent to this update.
21
+ # :tree - Optional String SHA of the tree to create the
22
+ # index from.
23
+ # :committer - Optional Gollum::Committer instance. If provided,
24
+ # assume that this operation is part of batch of
25
+ # updates and the commit happens later.
26
+ #
27
+ # Returns the Committer instance.
28
+ def initialize(wiki, options = {})
29
+ @wiki = wiki
30
+ @options = options
31
+ @callbacks = []
32
+ end
33
+
34
+ # Public: References the Git index for this commit.
35
+ #
36
+ # Returns a Grit::Index.
37
+ def index
38
+ @index ||= begin
39
+ idx = @wiki.repo.index
40
+ if tree = options[:tree]
41
+ idx.read_tree(tree)
42
+ elsif parent = parents.first
43
+ idx.read_tree(parent.tree.id)
44
+ end
45
+ idx
46
+ end
47
+ end
48
+
49
+ # Public: The committer for this commit.
50
+ #
51
+ # Returns a Grit::Actor.
52
+ def actor
53
+ @actor ||= begin
54
+ @options[:name] = @wiki.default_committer_name if @options[:name].to_s.empty?
55
+ @options[:email] = @wiki.default_committer_email if @options[:email].to_s.empty?
56
+ Grit::Actor.new(@options[:name], @options[:email])
57
+ end
58
+ end
59
+
60
+ # Public: The parent commits to this pending commit.
61
+ #
62
+ # Returns an array of Grit::Commit instances.
63
+ def parents
64
+ @parents ||= begin
65
+ arr = [@options[:parent] || @wiki.repo.commit(@wiki.ref)]
66
+ arr.flatten!
67
+ arr.compact!
68
+ arr
69
+ end
70
+ end
71
+
72
+ # Adds a page to the given Index.
73
+ #
74
+ # dir - The String subdirectory of the Gollum::Page without any
75
+ # prefix or suffix slashes (e.g. "foo/bar").
76
+ # name - The String Gollum::Page name.
77
+ # format - The Symbol Gollum::Page format.
78
+ # data - The String wiki data to store in the tree map.
79
+ # allow_same_ext - A Boolean determining if the tree map allows the same
80
+ # filename with the same extension.
81
+ #
82
+ # Raises Gollum::DuplicatePageError if a matching filename already exists.
83
+ # This way, pages are not inadvertently overwritten.
84
+ #
85
+ # Returns nothing (modifies the Index in place).
86
+ def add_to_index(dir, name, format, data, allow_same_ext = false)
87
+ path = @wiki.page_file_name(name, format)
88
+
89
+ dir = '/' if dir.strip.empty?
90
+
91
+ fullpath = ::File.join(*[@wiki.page_file_dir, dir, path].compact)
92
+ fullpath = fullpath[1..-1] if fullpath =~ /^\//
93
+
94
+ if index.current_tree && tree = index.current_tree / dir
95
+ downpath = path.downcase.sub(/\.\w+$/, '')
96
+
97
+ tree.blobs.each do |blob|
98
+ next if page_path_scheduled_for_deletion?(index.tree, fullpath)
99
+ file = blob.name.downcase.sub(/\.\w+$/, '')
100
+ file_ext = ::File.extname(blob.name).sub(/^\./, '')
101
+ if downpath == file && !(allow_same_ext && file_ext == ext)
102
+ raise DuplicatePageError.new(dir, blob.name, path)
103
+ end
104
+ end
105
+ end
106
+
107
+ index.add(fullpath, @wiki.normalize(data))
108
+ end
109
+
110
+ # Update the given file in the repository's working directory if there
111
+ # is a working directory present.
112
+ #
113
+ # dir - The String directory in which the file lives.
114
+ # name - The String name of the page (may be in human format).
115
+ # format - The Symbol format of the page.
116
+ #
117
+ # Returns nothing.
118
+ def update_working_dir(dir, name, format)
119
+ unless @wiki.repo.bare
120
+ if @wiki.page_file_dir
121
+ dir = dir.size.zero? ? @wiki.page_file_dir : ::File.join(dir, @wiki.page_file_dir)
122
+ end
123
+
124
+ path =
125
+ if dir == ''
126
+ @wiki.page_file_name(name, format)
127
+ else
128
+ ::File.join(dir, @wiki.page_file_name(name, format))
129
+ end
130
+
131
+ Dir.chdir(::File.join(@wiki.repo.path, '..')) do
132
+ if file_path_scheduled_for_deletion?(index.tree, path)
133
+ @wiki.repo.git.rm({'f' => true}, '--', path)
134
+ else
135
+ @wiki.repo.git.checkout({}, 'HEAD', '--', path)
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ # Writes the commit to Git and runs the after_commit callbacks.
142
+ #
143
+ # Returns the String SHA1 of the new commit.
144
+ def commit
145
+ sha1 = index.commit(@options[:message], parents, actor, nil, @wiki.ref)
146
+ @callbacks.each do |cb|
147
+ cb.call(self, sha1)
148
+ end
149
+ sha1
150
+ end
151
+
152
+ # Adds a callback to be fired after a commit.
153
+ #
154
+ # block - A block that expects this Committer instance and the created
155
+ # commit's SHA1 as the arguments.
156
+ #
157
+ # Returns nothing.
158
+ def after_commit(&block)
159
+ @callbacks << block
160
+ end
161
+
162
+ # Determine if a given page (regardless of format) is scheduled to be
163
+ # deleted in the next commit for the given Index.
164
+ #
165
+ # map - The Hash map:
166
+ # key - The String directory or filename.
167
+ # val - The Hash submap or the String contents of the file.
168
+ # path - The String path of the page file. This may include the format
169
+ # extension in which case it will be ignored.
170
+ #
171
+ # Returns the Boolean response.
172
+ def page_path_scheduled_for_deletion?(map, path)
173
+ parts = path.split('/')
174
+ if parts.size == 1
175
+ deletions = map.keys.select { |k| !map[k] }
176
+ downfile = parts.first.downcase.sub(/\.\w+$/, '')
177
+ deletions.any? { |d| d.downcase.sub(/\.\w+$/, '') == downfile }
178
+ else
179
+ part = parts.shift
180
+ if rest = map[part]
181
+ page_path_scheduled_for_deletion?(rest, parts.join('/'))
182
+ else
183
+ false
184
+ end
185
+ end
186
+ end
187
+
188
+ # Determine if a given file is scheduled to be deleted in the next commit
189
+ # for the given Index.
190
+ #
191
+ # map - The Hash map:
192
+ # key - The String directory or filename.
193
+ # val - The Hash submap or the String contents of the file.
194
+ # path - The String path of the file including extension.
195
+ #
196
+ # Returns the Boolean response.
197
+ def file_path_scheduled_for_deletion?(map, path)
198
+ parts = path.split('/')
199
+ if parts.size == 1
200
+ deletions = map.keys.select { |k| !map[k] }
201
+ deletions.any? { |d| d == parts.first }
202
+ else
203
+ part = parts.shift
204
+ if rest = map[part]
205
+ file_path_scheduled_for_deletion?(rest, parts.join('/'))
206
+ else
207
+ false
208
+ end
209
+ end
210
+ end
211
+
212
+ # Proxies methods t
213
+ def method_missing(name, *args)
214
+ index.send(name, *args)
215
+ end
216
+ end
217
+ end