jekyll-wikilinks 0.0.7 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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