jekyll-wikilinks 0.0.3 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,463 @@
1
+ require_relative "regex"
2
+
3
+ module Jekyll
4
+ module WikiLinks
5
+
6
+ # more of a "parser" than a parser
7
+ class Parser
8
+ attr_accessor :doc_manager, :markdown_converter, :wikilink_inlines, :wikilink_blocks
9
+
10
+ # Use Jekyll's native relative_url filter
11
+ include Jekyll::Filters::URLFilters
12
+
13
+ CONVERTER_CLASS = Jekyll::Converters::Markdown
14
+
15
+ def initialize(site)
16
+ @context ||= Jekyll::WikiLinks::Context.new(site)
17
+ @doc_manager ||= site.doc_mngr
18
+ @markdown_converter ||= site.find_converter_instance(CONVERTER_CLASS)
19
+ @wikilink_blocks, @wikilink_inlines = [], [], []
20
+ end
21
+
22
+ # parsing
23
+
24
+ def parse(doc_content)
25
+ @wikilink_blocks, @wikilink_inlines = [], [], []
26
+ if !$wiki_conf.disabled_attributes?
27
+ self.parse_block_singles(doc_content)
28
+ self.parse_block_lists_mkdn(doc_content)
29
+ self.parse_block_lists_comma(doc_content)
30
+ end
31
+ self.parse_inlines(doc_content)
32
+ end
33
+
34
+ def parse_block_singles(doc_content)
35
+ bullet_type = ""
36
+ typed_link_block_matches = doc_content.scan(REGEX_TYPED_LINK_BLOCK)
37
+ if !typed_link_block_matches.nil? && typed_link_block_matches.size != 0
38
+ typed_link_block_matches.each do |wl_match|
39
+ link_type = wl_match[0]
40
+ filename = wl_match[1]
41
+ typed_link_block_wikilink = WikiLinkBlock.new(
42
+ link_type,
43
+ bullet_type,
44
+ filename,
45
+ )
46
+ @wikilink_blocks << typed_link_block_wikilink
47
+ doc_content.gsub!(typed_link_block_wikilink.md_regex, "\n")
48
+ end
49
+ end
50
+ end
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")
79
+ 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
+ end
87
+ end
88
+ # process previous wikilink_list
89
+ if !processing_wikilink_list.nil? && processing_wikilink_list.has_items?
90
+ @wikilink_blocks << processing_wikilink_list
91
+ doc_content.gsub!(processing_wikilink_list.md_regex, "\n")
92
+ end
93
+ end
94
+ end
95
+
96
+ def parse_block_lists_mkdn(doc_content)
97
+ processing_link_type = nil
98
+ processing_wikilink_list = nil
99
+ bullet_type = nil
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|
155
+ @wikilink_inlines << WikiLinkInline.new(
156
+ wl_match[0],
157
+ wl_match[1],
158
+ wl_match[2],
159
+ wl_match[3],
160
+ wl_match[4],
161
+ wl_match[5],
162
+ )
163
+ end
164
+ end
165
+ # replace text
166
+ return if @wikilink_inlines.nil?
167
+ self.sort_typed_first
168
+ @wikilink_inlines.each do |wikilink|
169
+ doc_content.gsub!(
170
+ wikilink.md_link_regex,
171
+ self.build_html(wikilink)
172
+ )
173
+ end
174
+ end
175
+
176
+ # building/converting
177
+
178
+ def build_html_embed(title, content, url)
179
+ # multi-line for readability
180
+ return [
181
+ "<div class=\"#{$wiki_conf.css_name("embed_wrapper")}\">",
182
+ "<div class=\"#{$wiki_conf.css_name("embed_title")}\">",
183
+ "#{title}",
184
+ "</div>",
185
+ "<div class=\"#{$wiki_conf.css_name("embed_content")}\">",
186
+ "#{@markdown_converter.convert(content)}",
187
+ "</div>",
188
+ "<a class=\"#{$wiki_conf.css_name("embed_wiki_link")}\" href=\"#{url}\"></a>",
189
+ "</div>",
190
+ ].join("\n").gsub!("\n", "")
191
+ end
192
+
193
+ def build_html_img_embed(static_doc, is_svg=false)
194
+ svg_content = ""
195
+ if is_svg
196
+ File.open(static_doc.path, "r") do |svg_img|
197
+ svg_content = svg_img.read
198
+ end
199
+ return "<p><span class=\"#{$wiki_conf.css_name("embed_image_wrapper")}\">#{svg_content}</span></p>"
200
+ 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)}\"/></span></p>"
202
+ end
203
+ end
204
+
205
+ def build_html(wikilink)
206
+ if wikilink.is_img?
207
+ linked_static_doc = @doc_manager.get_image_by_fname(wikilink.filename)
208
+ if wikilink.embedded? && wikilink.is_img?
209
+ return build_html_img_embed(linked_static_doc, is_svg=wikilink.is_img_svg?)
210
+ end
211
+ end
212
+ linked_doc = @doc_manager.get_doc_by_fname(wikilink.filename)
213
+ if !linked_doc.nil?
214
+ link_type = wikilink.typed? ? " #{$wiki_conf.css_name("typed")} #{wikilink.link_type}" : ""
215
+
216
+ # label
217
+ wikilink_inner_txt = wikilink.clean_label_txt if wikilink.labelled?
218
+
219
+ lnk_doc_rel_url = relative_url(linked_doc.url)
220
+ # TODO not sure about downcase
221
+ fname_inner_txt = linked_doc['title'].downcase if wikilink_inner_txt.nil?
222
+
223
+ link_lvl = wikilink.describe['level']
224
+ if (link_lvl == "file")
225
+ wikilink_inner_txt = "#{fname_inner_txt}" if wikilink_inner_txt.nil?
226
+ return build_html_embed(
227
+ linked_doc['title'],
228
+ @doc_manager.get_doc_content(wikilink.filename),
229
+ lnk_doc_rel_url
230
+ ) if wikilink.embedded?
231
+ elsif (link_lvl == "header" && DocManager.doc_has_header?(linked_doc, wikilink.header_txt))
232
+ # from: https://github.com/jekyll/jekyll/blob/6855200ebda6c0e33f487da69e4e02ec3d8286b7/Rakefile#L74
233
+ lnk_doc_rel_url += "\#" + Jekyll::Utils.slugify(wikilink.header_txt)
234
+ wikilink_inner_txt = "#{fname_inner_txt} > #{wikilink.header_txt}" if wikilink_inner_txt.nil?
235
+ elsif (link_lvl == "block" && DocManager.doc_has_block_id?(linked_doc, wikilink.block_id))
236
+ lnk_doc_rel_url += "\#" + wikilink.block_id.downcase
237
+ wikilink_inner_txt = "#{fname_inner_txt} > ^#{wikilink.block_id}" if wikilink_inner_txt.nil?
238
+ else
239
+ return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_link_str + '</span>'
240
+ end
241
+ return '<a class="' + $wiki_conf.css_name("wiki") + link_type + '" href="' + lnk_doc_rel_url + '">' + wikilink_inner_txt + '</a>'
242
+ else
243
+ return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_link_str + '</span>'
244
+ end
245
+ end
246
+
247
+ # helpers
248
+
249
+ def sort_typed_first
250
+ # sorting inline wikilinks is necessary so when wikilinks are replaced,
251
+ # longer strings are replaced first so as not to accidentally overwrite
252
+ # substrings
253
+ # (this is especially likely if there is a matching wikilink that
254
+ # appears as both untyped and typed in a document)
255
+ temp = @wikilink_inlines.dup
256
+ @wikilink_inlines.clear()
257
+ typed_wikilinks = temp.select { |wl| wl.typed? }
258
+ untyped_wikilinks = temp.select { |wl| !wl.typed? }
259
+ @wikilink_inlines = typed_wikilinks.concat(untyped_wikilinks)
260
+ end
261
+ end
262
+
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
+ end
463
+ end
@@ -0,0 +1,66 @@
1
+ # regex.rb
2
+ # regex constants defining supported file types and valid names for files, variables, or text
3
+ #
4
+
5
+ module Jekyll
6
+ module WikiLinks
7
+ # <regex_variables> only work with 'match' function, not with 'scan' function. :/
8
+ # oh well...they are there for easier debugging...
9
+
10
+ # supported image formats
11
+ # from: https://docs.github.com/en/github/managing-files-in-a-repository/working-with-non-code-files/rendering-and-diffing-images
12
+ SUPPORTED_IMG_FORMATS = Set.new(['.png', '.jpg', '.gif', '.psd', '.svg'])
13
+
14
+ # wikilink constants
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
+
23
+ # wikilink usable char requirements
24
+ REGEX_LINK_TYPE_TXT = /(?<link-type-txt>([^\n\s\!\#\^\|\]]+))/i
25
+ REGEX_FILENAME = /(?<filename>([^\\\/:\#\^\|\[\]]+))/i
26
+ REGEX_HEADER_TXT = /(?<header-txt>([^\!\#\^\|\[\]]+))/i
27
+ REGEX_BLOCK_ID_TXT = /(?<block-id>([^\\\/:\!\#\^\|\[\]^\n]+))/i
28
+ REGEX_LABEL_TXT = /(?<label-txt>((.+?)(?=\]\])))/i
29
+
30
+ # target markdown text (headers, lists, and blocks)
31
+ ## kramdown regexes
32
+ ### atx header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L29
33
+ REGEX_ATX_HEADER = /^\#{1,6}[\t ]*([^ \t].*)\n/i
34
+ ### setext header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L17
35
+ REGEX_SETEXT_HEADER = /^ {0,3}([^ \t].*)\n[-=][-=]*[ \t\r\f\v]*\n/i
36
+ ## list item: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/list.rb#L49
37
+ REGEX_BULLET = /(?<bullet>[+*-])/i
38
+ # REGEX_LIST_ITEM = /(^ {0,3}[+*-])([\t| ].*?\n)/i
39
+ REGEX_LIST_ITEM = /(^ {0,3}#{REGEX_BULLET})(\s(?:#{REGEX_LINK_LEFT}#{REGEX_FILENAME}#{REGEX_LINK_RIGHT}))/i
40
+ ## new-markdown-style
41
+ REGEX_BLOCK = /.*\s\^#{REGEX_BLOCK_ID_TXT}/i
42
+
43
+ # wikilinks
44
+ ## inline
45
+ REGEX_WIKI_LINKS = %r{ # capture indeces
46
+ (#{REGEX_LINK_EMBED})? # 0
47
+ (#{REGEX_LINK_TYPE_TXT}#{REGEX_LINK_TYPE})? # 1
48
+ #{REGEX_LINK_LEFT}
49
+ #{REGEX_FILENAME} # 2
50
+ (#{REGEX_LINK_HEADER}#{REGEX_HEADER_TXT})? # 3
51
+ (#{REGEX_LINK_BLOCK}#{REGEX_BLOCK_ID_TXT})? # 4
52
+ (#{REGEX_LINK_LABEL}#{REGEX_LABEL_TXT})? # 5
53
+ #{REGEX_LINK_RIGHT}
54
+ }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
+
65
+ end
66
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module JekyllWikiLinks
4
- VERSION = "0.0.3"
5
- end
3
+ module Jekyll
4
+ module WikiLinks
5
+
6
+ VERSION = "0.0.7"
7
+
8
+ end
9
+ end