gollum-lib-4.2.7/ 0000755 0000041 0000041 00000000000 13172672532 013627 5 ustar www-data www-data gollum-lib-4.2.7/gollum-lib_java.gemspec 0000644 0000041 0000041 00000000416 13172672532 020241 0 ustar www-data www-data require File.join(File.dirname(__FILE__), 'gemspec.rb') require File.join(File.dirname(__FILE__), 'lib', 'gollum-lib', 'version.rb') default_adapter = ['gollum-rjgit_adapter', '~> 0.3'] Gem::Specification.new &specification(Gollum::Lib::VERSION, default_adapter, "java") gollum-lib-4.2.7/Rakefile 0000644 0000041 0000041 00000011105 13172672532 015272 0 ustar www-data www-data require 'rubygems' require 'rake' require 'date' ############################################################################# # # Helper functions # ############################################################################# def name "gollum-lib" end def version line = File.read("lib/gollum-lib/version.rb")[/^\s*VERSION\s*=\s*.*/] line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1] end # assumes x.y.z all digit version def next_version # x.y.z v = version.split '.' # bump z v[-1] = v[-1].to_i + 1 v.join '.' end def bump_version old_file = File.read("lib/gollum-lib/version.rb") old_version_line = old_file[/^\s*VERSION\s*=\s*.*/] new_version = next_version # replace first match of old version with new version old_file.sub!(old_version_line, " VERSION = '#{new_version}'") File.write("lib/gollum-lib/version.rb", old_file) new_version end def date Date.today.to_s end def rubyforge_project name end def gemspec_file "gemspec.rb" end def gemspecs ["#{name}.gemspec", "#{name}_java.gemspec"] end def gem_files ["#{name}-#{version}.gem", "#{name}-#{version}-java.gem"] end def replace_header(head, header_name) head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} end ############################################################################# # # Standard tasks # ############################################################################# task :default => :test require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' << '.' test.pattern = 'test/**/test_*.rb' test.verbose = true end desc "Generate RCov test coverage and open in your browser" task :coverage do require 'rcov' sh "rm -fr coverage" sh "rcov test/test_*.rb" sh "open coverage/index.html" end desc "Open an irb session preloaded with this library" task :console do sh "irb -rubygems -r ./lib/#{name}.rb" end ############################################################################# # # Custom tasks (add your own tasks here) # ############################################################################# desc "Update version number and gemspec" task :bump do puts "Updated version to #{bump_version}" # Execute does not invoke dependencies. # Manually invoke gemspec then validate. Rake::Task[:gemspec].execute Rake::Task[:validate].execute end desc "Build and install" task :install => :build do sh "gem install --local --no-ri --no-rdoc pkg/#{name}-#{version}.gem" end ############################################################################# # # Packaging tasks # ############################################################################# desc 'Create a release build' task :release => :build do unless `git branch` =~ /^\* master$/ puts "You must be on the master branch to release!" exit! end sh "git commit --allow-empty -a -m 'Release #{version}'" sh "git pull --rebase origin master" sh "git tag v#{version}" sh "git push origin master" sh "git push origin v#{version}" sh "gem push pkg/#{name}-#{version}.gem" sh "gem push pkg/#{name}-#{version}-java.gem" end desc 'Publish to rubygems. Same as release' task :publish => :release desc 'Build gem' task :build => :gemspec do sh "mkdir -p pkg" gemspecs.each do |gemspec| sh "gem build #{gemspec}" end gem_files.each do |gem_file| sh "mv #{gem_file} pkg" end end desc 'Update gemspec' task :gemspec => :validate do # read spec file and split out manifest section spec = File.read(gemspec_file) head, _manifest, tail = spec.split(" # = MANIFEST =\n") # replace name version and date replace_header(head, :name) replace_header(head, :date) #comment this out if your rubyforge_project has a different name replace_header(head, :rubyforge_project) # determine file list from git ls-files files = `git ls-files`. split("\n"). sort. reject { |file| file =~ /^\./ }. reject { |file| file =~ /^(rdoc|pkg|test|Home\.md|\.gitattributes|Guardfile)/ }. map { |file| " #{file}" }. join("\n") # piece file back together and write manifest = " s.files = %w(\n#{files}\n )\n" spec = [head, manifest, tail].join(" # = MANIFEST =\n") File.open(gemspec_file, 'w') { |io| io.write(spec) } puts "Updated #{gemspec_file}" end desc 'Validate lib files and version file' task :validate do libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"] unless libfiles.empty? puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir." exit! end unless Dir['VERSION*'].empty? puts "A `VERSION` file at root level violates Gem best practices." exit! end end gollum-lib-4.2.7/Gemfile 0000644 0000041 0000041 00000000074 13172672532 015123 0 ustar www-data www-data source 'https://rubygems.org' gemspec :name => 'gollum-lib' gollum-lib-4.2.7/HISTORY.md 0000644 0000041 0000041 00000001057 13172672532 015315 0 ustar www-data www-data # v4.2.1 * Performances improvements * Dependency updates # v4.2.0 * Changes since v4.1.0: ** Various performance improvements ** Dependency updates ** Bugfixes ** New Macro for listing contents of (sub)directories: `Navigation()` ** Table of Contents now supports setting max heading level # v4.0.2 /2015-0119 * Bugfixes # v4.0.1 /2014-12-04 * Security fix for [remote code execution issue](https://github.com/gollum/gollum/issues/913). Please update! # v0.0.1 / 2013-03-19 * First release, extrated from https://github.com/gollum/gollum gollum-lib-4.2.7/gollum-lib.gemspec 0000644 0000041 0000041 00000000561 13172672532 017241 0 ustar www-data www-data require File.join(File.dirname(__FILE__), 'gemspec.rb') require File.join(File.dirname(__FILE__), 'lib', 'gollum-lib', 'version.rb') if RUBY_PLATFORM == 'java' then default_adapter = ['gollum-rjgit_adapter', '~> 0.3'] else default_adapter = ['gollum-grit_adapter', '~> 1.0'] end Gem::Specification.new &specification(Gollum::Lib::VERSION, default_adapter) gollum-lib-4.2.7/lib/ 0000755 0000041 0000041 00000000000 13172672532 014375 5 ustar www-data www-data gollum-lib-4.2.7/lib/gollum-lib.rb 0000644 0000041 0000041 00000003762 13172672532 016775 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~ # stdlib require 'digest/md5' require 'digest/sha1' require 'ostruct' require 'pathname' DEFAULT_ADAPTER = RUBY_PLATFORM == 'java' ? 'rjgit_adapter' : 'grit_adapter' if defined?(Gollum::GIT_ADAPTER) require "#{Gollum::GIT_ADAPTER.downcase}_adapter" else require DEFAULT_ADAPTER end # external require 'github/markup' require 'sanitize' require 'gemojione' # internal require File.expand_path('../gollum-lib/git_access', __FILE__) require File.expand_path('../gollum-lib/hook', __FILE__) require File.expand_path('../gollum-lib/committer', __FILE__) require File.expand_path('../gollum-lib/pagination', __FILE__) require File.expand_path('../gollum-lib/blob_entry', __FILE__) require File.expand_path('../gollum-lib/wiki', __FILE__) require File.expand_path('../gollum-lib/page', __FILE__) require File.expand_path('../gollum-lib/macro', __FILE__) require File.expand_path('../gollum-lib/file', __FILE__) require File.expand_path('../gollum-lib/file_view', __FILE__) require File.expand_path('../gollum-lib/markup', __FILE__) require File.expand_path('../gollum-lib/markups', __FILE__) require File.expand_path('../gollum-lib/sanitization', __FILE__) require File.expand_path('../gollum-lib/filter', __FILE__) # Set ruby to UTF-8 mode # This is required for Ruby 1.8.7 which gollum still supports. $KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8' module Gollum def self.assets_path ::File.expand_path('gollum/frontend/public', ::File.dirname(__FILE__)) end class Error < StandardError; end class DuplicatePageError < Error attr_accessor :dir attr_accessor :existing_path attr_accessor :attempted_path def initialize(dir, existing, attempted, message = nil) @dir = dir @existing_path = existing @attempted_path = attempted super(message || "Cannot write #{@dir}/#{@attempted_path}, found #{@dir}/#{@existing_path}.") end end class InvalidGitRepositoryError < StandardError; end class NoSuchPathError < StandardError; end end gollum-lib-4.2.7/lib/gollum-lib/ 0000755 0000041 0000041 00000000000 13172672532 016440 5 ustar www-data www-data gollum-lib-4.2.7/lib/gollum-lib/macro.rb 0000644 0000041 0000041 00000002126 13172672532 020067 0 ustar www-data www-data module Gollum class Macro # Find the macro named, create an instance of that, and return it def self.instance(macro_name, wiki, page) begin self.const_get(macro_name).new(wiki, page) rescue NameError Unknown_Macro.new(macro_name) end end def initialize(wiki, page) @wiki = wiki @page = page end def render(*_args) raise ArgumentError, "#{self.class} does not implement #render. "+ "This is a bug in #{self.class}." end protected def html_error(s) "
#{s}
" end # The special class we reserve for only the finest of screwups. The # underscore is to make sure nobody can define a real, callable macro # with the same name, because that would be... exciting. class Unknown_Macro < Macro def initialize(macro_name) @macro_name = macro_name end def render(*_args) "!!!Unknown macro: #{@macro_name}!!!" end end end end Dir[File.expand_path('../macro/*.rb', __FILE__)].each { |f| require f } gollum-lib-4.2.7/lib/gollum-lib/pagination.rb 0000644 0000041 0000041 00000003651 13172672532 021123 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~ module Gollum module Pagination def self.included(klass) klass.extend ClassMethods class << klass # Default Integer max count of items to return in git commands. attr_accessor :per_page end klass.per_page = 30 end module ClassMethods # Turns a page number into an offset number for the git skip option. # # page - Integer page number. # # Returns an Integer. def page_to_skip(page) ([1, page.to_i].max - 1) * per_page end # Fills in git-specific options for the log command using simple # pagination options. # # options - Hash of options: # page - Optional Integer page number (default: 1) # per_page - Optional Integer max count of items to return. # Defaults to #per_class class method. # # Returns Hash with :max_count and :skip keys. def log_pagination_options(options = {}) skip = page_to_skip(options.delete(:page)) options[:max_count] = [options.delete(:per_page).to_i, per_page].max options[:skip] = skip if skip > 0 options end end # Turns a page number into an offset number for the git skip option. # # page - Integer page number. # # Returns an Integer. def page_to_skip(page) self.class.page_to_skip(page) end # Fills in git-specific options for the log command using simple # pagination options. # # options - Hash of options: # page - Optional Integer page number (default: 1) # per_page - Optional Integer max count of items to return. # Defaults to #per_class class method. # # Returns Hash with :max_count and :skip keys. def log_pagination_options(options = {}) self.class.log_pagination_options(options) end end end gollum-lib-4.2.7/lib/gollum-lib/filter/ 0000755 0000041 0000041 00000000000 13172672532 017725 5 ustar www-data www-data gollum-lib-4.2.7/lib/gollum-lib/filter/remote_code.rb 0000644 0000041 0000041 00000003677 13172672532 022554 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~ require 'net/http' require 'net/https' # ruby 1.8.7 fix, remove at upgrade require 'uri' require 'open-uri' # Remote code - fetch code from url and replace the contents to a # code-block that gets run the next parse. # Acceptable formats: # ```language:local-file.ext``` # ```language:/abs/other-file.ext``` # ```language:https://example.com/somefile.txt``` # class Gollum::Filter::RemoteCode < Gollum::Filter def extract(data) return data if @markup.format == :txt data.gsub(/^[ \t]*``` ?([^:\n\r]+):((http)?[^`\n\r]+)```/) do language = Regexp.last_match[1] uri = Regexp.last_match[2] protocol = Regexp.last_match[3] # Detect local file if protocol.nil? if (file = @markup.find_file(uri, @markup.wiki.ref)) contents = file.raw_data else # How do we communicate a render error? next html_error("File not found: #{CGI::escapeHTML(uri)}") end else contents = req(uri) end "```#{language}\n#{contents}\n```\n" end end def process(data) data end private def req(uri, cut = 1) uri = URI(uri) return "Too many redirects or retries" if cut >= 10 http = Net::HTTP.new uri.host, uri.port http.use_ssl = true resp = http.get uri.path, { 'Accept' => 'text/plain', 'Cache-Control' => 'no-cache', 'Connection' => 'keep-alive', 'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0' } code = resp.code.to_i return resp.body if code == 200 return "Not Found" if code == 404 return "Unhandled Response Code #{code}" unless code == 304 or not resp.header['location'].nil? loc = URI.parse resp.header['location'] uri2 = loc.relative? ? (uri + loc) : loc # overloads (+) req uri2, (cut + 1) end end gollum-lib-4.2.7/lib/gollum-lib/filter/macro.rb 0000644 0000041 0000041 00000002773 13172672532 021364 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~ # Replace specified tokens with dynamically generated content. class Gollum::Filter::Macro < Gollum::Filter def extract(data) quoted_arg = %r{".*?"} unquoted_arg = %r{[^,)]+} named_arg = %r{[a-z0-9_]+=".*?"} arg = %r{(?:#{quoted_arg}|#{unquoted_arg}|#{named_arg})} arg_list = %r{(\s*|#{arg}(?:\s*,\s*#{arg})*)} data.gsub(/('?)\<\<\s*([A-Z][A-Za-z0-9]*)\s*\(#{arg_list}\)\s*\>\>/) do next CGI.escape_html($&[1..-1]) unless Regexp.last_match[1].empty? id = Digest::SHA1.hexdigest(Regexp.last_match[2] + Regexp.last_match[3]) macro = Regexp.last_match[2] argstr = Regexp.last_match[3] args = [] opts = {} argstr.scan(/,?\s*(#{arg})\s*/) do |arguments| # Stabstabstab argument = arguments.first if argument =~ /^([a-z0-9_]+)="(.*?)"/ opts[Regexp.last_match[1]] = Regexp.last_match[2] elsif argument =~ /^"(.*)"$/ args << Regexp.last_match[1] else args << argument end end args << opts unless opts.empty? @map[id] = { :macro => macro, :args => args } id end end def process(data) @map.each do |id, spec| macro = spec[:macro] args = spec[:args] data.gsub!(id) do begin Gollum::Macro.instance(macro, @markup.wiki, @markup.page).render(*args) rescue StandardError => e "!!!Macro Error: #{e.message}!!!" end end end data end end gollum-lib-4.2.7/lib/gollum-lib/filter/emoji.rb 0000644 0000041 0000041 00000001252 13172672532 021355 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~ # Emoji # # Render emoji such as :smile: class Gollum::Filter::Emoji < Gollum::Filter EXTRACT_PATTERN = %r{ (?[\w-]+): (?!\]{^2}) }ix PROCESS_PATTERN = %r{ =EEMMOOJJII= (? block without any special markup.
class Gollum::Filter::PlainText < Gollum::Filter
def extract(data)
@markup.format == :txt ? "#{CGI.escapeHTML(data)}" : data
end
def process(data)
data
end
end gollum-lib-4.2.7/lib/gollum-lib/filter/metadata.rb 0000644 0000041 0000041 00000002060 13172672532 022030 0 ustar www-data www-data # Extract metadata for data and build metadata table. Metadata consists of
# key/value pairs in "key:value" format found between markers. Each
# key/value pair must be on its own line. Internal whitespace in keys and
# values is preserved, but external whitespace is ignored.
#
# Because ri and ruby 1.8.7 are awesome, the markers can't
# be included in this documentation without triggering
# `Unhandled special: Special: type=17`
# Please read the source code for the exact markers
class Gollum::Filter::Metadata < Gollum::Filter
def extract(data)
# The markers are ``
data.gsub(/\<\!--+\s+---(.*?)--+\>/m) do
@markup.metadata ||= {}
# Split untrusted input on newlines, then remove bits that look like
# HTML elements before parsing each line.
Regexp.last_match[1].split("\n").each do |line|
line.gsub!(/<[^>]*>/, '')
k, v = line.split(':', 2)
@markup.metadata[k.strip] = (v ? v.strip : '') if k
end
''
end
end
def process(data)
data
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter/render.rb 0000644 0000041 0000041 00000000627 13172672532 021536 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
class Gollum::Filter::Render < Gollum::Filter
def extract(data)
begin
data = GitHub::Markup.render(@markup.name, data)
if data.nil?
raise "There was an error converting #{@markup.name} to HTML."
end
rescue Object => e
data = html_error("Failed to render page: #{e.message}")
end
data
end
def process(data)
data
end
end gollum-lib-4.2.7/lib/gollum-lib/filter/code.rb 0000644 0000041 0000041 00000011261 13172672532 021165 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
# Code
#
# Render a block of code using the Rouge syntax-highlighter.
class Gollum::Filter::Code < Gollum::Filter
def extract(data)
case @markup.format
when :txt
return data
when :asciidoc
data.gsub!(/^(\[source,([^\r\n]*)\]\n)?----\n(.+?)\n----$/m) do
cache_codeblock(Regexp.last_match[2], Regexp.last_match[3])
end
when :org
org_headers = %r{([ \t]*#\+HEADER[S]?:[^\r\n]*\n)*}
org_name = %r{([ \t]*#\+NAME:[^\r\n]*\n)?}
org_lang = %r{[ ]*([^\n \r]*)[ ]*[^\r\n]*}
org_begin = %r{[ \t]*#\+BEGIN_SRC#{org_lang}\n}
org_end = %r{\n[ \t]*#\+END_SRC[ \t]*}
data.gsub!(/^#{org_headers}#{org_name}#{org_begin}(.+?)#{org_end}$/mi) do
cache_codeblock(Regexp.last_match[3], Regexp.last_match[4])
end
when :markdown
data.gsub!(/^([ \t]*)(~~~+) ?([^\r\n]+)?\r?\n(.+?)\r?\n\1(~~~+)[ \t\r]*$/m) do
m_indent = Regexp.last_match[1]
m_start = Regexp.last_match[2] # ~~~
m_lang = Regexp.last_match[3]
m_code = Regexp.last_match[4]
m_end = Regexp.last_match[5] # ~~~
# start and finish tilde fence must be the same length
next '' if m_start.length != m_end.length
lang = m_lang ? m_lang.strip : nil
if lang
lang = lang.match(/\.([^}\s]+)/)
lang = lang[1] unless lang.nil?
end
"#{m_indent}#{cache_codeblock(lang, m_code, m_indent)}"
end
end
data.gsub!(/^([ \t]*)``` ?([^\r\n]+)?\r?\n(.+?)\r?\n\1```[ \t]*\r?$/m) do
"#{Regexp.last_match[1]}#{cache_codeblock(Regexp.last_match[2].to_s.strip, Regexp.last_match[3], Regexp.last_match[1])}" # print the SHA1 ID with the proper indentation
end
data
end
# Process all code from the codemap and replace the placeholders with the
# final HTML.
#
# data - The String data (with placeholders).
# encoding - Encoding Constant or String.
#
# Returns the marked up String data.
def process(data)
return data if data.nil? || data.size.zero? || @map.size.zero?
blocks = []
@map.each do |_id, spec|
next if spec[:output] # cached
code = spec[:code]
remove_leading_space(code, /^#{spec[:indent]}/m)
remove_leading_space(code, /^( |\t)/m)
blocks << [spec[:lang], code]
end
highlighted = []
blocks.each do |lang, code|
encoding = @markup.encoding || 'utf-8'
if defined? Pygments
# Set the default lexer to 'text' to prevent #153 and #154
lang = lang || 'text'
lexer = Pygments::Lexer[(lang)] || Pygments::Lexer['text']
# must set startinline to true for php to be highlighted without
hl_code = lexer.highlight(code, :options => { :encoding => encoding.to_s, :startinline => true })
else # Rouge
begin
# if `lang` was not defined then assume plaintext
lexer = Rouge::Lexer.find_fancy(lang || 'plaintext')
formatter = Rouge::Formatters::HTML.new
wrap_template = '%s
'
# if `lang` is defined but cannot be found then wrap it with an error
if lexer.nil?
lexer = Rouge::Lexers::PlainText
wrap_template = '%s'
end
formatted = formatter.format(lexer.lex(code))
hl_code = Kernel.sprintf(wrap_template, formatted)
rescue
hl_code = code
end
end
highlighted << hl_code
end
@map.each do |id, spec|
body = spec[:output] || begin
if (body = highlighted.shift.to_s).size > 0
@markup.update_cache(:code, id, body)
body
else
"#{CGI.escapeHTML(spec[:code])}
"
end
end
# Removes paragraph tags surrounding blocks, see issue https://github.com/gollum/gollum-lib/issues/97
data.gsub!(/(#{id}<\/p>|#{id})/) { body }
end
data
end
private
# Remove the leading space from a code block. Leading space
# is only removed if every single line in the block has leading
# whitespace.
#
# code - The code block to remove spaces from
# regex - A regex to match whitespace
def remove_leading_space(code, regex)
if code.lines.all? { |line| line =~ /\A\r?\n\Z/ || line =~ regex }
code.gsub!(regex) { '' }
end
end
def cache_codeblock(language, code, indent = "")
language = language.to_s.empty? ? nil : language
id = Digest::SHA1.hexdigest("#{language}.#{code}")
cached = @markup.check_cache(:code, id)
@map[id] = cached ?
{ :output => cached } :
{ :lang => language, :code => code, :indent => indent }
id
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter/tags.rb 0000644 0000041 0000041 00000023054 13172672532 021214 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
# Render all tags (things in double-square-brackets). This one's a biggie.
class Gollum::Filter::Tags < Gollum::Filter
# Extract all tags into the tagmap and replace with placeholders.
def extract(data)
return data if @markup.format == :txt || @markup.format == :asciidoc
data.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/m) do
if Regexp.last_match[1] == "'" && Regexp.last_match[3] != "'"
"[[#{Regexp.last_match[2]}]]#{Regexp.last_match[3]}"
elsif Regexp.last_match[2].include?('][')
if Regexp.last_match[2][0..4] == 'file:'
pre = Regexp.last_match[1]
post = Regexp.last_match[3]
parts = Regexp.last_match[2].split('][')
parts[0][0..4] = ""
link = "#{parts[1]}|#{parts[0].sub(/\.org/, '')}"
id = register_tag(link)
"#{pre}#{id}#{post}"
else
Regexp.last_match[0]
end
else
id = register_tag(Regexp.last_match[2])
"#{Regexp.last_match[1]}#{id}#{Regexp.last_match[3]}"
end
end
data
end
def register_tag(tag)
id = "TAG#{Digest::SHA1.hexdigest(tag)}TAG"
@map[id] = tag
id
end
# Process all text nodes from the doc and replace the placeholders with the
# final markup.
def process(rendered_data)
doc = Nokogiri::HTML::DocumentFragment.parse(rendered_data)
doc.traverse do |node|
if node.text? then
content = node.content
content.gsub!(/TAG[a-f0-9]+TAG/) do |id|
if (tag = @map[id]) then
if is_preformatted?(node) then
"[[#{tag}]]"
else
process_tag(tag).gsub('%2f', '/')
end
end
end
node.replace(content) if content != node.content
end
end
doc.to_html
end
private
PREFORMATTED_TAGS = %w(code tt)
def is_preformatted?(node)
node && (PREFORMATTED_TAGS.include?(node.name) ||
node.ancestors.any? { |a| PREFORMATTED_TAGS.include?(a.name) })
end
# Process a single tag into its final HTML form.
#
# tag - The String tag contents (the stuff inside the double
# brackets).
#
# Returns the String HTML version of the tag.
def process_tag(tag)
if tag =~ /^_TOC_/
%{[[#{tag}]]}
elsif tag =~ /^_$/
%{
}
elsif (html = process_include_tag(tag))
html
elsif (html = process_image_tag(tag))
html
elsif (html = process_external_link_tag(tag))
html
elsif (html = process_file_link_tag(tag))
html
else
process_page_link_tag(tag)
end
end
# Attempt to process the tag as an include tag
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the String HTML if the tag is a valid image tag or nil
# if it is not.
#
def process_include_tag(tag)
return unless /^include:/.match(tag)
page_name = tag[8..-1]
resolved_page_name = ::File.expand_path(page_name, "/"+@markup.dir)
if @markup.include_levels > 0
page = find_page_from_name(resolved_page_name)
if page
page.formatted_data(@markup.encoding, @markup.include_levels-1)
else
html_error("Cannot include #{process_page_link_tag(resolved_page_name)} - does not exist yet")
end
else
html_error("Too many levels of included pages, will not include #{process_page_link_tag(resolved_page_name)}")
end
end
# Attempt to process the tag as an image tag.
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the String HTML if the tag is a valid image tag or nil
# if it is not.
def process_image_tag(tag)
parts = tag.split('|')
return if parts.size.zero?
name = parts[0].strip
if (file = @markup.find_file(name))
path = ::File.join @markup.wiki.base_path, file.path
elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i
path = name
elsif name =~ /.+(jpg|png|gif|svg|bmp)$/i
# If is image, file not found and no link, then populate with empty String
# We can than add an image not found alt attribute for this later
path = ""
end
if path
opts = parse_image_tag_options(tag)
containered = false
classes = [] # applied to whatever the outermost container is
attrs = [] # applied to the image
align = opts['align']
if opts['float']
containered = true
align ||= 'left'
if %w{left right}.include?(align)
classes << "float-#{align}"
end
elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align)
attrs << %{align="#{align}"}
elsif align
if %w{left center right}.include?(align)
containered = true
classes << "align-#{align}"
end
end
if (width = opts['width'])
if width =~ /^\d+(\.\d+)?(em|px)$/
attrs << %{width="#{width}"}
end
end
if (height = opts['height'])
if height =~ /^\d+(\.\d+)?(em|px)$/
attrs << %{height="#{height}"}
end
end
if path != "" && (alt = opts['alt'])
attrs << %{alt="#{alt}"}
elsif path == ""
attrs << %{alt="Image not found"}
end
attr_string = attrs.size > 0 ? attrs.join(' ') + ' ' : ''
if opts['frame'] || containered
classes << 'frame' if opts['frame']
%{} +
%{} +
%{
} +
(alt ? %{#{alt}} : '') +
%{} +
%{}
else
%{
}
end
end
end
# Parse any options present on the image tag and extract them into a
# Hash of option names and values.
#
# tag - The String tag contents (the stuff inside the double brackets).
#
# Returns the options Hash:
# key - The String option name.
# val - The String option value or true if it is a binary option.
def parse_image_tag_options(tag)
tag.split('|')[1..-1].inject({}) do |memo, attr|
parts = attr.split('=').map { |x| x.strip }
memo[parts[0]] = (parts.size == 1 ? true : parts[1])
memo
end
end
# Return the String HTML if the tag is a valid external link tag or
# nil if it is not.
def process_external_link_tag(tag)
parts = tag.split('|')
parts.reverse! if @markup.reverse_links?
return if parts.size.zero?
if parts.size == 1
url = parts[0].strip
else
name, url = *parts.compact.map(&:strip)
end
accepted_protocols = @markup.wiki.sanitization.protocols['a']['href'].dup
if accepted_protocols.include?(:relative)
accepted_protocols.select!{|protocol| protocol != :relative}
regexp = %r{^((#{accepted_protocols.join("|")}):)?(//)}
else
regexp = %r{^((#{accepted_protocols.join("|")}):)}
end
if url =~ regexp
if name.nil?
%{#{url}}
else
%{#{name}}
end
else
nil
end
end
# Attempt to process the tag as a file link tag.
#
# tag - The String tag contents (the stuff inside the double
# brackets).
#
# Returns the String HTML if the tag is a valid file link tag or nil
# if it is not.
def process_file_link_tag(tag)
parts = tag.split('|')
return if parts.size.zero?
name = parts[0].strip
path = parts[1] && parts[1].strip
if path && file = @markup.find_file(path)
path = ::File.join @markup.wiki.base_path, file.path
else
path = nil
end
if name && path && file
%{#{name}}
elsif name && path
%{#{name}}
else
nil
end
end
# Attempt to process the tag as a page link tag.
#
# tag - The String tag contents (the stuff inside the double
# brackets).
#
# Returns the String HTML if the tag is a valid page link tag or nil
# if it is not.
def process_page_link_tag(tag)
parts = tag.split('|')
parts.reverse! if @markup.reverse_links?
name, page_name = *parts.compact.map(&:strip)
cname = @markup.wiki.page_class.cname(page_name || name)
presence = "absent"
link_name = cname
page, extra = find_page_from_name(cname)
if page
link_name = @markup.wiki.page_class.cname(page.name)
presence = "present"
end
link = ::File.join(@markup.wiki.base_path, page ? page.escaped_url_path : CGI.escape(link_name))
# //page is invalid
# strip all duplicate forward slashes using helpers.rb trim_leading_slash
# //page => /page
link = trim_leading_slash link
%{#{name}}
end
# Find a page from a given cname. If the page has an anchor (#) and has
# no match, strip the anchor and try again.
#
# cname - The String canonical page name including path.
#
# Returns a Gollum::Page instance if a page is found, or an Array of
# [Gollum::Page, String extra] if a page without the extra anchor data
# is found.
def find_page_from_name(cname)
slash = cname.rindex('/')
unless slash.nil?
name = cname[slash+1..-1]
path = cname[0..slash]
page = @markup.wiki.paged(name, path)
else
page = @markup.wiki.paged(cname, '/') || @markup.wiki.page(cname)
end
if page
return page
end
if (pos = cname.index('#'))
[@markup.wiki.page(cname[0...pos]), cname[pos..-1]]
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter/plantuml.rb 0000644 0000041 0000041 00000010614 13172672532 022110 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
require 'net/http'
require 'uri'
require 'open-uri'
require 'zlib'
# PlantUML Diagrams
#
# This filter replaces PlantUML blocks with HTML img tags. These img tags
# point to a PlantUML web service that converts the UML text blocks into nice
# diagrams.
#
# For this to work you must have your own PlantUML server running somewhere.
# Just follow the instructions on the github page to run your own server:
#
# https://github.com/plantuml/plantuml-server
#
# Once you start you own plantuml server you need to configure this filter to
# point to it:
#
# Gollum::Filter::PlantUML.configure do |config|
# config.url = "http://localhost:8080/plantuml/png"
# end
#
# Then in your wiki pages simply add PlantUML blocks anywhere you want a
# diagram:
#
# @startuml
# Alice -> Bob: Authentication Request
# Bob --> Alice: Authentication Response
# Alice -> Bob: Another authentication Request
# Alice <-- Bob: another authentication Response
# @enduml
#
# To learn more about how to create cool PlantUML diagrams check the examples
# at: http://plantuml.sourceforge.net/
#
class Gollum::Filter::PlantUML < Gollum::Filter
DEFAULT_URL = "http://localhost:8080/plantuml/png"
# Configuration class used to change the behaviour of the PlatnUML filter.
#
# url: PlantUML server URL (e.g. http://localhost:8080)
# test: Set to true when running tests to skip the server check.
#
class Configuration
attr_accessor :url, :test, :verify_ssl
def initialize
@url = DEFAULT_URL
@verify_ssl = true
@test = false
end
end
class << self
attr_writer :configuration
end
def self.configuration
@configuration ||= Configuration.new
end
def self.configure
yield(configuration)
end
# Extract all sequence diagram blocks into the map and replace with
# placeholders.
def extract(data)
return data if @markup.format == :txt
data.gsub(/(@startuml\r?\n.+?\r?\n@enduml\r?$)/m) do
id = Digest::SHA1.hexdigest($1)
@map[id] = { :code => $1 }
id
end
end
# Process all diagrams from the map and replace the placeholders with
# the final HTML.
def process(data)
@map.each do |id, spec|
data.gsub!(id) do
render_plantuml(id, spec[:code])
end
end
data
end
private
def server_url
PlantUML::configuration.url
end
def test?
PlantUML::configuration.test
end
def verify_ssl?
PlantUML::configuration.verify_ssl
end
def render_plantuml(id, code)
if check_server
plantuml_url = gen_url(code)
"
"
else
html_error("Sorry, unable to render PlantUML diagram at this time")
end
end
# Compression code used to generate PlantUML URLs. Taken directly from the
# Transcoder class in the PlantUML java code.
def gen_url(text)
result = ""
compressedData = Zlib::Deflate.deflate(text)
compressedData.chars.each_slice(3) do |bytes|
#print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
result += append3bytes(b1, b2, b3)
end
"#{server_url}/#{result}"
end
def encode6bit(b)
if b < 10
return ('0'.ord + b).chr
end
b = b - 10
if b < 26
return ('A'.ord + b).chr
end
b = b - 26
if b < 26
return ('a'.ord + b).chr
end
b = b - 26
if b == 0
return '-'
end
if b == 1
return '_'
end
return '?'
end
def append3bytes(b1, b2, b3)
c1 = b1 >> 2
c2 = ((b1 & 0x3) << 4) | (b2 >> 4)
c3 = ((b2 & 0xF) << 2) | (b3 >> 6)
c4 = b3 & 0x3F
return encode6bit(c1 & 0x3F).chr +
encode6bit(c2 & 0x3F).chr +
encode6bit(c3 & 0x3F).chr +
encode6bit(c4 & 0x3F).chr
end
# Make a call to the PlantUML server with the simplest diagram possible to
# check if the server is available or not.
def check_server
return true if test?
check_url = "#{server_url}/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000"
uri = URI.parse(check_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless verify_ssl?
response = http.request_get(uri.request_uri)
return response.is_a?(Net::HTTPSuccess)
rescue
return false
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter/sanitize.rb 0000644 0000041 0000041 00000000517 13172672532 022103 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
class Gollum::Filter::Sanitize < Gollum::Filter
def extract(data)
data
end
def process(data)
if @markup.sanitize
doc = Nokogiri::HTML::DocumentFragment.parse(data)
doc = @markup.sanitize.clean_node!(doc)
doc.to_xml(@markup.to_xml_opts)
else
data
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter/wsd.rb 0000644 0000041 0000041 00000003077 13172672532 021056 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
require 'net/http'
require 'uri'
require 'open-uri'
# Web Sequence Diagrams
#
# Render an inline web sequence diagram by sending the WSD code through the
# online renderer available from www.websequencediagrams.com.
#
class Gollum::Filter::WSD < Gollum::Filter
WSD_URL = "http://www.websequencediagrams.com/index.php"
# Extract all sequence diagram blocks into the map and replace with
# placeholders.
def extract(data)
return data if @markup.format == :txt
data.gsub(/^\{\{\{\{\{\{ ?(.+?)\r?\n(.+?)\r?\n\}\}\}\}\}\}\r?$/m) do
id = Digest::SHA1.hexdigest(Regexp.last_match[2])
@map[id] = { :style => Regexp.last_match[1], :code => Regexp.last_match[2] }
id
end
end
# Process all diagrams from the map and replace the placeholders with
# the final HTML.
#
# data - The String data (with placeholders).
#
# Returns the marked up String data.
def process(data)
@map.each do |id, spec|
data.gsub!(id) do
render_wsd(spec[:code], spec[:style])
end
end
data
end
private
# Render the sequence diagram on the remote server.
#
# Returns an
tag to the rendered image, or an HTML error.
def render_wsd(code, style)
response = Net::HTTP.post_form(URI.parse(WSD_URL), 'style' => style, 'message' => code)
if response.body =~ /img: "(.+)"/
url = "//www.websequencediagrams.com/#{Regexp.last_match[1]}"
"
"
else
puts response.body
html_error("Sorry, unable to render sequence diagram at this time.")
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/sanitization.rb 0000644 0000041 0000041 00000013626 13172672532 021511 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
# Encapsulate sanitization options.
#
# This class does not yet support all options of Sanitize library.
# See http://github.com/rgrove/sanitize/.
class Sanitization
# Default whitelisted elements.
ELEMENTS = [
'a', 'abbr', 'acronym', 'address', 'area', 'b', 'big',
'blockquote', 'br', 'button', 'caption', 'center', 'cite',
'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir',
'div', 'dl', 'dt', 'em', 'fieldset', 'font', 'form', 'h1',
'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'input',
'ins', 'kbd', 'label', 'legend', 'li', 'map', 'mark', 'menu',
'ol', 'optgroup', 'option', 'p', 'pre', 'q', 's', 'samp',
'select', 'small', 'span', 'strike', 'strong', 'sub',
'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th',
'thead', 'tr', 'tt', 'u', 'ul', 'var'
].freeze
# Default whitelisted attributes.
ATTRIBUTES = {
'a' => ['href'],
'img' => ['src'],
:all => ['abbr', 'accept', 'accept-charset',
'accesskey', 'action', 'align', 'alt', 'axis',
'border', 'cellpadding', 'cellspacing', 'char',
'charoff', 'class', 'charset', 'checked', 'cite',
'clear', 'cols', 'colspan', 'color',
'compact', 'coords', 'datetime', 'dir',
'disabled', 'enctype', 'for', 'frame',
'headers', 'height', 'hreflang',
'hspace', 'id', 'ismap', 'label', 'lang',
'longdesc', 'maxlength', 'media', 'method',
'multiple', 'name', 'nohref', 'noshade',
'nowrap', 'prompt', 'readonly', 'rel', 'rev',
'rows', 'rowspan', 'rules', 'scope',
'selected', 'shape', 'size', 'span',
'start', 'summary', 'tabindex', 'target',
'title', 'type', 'usemap', 'valign', 'value',
'vspace', 'width']
}.freeze
# Default whitelisted protocols for URLs.
PROTOCOLS = {
'a' => { 'href' => ['http', 'https', 'mailto', 'ftp', 'irc', 'apt', :relative] },
'img' => { 'src' => ['http', 'https', :relative] },
'form' => { 'action' => ['http', 'https', :relative] }
}.freeze
ADD_ATTRIBUTES = lambda do |env, node|
if (add = env[:config][:add_attributes][node.name])
add.each do |key, value|
node[key] = value
end
end
end
# Default elements whose contents will be removed in addition
# to the elements themselve
REMOVE_CONTENTS = [
'script',
'style'
].freeze
# Default transformers to force @id attributes with 'wiki-' prefix
TRANSFORMERS = [
lambda do |env|
node = env[:node]
return if env[:is_whitelisted] || !node.element?
prefix = env[:config][:id_prefix]
found_attrs = %w(id name).select do |key|
if (value = node[key])
node[key] = value.gsub(/\A(#{prefix})?/, prefix)
end
end
if found_attrs.size > 0
ADD_ATTRIBUTES.call(env, node)
{}
end
end,
lambda do |env|
node = env[:node]
return unless (value = node['href'])
prefix = env[:config][:id_prefix]
node['href'] = value.gsub(/\A\#(#{prefix})?/, '#'+prefix)
ADD_ATTRIBUTES.call(env, node)
{}
end
].freeze
# Gets an Array of whitelisted HTML elements. Default: ELEMENTS.
attr_reader :elements
# Gets a Hash describing which attributes are allowed in which HTML
# elements. Default: ATTRIBUTES.
attr_reader :attributes
# Gets a Hash describing which URI protocols are allowed in HTML
# attributes. Default: PROTOCOLS
attr_reader :protocols
# Gets a Hash describing which URI protocols are allowed in HTML
# attributes. Default: TRANSFORMERS
attr_reader :transformers
# Gets or sets a String prefix which is added to ID attributes.
# Default: ''
attr_accessor :id_prefix
# Gets a Hash describing HTML attributes that Sanitize should add.
# Default: {}
attr_reader :add_attributes
# Gets an Array of element names whose contents will be removed in addition
# to the elements themselves. Default: REMOVE_CONTENTS
attr_reader :remove_contents
# Sets a boolean determining whether Sanitize allows HTML comments in the
# output. Default: false.
attr_writer :allow_comments
def initialize
@elements = ELEMENTS.dup
@attributes = ATTRIBUTES.dup
@protocols = PROTOCOLS.dup
@transformers = TRANSFORMERS.dup
@add_attributes = {}
@remove_contents = REMOVE_CONTENTS.dup
@allow_comments = false
@id_prefix = ''
yield self if block_given?
end
# Determines if Sanitize should allow HTML comments.
#
# Returns True if comments are allowed, or False.
def allow_comments?
!!@allow_comments
end
# Modifies the current Sanitization instance to sanitize older revisions
# of pages.
#
# Returns a Sanitization instance.
def history_sanitization
self.class.new do |sanitize|
sanitize.add_attributes['a'] = { 'rel' => 'nofollow' }
end
end
# Builds a Hash of options suitable for Sanitize.clean.
#
# Returns a Hash.
def to_hash
{ :elements => elements,
:attributes => attributes,
:protocols => protocols,
:add_attributes => add_attributes,
:remove_contents => remove_contents,
:allow_comments => allow_comments?,
:transformers => transformers,
:id_prefix => id_prefix
}
end
# Builds a Sanitize instance from the current options.
#
# Returns a Sanitize instance.
def to_sanitize
Sanitize.new(to_hash)
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/blob_entry.rb 0000644 0000041 0000041 00000005127 13172672532 021131 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class BlobEntry
# Gets the String SHA for this blob.
attr_reader :sha
# Gets the full path String for this blob.
attr_reader :path
# Gets the Fixnum size of this blob.
attr_reader :size
# Gets the Fixnum mode of this blob.
attr_reader :mode
def initialize(sha, path, size = nil, mode = nil)
@sha = sha
@path = path
@size = size
@mode = mode
@dir = @name = @blob = nil
end
# Gets the normalized directory path String for this blob.
def dir
@dir ||= self.class.normalize_dir(::File.dirname(@path))
end
# Gets the file base name String for this blob.
def name
@name ||= ::File.basename(@path)
end
# Gets a Gollum::Git::Blob instance for this blob.
#
# repo - Gollum::Git::Repo instance for the Gollum::Git::Blob.
#
# Returns an unbaked Gollum::Git::Blob instance.
def blob(repo)
@blob ||= Gollum::Git::Blob.create(repo,
:id => @sha, :name => name, :size => @size, :mode => @mode)
end
# Gets a Page instance for this blob.
#
# wiki - Gollum::Wiki instance for the Gollum::Page
#
# Returns a Gollum::Page instance.
def page(wiki, commit)
blob = self.blob(wiki.repo)
page = wiki.page_class.new(wiki).populate(blob, self.dir)
page.version = commit
page
end
# Gets a File instance for this blob.
#
# wiki - Gollum::Wiki instance for the Gollum::File
#
# Returns a Gollum::File instance.
def file(wiki, commit)
blob = self.blob(wiki.repo)
file = wiki.file_class.new(wiki).populate(blob, self.dir)
file.version = commit
file
end
def inspect
%(#)
end
# Normalizes a given directory name for searching through tree paths.
# Ensures that a directory begins with a slash, or
#
# normalize_dir("") # => ""
# normalize_dir(".") # => ""
# normalize_dir("foo") # => "/foo"
# normalize_dir("/foo/") # => "/foo"
# normalize_dir("/") # => ""
# normalize_dir("c:/") # => ""
#
# dir - String directory name.
#
# Returns a normalized String directory name, or nil if no directory
# is given.
def self.normalize_dir(dir)
return '' if dir =~ /^.:\/$/
if dir
dir = ::File.expand_path(dir, '/')
dir = dir[2..-1] if dir =~ /^[a-zA-Z]:\// # expand_path may add d:/ on windows
dir = '' if dir == '/'
end
dir
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/hook.rb 0000644 0000041 0000041 00000001262 13172672532 017726 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class Hook
@hooks = {}
class << self
def register(type, id, &block)
type_hooks = @hooks[type] ||= {}
type_hooks[id] = block
end
def unregister(type, id)
type_hooks = @hooks[type]
if type_hooks
type_hooks.delete(id)
@hooks.delete(type) if type_hooks.empty?
end
end
def get(type, id)
@hooks.fetch(type, {})[id]
end
def execute(type, *args)
type_hooks = @hooks[type]
if type_hooks
type_hooks.each_value do |block|
block.call(*args)
end
end
end
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/filter.rb 0000644 0000041 0000041 00000005531 13172672532 020256 0 ustar www-data www-data # A "filter", in Gollum-speak, is an object which extracts tokens from an
# input stream of an arbitrary markup language, then replaces them with a
# final form in a rendered form of the same document. Filters are composed
# into a "filter chain", which forms the order in which filters are applied
# in both the extraction and processing phases (processing happens in the
# reverse order to extraction). A single instance of a filter class is used
# for both the extraction and processing, so you can store internal state
# from the extraction phase for use in the processing phase.
#
# Any class which is to be used as a filter must have an `initialize` method
# which takes a single mandatory argument (the instance of the `Markup`
# class we're being called from), and must implement two methods: `extract`
# and `process`, both of which must take a string as input and return a
# (possibly modified) form of that string as output.
#
# An example rendering session: consider a filter chain with three filters
# in it, :A, :B, and :C (filter chains are specified as symbols, which are
# taken to be class names within the Gollum::Filter namespace). An
# equivalent of the following will take place:
#
# a = Gollum::Filter.const_get(:A).new
# b = Gollum::Filter.const_get(:B).new
# c = Gollum::Filter.const_get(:C).new
#
# data = ""
#
# data = a.extract(data)
# data = b.extract(data)
# data = c.extract(data)
#
# data = c.process(data)
# data = b.process(data)
# data = a.process(data)
#
# # `data` now contains the rendered document, ready for processing
#
# Note how the extraction steps go in the order of the filter chain, while
# the processing steps go in the reverse order. There hasn't (yet) been a
# case where that is a huge problem.
#
# If your particular filter doesn't need to do something with either the
# original markup or rendered forms, you can simply define the relevant
# method to be a pass-through (`def extract(d) d; end`), but you *must*
# define both methods yourself.
#
module Gollum
class Filter
include Gollum::Helpers
# Setup the object. Sets `@markup` to be the instance of Gollum::Markup that
# is running this filter chain, and sets `@map` to be an empty hash (for use
# in your extract/process operations).
def initialize(markup)
@markup = markup
@map = {}
end
def extract(_d)
raise RuntimeError,
"#{self.class} has not implemented ##extract!"
end
def process(_d)
raise RuntimeError,
"#{self.class} has not implemented ##process!"
end
protected
# Render a (presumably) non-fatal error as HTML
#
def html_error(message)
"#{message}
"
end
end
end
# Load all standard filters
Dir[File.expand_path('../filter/*.rb', __FILE__)].each { |f| require f }
gollum-lib-4.2.7/lib/gollum-lib/file_view.rb 0000644 0000041 0000041 00000011024 13172672532 020734 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
# FileView requires that:
# - All files in root dir are processed first
# - Then all the folders are sorted and processed
class FileView
# common use cases:
# set pages to wiki.pages and show_all to false
# set pages to wiki.pages + wiki.files and show_all to true
def initialize(pages, options = {})
@pages = pages
@show_all = options[:show_all] || false
@checked = options[:collapse_tree] ? '' : "checked"
end
def enclose_tree(string)
%Q(\n) + string + %Q(
)
end
def new_page(page)
name = page.name
url, valid_page = url_for_page page
%Q( #{name}#{valid_page ? "" : delete_file(url, valid_page)} )
end
def delete_file(url, valid_page)
%Q()
end
def new_folder(folder_path)
new_sub_folder folder_path
end
def new_sub_folder(path)
<<-HTML
HTML
end
def end_folder
"
\n"
end
def url_for_page(page)
url = ''
valid_page_name = false
if @show_all
# Remove ext for valid pages.
filename = page.filename
valid_page_name = Page::valid_page_name?(filename)
filename = valid_page_name ? filename.chomp(::File.extname(filename)) : filename
url = ::File.join(::File.dirname(page.path), filename)
else
url = ::File.join(::File.dirname(page.path), page.filename_stripped)
end
url = url[2..-1] if url[0, 2] == './'
return url, valid_page_name
end
def render_files
html = ''
count = @pages.size
folder_start = -1
# Process all pages until folders start
count.times do |index|
page = @pages[index]
path = page.path
unless path.include? '/'
# Page processed (not contained in a folder)
html += new_page page
else
# Folders start at the next index
folder_start = index
break # Pages finished, move on to folders
end
end
# If there are no folders, then we're done.
return enclose_tree(html) if folder_start <= -1
# Handle special case of only one folder.
if (count - folder_start == 1)
page = @pages[folder_start]
html += <<-HTML
#{new_page page}
HTML
return enclose_tree html
end
sorted_folders = []
(folder_start).upto count - 1 do |index|
sorted_folders += [[@pages[index].path, index]]
end
# http://stackoverflow.com/questions/3482814/sorting-list-of-string-paths-in-vb-net
sorted_folders.sort! do |first, second|
a = first[0]
b = second[0]
# use :: operator because gollum defines its own conflicting File class
dir_compare = ::File.dirname(a) <=> ::File.dirname(b)
# Sort based on directory name unless they're equal (0) in
# which case sort based on file name.
if dir_compare == 0
::File.basename(a) <=> ::File.basename(b)
else
dir_compare
end
end
# keep track of folder depth, 0 = at root.
cwd_array = []
changed = false
# process rest of folders
(0...sorted_folders.size).each do |i|
page = @pages[sorted_folders[i][1]]
path = page.path
folder = ::File.dirname path
tmp_array = folder.split '/'
(0...tmp_array.size).each do |index|
if cwd_array[index].nil? || changed
html += new_sub_folder tmp_array[index]
next
end
if cwd_array[index] != tmp_array[index]
changed = true
(cwd_array.size - index).times do
html += end_folder
end
html += new_sub_folder tmp_array[index]
end
end
html += new_page page
cwd_array = tmp_array
changed = false
end
# return the completed html
enclose_tree html
end # end render_files
end # end FileView class
end # end Gollum module
gollum-lib-4.2.7/lib/gollum-lib/file.rb 0000644 0000041 0000041 00000010437 13172672532 017711 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class File
Wiki.file_class = self
# Public: Initialize a file.
#
# wiki - The Gollum::Wiki in question.
#
# Returns a newly initialized Gollum::File.
def initialize(wiki)
@wiki = wiki
@blob = nil
@path = nil
@on_disk = false
@on_disk_path = nil
end
# Public: The url path required to reach this page within the repo.
#
# Returns the String url_path
def url_path
path = self.path
path = path.sub(/\/[^\/]+$/, '/') if path.include?('/')
path
end
# Public: The url_path, but CGI escaped.
#
# Returns the String url_path
def escaped_url_path
CGI.escape(self.url_path).gsub('%2F', '/')
end
# Public: The on-disk filename of the file.
#
# Returns the String name.
def name
return @path if on_disk?
@blob && @blob.name
end
alias filename name
# Public: The raw contents of the page.
#
# Returns the String data.
def raw_data
return IO.read(@on_disk_path) if on_disk?
return nil unless @blob
if !@wiki.repo.bare && @blob.is_symlink
new_path = @blob.symlink_target(::File.join(@wiki.repo.path, '..', self.path))
return IO.read(new_path) if new_path
end
@blob.data
end
# Public: Is this an on-disk file reference?
#
# Returns true if this is a pointer to an on-disk file
def on_disk?
@on_disk
end
# Public: The path to this file on disk
#
# Returns nil if on_disk? is false.
def on_disk_path
@on_disk_path
end
# Public: The Gollum::Git::Commit version of the file.
attr_accessor :version
# Public: The String path of the file.
attr_reader :path
# Public: The String mime type of the file.
def mime_type
@blob && @blob.mime_type
end
# Populate the File with information from the Blob.
#
# blob - The Gollum::Git::Blob that contains the info.
# path - The String directory path of the file.
#
# Returns the populated Gollum::File.
def populate(blob, path = nil)
@blob = blob
@path = "#{path}/#{blob.name}"[1..-1]
@on_disk = false
@on_disk_path = nil
self
end
#########################################################################
#
# Internal Methods
#
#########################################################################
# Return the file path to this file on disk, if available.
#
# Returns nil if the file isn't available on disk. This can occur if the
# repo is bare, if the commit isn't the HEAD, or if there are problems
# resolving symbolic links.
def get_disk_reference(name, commit)
return false if @wiki.repo.bare
return false if commit.sha != @wiki.repo.head.commit.sha
# This will try to resolve symbolic links, as well
pathname = Pathname.new(::File.expand_path(::File.join(@wiki.repo.path, '..', name)))
if pathname.symlink?
source = ::File.readlink(pathname.to_path)
realpath = ::File.join(::File.dirname(pathname.to_path), source)
return false unless realpath && ::File.exist?(realpath)
@on_disk_path = realpath.to_s
else
@on_disk_path = pathname.to_path
end
true
end
# Find a file in the given Gollum repo.
#
# name - The full String path.
# version - The String version ID to find.
# try_on_disk - If true, try to return just a reference to a file
# that exists on the disk.
#
# Returns a Gollum::File or nil if the file could not be found. Note
# that if you specify try_on_disk=true, you may or may not get a file
# for which on_disk? is actually true.
def find(name, version, try_on_disk = false)
checked = name.downcase
map = @wiki.tree_map_for(version)
commit = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version)
if (result = map.detect { |entry| entry.path.downcase == checked })
@path = name
@version = commit
if try_on_disk && get_disk_reference(name, commit)
@on_disk = true
else
@blob = result.blob(@wiki.repo)
end
self
end
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/helpers.rb 0000644 0000041 0000041 00000000354 13172672532 020431 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
module Helpers
def trim_leading_slash(url)
return url if url.nil?
url.gsub!('%2F', '/')
return '/' + url.gsub(/^\/+/, '') if url[0, 1] == '/'
url
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/version.rb 0000644 0000041 0000041 00000000073 13172672532 020452 0 ustar www-data www-data module Gollum
module Lib
VERSION = '4.2.7'
end
end
gollum-lib-4.2.7/lib/gollum-lib/wiki.rb 0000644 0000041 0000041 00000105621 13172672532 017735 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class Wiki
include Pagination
class << self
# Sets the page class used by all instances of this Wiki.
attr_writer :page_class
# Sets the file class used by all instances of this Wiki.
attr_writer :file_class
# Sets the markup class used by all instances of this Wiki.
attr_writer :markup_classes
# Sets the default ref for the wiki.
attr_writer :default_ref
# Sets the default name for commits.
attr_writer :default_committer_name
# Sets the default email for commits.
attr_writer :default_committer_email
# Array of chars to substitute whitespace for when trying to locate file in git repo.
attr_writer :default_ws_subs
# Sets sanitization options. Set to false to deactivate
# sanitization altogether.
attr_writer :sanitization
# Sets sanitization options. Set to false to deactivate
# sanitization altogether.
attr_writer :history_sanitization
# Hash for setting different default wiki options
# These defaults can be overridden by options passed directly to initialize()
attr_writer :default_options
# Gets the page class used by all instances of this Wiki.
# Default: Gollum::Page.
def page_class
@page_class ||
if superclass.respond_to?(:page_class)
superclass.page_class
else
::Gollum::Page
end
end
# Gets the file class used by all instances of this Wiki.
# Default: Gollum::File.
def file_class
@file_class ||
if superclass.respond_to?(:file_class)
superclass.file_class
else
::Gollum::File
end
end
# Gets the markup class used by all instances of this Wiki.
# Default: Gollum::Markup
def markup_classes
@markup_classes ||=
if superclass.respond_to?(:markup_classes)
superclass.markup_classes
else
Hash.new(::Gollum::Markup)
end
end
# Gets the default markup class used by all instances of this Wiki.
# Kept for backwards compatibility until Gollum v2.x
def markup_class(language=:default)
markup_classes[language]
end
# Sets the default markup class used by all instances of this Wiki.
# Kept for backwards compatibility until Gollum v2.x
def markup_class=(default)
@markup_classes = Hash.new(default).update(markup_classes)
default
end
alias_method :default_markup_class, :markup_class
alias_method :default_markup_class=, :markup_class=
# Gets the default sanitization options for current pages used by
# instances of this Wiki.
def sanitization
if @sanitization.nil?
@sanitization = Sanitization.new
end
@sanitization
end
# Gets the default sanitization options for older page revisions used by
# instances of this Wiki.
def history_sanitization
if @history_sanitization.nil?
@history_sanitization = sanitization ?
sanitization.history_sanitization :
false
end
@history_sanitization
end
def default_ref
@default_ref || 'master'
end
def default_committer_name
@default_committer_name || 'Anonymous'
end
def default_committer_email
@default_committer_email || 'anon@anon.com'
end
def default_ws_subs
@default_ws_subs || ['_', '-']
end
def default_options
@default_options || {}
end
end
# The String base path to prefix to internal links. For example, when set
# to "/wiki", the page "Hobbit" will be linked as "/wiki/Hobbit". Defaults
# to "/".
attr_reader :base_path
# Gets the sanitization options for current pages used by this Wiki.
attr_reader :sanitization
# Gets the sanitization options for older page revisions used by this Wiki.
attr_reader :history_sanitization
# Gets the String ref in which all page files reside.
attr_reader :ref
# Gets the String directory in which all page files reside.
attr_reader :page_file_dir
# Gets the Array of chars to sub for ws in filenames.
attr_reader :ws_subs
# Gets the boolean live preview value.
attr_reader :live_preview
# Injects custom css from custom.css in root repo.
# Defaults to false
attr_reader :css
# Sets page title to value of first h1
# Defaults to false
attr_reader :h1_title
# Gets the custom index page for / and subdirs (e.g. foo/)
attr_reader :index_page
# Gets side on which the sidebar should be shown
attr_reader :bar_side
# An array of symbols which refer to classes under Gollum::Filter,
# each of which is an element in the "filtering chain". See
# the documentation for Gollum::Filter for more on how this chain
# works, and what filter classes need to implement.
attr_reader :filter_chain
# Public: Initialize a new Gollum Repo.
#
# path - The String path to the Git repository that holds the Gollum
# site.
# options - Optional Hash:
# :universal_toc - Table of contents on all pages. Default: false
# :live_preview - Livepreview editing for markdown files. Default: true
# :base_path - String base path for all Wiki links.
# Default: "/"
# :page_class - The page Class. Default: Gollum::Page
# :file_class - The file Class. Default: Gollum::File
# :markup_classes - A hash containing the markup Classes for each
# document type. Default: { Gollum::Markup }
# :sanitization - An instance of Sanitization.
# :page_file_dir - String the directory in which all page files reside
# :ref - String the repository ref to retrieve pages from
# :ws_subs - Array of chars to sub for ws in filenames.
# :mathjax - Set to false to disable mathjax.
# :user_icons - Enable user icons on the history page. [gravatar, identicon, none].
# Default: none
# :show_all - Show all files in file view, not just valid pages.
# Default: false
# :collapse_tree - Start with collapsed file view. Default: false
# :css - Include the custom.css file from the repo.
# :emoji - Parse and interpret emoji tags (e.g. :heart:).
# :h1_title - Concatenate all h1's on a page to form the
# page title.
# :index_page - The default page to retrieve or create if the
# a directory is accessed.
# :bar_side - Where the sidebar should be displayed, may be:
# - :left
# - :right
# :allow_uploads - Set to true to allow file uploads.
# :per_page_uploads - Whether uploads should be stored in a central
# 'uploads' directory, or in a directory named for
# the page they were uploaded to.
# :filter_chain - Override the default filter chain with your own.
#
# Returns a fresh Gollum::Repo.
def initialize(path, options = {})
options = self.class.default_options.merge(options)
if path.is_a?(GitAccess)
options[:access] = path
path = path.path
end
# Use .fetch instead of ||
#
# o = { :a => false }
# o[:a] || true # => true
# o.fetch :a, true # => false
@path = path
@repo_is_bare = options.fetch :repo_is_bare, nil
@page_file_dir = options.fetch :page_file_dir, nil
@access = options.fetch :access, GitAccess.new(path, @page_file_dir, @repo_is_bare)
@base_path = options.fetch :base_path, "/"
@page_class = options.fetch :page_class, self.class.page_class
@file_class = options.fetch :file_class, self.class.file_class
@markup_classes = options.fetch :markup_classes, self.class.markup_classes
@repo = @access.repo
@ref = options.fetch :ref, self.class.default_ref
@sanitization = options.fetch :sanitization, self.class.sanitization
@ws_subs = options.fetch :ws_subs, self.class.default_ws_subs
@history_sanitization = options.fetch :history_sanitization, self.class.history_sanitization
@live_preview = options.fetch :live_preview, true
@universal_toc = options.fetch :universal_toc, false
@mathjax = options.fetch :mathjax, false
@show_all = options.fetch :show_all, false
@collapse_tree = options.fetch :collapse_tree, false
@css = options.fetch :css, false
@emoji = options.fetch :emoji, false
@h1_title = options.fetch :h1_title, false
@index_page = options.fetch :index_page, 'Home'
@bar_side = options.fetch :sidebar, :right
@user_icons = ['gravatar', 'identicon'].include?(options[:user_icons]) ?
options[:user_icons] : 'none'
@allow_uploads = options.fetch :allow_uploads, false
@per_page_uploads = options.fetch :per_page_uploads, false
@filter_chain = options.fetch :filter_chain,
[:Metadata, :PlainText, :TOC, :RemoteCode, :Code, :Macro, :Emoji, :Sanitize, :WSD, :PlantUML, :Tags, :Render]
@filter_chain.delete(:Emoji) unless options.fetch :emoji, false
end
# Public: check whether the wiki's git repo exists on the filesystem.
#
# Returns true if the repo exists, and false if it does not.
def exist?
@access.exist?
end
# Public: Get the formatted page for a given page name, version, and dir.
#
# name - The human or canonical String page name of the wiki page.
# version - The String version ID to find (default: @ref).
# dir - The directory String relative to the repo.
#
# Returns a Gollum::Page or nil if no matching page was found.
def page(name, version = @ref, dir = nil, exact = false)
version = @ref if version.nil?
@page_class.new(self).find(name, version, dir, exact)
end
# Public: Convenience method instead of calling page(name, nil, dir).
#
# name - The human or canonical String page name of the wiki page.
# version - The String version ID to find (default: @ref).
# dir - The directory String relative to the repo.
#
# Returns a Gollum::Page or nil if no matching page was found.
def paged(name, dir = nil, exact = false, version = @ref)
page(name, version, dir, exact)
end
# Public: Get the static file for a given name.
#
# name - The full String pathname to the file.
# version - The String version ID to find (default: @ref).
# try_on_disk - If true, try to return just a reference to a file
# that exists on the disk.
#
# Returns a Gollum::File or nil if no matching file was found. Note
# that if you specify try_on_disk=true, you may or may not get a file
# for which on_disk? is actually true.
def file(name, version = @ref, try_on_disk = false)
@file_class.new(self).find(name, version, try_on_disk)
end
# Public: Create an in-memory Page with the given data and format. This
# is useful for previewing what content will look like before committing
# it to the repository.
#
# name - The String name of the page.
# format - The Symbol format of the page.
# data - The new String contents of the page.
#
# Returns the in-memory Gollum::Page.
def preview_page(name, data, format)
page = @page_class.new(self)
ext = @page_class.format_to_ext(format.to_sym)
name = @page_class.cname(name) + '.' + ext
blob = OpenStruct.new(:name => name, :data => data, :is_symlink => false)
page.populate(blob)
page.version = @access.commit(@ref)
page
end
# Public: Write a new version of a page to the Gollum repo root.
#
# name - The String name of the page.
# format - The Symbol format of the page.
# data - The new String contents of the page.
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
# dir - The String subdirectory of the Gollum::Page without any
# prefix or suffix slashes (e.g. "foo/bar").
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
def write_page(name, format, data, commit = {}, dir = '')
# spaces must be dashes
sanitized_name = name.gsub(' ', '-')
sanitized_dir = dir.gsub(' ', '-')
sanitized_dir = ::File.join([@page_file_dir, sanitized_dir].compact)
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
filename = Gollum::Page.cname(sanitized_name)
committer.add_to_index(sanitized_dir, filename, format, data)
committer.after_commit do |index, _sha|
@access.refresh
index.update_working_dir(sanitized_dir, filename, format)
end
multi_commit ? committer : committer.commit
end
# Public: Rename an existing page without altering content.
#
# page - The Gollum::Page to update.
# rename - The String extension-less full path of the page (leading '/' is ignored).
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
# Returns false if the operation is a NOOP.
def rename_page(page, rename, commit = {})
return false if page.nil?
return false if rename.nil? or rename.empty?
(target_dir, target_name) = ::File.split(rename)
(source_dir, source_name) = ::File.split(page.path)
source_name = page.filename_stripped
# File.split gives us relative paths with ".", commiter.add_to_index doesn't like that.
target_dir = '' if target_dir == '.'
source_dir = '' if source_dir == '.'
target_dir = target_dir.gsub(/^\//, '')
# if the rename is a NOOP, abort
if source_dir == target_dir and source_name == target_name
return false
end
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
committer.delete(page.path)
committer.add_to_index(target_dir, target_name, page.format, page.raw_data)
committer.after_commit do |index, _sha|
@access.refresh
index.update_working_dir(source_dir, source_name, page.format)
index.update_working_dir(target_dir, target_name, page.format)
end
multi_commit ? committer : committer.commit
end
# Public: Update an existing page with new content. The location of the
# page inside the repository will not change. If the given format is
# different than the current format of the page, the filename will be
# changed to reflect the new format.
#
# page - The Gollum::Page to update.
# name - The String extension-less name of the page.
# format - The Symbol format of the page.
# data - The new String contents of the page.
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
def update_page(page, name, format, data, commit = {})
name ||= page.name
format ||= page.format
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
filename = (rename = page.name != name) ?
Gollum::Page.cname(name) : page.filename_stripped
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
if !rename && page.format == format
committer.add(page.path, normalize(data))
else
committer.delete(page.path)
committer.add_to_index(dir, filename, format, data)
end
committer.after_commit do |index, _sha|
@access.refresh
index.update_working_dir(dir, page.filename_stripped, page.format)
index.update_working_dir(dir, filename, format)
end
multi_commit ? committer : committer.commit
end
# Public: Delete a page.
#
# page - The Gollum::Page to delete.
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
def delete_page(page, commit)
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
committer.delete(page.path)
committer.after_commit do |index, _sha|
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
@access.refresh
index.update_working_dir(dir, page.filename_stripped, page.format)
end
multi_commit ? committer : committer.commit
end
# Public: Delete a file.
#
# path - The path to the file to delete
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the String SHA1 of the newly written version, or the
# Gollum::Committer instance if this is part of a batch update.
def delete_file(path, commit)
dir = ::File.dirname(path)
ext = ::File.extname(path)
format = ext.split('.').last || 'txt'
filename = ::File.basename(path, ext)
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
committer.delete(path)
committer.after_commit do |index, _sha|
dir = '' if dir == '.'
@access.refresh
index.update_working_dir(dir, filename, format)
end
multi_commit ? committer : committer.commit
end
# Public: Applies a reverse diff for a given page. If only 1 SHA is given,
# the reverse diff will be taken from its parent (^SHA...SHA). If two SHAs
# are given, the reverse diff is taken from SHA1...SHA2.
#
# page - The Gollum::Page to delete.
# sha1 - String SHA1 of the earlier parent if two SHAs are given,
# or the child.
# sha2 - Optional String SHA1 of the child.
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
#
# Returns a String SHA1 of the new commit, or nil if the reverse diff does
# not apply.
def revert_page(page, sha1, sha2 = nil, commit = {})
if sha2.is_a?(Hash)
commit = sha2
sha2 = nil
end
patch = full_reverse_diff_for(page, sha1, sha2)
committer = Committer.new(self, commit)
parent = committer.parents[0]
committer.options[:tree] = @repo.git.apply_patch(parent.sha, patch)
return false unless committer.options[:tree]
committer.after_commit do |index, _sha|
@access.refresh
files = []
if page
files << [page.path, page.filename_stripped, page.format]
else
# Grit::Diff can't parse reverse diffs.... yet
patch.each_line do |line|
if line =~ %r(^diff --git b/.+? a/(.+)$)
path = Regexp.last_match[1]
ext = ::File.extname(path)
name = ::File.basename(path, ext)
if (format = ::Gollum::Page.format_for(ext))
files << [path, name, format]
end
end
end
end
files.each do |(path, name, format)|
dir = ::File.dirname(path)
dir = '' if dir == '.'
index.update_working_dir(dir, name, format)
end
end
committer.commit
end
# Public: Applies a reverse diff to the repo. If only 1 SHA is given,
# the reverse diff will be taken from its parent (^SHA...SHA). If two SHAs
# are given, the reverse diff is taken from SHA1...SHA2.
#
# sha1 - String SHA1 of the earlier parent if two SHAs are given,
# or the child.
# sha2 - Optional String SHA1 of the child.
# commit - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
#
# Returns a String SHA1 of the new commit, or nil if the reverse diff does
# not apply.
def revert_commit(sha1, sha2 = nil, commit = {})
revert_page(nil, sha1, sha2, commit)
end
# Public: Lists all pages for this wiki.
#
# treeish - The String commit ID or ref to find (default: @ref)
#
# Returns an Array of Gollum::Page instances.
def pages(treeish = nil)
tree_list(treeish || @ref)
end
# Public: Lists all non-page files for this wiki.
#
# treeish - The String commit ID or ref to find (default: @ref)
#
# Returns an Array of Gollum::File instances.
def files(treeish = nil)
file_list(treeish || @ref)
end
# Public: Returns the number of pages accessible from a commit
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns a Fixnum
def size(ref = nil)
tree_map_for(ref || @ref).inject(0) do |num, entry|
num + (@page_class.valid_page_name?(entry.name) ? 1 : 0)
end
rescue Gollum::Git::NoSuchShaFound
0
end
# Public: Search all pages for this wiki.
#
# query - The string to search for
#
# Returns an Array with Objects of page name and count of matches
def search(query)
options = {:path => page_file_dir, :ref => ref}
results = {}
@repo.git.grep(query, options).each do |hit|
name = hit[:name]
count = hit[:count]
# Remove ext only from known extensions.
# test.pdf => test.pdf, test.md => test
file_name = Page::valid_page_name?(name) ? name.chomp(::File.extname(name)) : name
results[file_name] = count.to_i
end
# Use git ls-files '*query*' to search for file names. Grep only searches file content.
# Spaces are converted to dashes when saving pages to disk.
@repo.git.ls_files(query.gsub(' ','-'), options).each do |path|
# Remove ext only from known extensions.
file_name = Page::valid_page_name?(path) ? path.chomp(::File.extname(path)) : path
# If there's not already a result for file_name then
# the value is nil and nil.to_i is 0.
results[file_name] = results[file_name].to_i + 1;
end
results.map do |key, val|
{ :count => val, :name => key }
end
end
# Public: All of the versions that have touched the Page.
#
# options - The options Hash:
# :page - The Integer page number (default: 1).
# :per_page - The Integer max count of items to return.
#
# Returns an Array of Gollum::Git::Commit.
def log(options = {})
@repo.log(@ref, nil, log_pagination_options(options))
end
# Returns the latest changes in the wiki (globally)
#
# options - The options Hash:
# :max_count - The Integer number of items to return.
#
# Returns an Array of Gollum::Git::Commit.
def latest_changes(options={})
options[:max_count] = 10 unless options[:max_count]
@repo.log(@ref, nil, options)
end
# Public: Refreshes just the cached Git reference data. This should
# be called after every Gollum update.
#
# Returns nothing.
def clear_cache
@access.refresh
end
# Public: Creates a Sanitize instance using the Wiki's sanitization
# options.
#
# Returns a Sanitize instance.
def sanitizer
if (options = sanitization)
@sanitizer ||= options.to_sanitize
end
end
# Public: Creates a Sanitize instance using the Wiki's history sanitization
# options.
#
# Returns a Sanitize instance.
def history_sanitizer
if (options = history_sanitization)
@history_sanitizer ||= options.to_sanitize
end
end
# Public: Add an additional link to the filter chain.
#
# name - A symbol which represents the name of a class under the
# Gollum::Render namespace to insert into the chain.
#
# loc - A "location specifier" -- that is, where to put the new
# filter in the chain. This can be one of `:first`, `:last`,
# `:before => :SomeElement`, or `:after => :SomeElement`, where
# `:SomeElement` (if specified) is a symbol already in the
# filter chain. A `:before` or `:after` which references a
# filter that doesn't exist will cause `ArgumentError` to be
# raised.
#
# Returns nothing.
def add_filter(name, loc)
unless name.is_a? Symbol
raise ArgumentError,
"Invalid filter name #{name.inspect} (must be a symbol)"
end
case loc
when :first
@filter_chain.unshift(name)
when :last
@filter_chain.push(name)
when Hash
if loc.length != 1
raise ArgumentError,
"Invalid location specifier"
end
if ([:before, :after] && loc.keys).empty?
raise ArgumentError,
"Invalid location specifier"
end
next_to = loc.values.first
relative = loc.keys.first
i = @filter_chain.index(next_to)
if i.nil?
raise ArgumentError,
"Unknown filter #{next_to.inspect}"
end
i += 1 if relative == :after
@filter_chain.insert(i, name)
else
raise ArgumentError,
"Invalid location specifier"
end
end
# Remove the named filter from the filter chain.
#
# Returns nothing. Raises `ArgumentError` if the named filter doesn't
# exist in the chain.
def remove_filter(name)
unless name.is_a? Symbol
raise ArgumentError,
"Invalid filter name #{name.inspect} (must be a symbol)"
end
unless @filter_chain.delete(name)
raise ArgumentError,
"#{name.inspect} not found in filter chain"
end
end
#########################################################################
#
# Internal Methods
#
#########################################################################
# The Gollum::Git::Repo associated with the wiki.
#
# Returns the Gollum::Git::Repo.
attr_reader :repo
# The String path to the Git repository that holds the Gollum site.
#
# Returns the String path.
attr_reader :path
# Gets the page class used by all instances of this Wiki.
attr_reader :page_class
# Gets the file class used by all instances of this Wiki.
attr_reader :file_class
# Gets the markup class used by all instances of this Wiki.
attr_reader :markup_classes
# Toggles display of universal table of contents
attr_reader :universal_toc
# Toggles mathjax.
attr_reader :mathjax
# Toggles user icons. Default: 'none'
attr_reader :user_icons
# Toggles showing all files in files view. Default is false.
# When false, only valid pages in the git repo are displayed.
attr_reader :show_all
# Start with collapsed file view. Default: false
attr_reader :collapse_tree
# Toggles file upload functionality.
attr_reader :allow_uploads
# Toggles whether uploaded files go into 'uploads', or a directory
# named after the page they were uploaded to.
attr_reader :per_page_uploads
# Normalize the data.
#
# data - The String data to be normalized.
#
# Returns the normalized data String.
def normalize(data)
data.gsub(/\r/, '')
end
# Assemble a Page's filename from its name and format.
#
# name - The String name of the page (should be pre-canonicalized).
# format - The Symbol format of the page.
#
# Returns the String filename.
def page_file_name(name, format)
name + '.' + @page_class.format_to_ext(format)
end
# Fill an array with a list of pages.
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns a flat Array of Gollum::Page instances.
def tree_list(ref)
if (sha = @access.ref_to_sha(ref))
commit = @access.commit(sha)
tree_map_for(sha).inject([]) do |list, entry|
next list unless @page_class.valid_page_name?(entry.name)
list << entry.page(self, commit)
end
else
[]
end
end
# Fill an array with a list of files.
#
# ref - A String ref that is either a commit SHA or references one.
#
# Returns a flat Array of Gollum::File instances.
def file_list(ref)
if (sha = @access.ref_to_sha(ref))
commit = @access.commit(sha)
tree_map_for(sha).inject([]) do |list, entry|
next list if entry.name.start_with?('_')
next list if @page_class.valid_page_name?(entry.name)
list << entry.file(self, commit)
end
else
[]
end
end
# Creates a reverse diff for the given SHAs on the given Gollum::Page.
#
# page - The Gollum::Page to scope the patch to, or a String Path.
# sha1 - String SHA1 of the earlier parent if two SHAs are given,
# or the child.
# sha2 - Optional String SHA1 of the child.
#
# Returns a String of the reverse Diff to apply.
def full_reverse_diff_for(page, sha1, sha2 = nil)
sha1, sha2 = "#{sha1}^", sha1 if sha2.nil?
if page
path = (page.respond_to?(:path) ? page.path : page.to_s)
return repo.diff(sha2, sha1, path).first.diff
end
repo.diff(sha2, sha1).map { |d| d.diff }.join("\n")
end
# Creates a reverse diff for the given SHAs.
#
# sha1 - String SHA1 of the earlier parent if two SHAs are given,
# or the child.
# sha2 - Optional String SHA1 of the child.
#
# Returns a String of the reverse Diff to apply.
def full_reverse_diff(sha1, sha2 = nil)
full_reverse_diff_for(nil, sha1, sha2)
end
# Gets the default name for commits.
#
# Returns the String name.
def default_committer_name
@default_committer_name ||= \
@repo.config['user.name'] || self.class.default_committer_name
end
# Gets the default email for commits.
#
# Returns the String email address.
def default_committer_email
email = @repo.config['user.email']
email = email.delete('<>') if email
@default_committer_email ||= email || self.class.default_committer_email
end
# Gets the commit object for the given ref or sha.
#
# ref - A string ref or SHA pointing to a valid commit.
#
# Returns a Gollum::Git::Commit instance.
def commit_for(ref)
@access.commit(ref)
rescue Gollum::Git::NoSuchShaFound
end
# Finds a full listing of files and their blob SHA for a given ref. Each
# listing is cached based on its actual commit SHA.
#
# ref - A String ref that is either a commit SHA or references one.
# ignore_page_file_dir - Boolean, if true, searches all files within the git repo, regardless of dir/subdir
#
# Returns an Array of BlobEntry instances.
def tree_map_for(ref, ignore_page_file_dir=false)
if ignore_page_file_dir && !@page_file_dir.nil?
@root_access ||= GitAccess.new(path, nil, @repo_is_bare)
@root_access.tree(ref)
else
@access.tree(ref)
end
rescue Gollum::Git::NoSuchShaFound
[]
end
def inspect
%(#<#{self.class.name}:#{object_id} #{@repo.path}>)
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/markup.rb 0000644 0000041 0000041 00000013231 13172672532 020264 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
require 'digest/sha1'
require 'cgi'
require 'rouge'
require 'base64'
require File.expand_path '../helpers', __FILE__
# Use pygments if it's installed
begin
require 'pygments'
Pygments.start
rescue Exception
end
module Gollum
class Markup
include Helpers
@formats = {}
class << self
# Only use the formats that are specified in config.rb
def formats
if defined? Gollum::Page::FORMAT_NAMES
@formats.select { |_, value| Gollum::Page::FORMAT_NAMES.values.include? value[:name] }
else
@formats
end
end
# Register a file extension and associated markup type
#
# ext - The file extension
# name - The name of the markup type
# options - Hash of options:
# regexp - Regexp to match against.
# Defaults to exact match of ext.
#
# If given a block, that block will be registered with GitHub::Markup to
# render any matching pages
def register(ext, name, options = {}, &block)
@formats[ext] = { :name => name,
:regexp => options.fetch(:regexp, Regexp.new(ext.to_s)),
:reverse_links => options.fetch(:reverse_links, false) }
end
end
attr_accessor :toc
attr_accessor :metadata
attr_reader :encoding
attr_reader :sanitize
attr_reader :format
attr_reader :wiki
attr_reader :page
attr_reader :parent_page
attr_reader :sub_page
attr_reader :name
attr_reader :include_levels
attr_reader :to_xml_opts
attr_reader :dir
# Initialize a new Markup object.
#
# page - The Gollum::Page.
#
# Returns a new Gollum::Markup object, ready for rendering.
def initialize(page)
if page
@wiki = page.wiki
@name = page.filename
@data = page.text_data
@version = page.version.id if page.version
@format = page.format
@sub_page = page.sub_page
@parent_page = page.parent_page
@page = page
@dir = ::File.dirname(page.path)
end
@metadata = nil
@to_xml_opts = { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML ^ 1, :indent => 0, :encoding => 'UTF-8' }
end
def reverse_links?
self.class.formats[@format][:reverse_links]
end
# Render data using default chain in the target format.
#
# data - the data to render
# format - format to use as a symbol
# name - name using the extension of the format
#
# Returns the processed data
def render_default(data, format=:markdown, name='render_default.md')
# set instance vars so we're able to render data without a wiki or page.
@format = format
@name = name
chain = [:Metadata, :PlainText, :Emoji, :TOC, :RemoteCode, :Code, :Sanitize, :WSD, :Tags, :Render]
filter_chain = chain.map do |r|
Gollum::Filter.const_get(r).new(self)
end
process_chain data, filter_chain
end
# Process the filter chain
#
# data - the data to send through the chain
# filter_chain - the chain to process
#
# Returns the formatted data
def process_chain(data, filter_chain)
# First we extract the data through the chain...
filter_chain.each do |filter|
data = filter.extract(data)
end
# Then we process the data through the chain *backwards*
filter_chain.reverse.each do |filter|
data = filter.process(data)
end
# Finally, a little bit of cleanup, just because
data.gsub!(/<\/p>/) do
''
end
data
end
# Render the content with Gollum wiki syntax on top of the file's own
# markup language.
#
# no_follow - Boolean that determines if rel="nofollow" is added to all
# tags.
# encoding - Encoding Constant or String.
#
# Returns the formatted String content.
def render(no_follow = false, encoding = nil, include_levels = 10)
@sanitize = no_follow ?
@wiki.history_sanitizer :
@wiki.sanitizer
@encoding = encoding
@include_levels = include_levels
data = @data.dup
filter_chain = @wiki.filter_chain.map do |r|
Gollum::Filter.const_get(r).new(self)
end
# Since the last 'extract' action in our chain *should* be the markup
# to HTML converter, we now have HTML which we can parse and yield, for
# anyone who wants it
if block_given?
yield Nokogiri::HTML::DocumentFragment.parse(data)
end
process_chain data, filter_chain
end
# Find the given file in the repo.
#
# name - The String absolute or relative path of the file.
#
# Returns the Gollum::File or nil if none was found.
def find_file(name, version=@version)
if name =~ /^\//
@wiki.file(name[1..-1], version)
else
path = @dir == '.' ? name : ::File.join(@dir, name)
@wiki.file(path, version)
end
end
# Hook for getting the formatted value of extracted tag data.
#
# type - Symbol value identifying what type of data is being extracted.
# id - String SHA1 hash of original extracted tag data.
#
# Returns the String cached formatted data, or nil.
def check_cache(type, id)
end
# Hook for caching the formatted value of extracted tag data.
#
# type - Symbol value identifying what type of data is being extracted.
# id - String SHA1 hash of original extracted tag data.
# data - The String formatted value to be cached.
#
# Returns nothing.
def update_cache(type, id, data)
end
end
MarkupGFM = Markup
end
gollum-lib-4.2.7/lib/gollum-lib/page.rb 0000644 0000041 0000041 00000035172 13172672532 017711 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class Page
include Pagination
Wiki.page_class = self
SUBPAGENAMES = [:header, :footer, :sidebar]
# Sets a Boolean determing whether this page is a historical version.
#
# Returns nothing.
attr_writer :historical
# Parent page if this is a sub page
#
# Returns a Page
attr_accessor :parent_page
# Checks a filename against the registered markup extensions
#
# filename - String filename, like "Home.md"
#
# Returns e.g. ["Home", :markdown], or [] if the extension is unregistered
def self.parse_filename(filename)
return [] unless filename =~ /^(.+)\.([a-zA-Z]\w*)$/i
pref, ext = Regexp.last_match[1], Regexp.last_match[2]
Gollum::Markup.formats.each_pair do |name, format|
return [pref, name] if ext =~ format[:regexp]
end
[]
end
# Checks if a filename has a valid, registered extension
#
# filename - String filename, like "Home.md".
#
# Returns the matching String basename of the file without the extension.
def self.valid_filename?(filename)
self.parse_filename(filename).first
end
# Checks if a filename has a valid extension understood by GitHub::Markup.
# Also, checks if the filename has no "_" in the front (such as
# _Footer.md).
#
# filename - String filename, like "Home.md".
#
# Returns the matching String basename of the file without the extension.
def self.valid_page_name?(filename)
match = valid_filename?(filename)
filename =~ /^_/ ? false : match
end
# Public: The format of a given filename.
#
# filename - The String filename.
#
# Returns the Symbol format of the page; one of the registered format types
def self.format_for(filename)
self.parse_filename(filename).last
end
# Reusable filter to turn a filename (without path) into a canonical name.
# Strips extension, converts dashes to spaces.
#
# Returns the filtered String.
def self.canonicalize_filename(filename)
strip_filename(filename).gsub('-', ' ')
end
# Reusable filter to strip extension and path from filename
#
# filename - The string path or filename to strip
#
# Returns the stripped String.
def self.strip_filename(filename)
::File.basename(filename, ::File.extname(filename))
end
# Public: Initialize a page.
#
# wiki - The Gollum::Wiki in question.
#
# Returns a newly initialized Gollum::Page.
def initialize(wiki)
@wiki = wiki
@blob = nil
@formatted_data = nil
@doc = nil
@parent_page = nil
end
# Public: The on-disk filename of the page including extension.
#
# Returns the String name.
def filename
@blob && @blob.name
end
# Public: The on-disk filename of the page with extension stripped.
#
# Returns the String name.
def filename_stripped
self.class.strip_filename(filename)
end
# Public: The canonical page name without extension, and dashes converted
# to spaces.
#
# Returns the String name.
def name
self.class.canonicalize_filename(filename)
end
# Public: The title will be constructed from the
# filename by stripping the extension and replacing any dashes with
# spaces.
#
# Returns the fully sanitized String title.
def title
Sanitize.clean(name).strip
end
# Public: Determines if this is a sub-page
# Sub-pages have filenames beginning with an underscore
#
# Returns true or false.
def sub_page
filename =~ /^_/
end
# Public: The path of the page within the repo.
#
# Returns the String path.
attr_reader :path
# Public: The url path required to reach this page within the repo.
#
# Returns the String url_path
def url_path
path = if self.path.include?('/')
self.path.sub(/\/[^\/]+$/, '/')
else
''
end
path << Page.cname(self.name, '-', '-')
path
end
# Public: The display form of the url path required to reach this page within the repo.
#
# Returns the String url_path
def url_path_display
url_path.gsub("-", " ")
end
# Public: Defines title for page.rb
#
# Returns the String title
def url_path_title
metadata_title || url_path_display
end
# Public: Metadata title
#
# Set with in page content
#
# Returns the String title or nil if not defined
def metadata_title
if metadata
title = metadata['title']
return title unless title.nil?
end
nil
end
# Public: The url_path, but CGI escaped.
#
# Returns the String url_path
def escaped_url_path
CGI.escape(self.url_path).gsub('%2F', '/')
end
# Public: The raw contents of the page.
#
# Returns the String data.
def raw_data
return nil unless @blob
if !@wiki.repo.bare && @blob.is_symlink
new_path = @blob.symlink_target(::File.join(@wiki.repo.path, '..', self.path))
return IO.read(new_path) if new_path
end
@blob.data
end
# Public: A text data encoded in specified encoding.
#
# encoding - An Encoding or nil
#
# Returns a character encoding aware String.
def text_data(encoding=nil)
if raw_data.respond_to?(:encoding)
raw_data.force_encoding(encoding || Encoding::UTF_8)
else
raw_data
end
end
# Public: The formatted contents of the page.
#
# encoding - Encoding Constant or String.
#
# Returns the String data.
def formatted_data(encoding = nil, include_levels = 10, &block)
return nil unless @blob
if @formatted_data && @doc then
yield @doc if block_given?
else
@formatted_data = markup_class.render(historical?, encoding, include_levels) do |doc|
@doc = doc
yield doc if block_given?
end
end
@formatted_data
end
# Public: The table of contents of the page.
#
# formatted_data - page already marked up in html.
#
# Returns the String data.
def toc_data
return @parent_page.toc_data if @parent_page and @sub_page
formatted_data if markup_class.toc == nil
markup_class.toc
end
# Public: Embedded metadata.
#
# Returns Hash of metadata.
def metadata
formatted_data if markup_class.metadata == nil
markup_class.metadata
end
# Public: The format of the page.
#
# Returns the Symbol format of the page; one of the registered format types
def format
self.class.format_for(@blob.name)
end
# Gets the Gollum::Markup instance that will render this page's content.
#
# Returns a Gollum::Markup instance.
def markup_class
@markup_class ||= @wiki.markup_classes[format].new(self)
end
# Public: The current version of the page.
#
# Returns the Gollum::Git::Commit.
attr_reader :version
# Public: All of the versions that have touched the Page.
#
# options - The options Hash:
# :page - The Integer page number (default: 1).
# :per_page - The Integer max count of items to return.
# :follow - Follow's a file across renames, slower. (default: false)
#
# Returns an Array of Gollum::Git::Commit.
def versions(options = {})
@wiki.repo.git.versions_for_path(@path, @wiki.ref, log_pagination_options(options))
end
# Public: The last version that has touched the Page. Can be nil.
#
# Returns Gollum::Git::Commit, or nil.
def last_version
return @last_version if defined? @last_version
@last_version = @wiki.repo.git.versions_for_path(@path, @wiki.ref, {:max_count => 1}).first
end
# Public: The first 7 characters of the current version.
#
# Returns the first 7 characters of the current version.
def version_short
version.to_s[0, 7]
end
# Public: The header Page.
#
# Returns the header Page or nil if none exists.
def header
find_sub_pages unless defined?(@header)
@header
end
# Public: The footer Page.
#
# Returns the footer Page or nil if none exists.
def footer
find_sub_pages unless defined?(@footer)
@footer
end
# Public: The sidebar Page.
#
# Returns the sidebar Page or nil if none exists.
def sidebar
find_sub_pages unless defined?(@sidebar)
@sidebar
end
# Gets a Boolean determining whether this page is a historical version.
# Historical pages are pulled using exact SHA hashes and format all links
# with rel="nofollow"
#
# Returns true if the page is pulled from a named branch or tag, or false.
def historical?
!!@historical
end
#########################################################################
#
# Class Methods
#
#########################################################################
# Convert a human page name into a canonical page name.
#
# name - The String human page name.
# char_white_sub - Substitution for whitespace
# char_other_sub - Substitution for other special chars
#
# Examples
#
# Page.cname("Bilbo Baggins")
# # => 'Bilbo-Baggins'
#
# Page.cname("Bilbo Baggins",'_')
# # => 'Bilbo_Baggins'
#
# Returns the String canonical name.
def self.cname(name, char_white_sub = '-', char_other_sub = '-')
name.respond_to?(:gsub) ?
name.gsub(%r(\s), char_white_sub).gsub(%r([<>+]), char_other_sub) :
''
end
# Convert a format Symbol into an extension String.
#
# format - The format Symbol.
#
# Returns the String extension (no leading period).
def self.format_to_ext(format)
format == :markdown ? "md" : format.to_s
end
#########################################################################
#
# Internal Methods
#
#########################################################################
# The underlying wiki repo.
#
# Returns the Gollum::Wiki containing the page.
attr_reader :wiki
# Set the Gollum::Git::Commit version of the page.
#
# Returns nothing.
attr_writer :version
# Find a page in the given Gollum repo.
#
# name - The human or canonical String page name to find.
# version - The String version ID to find.
#
# Returns a Gollum::Page or nil if the page could not be found.
def find(name, version, dir = nil, exact = false)
map = @wiki.tree_map_for(version.to_s)
if (page = find_page_in_tree(map, name, dir, exact))
page.version = version.is_a?(Gollum::Git::Commit) ?
version : @wiki.commit_for(version)
page.historical = page.version.to_s == version.to_s
page
end
rescue Gollum::Git::NoSuchShaFound
end
# Find a page in a given tree.
#
# map - The Array tree map from Wiki#tree_map.
# name - The canonical String page name.
# checked_dir - Optional String of the directory a matching page needs
# to be in. The string should
#
# Returns a Gollum::Page or nil if the page could not be found.
def find_page_in_tree(map, name, checked_dir = nil, exact = false)
return nil if !map || name.to_s.empty?
checked_dir = BlobEntry.normalize_dir(checked_dir)
checked_dir = '' if exact && checked_dir.nil?
name = ::File.join(checked_dir, name) if checked_dir
map.each do |entry|
next if entry.name.to_s.empty?
path = checked_dir ? ::File.join(entry.dir, entry.name) : entry.name
next unless page_match(name, path)
return entry.page(@wiki, @version)
end
return nil # nothing was found
end
# Populate the Page with information from the Blob.
#
# blob - The Gollum::Git::Blob that contains the info.
# path - The String directory path of the page file.
#
# Returns the populated Gollum::Page.
def populate(blob, path=nil)
@blob = blob
@path = "#{path}/#{blob.name}"[1..-1]
self
end
# The full directory path for the given tree.
#
# treemap - The Hash treemap containing parentage information.
# tree - The Gollum::Git::Tree for which to compute the path.
#
# Returns the String path.
def tree_path(treemap, tree)
if (ptree = treemap[tree])
tree_path(treemap, ptree) + '/' + tree.name
else
''
end
end
# Compare the canonicalized versions of the two names.
#
# name - The human or canonical String page name.
# path - the String path on disk (including file extension).
#
# Returns a Boolean.
def page_match(name, path)
if (match = self.class.valid_filename?(path))
@wiki.ws_subs.each do |sub|
return true if Page.cname(name).downcase == Page.cname(match, sub).downcase
end
end
false
end
# Loads sub pages. Sub page names (footers, headers, sidebars) are prefixed with
# an underscore to distinguish them from other Pages. If there is not one within
# the current directory, starts walking up the directory tree to try and find one
# within parent directories.
def find_sub_pages(subpagenames = SUBPAGENAMES, map = nil)
subpagenames.each{|subpagename| instance_variable_set("@#{subpagename}", nil)}
return nil if self.filename =~ /^_/ || ! self.version
map ||= @wiki.tree_map_for(@wiki.ref, true)
valid_names = subpagenames.map(&:capitalize).join("|")
# From Ruby 2.2 onwards map.select! could be used
map = map.select{|entry| entry.name =~ /^_(#{valid_names})/ }
return if map.empty?
subpagenames.each do |subpagename|
dir = ::Pathname.new(self.path)
while dir = dir.parent do
subpageblob = map.find do |blob_entry|
filename = "_#{subpagename.to_s.capitalize}"
searchpath = dir == Pathname.new('.') ? Pathname.new(filename) : dir + filename
entrypath = ::Pathname.new(blob_entry.path)
# Ignore extentions
entrypath = entrypath.dirname + entrypath.basename(entrypath.extname)
entrypath == searchpath
end
if subpageblob
instance_variable_set("@#{subpagename}", subpageblob.page(@wiki, @version) )
break
end
break if dir == Pathname.new('.')
end
end
end
def inspect
%(#<#{self.class.name}:#{object_id} #{name} (#{format}) @wiki=#{@wiki.repo.path.inspect}>)
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/committer.rb 0000644 0000041 0000041 00000020125 13172672532 020770 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
# Responsible for handling the commit process for a Wiki. It sets up the
# Git index, provides methods for modifying the tree, and stores callbacks
# to be fired after the commit has been made. This is specifically
# designed to handle multiple updated pages in a single commit.
class Committer
# Gets the instance of the Gollum::Wiki that is being updated.
attr_reader :wiki
# Gets a Hash of commit options.
attr_reader :options
# Initializes the Committer.
#
# wiki - The Gollum::Wiki instance that is being updated.
# options - The commit Hash details:
# :message - The String commit message.
# :name - The String author full name.
# :email - The String email address.
# :parent - Optional Gollum::Git::Commit parent to this update.
# :tree - Optional String SHA of the tree to create the
# index from.
# :committer - Optional Gollum::Committer instance. If provided,
# assume that this operation is part of batch of
# updates and the commit happens later.
#
# Returns the Committer instance.
def initialize(wiki, options = {})
@wiki = wiki
@options = options
@callbacks = []
after_commit { |*args| Hook.execute(:post_commit, *args) }
end
# Public: References the Git index for this commit.
#
# Returns a Gollum::Git::Index.
def index
@index ||= begin
idx = @wiki.repo.index
if (tree = options[:tree])
idx.read_tree(tree)
elsif (parent = parents.first)
idx.read_tree(parent.tree.id)
end
idx
end
end
# Public: The committer for this commit.
#
# Returns a Gollum::Git::Actor.
def actor
@actor ||= begin
@options[:name] = @wiki.default_committer_name if @options[:name].nil?
@options[:email] = @wiki.default_committer_email if @options[:email].nil?
Gollum::Git::Actor.new(@options[:name], @options[:email])
end
end
# Public: The parent commits to this pending commit.
#
# Returns an array of Gollum::Git::Commit instances.
def parents
@parents ||= begin
arr = [@options[:parent] || @wiki.repo.commit(@wiki.ref)]
arr.flatten!
arr.compact!
arr
end
end
# Adds a page to the given Index.
#
# dir - The String subdirectory of the Gollum::Page without any
# prefix or suffix slashes (e.g. "foo/bar").
# name - The String Gollum::Page filename_stripped.
# format - The Symbol Gollum::Page format.
# data - The String wiki data to store in the tree map.
# allow_same_ext - A Boolean determining if the tree map allows the same
# filename with the same extension.
#
# Raises Gollum::DuplicatePageError if a matching filename already exists.
# This way, pages are not inadvertently overwritten.
#
# Returns nothing (modifies the Index in place).
def add_to_index(dir, name, format, data, allow_same_ext = false)
# spaces must be dashes
dir.gsub!(' ', '-')
name.gsub!(' ', '-')
path = @wiki.page_file_name(name, format)
dir = '/' if dir.strip.empty?
fullpath = ::File.join(*[dir, path])
fullpath = fullpath[1..-1] if fullpath =~ /^\//
if index.current_tree && (tree = index.current_tree / (@wiki.page_file_dir || '/'))
tree = tree / dir unless tree.nil?
end
if tree
downpath = path.downcase.sub(/\.\w+$/, '')
tree.blobs.each do |blob|
next if page_path_scheduled_for_deletion?(index.tree, fullpath)
existing_file = blob.name.downcase.sub(/\.\w+$/, '')
existing_file_ext = ::File.extname(blob.name).sub(/^\./, '')
new_file_ext = ::File.extname(path).sub(/^\./, '')
if downpath == existing_file && !(allow_same_ext && new_file_ext == existing_file_ext)
raise DuplicatePageError.new(dir, blob.name, path)
end
end
end
fullpath = fullpath.force_encoding('ascii-8bit') if fullpath.respond_to?(:force_encoding)
begin
data = @wiki.normalize(data)
rescue ArgumentError => err
# Swallow errors that arise from data being binary
raise err unless err.message.include?('invalid byte sequence')
end
index.add(fullpath, data)
end
# Update the given file in the repository's working directory if there
# is a working directory present.
#
# dir - The String directory in which the file lives.
# name - The String name of the page or the stripped filename
# (should be pre-canonicalized if required).
# format - The Symbol format of the page.
#
# Returns nothing.
def update_working_dir(dir, name, format)
unless @wiki.repo.bare
if @wiki.page_file_dir && dir !~ /^#{@wiki.page_file_dir}/
dir = dir.size.zero? ? @wiki.page_file_dir : ::File.join(@wiki.page_file_dir, dir)
end
path =
if dir == ''
@wiki.page_file_name(name, format)
else
::File.join(dir, @wiki.page_file_name(name, format))
end
path = path.force_encoding('ascii-8bit') if path.respond_to?(:force_encoding)
Dir.chdir(::File.join(@wiki.repo.path, '..')) do
if file_path_scheduled_for_deletion?(index.tree, path)
@wiki.repo.git.rm(path, :force => true)
else
@wiki.repo.git.checkout(path, 'HEAD')
end
end
end
end
# Writes the commit to Git and runs the after_commit callbacks.
#
# Returns the String SHA1 of the new commit.
def commit
sha1 = index.commit(@options[:message], parents, actor, nil, @wiki.ref)
@callbacks.each do |cb|
cb.call(self, sha1)
end
sha1
end
# Adds a callback to be fired after a commit.
#
# block - A block that expects this Committer instance and the created
# commit's SHA1 as the arguments.
#
# Returns nothing.
def after_commit(&block)
@callbacks << block
end
# Determine if a given page (regardless of format) is scheduled to be
# deleted in the next commit for the given Index.
#
# map - The Hash map:
# key - The String directory or filename.
# val - The Hash submap or the String contents of the file.
# path - The String path of the page file. This may include the format
# extension in which case it will be ignored.
#
# Returns the Boolean response.
def page_path_scheduled_for_deletion?(map, path)
parts = path.split('/')
if parts.size == 1
deletions = map.keys.select { |k| !map[k] }
downfile = parts.first.downcase.sub(/\.\w+$/, '')
deletions.any? { |d| d.downcase.sub(/\.\w+$/, '') == downfile }
else
part = parts.shift
if (rest = map[part])
page_path_scheduled_for_deletion?(rest, parts.join('/'))
else
false
end
end
end
# Determine if a given file is scheduled to be deleted in the next commit
# for the given Index.
#
# map - The Hash map:
# key - The String directory or filename.
# val - The Hash submap or the String contents of the file.
# path - The String path of the file including extension.
#
# Returns the Boolean response.
def file_path_scheduled_for_deletion?(map, path)
parts = path.split('/')
if parts.size == 1
deletions = map.keys.select { |k| !map[k] }
deletions.any? { |d| d == parts.first }
else
part = parts.shift
if (rest = map[part])
file_path_scheduled_for_deletion?(rest, parts.join('/'))
else
false
end
end
end
# Proxies methods t
def method_missing(name, *args)
args.map! { |item| item.respond_to?(:force_encoding) ? item.force_encoding('ascii-8bit') : item }
index.send(name, *args)
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/git_access.rb 0000644 0000041 0000041 00000015063 13172672532 021076 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
# Controls all access to the Git objects from Gollum. Extend this class to
# add custom caching for special cases.
class GitAccess
# Initializes the GitAccess instance.
#
# path - The String path to the Git repository that holds the
# Gollum site.
# page_file_dir - String the directory in which all page files reside
#
# Returns this instance.
def initialize(path, page_file_dir = nil, bare = nil)
@page_file_dir = page_file_dir
@path = path
@repo = Gollum::Git::Repo.new(path, { :is_bare => bare })
clear
end
# Public: Determines whether the Git repository exists on disk.
#
# Returns true if it exists, or false.
def exist?
@repo.git.exist?
end
# Public: Converts a given Git reference to a SHA, using the cache if
# available.
#
# ref - a String Git reference (ex: "master")
#
# Returns a String, or nil if the ref isn't found.
def ref_to_sha(ref)
ref = ref.to_s
return if ref.empty?
sha =
if sha?(ref)
ref
else
get_cache(:ref, ref) { ref_to_sha!(ref) }
end.to_s
sha.empty? ? nil : sha
end
# Public: Gets a recursive list of Git blobs for the whole tree at the
# given commit.
#
# ref - A String Git reference or Git SHA to a commit.
#
# Returns an Array of BlobEntry instances.
def tree(ref)
if (sha = ref_to_sha(ref))
get_cache(:tree, sha) { tree!(sha) }
else
[]
end
end
# Public: Fetches the contents of the Git blob at the given SHA.
#
# sha - A String Git SHA.
#
# Returns the String content of the blob.
def blob(sha)
cat_file!(sha)
end
# Public: Looks up the Git commit using the given Git SHA or ref.
#
# ref - A String Git SHA or ref.
#
# Returns a Gollum::Git::Commit.
def commit(ref)
if sha?(ref)
get_cache(:commit, ref) { commit!(ref) }
else
if (sha = get_cache(:ref, ref))
commit(sha)
else
if (cm = commit!(ref))
set_cache(:ref, ref, cm.id)
set_cache(:commit, cm.id, cm)
end
end
end
end
# Public: Clears all of the cached data that this GitAccess is tracking.
#
# Returns nothing.
def clear
@ref_map = {}
@tree_map = {}
@commit_map = {}
end
# Public: Refreshes just the cached Git reference data. This should
# be called after every Gollum update.
#
# Returns nothing.
def refresh
@ref_map.clear
end
#########################################################################
#
# Internal Methods
#
#########################################################################
# Gets the String path to the Git repository.
attr_reader :path
# Gets the Gollum::Git::Repo instance for the Git repository.
attr_reader :repo
# Gets a Hash cache of refs to commit SHAs.
#
# {"master" => "abc123", ...}
#
attr_reader :ref_map
# Gets a Hash cache of commit SHAs to a recursive tree of blobs.
#
# {"abc123" => [, ]}
#
attr_reader :tree_map
# Gets a Hash cache of commit SHAs to the Gollum::Git::Commit instance.
#
# {"abcd123" => }
#
attr_reader :commit_map
# Checks to see if the given String is a 40 character hex SHA.
#
# str - Possible String SHA.
#
# Returns true if the String is a SHA, or false.
def sha?(str)
!!(str =~ /^[0-9a-f]{40}$/)
end
# Looks up the Git SHA for the given Git ref.
#
# ref - String Git ref.
#
# Returns a String SHA.
def ref_to_sha!(ref)
commit = @repo.commit(ref)
commit ? commit.id : nil
end
# Looks up the Git blobs for a given commit.
#
# sha - String commit SHA.
#
# Returns an Array of BlobEntry instances.
def tree!(sha)
tree = @repo.lstree(sha, { :recursive => true })
items = []
tree.each do |entry|
if entry[:type] == 'blob'
items << BlobEntry.new(entry[:sha], entry[:path], entry[:size], entry[:mode].to_i(8))
end
end
if (dir = @page_file_dir)
regex = /^#{dir}\//
items.select { |i| i.path =~ regex }
else
items
end
end
# Reads the content from the Git db at the given SHA.
#
# sha - The String SHA.
#
# Returns the String content of the Git object.
def cat_file!(sha)
@repo.git.cat_file({ :p => true }, sha)
end
# Reads a Git commit.
#
# sha - The string SHA of the Git commit.
#
# Returns a Gollum::Git::Commit.
def commit!(sha)
@repo.commit(sha)
end
# Attempts to get the given data from a cache. If it doesn't exist, it'll
# pass the results of the yielded block to the cache for future accesses.
#
# name - The cache prefix used in building the full cache key.
# key - The unique cache key suffix, usually a String Git SHA.
#
# Yields a block to pass to the cache.
# Returns the cached result.
def get_cache(name, key)
cache = instance_variable_get("@#{name}_map")
value = cache[key]
if value.nil? && block_given?
set_cache(name, key, value = yield)
end
value == :_nil ? nil : value
end
# Writes some data to the internal cache.
#
# name - The cache prefix used in building the full cache key.
# key - The unique cache key suffix, usually a String Git SHA.
# value - The value to write to the cache.
#
# Returns nothing.
def set_cache(name, key, value)
cache = instance_variable_get("@#{name}_map")
cache[key] = value || :_nil
end
# Parses a line of output from the `ls-tree` command.
#
# line - A String line of output:
# "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
#
# Returns an Array of BlobEntry instances.
def parse_tree_line(line)
mode, _type, sha, size, *name = line.split(/\s+/)
BlobEntry.new(sha, name.join(' '), size.to_i, mode.to_i(8))
end
# Decode octal sequences (\NNN) in tree path names.
#
# path - String path name.
#
# Returns a decoded String.
def decode_git_path(path)
if path[0] == ?" && path[-1] == ?"
path = path[1...-1]
path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
end
path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m}")) }
path
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/macro/ 0000755 0000041 0000041 00000000000 13172672532 017541 5 ustar www-data www-data gollum-lib-4.2.7/lib/gollum-lib/macro/global_toc.rb 0000644 0000041 0000041 00000000624 13172672532 022175 0 ustar www-data www-data module Gollum
class Macro
class GlobalTOC < Gollum::Macro
def render(title = "Global Table of Contents")
if @wiki.pages.size > 0
result = '' + @wiki.pages.map { |p| "- #{p.url_path_display}
" }.join + '
'
end
"#{title}#{result}"
end
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/macro/series.rb 0000644 0000041 0000041 00000003465 13172672532 021370 0 ustar www-data www-data module Gollum
class Macro
class Series < Gollum::Macro
def render(series_prefix = "")
raise "This page's name does not match the prefix '#{series_prefix}'" unless @page.name =~ /^#{series_prefix}/
render_links(*find_series(series_prefix))
end
def render_links(previous_page, next_page)
result = "Previous: #{previous_page.name}" if previous_page
result = "#{result}#{result ? ' | ' : ''}Next: #{next_page.name}" if next_page
wrap_result(result)
end
def wrap_result(result)
result.nil? ? "" : "#{result}"
end
def find_series(series_prefix = "")
dir = @wiki.pages.select {|page| ::File.dirname(page.path) == ::File.dirname(@page.path)}
dir.select! {|page| page.name =~ /\A#{series_prefix}/ } unless series_prefix.empty?
dir.sort_by! {|page| page.name}
self_index = dir.find_index {|page| page.name == @page.name}
if self_index > 0
return dir[self_index-1], dir[self_index+1]
else
return nil, dir[self_index+1]
end
end
end
class SeriesStart < Gollum::Macro::Series
def render_links(previous_page, next_page)
result = "Next: #{next_page.name}" if next_page
wrap_result(result)
end
end
class SeriesEnd < Gollum::Macro::Series
def render_links(previous_page, next_page)
result = "Previous: #{previous_page.name}" if previous_page
wrap_result(result)
end
end
end
end gollum-lib-4.2.7/lib/gollum-lib/macro/all_pages.rb 0000644 0000041 0000041 00000000362 13172672532 022016 0 ustar www-data www-data module Gollum
class Macro
class AllPages < Gollum::Macro
def render
if @wiki.pages.size > 0
'' + @wiki.pages.map { |p| "- #{p.name}
" }.join + '
'
end
end
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/macro/navigation.rb 0000644 0000041 0000041 00000001335 13172672532 022227 0 ustar www-data www-data module Gollum
class Macro
class Navigation < Gollum::Macro
def render(title = "Navigate in the TOC", toc_root_path = ::File.dirname(@page.path), full_path = false)
if @wiki.pages.size > 0
list_items = @wiki.pages.map do |page|
if page.url_path.start_with?(toc_root_path)
path_display = full_path ? page.url_path_display : page.url_path_display.sub(toc_root_path.gsub("-", " "), "").sub(/^\//,'')
"#{path_display} "
end
end
result = "#{list_items.join}
"
end
"#{title}#{result}"
end
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/gitcode.rb 0000644 0000041 0000041 00000003022 13172672532 020400 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
require 'net/http'
require 'net/https' # ruby 1.8.7 fix, remove at upgrade
require 'uri'
require 'open-uri'
module Gollum
class Gitcode
def initialize(path)
raise(ArgumentError, 'path is nil or empty') if path.nil? or path.empty?
@uri = URI::HTTP.build({
:path => self.unchomp(path),
:host => 'raw.github.com',
:scheme => 'https',
:port => 443 })
end
def contents
@contents ||= self.req @uri
end
def unchomp(p)
return p if p.nil?
p[0] == '/' ? p : ('/' + p)
end
def req(uri, cut = 1)
return "Too many redirects or retries" if cut >= 10
http = Net::HTTP.new uri.host, uri.port
http.use_ssl = true
resp = http.get uri.path, {
'Accept' => 'text/plain',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
'Host' => uri.host,
'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0'
}
code = resp.code.to_i
return resp.body if code == 200
return "Not Found" if code == 404
return "Unhandled Response Code #{code}" unless code == 304 or not resp.header['location'].nil?
loc = URI.parse resp.header['location']
uri2 = loc.relative?() ? (uri + loc) : loc # overloads (+)
return req uri2, (cut + 1)
end
end
end
gollum-lib-4.2.7/lib/gollum-lib/markups.rb 0000644 0000041 0000041 00000001357 13172672532 020455 0 ustar www-data www-data # ~*~ encoding: utf-8 ~*~
module Gollum
class Markup
GitHub::Markup::Markdown::MARKDOWN_GEMS['kramdown'] = proc { |content|
Kramdown::Document.new(content, :auto_ids => false, :input => "markdown").to_html
}
register(:markdown, "Markdown", :regexp => /md|mkdn?|mdown|markdown/)
register(:textile, "Textile")
register(:rdoc, "RDoc")
register(:org, "Org-mode")
register(:creole, "Creole", :reverse_links => true)
register(:rest, "reStructuredText", :regexp => /re?st(\.txt)?/)
register(:asciidoc, "AsciiDoc")
register(:mediawiki, "MediaWiki", :regexp => /(media)?wiki/, :reverse_links => true)
register(:pod, "Pod")
register(:txt, "Plain Text")
end
end gollum-lib-4.2.7/docs/ 0000755 0000041 0000041 00000000000 13172672532 014557 5 ustar www-data www-data gollum-lib-4.2.7/docs/sanitization.md 0000644 0000041 0000041 00000002422 13172672532 017615 0 ustar www-data www-data Sanitization Rules
==================
Gollum uses the [Sanitize](http://wonko.com/post/sanitize) gem for HTML
sanitization.
See `lib/gollum-lib/sanitization.rb` for actual settings.
## ALLOWED TAGS
a, abbr, acronym, address, area, b, big, blockquote, br, button, caption,
center, cite, code, col, colgroup, dd, del, dfn, dir, div, dl, dt, em,
fieldset, font, form, h1, h2, h3, h4, h5, h6, hr, i, img, input, ins, kbd,
label, legend, li, map, menu, ol, optgroup, option, p, pre, q, s, samp,
select, small, span, strike, strong, sub, sup, table, tbody, td, textarea,
tfoot, th, thead, tr, tt, u, ul, var
## ALLOWED ATTRIBUTES
abbr, accept, accept-charset, accesskey, action, align, alt, axis, border,
cellpadding, cellspacing, char, charoff, charset, checked, cite, class, clear,
cols, colspan, color, compact, coords, datetime, dir, disabled, enctype, for,
frame, headers, height, href, hreflang, hspace, id, ismap, label, lang,
longdesc, maxlength, media, method, multiple, name, nohref, noshade, nowrap,
prompt, readonly, rel, rev, rows, rowspan, rules, scope, selected, shape,
size, span, src, start, summary, tabindex, target, title, type, usemap,
valign, value, vspace, width
## ALLOWED PROTOCOLS
a href: http, https, mailto, ftp, irc, apt
img src: http, https
form action: http, https
gollum-lib-4.2.7/licenses/ 0000755 0000041 0000041 00000000000 13172672532 015434 5 ustar www-data www-data gollum-lib-4.2.7/licenses/licenses.txt 0000644 0000041 0000041 00000000623 13172672532 020003 0 ustar www-data www-data For gollum code, everything should fall under the existing MIT License.
Alternative permissive licenses (such as BSD) for 3rd party dependencies are
acceptable. For image assets in Gollum, CC BY or CC BY-SA is fine. Anything
released under a copyleft license (for example GPL, AGPL, LGPL, MPL, EPL,
etc.) is not permitted in gollum. Public domain, CC BY or CC BY-SA for code in
gollum is not permitted.
gollum-lib-4.2.7/LICENSE 0000644 0000041 0000041 00000002100 13172672532 014625 0 ustar www-data www-data (The MIT License)
Copyright (c) Tom Preston-Werner, Rick Olson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
gollum-lib-4.2.7/gemspec.rb 0000644 0000041 0000041 00000007607 13172672532 015611 0 ustar www-data www-data def specification(version, default_adapter, platform = nil)
Proc.new do |s|
s.specification_version = 2 if s.respond_to? :specification_version=
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
s.rubygems_version = '0.0.1'
s.required_ruby_version = '>= 1.9'
s.name = 'gollum-lib'
s.version = version
s.platform = platform if platform
s.date = '2017-07-31'
s.rubyforge_project = 'gollum-lib'
s.license = 'MIT'
s.summary = 'A simple, Git-powered wiki.'
s.description = 'A simple, Git-powered wiki with a sweet API and local frontend.'
s.authors = ['Tom Preston-Werner', 'Rick Olson']
s.email = 'tom@github.com'
s.homepage = 'http://github.com/gollum/gollum-lib'
s.require_paths = %w(lib)
s.rdoc_options = ['--charset=UTF-8']
s.extra_rdoc_files = %w(README.md LICENSE)
s.add_dependency *default_adapter
s.add_dependency 'rouge', '~> 2.1'
if RUBY_VERSION < '2.1'
s.add_dependency 'nokogiri', '~> 1.6.1'
else
s.add_dependency 'nokogiri', '>= 1.6.1', '< 2.0'
end
s.add_dependency 'stringex', '~> 2.6'
s.add_dependency 'sanitize', '~> 2.1'
s.add_dependency 'github-markup', '~> 1.6'
s.add_dependency 'gemojione', '~> 3.2'
s.add_development_dependency 'org-ruby', '~> 0.9.9'
s.add_development_dependency 'kramdown', '~> 1.6.0'
s.add_development_dependency 'RedCloth', '~> 4.2.9'
s.add_development_dependency 'mocha', '~> 1.1.0'
s.add_development_dependency 'shoulda', '~> 3.5.0'
s.add_development_dependency 'wikicloth', '~> 0.8.3'
s.add_development_dependency 'rake', '~> 10.4.0'
s.add_development_dependency 'pry', '~> 0.10.1'
# required by pry
s.add_development_dependency 'rb-readline', '~> 0.5.1'
# updating minitest-reporters requires a new minitest which fails with gollum's tests.
s.add_development_dependency 'test-unit', '~> 3.1.5'
s.add_development_dependency 'minitest-reporters', '~> 0.14.16'
s.add_development_dependency 'nokogiri-diff', '~> 0.2.0'
# required by guard
s.add_development_dependency 'guard', '~> 2.8.2'
s.add_development_dependency 'guard-minitest', '~> 2.3.2'
s.add_development_dependency 'rb-inotify', '~> 0.9.3'
s.add_development_dependency 'rb-fsevent', '~> 0.9.4'
s.add_development_dependency 'rb-fchange', '~> 0.0.6'
s.add_development_dependency 'twitter_cldr', '~> 3.1.0'
# = MANIFEST =
s.files = %w(
Gemfile
HISTORY.md
LICENSE
README.md
Rakefile
docs/sanitization.md
gemspec.rb
gollum-lib.gemspec
gollum-lib_java.gemspec
lib/gollum-lib.rb
lib/gollum-lib/blob_entry.rb
lib/gollum-lib/committer.rb
lib/gollum-lib/file.rb
lib/gollum-lib/file_view.rb
lib/gollum-lib/filter.rb
lib/gollum-lib/filter/code.rb
lib/gollum-lib/filter/emoji.rb
lib/gollum-lib/filter/macro.rb
lib/gollum-lib/filter/metadata.rb
lib/gollum-lib/filter/plain_text.rb
lib/gollum-lib/filter/plantuml.rb
lib/gollum-lib/filter/remote_code.rb
lib/gollum-lib/filter/render.rb
lib/gollum-lib/filter/sanitize.rb
lib/gollum-lib/filter/tags.rb
lib/gollum-lib/filter/toc.rb
lib/gollum-lib/filter/wsd.rb
lib/gollum-lib/git_access.rb
lib/gollum-lib/gitcode.rb
lib/gollum-lib/helpers.rb
lib/gollum-lib/hook.rb
lib/gollum-lib/macro.rb
lib/gollum-lib/macro/all_pages.rb
lib/gollum-lib/macro/global_toc.rb
lib/gollum-lib/macro/navigation.rb
lib/gollum-lib/macro/series.rb
lib/gollum-lib/markup.rb
lib/gollum-lib/markups.rb
lib/gollum-lib/page.rb
lib/gollum-lib/pagination.rb
lib/gollum-lib/sanitization.rb
lib/gollum-lib/version.rb
lib/gollum-lib/wiki.rb
licenses/licenses.txt
)
# = MANIFEST =
s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
end
end
gollum-lib-4.2.7/README.md 0000644 0000041 0000041 00000016656 13172672532 015124 0 ustar www-data www-data gollum lib -- A wiki built on top of Git
========================================
[](http://badge.fury.io/rb/gollum-lib)
[](https://travis-ci.org/gollum/gollum-lib)
[](https://gemnasium.com/gollum/gollum-lib)
## DESCRIPTION
[Gollum](https://github.com/gollum/gollum) is a simple wiki system built on
top of Git that powers GitHub Wikis.
Gollum-lib is the Ruby API that allows you to retrieve raw or formatted wiki
content from a Git repository, write new content to the repository, and collect
various meta data about the wiki as a whole.
Gollum-lib follows the rules of [Semantic Versioning](http://semver.org/) and uses
[TomDoc](http://tomdoc.org/) for inline documentation.
## SYSTEM REQUIREMENTS
- Ruby 1.9.3+ (>2.0 recommended)
- Unix like operating system (OS X, Ubuntu, Debian, and more)
- Will not work on Windows with the default [grit](https://github.com/github/grit) adapter, but might work via JRuby (please let us know!)
## INSTALLATION
The best way to install Gollum-lib is with RubyGems:
```bash
$ [sudo] gem install gollum-lib
```
If you're installing from source, you can use [Bundler][bundler] to pick up all the
gems:
```bash
$ bundle install
```
In order to use the various formats that Gollum supports, you will need to
separately install the necessary dependencies for each format. You only need
to install the dependencies for the formats that you plan to use.
* [AsciiDoc](http://www.methods.co.nz/asciidoc/) -- `gem install asciidoctor`
* [Creole](http://wikicreole.org/) -- `gem install creole`
* [Markdown](http://daringfireball.net/projects/markdown/) -- `gem install redcarpet`
* [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) -- `gem install github-markdown`
* [Org](http://orgmode.org/) -- `gem install org-ruby`
* [Pod](http://search.cpan.org/dist/perl/pod/perlpod.pod) -- `Pod::Simple::HTML` comes with Perl >= 5.10. Lower versions should install Pod::Simple from CPAN.
* [RDoc](http://rdoc.sourceforge.net/)
* [ReStructuredText](http://docutils.sourceforge.net/rst.html) -- `easy_install docutils`
* [Textile](http://www.textism.com/tools/textile/) -- `gem install RedCloth`
* [MediaWiki](http://www.mediawiki.org/wiki/Help:Formatting) -- `gem install wikicloth`
[bundler]: http://gembundler.com/
## SYNTAX
Gollum supports a variety of formats and extensions (Markdown, MediaWiki, Textile, …).
On top of these formats Gollum lets you insert headers, footers, links, image, math and more.
Check out the [Gollum Wiki](https://github.com/gollum/gollum/wiki) for all of Gollum's formats and syntactic options.
## API DOCUMENTATION
Initialize the `Gollum::Repo` object:
```ruby
# Require rubygems if necessary
require 'rubygems'
# Require the Gollum library
require 'gollum-lib'
# Create a new Gollum::Wiki object by initializing it with the path to the
# Git repository.
wiki = Gollum::Wiki.new("my-gollum-repo.git")
# =>
```
By default, internal wiki links are all absolute from the root. To specify a different
base path, you can specify the `:base_path` option:
```ruby
wiki = Gollum::Wiki.new("my-gollum-repo.git", :base_path => "/wiki")
```
Note that `base_path` just modifies the links.
Get the latest version of the given human or canonical page name:
```ruby
page = wiki.page('page-name')
# =>
page.raw_data
# => "# My wiki page"
page.formatted_data
# => "My wiki page
"
page.format
# => :markdown
vsn = page.version
# =>
vsn.id
# => '3ca43e12377ea1e32ea5c9ce5992ec8bf266e3e5'
```
Get the footer (if any) for a given page:
```ruby
page.footer
# =>
```
Get the header (if any) for a given page:
```ruby
page.header
# =>
```
Get a list of versions for a given page:
```ruby
vsns = wiki.page('page-name').versions
# => []
vsns.first.id
# => '3ca43e12377ea1e32ea5c9ce5992ec8bf266e3e5'
vsns.first.authored_date
# => Sun Mar 28 19:11:21 -0700 2010
```
Get a specific version of a given canonical page file:
```ruby
wiki.page('page-name', '5ec521178e0eec4dc39741a8978a2ba6616d0f0a')
```
Get the latest version of a given static file:
```ruby
file = wiki.file('asset.js')
# =>
file.raw_data
# => "alert('hello');"
file.version
# =>
```
Get a specific version of a given static file:
```ruby
wiki.file('asset.js', '5ec521178e0eec4dc39741a8978a2ba6616d0f0a')
```
Get an in-memory Page preview (useful for generating previews for web
interfaces):
```ruby
preview = wiki.preview_page("My Page", "# Contents", :markdown)
preview.formatted_data
# => "Contents
"
```
Methods that write to the repository require a Hash of commit data that takes
the following form:
```ruby
commit = { :message => 'commit message',
:name => 'Tom Preston-Werner',
:email => 'tom@github.com' }
```
Write a new version of a page (the file will be created if it does not already
exist) and commit the change. The file will be written at the repo root.
```ruby
wiki.write_page('Page Name', :markdown, 'Page contents', commit)
```
Update an existing page. If the format is different than the page's current
format, the file name will be changed to reflect the new format.
```ruby
page = wiki.page('Page Name')
wiki.update_page(page, page.name, page.format, 'Page contents', commit)
```
To delete a page and commit the change:
```ruby
wiki.delete_page(page, commit)
```
Register or unregister a hook to be called after a page commit:
```ruby
Gollum::Hook.register(:post_commit, :hook_id) do |committer, sha1|
# Your code here
end
Gollum::Hook.unregister(:post_commit, :hook_id)
```
## WINDOWS FILENAME VALIDATION
Note that filenames on windows must not contain any of the following characters `\ / : * ? " < > |`. See [this support article](http://support.microsoft.com/kb/177506) for details.
## CONTRIBUTE
If you'd like to hack on Gollum-lib, start by forking the repo on GitHub:
http://github.com/gollum/gollum-lib
To get all of the dependencies, install the gem first. The best way to get
your changes merged back into core is as follows:
1. Clone down your fork
1. Create a thoughtfully named topic branch to contain your change
1. Hack away
1. Add tests and make sure everything still passes by running `rake`
1. If you are adding new functionality, document it in the README
1. Do not change the version number, I will do that on my end
1. If necessary, rebase your commits into logical chunks, without errors
1. Push the branch up to GitHub
1. Send a pull request to the gollum/gollum-lib project.
## RELEASING
Gollum-lib uses [Semantic Versioning](http://semver.org/). Having `x.y.z` :
For z releases:
```bash
$ rake bump
$ rake release
```
For x.y releases:
```bash
$ rake gemspec
$ rake release
```
## BUILDING THE GEM FROM MASTER
```bash
$ gem uninstall -aIx gollum-lib
$ git clone https://github.com/gollum/gollum-lib.git
$ cd gollum-lib
gollum-lib$ rake build
gollum-lib$ rake install
```
## RUN THE TESTS
```bash
$ bundle install
$ bundle exec rake test
```
## WORK WITH TEST REPOS
An example of how to add a test file to the bare repository `lotr.git`.
```bash
$ mkdir tmp; cd tmp
$ git clone ../lotr.git/ .
Cloning into '.'...
done.
$ git log
$ echo "test" > test.md
$ git add . ; git commit -am "Add test"
$ git push ../lotr.git/ master
```