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.
@@ -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.parse_block_singles(doc_content)
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 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,
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
- @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")
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
- 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")
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 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|
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.md_link_regex,
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)}\"/></span></p>"
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.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
120
+ if !wikilink.is_valid?
121
+ return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_str + '</span>'
211
122
  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
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.typed? }
258
- untyped_wikilinks = temp.select { |wl| !wl.typed? }
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 = /(?<embed>(\!))/
18
- REGEX_LINK_TYPE = /\s*::\s*/
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
- # 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
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 = /^\#{1,6}[\t ]*([^ \t].*)\n/i
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 = /^ {0,3}([^ \t].*)\n[-=][-=]*[ \t\r\f\v]*\n/i
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 = /(?<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
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
- REGEX_WIKI_LINKS = %r{ # capture indeces
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