jekyll-wikilinks 0.0.7 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/jekyll-wikilinks/config.rb +17 -13
- data/lib/jekyll-wikilinks/patch/doc_manager.rb +54 -19
- data/lib/jekyll-wikilinks/patch/site.rb +1 -1
- data/lib/jekyll-wikilinks/plugins/filter.rb +39 -31
- data/lib/jekyll-wikilinks/plugins/generator.rb +4 -4
- data/lib/jekyll-wikilinks/util/link_index.rb +53 -66
- data/lib/jekyll-wikilinks/util/parser.rb +82 -364
- data/lib/jekyll-wikilinks/util/regex.rb +36 -30
- data/lib/jekyll-wikilinks/util/wikilink.rb +312 -0
- data/lib/jekyll-wikilinks/version.rb +1 -1
- data/lib/jekyll-wikilinks.rb +3 -22
- metadata +3 -2
@@ -1,4 +1,6 @@
|
|
1
|
+
require "nokogiri"
|
1
2
|
require_relative "regex"
|
3
|
+
require_relative "wikilink"
|
2
4
|
|
3
5
|
module Jekyll
|
4
6
|
module WikiLinks
|
@@ -14,145 +16,55 @@ module Jekyll
|
|
14
16
|
|
15
17
|
def initialize(site)
|
16
18
|
@context ||= Jekyll::WikiLinks::Context.new(site)
|
19
|
+
# do not use @dm in parser -- it is only meant to be passed down into wikilink classes.
|
17
20
|
@doc_manager ||= site.doc_mngr
|
18
21
|
@markdown_converter ||= site.find_converter_instance(CONVERTER_CLASS)
|
19
|
-
@wikilink_blocks, @wikilink_inlines = [], []
|
22
|
+
@wikilink_blocks, @wikilink_inlines = [], []
|
20
23
|
end
|
21
24
|
|
22
25
|
# parsing
|
23
26
|
|
24
|
-
def parse(doc_content)
|
25
|
-
@wikilink_blocks, @wikilink_inlines = [], []
|
27
|
+
def parse(doc_filename, doc_content)
|
28
|
+
@wikilink_blocks, @wikilink_inlines = [], []
|
26
29
|
if !$wiki_conf.disabled_attributes?
|
27
|
-
self.
|
28
|
-
self.parse_block_lists_mkdn(doc_content)
|
29
|
-
self.parse_block_lists_comma(doc_content)
|
30
|
+
self.parse_blocks(doc_filename, doc_content)
|
30
31
|
end
|
31
|
-
self.parse_inlines(doc_content)
|
32
|
-
end
|
33
|
-
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
link_type
|
43
|
-
bullet_type
|
44
|
-
filename,
|
32
|
+
self.parse_inlines(doc_filename, doc_content)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_blocks(doc_filename, doc_content)
|
36
|
+
block_matches = doc_content.scan(REGEX_WIKI_LINK_BLOCKS)
|
37
|
+
if !block_matches.nil? && block_matches.size != 0
|
38
|
+
block_matches.each do |wl_match|
|
39
|
+
# init block wikilink
|
40
|
+
wikilink_block = WikiLinkBlock.new(
|
41
|
+
@doc_manager,
|
42
|
+
doc_filename,
|
43
|
+
wl_match[0], # link_type
|
44
|
+
wl_match[2], # bullet_type
|
45
45
|
)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
def parse_block_lists_comma(doc_content)
|
53
|
-
processing_link_type = nil
|
54
|
-
processing_wikilink_list = nil
|
55
|
-
bullet_type = ","
|
56
|
-
typed_link_block_list_item_matches = doc_content.scan(REGEX_TYPED_LINK_BLOCK_LIST_COMMA)
|
57
|
-
if !typed_link_block_list_item_matches.nil? && typed_link_block_list_item_matches.size != 0
|
58
|
-
# Match 1
|
59
|
-
# link-type-txt link-type
|
60
|
-
# filename link
|
61
|
-
# 3. alink
|
62
|
-
# Match 2
|
63
|
-
# link-type-txt
|
64
|
-
# filename
|
65
|
-
# 3. blink
|
66
|
-
# Match 3
|
67
|
-
# link-type-txt
|
68
|
-
# filename
|
69
|
-
# 3. clink
|
70
|
-
typed_link_block_list_item_matches.each do |wl_match|
|
71
|
-
link_type = wl_match[0]
|
72
|
-
link_filename_1 = wl_match[1]
|
73
|
-
link_filename_2 = wl_match[2]
|
74
|
-
if !link_type.nil?
|
75
|
-
# process previous wikilink_list
|
76
|
-
if !processing_wikilink_list.nil? && processing_wikilink_list.has_items?
|
77
|
-
@wikilink_blocks << processing_wikilink_list
|
78
|
-
doc_content.gsub!(processing_wikilink_list.md_regex, "\n")
|
46
|
+
# extract + add filenames
|
47
|
+
items = wl_match[1]
|
48
|
+
filename_matches = items.scan(/#{REGEX_LINK_LEFT}#{REGEX_FILENAME}#{REGEX_LINK_RIGHT}/i)
|
49
|
+
filename_matches.each do |match|
|
50
|
+
match.each do |fname|
|
51
|
+
wikilink_block.add_item(fname)
|
79
52
|
end
|
80
|
-
processing_link_type = link_type
|
81
|
-
processing_wikilink_list = WikiLinkBlock.new(processing_link_type, bullet_type, link_filename_1)
|
82
|
-
processing_wikilink_list.add_item(bullet_type, link_filename_2) if !link_filename_2.nil?
|
83
|
-
else
|
84
|
-
Jekyll.logger.error("'processing_wikilink_list' was nil") if processing_wikilink_list.nil?
|
85
|
-
processing_wikilink_list.add_item(bullet_type, link_filename_2)
|
86
53
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
@wikilink_blocks << processing_wikilink_list
|
91
|
-
doc_content.gsub!(processing_wikilink_list.md_regex, "\n")
|
54
|
+
# replace text
|
55
|
+
doc_content.gsub!(wikilink_block.md_regex, "\n")
|
56
|
+
@wikilink_blocks << wikilink_block
|
92
57
|
end
|
93
58
|
end
|
94
59
|
end
|
95
60
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
typed_link_block_list_item_matches = doc_content.scan(REGEX_TYPED_LINK_BLOCK_LIST_MKDN)
|
101
|
-
if !typed_link_block_list_item_matches.nil? && typed_link_block_list_item_matches.size != 0
|
102
|
-
# Match 1
|
103
|
-
# link-type-txt more-types
|
104
|
-
# bullet
|
105
|
-
# filename
|
106
|
-
# Match 2
|
107
|
-
# link-type-txt
|
108
|
-
# bullet *
|
109
|
-
# filename alink
|
110
|
-
# Match 3
|
111
|
-
# link-type-txt
|
112
|
-
# bullet *
|
113
|
-
# filename blink
|
114
|
-
# Match 4
|
115
|
-
# link-type-txt more-types
|
116
|
-
# bullet
|
117
|
-
# filename
|
118
|
-
# Match 5
|
119
|
-
# link-type-txt
|
120
|
-
# bullet +
|
121
|
-
# filename alink
|
122
|
-
# Match 6
|
123
|
-
# link-type-txt
|
124
|
-
# bullet +
|
125
|
-
# filename blink
|
126
|
-
typed_link_block_list_item_matches.each do |wl_match|
|
127
|
-
link_type = wl_match[0]
|
128
|
-
bullet_type = wl_match[1]
|
129
|
-
link_filename = wl_match[2]
|
130
|
-
if !link_type.nil?
|
131
|
-
# process previous wikilink_list
|
132
|
-
if !processing_wikilink_list.nil? && processing_wikilink_list.has_items?
|
133
|
-
@wikilink_blocks << processing_wikilink_list
|
134
|
-
doc_content.gsub!(processing_wikilink_list.md_regex, "\n")
|
135
|
-
end
|
136
|
-
processing_link_type = link_type
|
137
|
-
processing_wikilink_list = WikiLinkBlock.new(processing_link_type)
|
138
|
-
else
|
139
|
-
Jekyll.logger.error("'processing_wikilink_list' was nil") if processing_wikilink_list.nil?
|
140
|
-
processing_wikilink_list.add_item(bullet_type, link_filename)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
# process previous wikilink_list
|
144
|
-
if !processing_wikilink_list.nil? && processing_wikilink_list.has_items?
|
145
|
-
@wikilink_blocks << processing_wikilink_list
|
146
|
-
doc_content.gsub!(processing_wikilink_list.md_regex, "\n")
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def parse_inlines(doc_content)
|
152
|
-
wikilink_matches = doc_content.scan(REGEX_WIKI_LINKS)
|
153
|
-
if !wikilink_matches.nil? && wikilink_matches.size != 0
|
154
|
-
wikilink_matches.each do |wl_match|
|
61
|
+
def parse_inlines(doc_filename, doc_content)
|
62
|
+
inline_matches = doc_content.scan(REGEX_WIKI_LINK_INLINES)
|
63
|
+
if !inline_matches.nil? && inline_matches.size != 0
|
64
|
+
inline_matches.each do |wl_match|
|
155
65
|
@wikilink_inlines << WikiLinkInline.new(
|
66
|
+
@doc_manager,
|
67
|
+
doc_filename,
|
156
68
|
wl_match[0],
|
157
69
|
wl_match[1],
|
158
70
|
wl_match[2],
|
@@ -164,10 +76,12 @@ module Jekyll
|
|
164
76
|
end
|
165
77
|
# replace text
|
166
78
|
return if @wikilink_inlines.nil?
|
79
|
+
# process typed wikilinks first so we don't accidentally
|
80
|
+
# overwrite them when handling untyped wikilinks
|
167
81
|
self.sort_typed_first
|
168
82
|
@wikilink_inlines.each do |wikilink|
|
169
83
|
doc_content.gsub!(
|
170
|
-
wikilink.
|
84
|
+
wikilink.md_regex,
|
171
85
|
self.build_html(wikilink)
|
172
86
|
)
|
173
87
|
end
|
@@ -198,50 +112,53 @@ module Jekyll
|
|
198
112
|
end
|
199
113
|
return "<p><span class=\"#{$wiki_conf.css_name("embed_image_wrapper")}\">#{svg_content}</span></p>"
|
200
114
|
else
|
201
|
-
return "<p><span class=\"#{$wiki_conf.css_name("embed_image_wrapper")}\"><img class=\"#{$wiki_conf.css_name("embed_image")}\" src=\"#{relative_url(static_doc.relative_path)}\"
|
115
|
+
return "<p><span class=\"#{$wiki_conf.css_name("embed_image_wrapper")}\"><img class=\"#{$wiki_conf.css_name("embed_image")}\" src=\"#{relative_url(static_doc.relative_path)}\"></span></p>"
|
202
116
|
end
|
203
117
|
end
|
204
118
|
|
205
119
|
def build_html(wikilink)
|
206
|
-
if wikilink.
|
207
|
-
|
208
|
-
if wikilink.embedded? && wikilink.is_img?
|
209
|
-
return build_html_img_embed(linked_static_doc, is_svg=wikilink.is_img_svg?)
|
210
|
-
end
|
120
|
+
if !wikilink.is_valid?
|
121
|
+
return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_str + '</span>'
|
211
122
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
123
|
+
# image processing
|
124
|
+
if wikilink.embedded? && wikilink.is_img?
|
125
|
+
return build_html_img_embed(wikilink.linked_img, is_svg=wikilink.is_img_svg?)
|
126
|
+
end
|
127
|
+
# markdown file processing
|
128
|
+
linked_doc = wikilink.linked_doc
|
129
|
+
link_type_txt = wikilink.is_typed? ? " #{$wiki_conf.css_name("typed")} #{wikilink.link_type}" : ""
|
130
|
+
lnk_doc_rel_url = relative_url(linked_doc.url)
|
131
|
+
if wikilink.labelled?
|
132
|
+
inner_txt = wikilink.label_txt
|
133
|
+
elsif linked_doc.data.keys.include?('title')
|
134
|
+
inner_txt = linked_doc.data['title'].downcase
|
135
|
+
# in case there is no 'title' frontmatter attribute
|
136
|
+
# (i'm seeing deprecation warnings, but there might
|
137
|
+
# be bugs caused by not using this...)
|
138
|
+
elsif linked_doc.respond_to?(:title)
|
139
|
+
inner_txt = linked_doc.title.downcase
|
140
|
+
# pages don't have automatically generated titles
|
141
|
+
else
|
142
|
+
inner_txt = Jekyll::Utils.slugify(linked_doc.basename)
|
143
|
+
end
|
144
|
+
# level-specific
|
145
|
+
if (wikilink.level == "file_path" || wikilink.level == "filename")
|
146
|
+
return build_html_embed(
|
147
|
+
linked_doc.title,
|
148
|
+
linked_doc.content,
|
149
|
+
lnk_doc_rel_url
|
150
|
+
) if wikilink.embedded?
|
151
|
+
elsif (wikilink.level == "header")
|
152
|
+
# from: https://github.com/jekyll/jekyll/blob/6855200ebda6c0e33f487da69e4e02ec3d8286b7/Rakefile#L74
|
153
|
+
lnk_doc_rel_url += "\#" + Jekyll::Utils.slugify(wikilink.header_txt)
|
154
|
+
inner_txt += " > #{wikilink.header_txt.downcase}" if !wikilink.labelled?
|
155
|
+
elsif (wikilink.level == "block")
|
156
|
+
lnk_doc_rel_url += "\#" + wikilink.block_id
|
157
|
+
inner_txt += " > ^#{wikilink.block_id}" if !wikilink.labelled?
|
158
|
+
else
|
159
|
+
Jekyll.logger.error("Jekyll-Wikilinks: Invalid wikilink level")
|
160
|
+
end
|
161
|
+
return '<a class="' + $wiki_conf.css_name("wiki") + link_type_txt + '" href="' + lnk_doc_rel_url + '">' + inner_txt + '</a>'
|
245
162
|
end
|
246
163
|
|
247
164
|
# helpers
|
@@ -254,210 +171,11 @@ module Jekyll
|
|
254
171
|
# appears as both untyped and typed in a document)
|
255
172
|
temp = @wikilink_inlines.dup
|
256
173
|
@wikilink_inlines.clear()
|
257
|
-
typed_wikilinks = temp.select { |wl| wl.
|
258
|
-
untyped_wikilinks = temp.select { |wl| !wl.
|
174
|
+
typed_wikilinks = temp.select { |wl| wl.is_typed? }
|
175
|
+
untyped_wikilinks = temp.select { |wl| !wl.is_typed? }
|
259
176
|
@wikilink_inlines = typed_wikilinks.concat(untyped_wikilinks)
|
260
177
|
end
|
261
178
|
end
|
262
179
|
|
263
|
-
# validation
|
264
|
-
|
265
|
-
def has_target_attr?(attribute)
|
266
|
-
attribute.list_item.each do |li|
|
267
|
-
return false if @doc_manager.get_doc_by_fname(li[1]).nil?
|
268
|
-
end
|
269
|
-
return true
|
270
|
-
end
|
271
|
-
|
272
|
-
def has_target_wl?(wikilink)
|
273
|
-
level = wikilink.describe['level']
|
274
|
-
linked_doc = @doc_manager.get_doc_by_fname(wikilink.filename)
|
275
|
-
return false if linked_doc.nil?
|
276
|
-
return false if level == "header" && !DocManager.doc_has_header?(linked_doc, wikilink.header_txt)
|
277
|
-
return false if level == "block" && !DocManager.doc_has_block_id?(linked_doc, wikilink.block_id)
|
278
|
-
return true
|
279
|
-
end
|
280
|
-
|
281
|
-
# wikilinks
|
282
|
-
|
283
|
-
class WikiLinkBlock
|
284
|
-
attr_accessor :link_type, :list_items
|
285
|
-
|
286
|
-
# parameters ordered by appearance in regex
|
287
|
-
def initialize(link_type, bullet_type=nil, filename=nil)
|
288
|
-
@link_type ||= link_type
|
289
|
-
@list_items = [] # li[0] = bullet_type; li[1] = filename
|
290
|
-
@list_items << [ bullet_type, filename ] if !bullet_type.nil? && !filename.nil?
|
291
|
-
end
|
292
|
-
|
293
|
-
def add_item(bullet_type, filename)
|
294
|
-
return if bullet_type.nil? || bullet_type.empty? || filename.nil? || filename.empty?
|
295
|
-
@list_items << [ bullet_type, filename ]
|
296
|
-
end
|
297
|
-
|
298
|
-
def md_regex
|
299
|
-
if typed? && has_items?
|
300
|
-
# single
|
301
|
-
if bullet_type?.empty?
|
302
|
-
link_type = %r{#{@link_type}#{REGEX_LINK_TYPE}}
|
303
|
-
list_item_strs = @list_items.map { |li| /#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\n/i }
|
304
|
-
md_link_regex = /#{link_type}#{list_item_strs.join("")}/i
|
305
|
-
# list (comma)
|
306
|
-
elsif bullet_type? == ","
|
307
|
-
tmp_list_items = @list_items.dup
|
308
|
-
first_item = tmp_list_items.shift()
|
309
|
-
link_type = /#{@link_type}#{REGEX_LINK_TYPE}#{REGEX_LINK_LEFT}#{first_item[1]}#{REGEX_LINK_RIGHT}\s*/i
|
310
|
-
list_item_strs = tmp_list_items.map { |li| /#{li[0]}\s*#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\s*/i }
|
311
|
-
md_link_regex = /#{link_type}#{list_item_strs.join('')}/i
|
312
|
-
# list (md)
|
313
|
-
elsif !bullet_type?.match(REGEX_BULLET).nil?
|
314
|
-
link_type = %r{#{@link_type}#{REGEX_LINK_TYPE}\n}
|
315
|
-
list_item_strs = @list_items.map { |li| /#{Regexp.escape(li[0])}\s#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\n/i }
|
316
|
-
md_link_regex = /#{link_type}#{list_item_strs.join("")}/i
|
317
|
-
else
|
318
|
-
Jekyll.logger.error("bullet_types not uniform or invalid: #{bullet_type?}")
|
319
|
-
end
|
320
|
-
return md_link_regex
|
321
|
-
else
|
322
|
-
Jekyll.logger.error("WikiLinkBlockList.md_regex error")
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def md_str
|
327
|
-
if typed? && has_items?
|
328
|
-
if bullet_type? == ","
|
329
|
-
link_type = "#{@link_type}::"
|
330
|
-
list_item_strs = @list_items.map { |li| "\[\[#{li[1]}\]\]#{li[0]}" }
|
331
|
-
md_link_str = (link_type + list_item_strs.join('')).delete_suffix(",")
|
332
|
-
elsif "+*-".include?(bullet_type?)
|
333
|
-
link_type = "#{@link_type}::\n"
|
334
|
-
list_item_strs = @list_items.map { |li| li[0] + " \[\[#{li[1]}\]\]\n" }
|
335
|
-
md_link_str = link_type + list_item_strs.join('')
|
336
|
-
else
|
337
|
-
Jekyll.logger.error("Not a valid bullet_type: #{bullet_type?}")
|
338
|
-
end
|
339
|
-
return md_link_str
|
340
|
-
else
|
341
|
-
Jekyll.logger.error("WikiLinkBlockList.md_str error")
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
def bullet_type?
|
346
|
-
bullets = @list_items.map { |li| li[0] }
|
347
|
-
return bullets.uniq.first if bullets.uniq.size == 1
|
348
|
-
end
|
349
|
-
|
350
|
-
def has_items?
|
351
|
-
return !@list_items.nil? && !@list_items.empty?
|
352
|
-
end
|
353
|
-
|
354
|
-
def typed?
|
355
|
-
return !@link_type.nil? && !@link_type.empty?
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
# the wikilink class knows everything about the original markdown syntax and its semantic meaning
|
360
|
-
class WikiLinkInline
|
361
|
-
attr_accessor :embed, :link_type, :filename, :header_txt, :block_id, :label_txt
|
362
|
-
|
363
|
-
FILENAME = "filename"
|
364
|
-
HEADER_TXT = "header_txt"
|
365
|
-
BLOCK_ID = "block_id"
|
366
|
-
|
367
|
-
# parameters ordered by appearance in regex
|
368
|
-
def initialize(embed, link_type, filename, header_txt, block_id, label_txt)
|
369
|
-
@embed ||= embed
|
370
|
-
@link_type ||= link_type
|
371
|
-
@filename ||= filename
|
372
|
-
@header_txt ||= header_txt
|
373
|
-
@block_id ||= block_id
|
374
|
-
@label_txt ||= label_txt
|
375
|
-
end
|
376
|
-
|
377
|
-
# labels are really flexible, so we need to handle them with a bit more care
|
378
|
-
def clean_label_txt
|
379
|
-
return @label_txt.sub("[", "\\[").sub("]", "\\]")
|
380
|
-
end
|
381
|
-
|
382
|
-
# TODO: remove this once parsing is migrated to nokogiri...?
|
383
|
-
def md_link_str
|
384
|
-
embed = embedded? ? "!" : ""
|
385
|
-
link_type = typed? ? "#{@link_type}::" : ""
|
386
|
-
filename = described?(FILENAME) ? @filename : ""
|
387
|
-
if described?(HEADER_TXT)
|
388
|
-
header = "\##{@header_txt}"
|
389
|
-
block = ""
|
390
|
-
elsif described?(BLOCK_ID)
|
391
|
-
header = ""
|
392
|
-
block = "\#\^#{@block_id}"
|
393
|
-
elsif !described?(FILENAME)
|
394
|
-
Jekyll.logger.error "Invalid link level in 'md_link_str'. See WikiLink's 'md_link_str' for details"
|
395
|
-
end
|
396
|
-
label_ = labelled? ? "\|#{@label_txt}" : ""
|
397
|
-
return "#{embed}#{link_type}\[\[#{filename}#{header}#{block}#{label_}\]\]"
|
398
|
-
end
|
399
|
-
|
400
|
-
def md_link_regex
|
401
|
-
regex_embed = embedded? ? REGEX_LINK_EMBED : %r{}
|
402
|
-
regex_link_type = typed? ? %r{#{@link_type}#{REGEX_LINK_TYPE}} : %r{}
|
403
|
-
filename = described?(FILENAME) ? @filename : ""
|
404
|
-
if described?(HEADER_TXT)
|
405
|
-
header = %r{#{REGEX_LINK_HEADER}#{@header_txt}}
|
406
|
-
block = %r{}
|
407
|
-
elsif described?(BLOCK_ID)
|
408
|
-
header = %r{}
|
409
|
-
block = %r{#{REGEX_LINK_BLOCK}#{@block_id}}
|
410
|
-
elsif !described?(FILENAME)
|
411
|
-
Jekyll.logger.error "Invalid link level in regex. See WikiLink's 'md_link_regex' for details"
|
412
|
-
end
|
413
|
-
label_ = labelled? ? %r{#{REGEX_LINK_LABEL}#{clean_label_txt}} : %r{}
|
414
|
-
return %r{#{regex_embed}#{regex_link_type}#{REGEX_LINK_LEFT}#{filename}#{header}#{block}#{label_}#{REGEX_LINK_RIGHT}}
|
415
|
-
end
|
416
|
-
|
417
|
-
def describe
|
418
|
-
return {
|
419
|
-
'level' => level,
|
420
|
-
'labelled' => labelled?,
|
421
|
-
'embedded' => embedded?,
|
422
|
-
'typed_link' => typed?,
|
423
|
-
}
|
424
|
-
end
|
425
|
-
|
426
|
-
def labelled?
|
427
|
-
return !@label_txt.nil? && !@label_txt.empty?
|
428
|
-
end
|
429
|
-
|
430
|
-
def typed?
|
431
|
-
return !@link_type.nil? && !@link_type.empty?
|
432
|
-
end
|
433
|
-
|
434
|
-
def embedded?
|
435
|
-
return !@embed.nil? && @embed == "!"
|
436
|
-
end
|
437
|
-
|
438
|
-
def is_img?
|
439
|
-
# github supported image formats: https://docs.github.com/en/github/managing-files-in-a-repository/working-with-non-code-files/rendering-and-diffing-images
|
440
|
-
return SUPPORTED_IMG_FORMATS.any?{ |ext| ext == File.extname(@filename).downcase }
|
441
|
-
end
|
442
|
-
|
443
|
-
def is_img_svg?
|
444
|
-
return File.extname(@filename).downcase == ".svg"
|
445
|
-
end
|
446
|
-
|
447
|
-
def described?(chunk)
|
448
|
-
return (!@filename.nil? && !@filename.empty?) if chunk == FILENAME
|
449
|
-
return (!@header_txt.nil? && !@header_txt.empty?) if chunk == HEADER_TXT
|
450
|
-
return (!@block_id.nil? && !@block_id.empty?) if chunk == BLOCK_ID
|
451
|
-
Jekyll.logger.error "There is no link level '#{chunk}' in WikiLink Struct"
|
452
|
-
end
|
453
|
-
|
454
|
-
def level
|
455
|
-
return "file" if described?(FILENAME) && !described?(HEADER_TXT) && !described?(BLOCK_ID)
|
456
|
-
return "header" if described?(FILENAME) && described?(HEADER_TXT) && !described?(BLOCK_ID)
|
457
|
-
return "block" if described?(FILENAME) && !described?(HEADER_TXT) && described?(BLOCK_ID)
|
458
|
-
return "invalid"
|
459
|
-
end
|
460
|
-
end
|
461
|
-
|
462
180
|
end
|
463
181
|
end
|
@@ -12,37 +12,43 @@ module Jekyll
|
|
12
12
|
SUPPORTED_IMG_FORMATS = Set.new(['.png', '.jpg', '.gif', '.psd', '.svg'])
|
13
13
|
|
14
14
|
# wikilink constants
|
15
|
-
REGEX_LINK_LEFT
|
16
|
-
REGEX_LINK_RIGHT
|
17
|
-
REGEX_LINK_EMBED
|
18
|
-
REGEX_LINK_TYPE
|
19
|
-
REGEX_LINK_HEADER
|
20
|
-
REGEX_LINK_BLOCK
|
21
|
-
REGEX_LINK_LABEL
|
15
|
+
REGEX_LINK_LEFT = /\[\[/
|
16
|
+
REGEX_LINK_RIGHT = /\]\]/
|
17
|
+
REGEX_LINK_EMBED = /(?<embed>\!)/
|
18
|
+
REGEX_LINK_TYPE = /\s*::\s*/
|
19
|
+
REGEX_LINK_HEADER = /\#/
|
20
|
+
REGEX_LINK_BLOCK = /\#\^/
|
21
|
+
REGEX_LINK_LABEL = /\|/
|
22
22
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
# wikitext usable char requirements
|
24
|
+
REGEX_LINK_TYPE_CHARS = /[^\n\s\!\#\^\|\]]+/i
|
25
|
+
REGEX_FILENAME_CHARS = /[^\\:\#\^\|\[\]]+/i
|
26
|
+
REGEX_HEADER_CHARS = /[^\!\#\^\|\[\]]+/i
|
27
|
+
REGEX_BLOCK_ID_CHARS = /[^\\\/:\!\#\^\|\[\]^\n]+/i
|
28
|
+
REGEX_LABEL_CHARS = /(.+?)(?=\]{2}[^\]])/i
|
29
|
+
|
30
|
+
# capture groups
|
31
|
+
REGEX_LINK_TYPE_TXT = /(?<link-type-txt>#{REGEX_LINK_TYPE_CHARS})/i
|
32
|
+
REGEX_FILENAME = /(?<filename>#{REGEX_FILENAME_CHARS})/i
|
33
|
+
REGEX_HEADER_TXT = /(?<header-txt>#{REGEX_HEADER_CHARS})/i
|
34
|
+
REGEX_BLOCK_ID_TXT = /(?<block-id>#{REGEX_BLOCK_ID_CHARS})/i
|
35
|
+
REGEX_LABEL_TXT = /(?<label-txt>#{REGEX_LABEL_CHARS})/i
|
29
36
|
|
30
37
|
# target markdown text (headers, lists, and blocks)
|
31
38
|
## kramdown regexes
|
32
39
|
### atx header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L29
|
33
|
-
REGEX_ATX_HEADER
|
40
|
+
REGEX_ATX_HEADER = /^\#{1,6}[\t ]*([^ \t].*)\n/i
|
34
41
|
### setext header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L17
|
35
|
-
REGEX_SETEXT_HEADER
|
42
|
+
REGEX_SETEXT_HEADER = /^\s{0,3}([^ \t].*)\n[-=][-=]*[ \t\r\f\v]*\n/i
|
36
43
|
## list item: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/list.rb#L49
|
37
|
-
REGEX_BULLET
|
38
|
-
|
39
|
-
|
40
|
-
## new-markdown-style
|
41
|
-
REGEX_BLOCK = /.*\s\^#{REGEX_BLOCK_ID_TXT}/i
|
44
|
+
REGEX_BULLET = /(?<bullet>[+*-])/i
|
45
|
+
## markdown-style block-reference
|
46
|
+
REGEX_BLOCK = /.*\s\^#{REGEX_BLOCK_ID_TXT}/i
|
42
47
|
|
43
48
|
# wikilinks
|
49
|
+
|
44
50
|
## inline
|
45
|
-
|
51
|
+
REGEX_WIKI_LINK_INLINES = %r{ # capture indeces
|
46
52
|
(#{REGEX_LINK_EMBED})? # 0
|
47
53
|
(#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE})? # 1
|
48
54
|
#{REGEX_LINK_LEFT}
|
@@ -52,15 +58,15 @@ module Jekyll
|
|
52
58
|
(#{REGEX_LINK_LABEL}#{REGEX_LABEL_TXT})? # 5
|
53
59
|
#{REGEX_LINK_RIGHT}
|
54
60
|
}x
|
55
|
-
## block
|
56
|
-
REGEX_TYPED_LINK_BLOCK = /#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE}#{REGEX_LINK_LEFT}#{REGEX_FILENAME}#{REGEX_LINK_RIGHT}\n/i
|
57
|
-
# TODO: keep an eye on this -- using REGEX_FILENAME in two places
|
58
|
-
REGEX_TYPED_LINK_BLOCK_LIST_COMMA = /(?:#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE}\s*(?:#{REGEX_LINK_LEFT}#{REGEX_FILENAME}#{REGEX_LINK_RIGHT})\s*|\G)\s*(?:,\s*#{REGEX_LINK_LEFT}#{REGEX_FILENAME}#{REGEX_LINK_RIGHT})\s*/i
|
59
|
-
REGEX_TYPED_LINK_BLOCK_LIST_MKDN = /#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE}\n|\G(?:#{REGEX_LIST_ITEM}\n)/i
|
60
|
-
|
61
|
-
# parsing for wikilinks in html
|
62
|
-
# identify missing links in doc via .invalid-wiki-link class and nested doc-text.
|
63
|
-
REGEX_INVALID_WIKI_LINK = /invalid-wiki-link(?:[^\]]+)\[\[(?<wiki-text>([^\]]+))\]\]/i
|
64
61
|
|
62
|
+
## block
|
63
|
+
### single
|
64
|
+
REGEX_SINGLE = /#{REGEX_LINK_LEFT}#{REGEX_FILENAME_CHARS}#{REGEX_LINK_RIGHT}/i
|
65
|
+
### list (comma is responsible for catching the single case)
|
66
|
+
REGEX_LIST_COMMA = /((?:\s*#{REGEX_SINGLE}\s*)(?:,\s*#{REGEX_SINGLE}\s*)*)/i
|
67
|
+
REGEX_LIST_MKDN = /((?<=\n)\s{0,3}#{REGEX_BULLET}\s#{REGEX_SINGLE}\s*)+/i # (see REGEX_LIST_ITEM)
|
68
|
+
### process
|
69
|
+
REGEX_BLOCK_TYPES = /((?<!\n)(?:#{REGEX_LIST_COMMA})|#{REGEX_LIST_MKDN})/i
|
70
|
+
REGEX_WIKI_LINK_BLOCKS = /^\s{0,3}#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE}(?:\s*|\G)(?<items>#{REGEX_BLOCK_TYPES})\n/i
|
65
71
|
end
|
66
72
|
end
|