gollum-lib 5.0.a.4 → 5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +12 -7
  4. data/Rakefile +5 -5
  5. data/adapter_dependencies.rb +7 -0
  6. data/gemspec.rb +18 -10
  7. data/gollum-lib.gemspec +2 -6
  8. data/gollum-lib_java.gemspec +2 -2
  9. data/lib/gollum-lib.rb +9 -9
  10. data/lib/gollum-lib/blob_entry.rb +2 -8
  11. data/lib/gollum-lib/committer.rb +22 -60
  12. data/lib/gollum-lib/file.rb +105 -82
  13. data/lib/gollum-lib/file_view.rb +8 -4
  14. data/lib/gollum-lib/filter.rb +12 -0
  15. data/lib/gollum-lib/filter/code.rb +9 -13
  16. data/lib/gollum-lib/filter/critic_markup.rb +97 -0
  17. data/lib/gollum-lib/filter/emoji.rb +10 -8
  18. data/lib/gollum-lib/filter/macro.rb +5 -2
  19. data/lib/gollum-lib/filter/plantuml.rb +1 -1
  20. data/lib/gollum-lib/filter/remote_code.rb +3 -2
  21. data/lib/gollum-lib/filter/render.rb +25 -2
  22. data/lib/gollum-lib/filter/sanitize.rb +1 -8
  23. data/lib/gollum-lib/filter/tags.rb +57 -47
  24. data/lib/gollum-lib/filter/toc.rb +17 -21
  25. data/lib/gollum-lib/filter/yaml.rb +1 -1
  26. data/lib/gollum-lib/git_access.rb +0 -25
  27. data/lib/gollum-lib/helpers.rb +13 -3
  28. data/lib/gollum-lib/macro/audio.rb +9 -0
  29. data/lib/gollum-lib/macro/global_toc.rb +2 -1
  30. data/lib/gollum-lib/macro/navigation.rb +8 -6
  31. data/lib/gollum-lib/macro/note.rb +19 -0
  32. data/lib/gollum-lib/macro/octicon.rb +12 -0
  33. data/lib/gollum-lib/macro/warn.rb +11 -0
  34. data/lib/gollum-lib/markup.rb +17 -32
  35. data/lib/gollum-lib/markups.rb +11 -7
  36. data/lib/gollum-lib/page.rb +79 -165
  37. data/lib/gollum-lib/pagination.rb +7 -6
  38. data/lib/gollum-lib/redirects.rb +38 -0
  39. data/lib/gollum-lib/sanitization.rb +32 -357
  40. data/lib/gollum-lib/version.rb +1 -1
  41. data/lib/gollum-lib/wiki.rb +216 -404
  42. metadata +73 -28
  43. data/ROADMAP +0 -6
@@ -21,15 +21,14 @@ class Gollum::Filter::TOC < Gollum::Filter
21
21
  next if (i == 0 && header.name =~ /[Hh]1/) && @markup.wiki && @markup.wiki.h1_title
22
22
 
23
23
  anchor_name = generate_anchor_name(header)
24
-
25
24
  add_anchor_to_header header, anchor_name
26
25
  add_entry_to_toc header, anchor_name
27
26
  end
28
27
  if not @toc_doc.nil?
29
- toc_str = @toc_doc.to_xml(@markup.to_xml_opts)
28
+ toc_str = @toc_doc.to_xml(@markup.class.to_xml_opts)
30
29
  end
31
30
 
32
- data = @doc.to_xml(@markup.to_xml_opts)
31
+ data = @doc.to_xml(@markup.class.to_xml_opts)
33
32
  end
34
33
 
35
34
  @markup.toc = toc_str
@@ -51,7 +50,7 @@ class Gollum::Filter::TOC < Gollum::Filter
51
50
  e.remove
52
51
  end
53
52
  end
54
- toc_clone.to_xml(@markup.to_xml_opts)
53
+ toc_clone.to_xml(@markup.class.to_xml_opts)
55
54
  end
56
55
  end
57
56
 
@@ -60,9 +59,9 @@ class Gollum::Filter::TOC < Gollum::Filter
60
59
 
61
60
  private
62
61
 
63
- # Generates the anchor name from the given header element
62
+ # Generates the anchor name from the given header element
64
63
  # removing all non alphanumeric characters, replacing them
65
- # with single dashes.
64
+ # with single dashes.
66
65
  #
67
66
  # Generates heading ancestry prefixing the headings
68
67
  # ancestor names to the generated name.
@@ -70,31 +69,28 @@ class Gollum::Filter::TOC < Gollum::Filter
70
69
  # Prefixes duplicate anchors with an index
71
70
  def generate_anchor_name(header)
72
71
  name = header.content
73
- level = header.name.gsub(/[hH]/, '').to_i
72
+ level = header.name[1..-1].to_i
74
73
 
75
74
  # normalize the header name
76
- name.gsub!(/[^\d\w\u00C0-\u1FFF\u2C00-\uD7FF]/, "-")
77
- name.gsub!(/-+/, "-")
78
- name.gsub!(/^-/, "")
79
- name.gsub!(/-$/, "")
75
+ name.gsub!(/[^\d\w\u00C0-\u1FFF\u2C00-\uD7FF]/, '-')
76
+ name.gsub!(/-+/, '-')
77
+ name.gsub!(/^-/, '')
78
+ name.gsub!(/-$/, '')
80
79
  name.downcase!
81
80
 
82
- @current_ancestors[level - 1] = name
83
- @current_ancestors = @current_ancestors.take(level)
84
- anchor_name = @current_ancestors.compact.join("_")
85
-
86
81
  # Ensure duplicate anchors have a unique prefix or the toc will break
87
- index = increment_anchor_index(anchor_name)
88
- anchor_name = "#{index}-#{anchor_name}" unless index.zero? # if the index is zero this name is unique
89
-
90
- anchor_name
82
+ index = increment_anchor_index(name)
83
+ index.zero? ? name : "#{name}-#{index}"
91
84
  end
92
85
 
93
86
  # Creates an anchor element with the given name and adds it before
94
87
  # the given header element.
95
88
  def add_anchor_to_header(header, name)
96
- anchor_element = %Q(<a class="anchor" id="#{name}" href="##{name}"><i class="fa fa-link"></i></a>)
97
- header.children.before anchor_element # Add anchor element before the header
89
+ a = Nokogiri::XML::Node.new('a', @doc)
90
+ a['class'] = 'anchor'
91
+ a['id'] = name
92
+ a['href'] = "##{name}"
93
+ header.children.before(a) # Add anchor element before the header
98
94
  end
99
95
 
100
96
  # Adds an entry to the TOC for the given header. The generated entry
@@ -10,7 +10,7 @@ class Gollum::Filter::YAML < Gollum::Filter
10
10
  data.gsub!(YAML_FRONT_MATTER_REGEXP) do
11
11
  @markup.metadata ||= {}
12
12
  begin
13
- frontmatter = ::YAML.safe_load(@markup.sanitize.clean(Regexp.last_match[1]))
13
+ frontmatter = ::YAML.safe_load(sanitize(Regexp.last_match[1]))
14
14
  @markup.metadata.merge!(frontmatter) if frontmatter.respond_to?(:keys) && frontmatter.respond_to?(:values)
15
15
  rescue ::Psych::SyntaxError, ::Psych::DisallowedClass, ::Psych::BadAlias => error
16
16
  @markup.metadata['errors'] ||= []
@@ -218,30 +218,5 @@ module Gollum
218
218
  cache = instance_variable_get("@#{name}_map")
219
219
  cache[key] = value || :_nil
220
220
  end
221
-
222
- # Parses a line of output from the `ls-tree` command.
223
- #
224
- # line - A String line of output:
225
- # "100644 blob 839c2291b30495b9a882c17d08254d3c90d8fb53 Home.md"
226
- #
227
- # Returns an Array of BlobEntry instances.
228
- def parse_tree_line(line)
229
- mode, _type, sha, size, *name = line.split(/\s+/)
230
- BlobEntry.new(sha, name.join(' '), size.to_i, mode.to_i(8))
231
- end
232
-
233
- # Decode octal sequences (\NNN) in tree path names.
234
- #
235
- # path - String path name.
236
- #
237
- # Returns a decoded String.
238
- def decode_git_path(path)
239
- if path[0] == ?" && path[-1] == ?"
240
- path = path[1...-1]
241
- path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
242
- end
243
- path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m}")) }
244
- path
245
- end
246
221
  end
247
222
  end
@@ -1,13 +1,23 @@
1
1
  # ~*~ encoding: utf-8 ~*~
2
+
2
3
  module Gollum
3
4
  module Helpers
4
-
5
- def trim_leading_slash(url)
6
- return url if url.nil?
5
+
6
+ # If url starts with a leading slash, trim down its number of leading slashes to 1. Else, return url unchanged.
7
+ def trim_leading_slashes(url)
8
+ return nil if url.nil?
7
9
  url.gsub!('%2F', '/')
8
10
  return '/' + url.gsub(/^\/+/, '') if url[0, 1] == '/'
9
11
  url
10
12
  end
13
+
14
+ # Take a link path and turn it into a string for display as link text.
15
+ # For example:
16
+ # '/opt/local/bin/ruby.ext' -> 'ruby'
17
+ def path_to_link_text(str)
18
+ return nil unless str
19
+ ::File.basename(str, ::File.extname(str))
20
+ end
11
21
 
12
22
  end
13
23
  end
@@ -0,0 +1,9 @@
1
+ module Gollum
2
+ class Macro
3
+ class Audio < Gollum::Macro
4
+ def render (fname)
5
+ "<audio width=\"100%\" height=\"100%\" src=\"#{fname}\" controls=\"\"> HTML5 audio is not supported on this Browser.</audio>"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -3,7 +3,8 @@ module Gollum
3
3
  class GlobalTOC < Gollum::Macro
4
4
  def render(title = "Global Table of Contents")
5
5
  if @wiki.pages.size > 0
6
- result = '<ul>' + @wiki.pages.map { |p| "<li><a href=\"/#{p.url_path}\">#{p.url_path}</a></li>" }.join + '</ul>'
6
+ prepath = @wiki.base_path.sub(/\/$/, '')
7
+ result = '<ul>' + @wiki.pages.map { |p| "<li><a href=\"#{prepath}/#{p.escaped_url_path}\">#{p.url_path}</a></li>" }.join + '</ul>'
7
8
  end
8
9
  "<div class=\"toc\"><div class=\"toc-title\">#{title}</div>#{result}</div>"
9
10
  end
@@ -2,12 +2,14 @@ module Gollum
2
2
  class Macro
3
3
  class Navigation < Gollum::Macro
4
4
 
5
- def render(title = "Navigate in the TOC", toc_root_path = ::File.dirname(@page.path), full_path = false)
6
- if @wiki.pages.size > 0
7
- list_items = @wiki.pages.map do |page|
8
- if page.url_path.start_with?(toc_root_path)
9
- path_display = full_path ? page.url_path_display : page.url_path.sub(toc_root_path,"").sub(/^\//,'')
10
- "<li><a href=\"/#{page.url_path}\">#{path_display}</a></li>"
5
+ def render(title = "Navigate this directory", toc_root_path = ::File.dirname(@page.url_path), full_path = false)
6
+ pages = @wiki.pages
7
+ if pages.size > 0
8
+ prepath=@wiki.base_path.sub(/\/$/, '')
9
+ list_items = pages.map do |page|
10
+ if toc_root_path == '.' || page.url_path =~ /^#{toc_root_path}\//
11
+ path_display = (full_path || toc_root_path == '.') ? page.url_path : page.url_path.sub(/^#{toc_root_path}\//,"").sub(/^\//,'')
12
+ "<li><a href=\"#{prepath}/#{page.escaped_url_path}\">#{path_display}</a></li>"
11
13
  end
12
14
  end
13
15
  result = "<ul>#{list_items.join}</ul>"
@@ -0,0 +1,19 @@
1
+ module Gollum
2
+ class Macro
3
+ class Note < Gollum::Macro
4
+ def render(notice, octicon = 'info')
5
+ icon = ""
6
+ unless octicon.empty?
7
+ begin
8
+ icon = Octicons::Octicon.new(octicon, {width: 24, height: 24})
9
+ rescue RuntimeError
10
+ icon = Octicons::Octicon.new('info', {width: 24, height: 24})
11
+ end
12
+ icon.options[:class] << ' mr-2'
13
+ icon = icon.to_svg
14
+ end
15
+ "<div class='flash'>#{icon}#{notice}</div>"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module Gollum
2
+ class Macro
3
+ class Octicon < Gollum::Macro
4
+ def render(symbol, height = nil, width = nil)
5
+ parameters = {}
6
+ parameters[:height] = height if height
7
+ parameters[:width] = width if width
8
+ "<div>#{Octicons::Octicon.new(symbol, parameters).to_svg}</div>"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Gollum
2
+ class Macro
3
+ class Warn < Gollum::Macro
4
+ def render(warning)
5
+ icon = Octicons::Octicon.new('alert', {width: 24, height: 24})
6
+ icon.options[:class] << ' mr-2'
7
+ "<div class='flash flash-warn'>#{icon.to_svg}#{warning}</div>"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,5 @@
1
1
  # ~*~ encoding: utf-8 ~*~
2
2
  require 'digest/sha1'
3
- require 'cgi'
4
3
  require 'rouge'
5
4
  require 'base64'
6
5
 
@@ -23,6 +22,10 @@ module Gollum
23
22
 
24
23
  class << self
25
24
 
25
+ def to_xml_opts
26
+ { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML ^ 1, :indent => 0, :encoding => 'UTF-8' }
27
+ end
28
+
26
29
  # Only use the formats that are specified in config.rb
27
30
  def formats
28
31
  if defined? Gollum::Page::FORMAT_NAMES
@@ -66,7 +69,6 @@ module Gollum
66
69
  attr_accessor :toc
67
70
  attr_accessor :metadata
68
71
  attr_reader :encoding
69
- attr_reader :sanitize
70
72
  attr_reader :format
71
73
  attr_reader :wiki
72
74
  attr_reader :page
@@ -74,8 +76,8 @@ module Gollum
74
76
  attr_reader :sub_page
75
77
  attr_reader :name
76
78
  attr_reader :include_levels
77
- attr_reader :to_xml_opts
78
79
  attr_reader :dir
80
+ attr_reader :historical
79
81
 
80
82
  # Initialize a new Markup object.
81
83
  #
@@ -91,9 +93,8 @@ module Gollum
91
93
  @sub_page = page.sub_page
92
94
  @parent_page = page.parent_page
93
95
  @page = page
94
- @dir = ::File.dirname(page.path)
96
+ @dir = ::File.dirname("/#{@page.url_path}")
95
97
  @metadata = nil
96
- @to_xml_opts = { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML ^ 1, :indent => 0, :encoding => 'UTF-8' }
97
98
  end
98
99
 
99
100
  # Whether or not this markup's format uses reversed-order links ([description | url] rather than [url | description]). Defaults to false.
@@ -124,6 +125,11 @@ module Gollum
124
125
  data = filter.extract(data)
125
126
  end
126
127
 
128
+ # Since the last 'extract' action in our chain *should* be the markup
129
+ # to HTML converter, we now have HTML which we can parse and yield, for
130
+ # anyone who wants it
131
+ yield Nokogiri::HTML::DocumentFragment.parse(data) if block_given?
132
+
127
133
  # Then we process the data through the chain *backwards*
128
134
  filter_chain.reverse.each do |filter|
129
135
  data = filter.process(data)
@@ -133,48 +139,27 @@ module Gollum
133
139
  end
134
140
 
135
141
  # Render the content with Gollum wiki syntax on top of the file's own
136
- # markup language.
142
+ # markup language. Takes an optional block that will be executed after
143
+ # the markup rendering step in the filter chain.
137
144
  #
138
145
  # no_follow - Boolean that determines if rel="nofollow" is added to all
139
146
  # <a> tags.
140
147
  # encoding - Encoding Constant or String.
141
148
  #
142
149
  # Returns the formatted String content.
143
- def render(no_follow = false, encoding = nil, include_levels = 10)
144
- @sanitize = no_follow ? @wiki.history_sanitizer : @wiki.sanitizer
145
-
150
+ def render(no_follow = false, encoding = nil, include_levels = 10, &block)
151
+ @historical = no_follow
146
152
  @encoding = encoding
147
153
  @include_levels = include_levels
148
154
 
149
- data = @data.dup
155
+ data = @data.dup
150
156
 
151
157
  filter_chain = @wiki.filter_chain.reject {|filter| skip_filter?(filter)}
152
158
  filter_chain.map! do |filter_sym|
153
159
  Gollum::Filter.const_get(filter_sym).new(self)
154
160
  end
155
161
 
156
- # Since the last 'extract' action in our chain *should* be the markup
157
- # to HTML converter, we now have HTML which we can parse and yield, for
158
- # anyone who wants it
159
- if block_given?
160
- yield Nokogiri::HTML::DocumentFragment.parse(data)
161
- end
162
-
163
- process_chain data, filter_chain
164
- end
165
-
166
- # Find the given file in the repo.
167
- #
168
- # name - The String absolute or relative path of the file.
169
- #
170
- # Returns the Gollum::File or nil if none was found.
171
- def find_file(name, version=@version)
172
- if name =~ /^\//
173
- @wiki.file(name[1..-1], version)
174
- else
175
- path = @dir == '.' ? name : ::File.join(@dir, name)
176
- @wiki.file(path, version)
177
- end
162
+ process_chain(data, filter_chain, &block)
178
163
  end
179
164
 
180
165
  # Hook for getting the formatted value of extracted tag data.
@@ -55,12 +55,16 @@ end
55
55
 
56
56
  module Gollum
57
57
  class Markup
58
- GitHub::Markup::Markdown::MARKDOWN_GEMS['kramdown'] = proc { |content|
59
- Kramdown::Document.new(content, :auto_ids => false, :smart_quotes => ["'", "'", '"', '"'].map{|char| char.codepoints.first}).to_html
60
- }
61
- GitHub::Markup::Markdown::MARKDOWN_GEMS['pandoc-ruby'] = proc { |content|
62
- PandocRuby.convert(content, :s, :from => :markdown, :to => :html, :filter => 'pandoc-citeproc')
63
- } if gem_exists?('pandoc-ruby')
58
+ if gem_exists?('pandoc-ruby')
59
+ GitHub::Markup::Markdown::MARKDOWN_GEMS.delete('kramdown')
60
+ GitHub::Markup::Markdown::MARKDOWN_GEMS['pandoc-ruby'] = proc { |content|
61
+ PandocRuby.convert(content, :from => :markdown, :to => :html, :filter => 'pandoc-citeproc')
62
+ }
63
+ else
64
+ GitHub::Markup::Markdown::MARKDOWN_GEMS['kramdown'] = proc { |content|
65
+ Kramdown::Document.new(content, :input => "GFM", :hard_wrap => 'false', :auto_ids => false, :math_engine => nil, :smart_quotes => ["'", "'", '"', '"'].map{|char| char.codepoints.first}).to_html
66
+ }
67
+ end
64
68
 
65
69
  # markdown, rdoc, and plain text are always supported.
66
70
  register(:markdown, "Markdown", :extensions => ['md','mkd','mkdn','mdown','markdown'])
@@ -76,7 +80,7 @@ module Gollum
76
80
  register(:creole, "Creole",
77
81
  :enabled => MarkupRegisterUtils::gem_exists?("creole"),
78
82
  :reverse_links => true)
79
- register(:rest, "reStructuredText",
83
+ register(:rst, "reStructuredText",
80
84
  :enabled => MarkupRegisterUtils::executable_exists?("python2"),
81
85
  :extensions => ['rest', 'rst'])
82
86
  register(:asciidoc, "AsciiDoc",
@@ -1,21 +1,28 @@
1
1
  # ~*~ encoding: utf-8 ~*~
2
2
  module Gollum
3
- class Page
3
+ class Page < Gollum::File
4
4
  include Pagination
5
-
6
- Wiki.page_class = self
7
5
 
8
6
  SUBPAGENAMES = [:header, :footer, :sidebar]
9
-
10
- # Sets a Boolean determing whether this page is a historical version.
11
- #
12
- # Returns nothing.
13
- attr_writer :historical
14
7
 
15
- # Parent page if this is a sub page
16
- #
17
- # Returns a Page
18
- attr_accessor :parent_page
8
+ class << self
9
+ # For use with self.find: returns true if the given query corresponds to the in-repo path of the BlobEntry.
10
+ #
11
+ # query - The String path to match.
12
+ # entry - The BlobEntry to check against.
13
+ # global_match - If true, find a File matching path's filename, but not its directory (so anywhere in the repo)
14
+ def path_match(query, entry, global_match = false, hyphened_tags = false, case_insensitive = false)
15
+ return false if "#{entry.name}".empty?
16
+ return false unless valid_extension?(entry.name)
17
+ entry_name = valid_extension?(query) ? entry.name : strip_filename(entry.name)
18
+ match_path = ::File.join([
19
+ '/',
20
+ global_match ? nil : entry.dir,
21
+ entry_name
22
+ ].compact)
23
+ path_compare(query, match_path, hyphened_tags, case_insensitive)
24
+ end
25
+ end
19
26
 
20
27
  # Checks if a filename has a valid, registered extension
21
28
  #
@@ -27,14 +34,14 @@ module Gollum
27
34
  end
28
35
 
29
36
  # Checks if a filename has a valid extension understood by GitHub::Markup.
30
- # Also, checks if the filename has no "_" in the front (such as
31
- # _Footer.md).
37
+ # Also, checks if the filename is subpages (such as _Footer.md).
32
38
  #
33
39
  # filename - String filename, like "Home.md".
34
40
  #
35
41
  # Returns true or false.
36
42
  def self.valid_page_name?(filename)
37
- !(filename =~ /^_/) && self.valid_extension?(filename)
43
+ subpage_names = SUBPAGENAMES.map(&:capitalize).join("|")
44
+ filename =~ /^_(#{subpage_names})/ ? false : self.valid_extension?(filename)
38
45
  end
39
46
 
40
47
  # Public: The format of a given filename.
@@ -59,32 +66,27 @@ module Gollum
59
66
  ::File.basename(filename.to_s, ::File.extname(filename.to_s))
60
67
  end
61
68
 
62
- # Public: Initialize a page.
69
+ # Public: Initialize a Page.
63
70
  #
64
- # wiki - The Gollum::Wiki in question.
71
+ # wiki - The Gollum::Wiki
72
+ # blob - The Gollum::Git::Blob
73
+ # path - The String path
74
+ # version - The String SHA or Gollum::Git::Commit version
75
+ # try_on_disk - If true, try to get an on disk reference for this page.
65
76
  #
66
77
  # Returns a newly initialized Gollum::Page.
67
- def initialize(wiki)
68
- @wiki = wiki
69
- @blob = nil
78
+ def initialize(wiki, blob, path, version, try_on_disk = false)
79
+ super
70
80
  @formatted_data = nil
71
81
  @doc = nil
72
82
  @parent_page = nil
83
+ @historical = @version.to_s == version.to_s
73
84
  end
74
85
 
75
- # Public: The SHA hash identifying this page
76
- #
77
- # Returns the String SHA.
78
- def sha
79
- @blob && @blob.id
80
- end
81
-
82
- # Public: The on-disk filename of the page including extension.
86
+ # Parent page if this is a sub page
83
87
  #
84
- # Returns the String name.
85
- def filename
86
- @blob && @blob.name
87
- end
88
+ # Returns a Page
89
+ attr_accessor :parent_page
88
90
 
89
91
  # Public: The on-disk filename of the page with extension stripped.
90
92
  #
@@ -105,7 +107,7 @@ module Gollum
105
107
  #
106
108
  # Returns the fully sanitized String title.
107
109
  def title
108
- Sanitize.clean(name).strip
110
+ @wiki.sanitizer.clean(name).strip
109
111
  end
110
112
 
111
113
  # Public: Determines if this is a sub-page
@@ -116,30 +118,11 @@ module Gollum
116
118
  filename =~ /^_/
117
119
  end
118
120
 
119
- # Public: The path of the page within the repo.
120
- #
121
- # Returns the String path.
122
- attr_reader :path
123
-
124
- # Public: The url path required to reach this page within the repo.
125
- #
126
- # Returns the String url_path
127
- def url_path
128
- construct_path(filename)
129
- end
130
-
131
121
  # Public: Defines title for page.rb
132
122
  #
133
123
  # Returns the String title
134
124
  def url_path_title
135
- metadata_title || construct_path(name)
136
- end
137
-
138
- # Public: The url_path, but CGI escaped.
139
- #
140
- # Returns the String url_path
141
- def escaped_url_path
142
- CGI.escape(self.url_path).gsub('%2F', '/')
125
+ metadata_title || name
143
126
  end
144
127
 
145
128
  # Public: Metadata title
@@ -148,35 +131,16 @@ module Gollum
148
131
  #
149
132
  # Returns the String title or nil if not defined
150
133
  def metadata_title
151
- if metadata
152
- title = metadata['title']
153
- return title unless title.nil?
154
- end
155
-
156
- nil
134
+ metadata ? metadata['title'] : nil
157
135
  end
158
136
 
159
137
  # Public: Whether or not to display the metadata
160
138
  def display_metadata?
161
- return false if metadata.empty? || (metadata.size == 1 && metadata['title'])
139
+ return false if (metadata.keys - ['title', 'header_enum']).empty?
162
140
  return false if metadata['display_metadata'] == false
163
141
  @wiki.display_metadata
164
142
  end
165
143
 
166
- # Public: The raw contents of the page.
167
- #
168
- # Returns the String data.
169
- def raw_data
170
- return nil unless @blob
171
-
172
- if !@wiki.repo.bare && @blob.is_symlink
173
- new_path = @blob.symlink_target(::File.join(@wiki.repo.path, '..', self.path))
174
- return IO.read(new_path) if new_path
175
- end
176
-
177
- @blob.data
178
- end
179
-
180
144
  # Public: A text data encoded in specified encoding.
181
145
  #
182
146
  # encoding - An Encoding or nil
@@ -225,8 +189,12 @@ module Gollum
225
189
  #
226
190
  # Returns Hash of metadata.
227
191
  def metadata
228
- formatted_data if markup.metadata == nil
229
- markup.metadata || {}
192
+ unless @metadata
193
+ formatted_data if markup.metadata == nil
194
+ @metadata = @wiki.metadata.merge(markup.metadata || {})
195
+ else
196
+ @metadata
197
+ end
230
198
  end
231
199
 
232
200
  # Public: The format of the page.
@@ -240,20 +208,15 @@ module Gollum
240
208
  #
241
209
  # Returns a Gollum::Markup instance.
242
210
  def markup
243
- @markup ||= @wiki.markup_classes[format].new(self)
211
+ @markup ||= ::Gollum::Markup.new(self)
244
212
  end
245
213
 
246
- # Public: The current version of the page.
247
- #
248
- # Returns the Gollum::Git::Commit.
249
- attr_reader :version
250
-
251
214
  # Public: All of the versions that have touched the Page.
252
215
  #
253
216
  # options - The options Hash:
254
- # :page - The Integer page number (default: 1).
255
- # :per_page - The Integer max count of items to return.
256
- # :follow - Follow's a file across renames, slower. (default: false)
217
+ # :page_num - The Integer page number (default: 1).
218
+ # :per_page - The Integer max count of items to return.
219
+ # :follow - Follow's a file across renames, slower. (default: false)
257
220
  #
258
221
  # Returns an Array of Gollum::Git::Commit.
259
222
  def versions(options = {})
@@ -317,77 +280,11 @@ module Gollum
317
280
  format == :markdown ? "md" : format.to_s
318
281
  end
319
282
 
320
- #########################################################################
321
- #
322
- # Internal Methods
323
- #
324
- #########################################################################
325
-
326
283
  # The underlying wiki repo.
327
284
  #
328
285
  # Returns the Gollum::Wiki containing the page.
329
286
  attr_reader :wiki
330
287
 
331
- # Set the Gollum::Git::Commit version of the page.
332
- #
333
- # Returns nothing.
334
- attr_writer :version
335
-
336
- # Find a page in the given Gollum repo.
337
- #
338
- # name - The human or canonical String page name to find.
339
- # version - The String version ID to find.
340
- #
341
- # Returns a Gollum::Page or nil if the page could not be found.
342
- def find(name, version, dir = nil, exact = false)
343
- map = @wiki.tree_map_for(version.to_s)
344
- if (page = find_page_in_tree(map, name, dir, exact))
345
- page.version = version.is_a?(Gollum::Git::Commit) ?
346
- version : @wiki.commit_for(version)
347
- page.historical = page.version.to_s == version.to_s
348
- page
349
- end
350
- rescue Gollum::Git::NoSuchShaFound
351
- end
352
-
353
- # Find a page in a given tree.
354
- #
355
- # map - The Array tree map from Wiki#tree_map.
356
- # name - The canonical String page name.
357
- # checked_dir - Optional String of the directory a matching page needs
358
- # to be in. The string should
359
- #
360
- # Returns a Gollum::Page or nil if the page could not be found.
361
- def find_page_in_tree(map, name, checked_dir = nil, exact = false)
362
- return nil if !map || name.to_s.empty?
363
-
364
- checked_dir = BlobEntry.normalize_dir(checked_dir)
365
- checked_dir = '' if exact && checked_dir.nil?
366
- query = checked_dir ? ::File.join(checked_dir, name) : name
367
-
368
- map.each do |entry|
369
- next if entry.name.to_s.empty? || !self.class.valid_extension?(entry.name)
370
- entry_name = ::File.extname(name).empty? ? ::Gollum::Page.strip_filename(entry.name) : entry.name
371
- path = checked_dir ? ::File.join(entry.dir, entry_name) : entry_name
372
- next unless query.downcase == path.downcase
373
- return entry.page(@wiki, @version)
374
- end
375
-
376
- return nil # nothing was found
377
- end
378
-
379
- # Populate the Page with information from the Blob.
380
- #
381
- # blob - The Gollum::Git::Blob that contains the info.
382
- # path - The String directory path of the page file.
383
- #
384
- # Returns the populated Gollum::Page.
385
- def populate(blob, path=nil)
386
- @blob = blob
387
- @path = "#{path}/#{blob.name}"[1..-1]
388
- self
389
- end
390
-
391
288
  # The full directory path for the given tree.
392
289
  #
393
290
  # treemap - The Hash treemap containing parentage information.
@@ -396,7 +293,7 @@ module Gollum
396
293
  # Returns the String path.
397
294
  def tree_path(treemap, tree)
398
295
  if (ptree = treemap[tree])
399
- tree_path(treemap, ptree) + '/' + tree.name
296
+ "#{tree_path(treemap, ptree)}#{::File::SEPARATOR}#{tree.name}"
400
297
  else
401
298
  ''
402
299
  end
@@ -409,7 +306,7 @@ module Gollum
409
306
  def find_sub_pages(subpagenames = SUBPAGENAMES, map = nil)
410
307
  subpagenames.each{|subpagename| instance_variable_set("@#{subpagename}", nil)}
411
308
  return nil if self.filename =~ /^_/ || ! self.version
412
-
309
+
413
310
  map ||= @wiki.tree_map_for(@wiki.ref, true)
414
311
  valid_names = subpagenames.map(&:capitalize).join("|")
415
312
  # From Ruby 2.2 onwards map.select! could be used
@@ -425,34 +322,51 @@ module Gollum
425
322
  searchpath = dir == Pathname.new('.') ? Pathname.new(filename) : dir + filename
426
323
  entrypath = ::Pathname.new(blob_entry.path)
427
324
  # Ignore extentions
428
- entrypath = entrypath.dirname + entrypath.basename(entrypath.extname)
325
+ entrypath = entrypath.dirname + entrypath.basename(entrypath.extname)
429
326
  entrypath == searchpath
430
327
  end
431
-
328
+
432
329
  if subpageblob
433
330
  instance_variable_set("@#{subpagename}", subpageblob.page(@wiki, @version) )
331
+ instance_variable_get("@#{subpagename}").parent_page = self
434
332
  break
435
333
  end
436
334
 
437
335
  break if dir == Pathname.new('.')
438
336
  end
439
- end
337
+ end
440
338
  end
441
339
 
442
340
  def inspect
443
341
  %(#<#{self.class.name}:#{object_id} #{name} (#{format}) @wiki=#{@wiki.repo.path.inspect}>)
444
342
  end
445
343
 
446
- private
344
+ end
447
345
 
448
- def construct_path(name)
449
- path = if self.path.include?('/')
450
- self.path.sub(/\/[^\/]+$/, '/')
451
- else
452
- ''
453
- end
454
- path << name
346
+ class PreviewPage < Gollum::Page
347
+ include Pagination
348
+
349
+ SUBPAGENAMES.each do |subpage|
350
+ define_method(subpage) do
351
+ instance_variable_get("@#{subpage}")
352
+ end
353
+ define_method("set_#{subpage}") do |val|
354
+ instance_variable_set("@#{subpage}", PreviewPage.new(@wiki, "_#{subpage.to_s.capitalize}.md", val, @version, self))
355
+ end
356
+ end
357
+
358
+ attr_accessor :path
359
+
360
+ def initialize(wiki, name, data, version, parent_page = nil)
361
+ @wiki = wiki
362
+ @path = name
363
+ @blob = OpenStruct.new(:name => name, :data => data, :is_symlink => false)
364
+ @version = version
365
+ @formatted_data = nil
366
+ @doc = nil
367
+ @parent_page = parent_page
368
+ @historical = false
455
369
  end
456
-
457
370
  end
371
+
458
372
  end