gollum-lib 5.0.a.4-java → 5.0.5-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/HISTORY.md +4 -0
- data/README.md +12 -7
- data/Rakefile +8 -7
- data/gemspec.rb +17 -10
- data/gollum-lib.gemspec +8 -6
- data/gollum-lib_java.gemspec +2 -2
- data/lib/gollum-lib.rb +9 -9
- data/lib/gollum-lib/blob_entry.rb +2 -8
- data/lib/gollum-lib/committer.rb +23 -61
- data/lib/gollum-lib/file.rb +105 -82
- data/lib/gollum-lib/file_view.rb +8 -4
- data/lib/gollum-lib/filter.rb +12 -0
- data/lib/gollum-lib/filter/code.rb +9 -13
- data/lib/gollum-lib/filter/critic_markup.rb +97 -0
- data/lib/gollum-lib/filter/emoji.rb +11 -8
- data/lib/gollum-lib/filter/macro.rb +5 -2
- data/lib/gollum-lib/filter/plantuml.rb +1 -1
- data/lib/gollum-lib/filter/remote_code.rb +3 -2
- data/lib/gollum-lib/filter/render.rb +25 -2
- data/lib/gollum-lib/filter/sanitize.rb +1 -8
- data/lib/gollum-lib/filter/tags.rb +57 -46
- data/lib/gollum-lib/filter/toc.rb +17 -21
- data/lib/gollum-lib/filter/yaml.rb +1 -1
- data/lib/gollum-lib/git_access.rb +0 -25
- data/lib/gollum-lib/helpers.rb +13 -3
- data/lib/gollum-lib/macro.rb +4 -0
- data/lib/gollum-lib/macro/audio.rb +9 -0
- data/lib/gollum-lib/macro/global_toc.rb +2 -1
- data/lib/gollum-lib/macro/navigation.rb +8 -6
- data/lib/gollum-lib/macro/note.rb +19 -0
- data/lib/gollum-lib/macro/octicon.rb +12 -0
- data/lib/gollum-lib/macro/series.rb +2 -2
- data/lib/gollum-lib/macro/warn.rb +11 -0
- data/lib/gollum-lib/markup.rb +17 -32
- data/lib/gollum-lib/markups.rb +13 -8
- data/lib/gollum-lib/page.rb +80 -166
- data/lib/gollum-lib/pagination.rb +7 -6
- data/lib/gollum-lib/redirects.rb +42 -0
- data/lib/gollum-lib/sanitization.rb +32 -357
- data/lib/gollum-lib/version.rb +1 -1
- data/lib/gollum-lib/wiki.rb +216 -404
- metadata +65 -27
- data/ROADMAP +0 -6
@@ -14,17 +14,11 @@ class Gollum::Filter::Emoji < Gollum::Filter
|
|
14
14
|
(?!\]{^2})
|
15
15
|
}ix
|
16
16
|
|
17
|
-
PROCESS_PATTERN = %r{
|
18
|
-
=EEMMOOJJII=
|
19
|
-
(?<name>[\w-]+)
|
20
|
-
=IIJJOOMMEE=
|
21
|
-
}ix
|
22
|
-
|
23
17
|
def extract(data)
|
24
18
|
data.gsub! EXTRACT_PATTERN do
|
25
19
|
case
|
26
20
|
when $~[:escape] then $&[1..-1]
|
27
|
-
when emoji_exists?($~[:name]) then "
|
21
|
+
when emoji_exists?($~[:name]) then "#{open_pattern}#{$~[:name]}#{close_pattern}"
|
28
22
|
else $&
|
29
23
|
end
|
30
24
|
end
|
@@ -32,12 +26,21 @@ class Gollum::Filter::Emoji < Gollum::Filter
|
|
32
26
|
end
|
33
27
|
|
34
28
|
def process(data)
|
35
|
-
|
29
|
+
src = ::File.join(@markup.wiki.base_path, '/gollum/emoji/\\k<name>')
|
30
|
+
data.gsub! process_pattern, %Q(<img src="#{src}" alt="\\k<name>" class="emoji">)
|
36
31
|
data
|
37
32
|
end
|
38
33
|
|
39
34
|
private
|
40
35
|
|
36
|
+
def process_pattern
|
37
|
+
%r{
|
38
|
+
#{open_pattern}
|
39
|
+
(?<name>[\w-]+)
|
40
|
+
#{close_pattern}
|
41
|
+
}ix
|
42
|
+
end
|
43
|
+
|
41
44
|
def emoji_exists?(name)
|
42
45
|
@index ||= Gemojione::Index.new
|
43
46
|
!!@index.find_by_name(name)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# ~*~ encoding: utf-8 ~*~
|
2
|
+
require 'octicons'
|
2
3
|
|
3
4
|
# Replace specified tokens with dynamically generated content.
|
4
5
|
class Gollum::Filter::Macro < Gollum::Filter
|
@@ -12,7 +13,7 @@ class Gollum::Filter::Macro < Gollum::Filter
|
|
12
13
|
|
13
14
|
data.gsub(/('?)\<\<\s*([A-Z][A-Za-z0-9]*)\s*\(#{arg_list}\)\s*\>\>/) do
|
14
15
|
next CGI.escape_html($&[1..-1]) unless Regexp.last_match[1].empty?
|
15
|
-
id = Digest::SHA1.hexdigest(Regexp.last_match[2] + Regexp.last_match[3])
|
16
|
+
id = "#{open_pattern}#{Digest::SHA1.hexdigest(Regexp.last_match[2] + Regexp.last_match[3])}#{close_pattern}"
|
16
17
|
macro = Regexp.last_match[2]
|
17
18
|
argstr = Regexp.last_match[3]
|
18
19
|
args = []
|
@@ -47,7 +48,9 @@ class Gollum::Filter::Macro < Gollum::Filter
|
|
47
48
|
begin
|
48
49
|
Gollum::Macro.instance(macro, @markup.wiki, @markup.page).render(*args)
|
49
50
|
rescue StandardError => e
|
50
|
-
|
51
|
+
icon = Octicons::Octicon.new('zap', {width: 24, height: 24})
|
52
|
+
icon.options[:class] << ' mr-2'
|
53
|
+
"<div class='flash flash-error'>#{icon.to_svg}Macro Error for #{macro}: #{e.message}</div>"
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -70,7 +70,7 @@ class Gollum::Filter::PlantUML < Gollum::Filter
|
|
70
70
|
# placeholders.
|
71
71
|
def extract(data)
|
72
72
|
data.gsub(/(@startuml\r?\n.+?\r?\n@enduml\r?$)/m) do
|
73
|
-
id = Digest::SHA1.hexdigest($1)
|
73
|
+
id = "#{open_pattern}#{Digest::SHA1.hexdigest($1)}#{close_pattern}"
|
74
74
|
@map[id] = { :code => $1 }
|
75
75
|
id
|
76
76
|
end
|
@@ -20,7 +20,7 @@ class Gollum::Filter::RemoteCode < Gollum::Filter
|
|
20
20
|
|
21
21
|
# Detect local file
|
22
22
|
if protocol.nil?
|
23
|
-
if (file = @markup.
|
23
|
+
if (file = @markup.wiki.file(uri, @markup.wiki.ref))
|
24
24
|
contents = file.raw_data
|
25
25
|
else
|
26
26
|
# How do we communicate a render error?
|
@@ -45,7 +45,8 @@ class Gollum::Filter::RemoteCode < Gollum::Filter
|
|
45
45
|
return "Too many redirects or retries" if cut >= 10
|
46
46
|
http = Net::HTTP.new uri.host, uri.port
|
47
47
|
http.use_ssl = true
|
48
|
-
|
48
|
+
path = uri.path.empty? ? '/' : uri.path
|
49
|
+
resp = http.get path, {
|
49
50
|
'Accept' => 'text/plain',
|
50
51
|
'Cache-Control' => 'no-cache',
|
51
52
|
'Connection' => 'keep-alive',
|
@@ -3,7 +3,11 @@
|
|
3
3
|
class Gollum::Filter::Render < Gollum::Filter
|
4
4
|
def extract(data)
|
5
5
|
begin
|
6
|
-
|
6
|
+
working_dir = Pathname.new(@markup.wiki.path).join(@markup.dir)
|
7
|
+
working_dir = working_dir.exist? ? working_dir.to_s : '.'
|
8
|
+
Dir.chdir(working_dir) do
|
9
|
+
data = GitHub::Markup.render_s(@markup.format, data)
|
10
|
+
end
|
7
11
|
if data.nil?
|
8
12
|
raise "There was an error converting #{@markup.name} to HTML."
|
9
13
|
end
|
@@ -15,6 +19,25 @@ class Gollum::Filter::Render < Gollum::Filter
|
|
15
19
|
end
|
16
20
|
|
17
21
|
def process(data)
|
22
|
+
data = add_editable_header_class(data)
|
18
23
|
data
|
19
24
|
end
|
20
|
-
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def add_editable_header_class(data)
|
29
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(data)
|
30
|
+
doc.css('h1,h2,h3,h4,h5,h6').each_with_index do |header, i|
|
31
|
+
next if header.content.empty?
|
32
|
+
next if header.inner_html.match(PLACEHOLDER_PATTERN)
|
33
|
+
klass = header['class']
|
34
|
+
if klass
|
35
|
+
header['class'] = klass << ' editable'
|
36
|
+
else
|
37
|
+
header['class'] = 'editable'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
doc.to_xml(@markup.class.to_xml_opts)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -6,13 +6,6 @@ class Gollum::Filter::Sanitize < Gollum::Filter
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def process(data)
|
9
|
-
|
10
|
-
doc = Nokogiri::HTML::DocumentFragment.parse(data)
|
11
|
-
doc = @markup.sanitize.clean_node!(doc)
|
12
|
-
|
13
|
-
doc.to_xml(@markup.to_xml_opts).gsub(/<p><\/p>/, '')
|
14
|
-
else
|
15
|
-
data
|
16
|
-
end
|
9
|
+
sanitize(data)
|
17
10
|
end
|
18
11
|
end
|
@@ -34,7 +34,7 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
34
34
|
doc.traverse do |node|
|
35
35
|
if node.text? then
|
36
36
|
content = node.content
|
37
|
-
content.gsub!(
|
37
|
+
content.gsub!(%r{#{open_pattern}[a-f0-9]+#{close_pattern}}) do |id|
|
38
38
|
if (tag = @map[id]) then
|
39
39
|
if is_preformatted?(node) then
|
40
40
|
"[[#{tag}]]"
|
@@ -56,7 +56,7 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
56
56
|
INCLUDE_TAG = 'include:'
|
57
57
|
|
58
58
|
def register_tag(tag)
|
59
|
-
id = "
|
59
|
+
id = "#{open_pattern}#{Digest::SHA1.hexdigest(tag)}#{close_pattern}"
|
60
60
|
@map[id] = tag
|
61
61
|
id
|
62
62
|
end
|
@@ -77,7 +77,6 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
77
77
|
return generate_link('', nil, nil, :page_absent) if link_part.nil?
|
78
78
|
img_args = extra ? [extra, link_part] : [link_part]
|
79
79
|
mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
|
80
|
-
|
81
80
|
result = if tag =~ /^_TOC_/
|
82
81
|
%{[[#{tag}]]}
|
83
82
|
elsif link_part =~ /^_$/
|
@@ -122,9 +121,9 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
122
121
|
len = INCLUDE_TAG.length
|
123
122
|
return html_error('Cannot process include directive: no page name given') if tag.length <= len
|
124
123
|
page_name = tag[len..-1]
|
125
|
-
resolved_page_name = ::File.
|
124
|
+
resolved_page_name = ::File.join(@markup.dir, page_name)
|
126
125
|
if @markup.include_levels > 0
|
127
|
-
page =
|
126
|
+
page = find_page_or_file_from_path(resolved_page_name)
|
128
127
|
if page
|
129
128
|
page.formatted_data(@markup.encoding, @markup.include_levels-1)
|
130
129
|
else
|
@@ -146,8 +145,8 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
146
145
|
opts = parse_image_tag_options(options)
|
147
146
|
if path =~ /^https?:\/\/.+$/i
|
148
147
|
generate_image(path, opts)
|
149
|
-
elsif file =
|
150
|
-
generate_image(generate_href_for_path(file.
|
148
|
+
elsif file = find_page_or_file_from_path(path, :file)
|
149
|
+
generate_image(generate_href_for_path(file.url_path), opts)
|
151
150
|
else
|
152
151
|
generate_image('', opts)
|
153
152
|
end
|
@@ -173,14 +172,8 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
173
172
|
# Return the String HTML if the tag is a valid external link tag or
|
174
173
|
# nil if it is not.
|
175
174
|
def process_external_link_tag(url, pretty_name = nil)
|
176
|
-
|
177
|
-
if
|
178
|
-
accepted_protocols.select!{|protocol| protocol != :relative}
|
179
|
-
regexp = %r{^((#{accepted_protocols.join("|")}):)?(//)}
|
180
|
-
else
|
181
|
-
regexp = %r{^((#{accepted_protocols.join("|")}):)}
|
182
|
-
end
|
183
|
-
if url =~ regexp
|
175
|
+
@accepted_protocols_regex ||= %r{^((#{::Gollum::Sanitization.accepted_protocols.join('|')}):)?(//)}
|
176
|
+
if url =~ @accepted_protocols_regex
|
184
177
|
generate_link(url, pretty_name, nil, :external)
|
185
178
|
else
|
186
179
|
nil
|
@@ -195,8 +188,9 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
195
188
|
# Returns the String HTML if the tag is a valid file link tag or nil
|
196
189
|
# if it is not.
|
197
190
|
def process_file_link_tag(link_part, pretty_name)
|
198
|
-
|
199
|
-
|
191
|
+
return nil if ::Gollum::Page.valid_extension?(link_part)
|
192
|
+
if file = find_page_or_file_from_path(link_part, :file)
|
193
|
+
generate_link(file.url_path, pretty_name, nil, :file)
|
200
194
|
else
|
201
195
|
nil
|
202
196
|
end
|
@@ -212,18 +206,32 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
212
206
|
def process_page_link_tag(link_part, pretty_name = nil)
|
213
207
|
presence = :page_absent
|
214
208
|
link = link_part
|
215
|
-
page =
|
209
|
+
page = find_page_or_file_from_path(link)
|
216
210
|
|
217
211
|
# If no match yet, try finding page with anchor removed
|
218
|
-
if
|
219
|
-
|
220
|
-
|
221
|
-
|
212
|
+
if page.nil?
|
213
|
+
if pos = link.rindex('#')
|
214
|
+
extra = link[pos..-1]
|
215
|
+
link = link[0...pos]
|
216
|
+
else
|
217
|
+
extra = nil
|
218
|
+
end
|
219
|
+
|
220
|
+
if link.empty? && extra # Internal anchor link, don't search for the page but return immediately
|
221
|
+
return generate_link(nil, pretty_name, extra, :internal_anchor)
|
222
|
+
end
|
223
|
+
|
224
|
+
page = find_page_or_file_from_path(link)
|
225
|
+
end
|
226
|
+
presence = :page_present if page
|
227
|
+
|
228
|
+
if pretty_name
|
229
|
+
name = pretty_name
|
230
|
+
else
|
231
|
+
name = page ? path_to_link_text(link) : link
|
222
232
|
end
|
223
|
-
presence = :page_present if page
|
224
233
|
|
225
|
-
|
226
|
-
link = page ? page.escaped_url_path : CGI.escape(link)
|
234
|
+
link = page ? page.escaped_url_path : ERB::Util.url_encode(link).force_encoding('utf-8')
|
227
235
|
generate_link(link, name, extra, presence)
|
228
236
|
end
|
229
237
|
|
@@ -232,15 +240,15 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
232
240
|
# path - The String path to search for.
|
233
241
|
#
|
234
242
|
# Returns a Gollum::Page instance if a page is found, or nil otherwise
|
235
|
-
def
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
243
|
+
def find_page_or_file_from_path(path, kind = :page)
|
244
|
+
if Pathname.new(path).relative?
|
245
|
+
result = @markup.wiki.send(kind, ::File.join(@markup.dir, path))
|
246
|
+
if result.nil? && @markup.wiki.global_tag_lookup # 4.x link compatibility option. Slow!
|
247
|
+
result = @markup.wiki.send(kind, path, nil, true)
|
248
|
+
end
|
249
|
+
result
|
242
250
|
else
|
243
|
-
@markup.wiki.
|
251
|
+
@markup.wiki.send(kind, path)
|
244
252
|
end
|
245
253
|
end
|
246
254
|
|
@@ -264,7 +272,8 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
264
272
|
#
|
265
273
|
# Returns a String href.
|
266
274
|
def generate_href_for_path(path, extra = nil)
|
267
|
-
|
275
|
+
return extra if !path && extra # Internal anchor link
|
276
|
+
"#{trim_leading_slashes(::File.join(@markup.wiki.base_path, path))}#{extra}"
|
268
277
|
end
|
269
278
|
|
270
279
|
# Construct a CSS class and attribute string for different kinds of links: internal Pages (absent or present) and Files, and External links.
|
@@ -278,6 +287,8 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
278
287
|
'class="internal absent"'
|
279
288
|
when :page_present
|
280
289
|
'class="internal present"'
|
290
|
+
when :internal_anchor
|
291
|
+
'class="internal anchorlink"'
|
281
292
|
when :file
|
282
293
|
nil
|
283
294
|
when :external
|
@@ -299,10 +310,10 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
299
310
|
attr_string = attrs.map {|key, value| "#{key}=\"#{value}\""}.join(' ')
|
300
311
|
|
301
312
|
if containered
|
302
|
-
%{<span class="#{classes.join(' ')}">} +
|
303
|
-
%{<span>} +
|
313
|
+
%{<span class="d-flex #{classes[:container].join(' ')}">} +
|
314
|
+
%{<span class="#{classes[:nested].join(' ')}">} +
|
304
315
|
%{<img src="#{path}" #{attr_string}/>} +
|
305
|
-
(attrs[:alt] ? %{<span>#{attrs[:alt]}</span>} : '') +
|
316
|
+
(options[:frame] && attrs[:alt] ? %{<span class="clearfix">#{attrs[:alt]}</span>} : '') +
|
306
317
|
%{</span>} +
|
307
318
|
%{</span>}
|
308
319
|
else
|
@@ -314,31 +325,31 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
314
325
|
#
|
315
326
|
# options - The Hash of parsed image options.
|
316
327
|
#
|
317
|
-
# Returns
|
328
|
+
# Returns a Hash containing CSS class Arrays, a Hash of CSS attributes, and a Boolean indicating whether or not the image is containered.
|
318
329
|
def generate_image_attributes(options)
|
319
330
|
containered = false
|
320
|
-
classes = [] # applied to
|
331
|
+
classes = {container: [], nested: []} # applied to the container(s)
|
321
332
|
attrs = {} # applied to the image
|
322
333
|
|
323
334
|
align = options[:align]
|
324
335
|
if options[:float]
|
325
336
|
containered = true
|
326
|
-
align
|
327
|
-
|
328
|
-
classes << "float-#{align}"
|
329
|
-
end
|
337
|
+
align = 'left' unless align == 'right'
|
338
|
+
classes[:container] << "float-#{align} pb-4"
|
330
339
|
elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align)
|
331
340
|
attrs[:align] = align
|
332
341
|
elsif align
|
333
342
|
if %w{left center right}.include?(align)
|
334
343
|
containered = true
|
335
|
-
|
344
|
+
text_align = "text-#{align}"
|
345
|
+
align = 'end' if align == 'right'
|
346
|
+
classes[:container] << "flex-justify-#{align} #{text_align}"
|
336
347
|
end
|
337
348
|
end
|
338
349
|
|
339
|
-
if options[:frame]
|
350
|
+
if options[:frame]
|
340
351
|
containered = true
|
341
|
-
classes << '
|
352
|
+
classes[:nested] << 'border p-4'
|
342
353
|
end
|
343
354
|
|
344
355
|
attrs[:alt] = options[:alt] if options[:alt]
|
@@ -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
|
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(
|
88
|
-
|
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
|
-
|
97
|
-
|
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(
|
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'] ||= []
|