jekyll-wikilinks 0.0.6 → 0.0.10

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, "")
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, "")
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, "")
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, "")
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, "")
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,9 +76,10 @@ module Jekyll
164
76
  end
165
77
  # replace text
166
78
  return if @wikilink_inlines.nil?
79
+ self.sort_typed_first
167
80
  @wikilink_inlines.each do |wikilink|
168
81
  doc_content.gsub!(
169
- wikilink.md_link_regex,
82
+ wikilink.md_regex,
170
83
  self.build_html(wikilink)
171
84
  )
172
85
  end
@@ -197,249 +110,58 @@ module Jekyll
197
110
  end
198
111
  return "<p><span class=\"#{$wiki_conf.css_name("embed_image_wrapper")}\">#{svg_content}</span></p>"
199
112
  else
200
- 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>"
113
+ 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>"
201
114
  end
202
115
  end
203
116
 
204
117
  def build_html(wikilink)
205
- if wikilink.is_img?
206
- linked_static_doc = @doc_manager.get_image_by_fname(wikilink.filename)
207
- if wikilink.embedded? && wikilink.is_img?
208
- return build_html_img_embed(linked_static_doc, is_svg=wikilink.is_img_svg?)
209
- end
118
+ if !wikilink.is_valid?
119
+ return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_str + '</span>'
210
120
  end
211
- linked_doc = @doc_manager.get_doc_by_fname(wikilink.filename)
212
- if !linked_doc.nil?
213
- link_type = wikilink.typed? ? " typed #{wikilink.link_type}" : ""
214
-
215
- # label
216
- wikilink_inner_txt = wikilink.clean_label_txt if wikilink.labelled?
217
-
218
- lnk_doc_rel_url = relative_url(linked_doc.url)
219
- # TODO not sure about downcase
220
- fname_inner_txt = linked_doc['title'].downcase if wikilink_inner_txt.nil?
221
-
222
- link_lvl = wikilink.describe['level']
223
- if (link_lvl == "file")
224
- wikilink_inner_txt = "#{fname_inner_txt}" if wikilink_inner_txt.nil?
225
- return build_html_embed(
226
- linked_doc['title'],
227
- @doc_manager.get_doc_content(wikilink.filename),
228
- lnk_doc_rel_url
229
- ) if wikilink.embedded?
230
- elsif (link_lvl == "header" && DocManager.doc_has_header?(linked_doc, wikilink.header_txt))
231
- # from: https://github.com/jekyll/jekyll/blob/6855200ebda6c0e33f487da69e4e02ec3d8286b7/Rakefile#L74
232
- lnk_doc_rel_url += "\#" + Jekyll::Utils.slugify(wikilink.header_txt)
233
- wikilink_inner_txt = "#{fname_inner_txt} > #{wikilink.header_txt}" if wikilink_inner_txt.nil?
234
- elsif (link_lvl == "block" && DocManager.doc_has_block_id?(linked_doc, wikilink.block_id))
235
- lnk_doc_rel_url += "\#" + wikilink.block_id.downcase
236
- wikilink_inner_txt = "#{fname_inner_txt} > ^#{wikilink.block_id}" if wikilink_inner_txt.nil?
237
- else
238
- return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_link_str + '</span>'
239
- end
240
- return '<a class="' + $wiki_conf.css_name("wiki") + link_type + '" href="' + lnk_doc_rel_url + '">' + wikilink_inner_txt + '</a>'
241
- else
242
- return '<span class="' + $wiki_conf.css_name("invalid_wiki") + '">' + wikilink.md_link_str + '</span>'
243
- end
244
- end
245
- end
246
-
247
- # validation
248
-
249
- def has_target_attr?(attribute)
250
- attribute.list_item.each do |li|
251
- return false if @doc_manager.get_doc_by_fname(li[1]).nil?
252
- end
253
- return true
254
- end
255
-
256
- def has_target_wl?(wikilink)
257
- level = wikilink.describe['level']
258
- linked_doc = @doc_manager.get_doc_by_fname(wikilink.filename)
259
- return false if linked_doc.nil?
260
- return false if level == "header" && !DocManager.doc_has_header?(linked_doc, wikilink.header_txt)
261
- return false if level == "block" && !DocManager.doc_has_block_id?(linked_doc, wikilink.block_id)
262
- return true
263
- end
264
-
265
- # wikilinks
266
-
267
- class WikiLinkBlock
268
- attr_accessor :link_type, :list_items
269
-
270
- # parameters ordered by appearance in regex
271
- def initialize(link_type, bullet_type=nil, filename=nil)
272
- @link_type ||= link_type
273
- @list_items = [] # li[0] = bullet_type; li[1] = filename
274
- @list_items << [ bullet_type, filename ] if !bullet_type.nil? && !filename.nil?
275
- end
276
-
277
- def add_item(bullet_type, filename)
278
- return if bullet_type.nil? || bullet_type.empty? || filename.nil? || filename.empty?
279
- @list_items << [ bullet_type, filename ]
280
- end
281
-
282
- def md_regex
283
- if typed? && has_items?
284
- # single
285
- if bullet_type?.empty?
286
- link_type = %r{#{@link_type}#{REGEX_LINK_TYPE}}
287
- list_item_strs = @list_items.map { |li| /#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\n/i }
288
- md_link_regex = /#{link_type}#{list_item_strs.join("")}/i
289
- # list (comma)
290
- elsif bullet_type? == ","
291
- tmp_list_items = @list_items.dup
292
- first_item = tmp_list_items.shift()
293
- link_type = /#{@link_type}#{REGEX_LINK_TYPE}#{REGEX_LINK_LEFT}#{first_item[1]}#{REGEX_LINK_RIGHT}\s*/i
294
- list_item_strs = tmp_list_items.map { |li| /#{li[0]}\s*#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\s*/i }
295
- md_link_regex = /#{link_type}#{list_item_strs.join('')}/i
296
- # list (md)
297
- elsif !bullet_type?.match(REGEX_BULLET).nil?
298
- link_type = %r{#{@link_type}#{REGEX_LINK_TYPE}\n}
299
- list_item_strs = @list_items.map { |li| /#{Regexp.escape(li[0])}\s#{REGEX_LINK_LEFT}#{li[1]}#{REGEX_LINK_RIGHT}\n/i }
300
- md_link_regex = /#{link_type}#{list_item_strs.join("")}/i
301
- else
302
- Jekyll.logger.error("bullet_types not uniform or invalid: #{bullet_type?}")
303
- end
304
- return md_link_regex
305
- else
306
- Jekyll.logger.error("WikiLinkBlockList.md_regex error")
121
+ # image processing
122
+ if wikilink.embedded? && wikilink.is_img?
123
+ return build_html_img_embed(wikilink.linked_img, is_svg=wikilink.is_img_svg?)
307
124
  end
308
- end
309
-
310
- def md_str
311
- if typed? && has_items?
312
- if bullet_type? == ","
313
- link_type = "#{@link_type}::"
314
- list_item_strs = @list_items.map { |li| "\[\[#{li[1]}\]\]#{li[0]}" }
315
- md_link_str = (link_type + list_item_strs.join('')).delete_suffix(",")
316
- elsif "+*-".include?(bullet_type?)
317
- link_type = "#{@link_type}::\n"
318
- list_item_strs = @list_items.map { |li| li[0] + " \[\[#{li[1]}\]\]\n" }
319
- md_link_str = link_type + list_item_strs.join('')
320
- else
321
- Jekyll.logger.error("Not a valid bullet_type: #{bullet_type?}")
322
- end
323
- return md_link_str
125
+ # markdown file processing
126
+ linked_doc = wikilink.linked_doc
127
+ link_type_txt = wikilink.is_typed? ? " #{$wiki_conf.css_name("typed")} #{wikilink.link_type}" : ""
128
+
129
+ inner_txt = wikilink.label_txt if wikilink.labelled?
130
+ lnk_doc_rel_url = relative_url(linked_doc.url)
131
+
132
+ if (wikilink.level == "file")
133
+ inner_txt = "#{linked_doc['title'].downcase}" if inner_txt.nil?
134
+ return build_html_embed(
135
+ linked_doc['title'],
136
+ linked_doc.content,
137
+ lnk_doc_rel_url
138
+ ) if wikilink.embedded?
139
+ elsif (wikilink.level == "header")
140
+ # from: https://github.com/jekyll/jekyll/blob/6855200ebda6c0e33f487da69e4e02ec3d8286b7/Rakefile#L74
141
+ lnk_doc_rel_url += "\#" + Jekyll::Utils.slugify(wikilink.header_txt)
142
+ inner_txt = "#{linked_doc['title'].downcase} > #{wikilink.header_txt.downcase}" if inner_txt.nil?
143
+ elsif (wikilink.level == "block")
144
+ lnk_doc_rel_url += "\#" + wikilink.block_id
145
+ inner_txt = "#{linked_doc['title'].downcase} > ^#{wikilink.block_id}" if inner_txt.nil?
324
146
  else
325
- Jekyll.logger.error("WikiLinkBlockList.md_str error")
326
- end
327
- end
328
-
329
- def bullet_type?
330
- bullets = @list_items.map { |li| li[0] }
331
- return bullets.uniq.first if bullets.uniq.size == 1
332
- end
333
-
334
- def has_items?
335
- return !@list_items.nil? && !@list_items.empty?
336
- end
337
-
338
- def typed?
339
- return !@link_type.nil? && !@link_type.empty?
340
- end
341
- end
342
-
343
- # the wikilink class knows everything about the original markdown syntax and its semantic meaning
344
- class WikiLinkInline
345
- attr_accessor :embed, :link_type, :filename, :header_txt, :block_id, :label_txt
346
-
347
- FILENAME = "filename"
348
- HEADER_TXT = "header_txt"
349
- BLOCK_ID = "block_id"
350
-
351
- # parameters ordered by appearance in regex
352
- def initialize(embed, link_type, filename, header_txt, block_id, label_txt)
353
- @embed ||= embed
354
- @link_type ||= link_type
355
- @filename ||= filename
356
- @header_txt ||= header_txt
357
- @block_id ||= block_id
358
- @label_txt ||= label_txt
359
- end
360
-
361
- # labels are really flexible, so we need to handle them with a bit more care
362
- def clean_label_txt
363
- return @label_txt.sub("[", "\\[").sub("]", "\\]")
364
- end
365
-
366
- # TODO: remove this once parsing is migrated to nokogiri...?
367
- def md_link_str
368
- embed = embedded? ? "!" : ""
369
- link_type = typed? ? "#{@link_type}::" : ""
370
- filename = described?(FILENAME) ? @filename : ""
371
- if described?(HEADER_TXT)
372
- header = "\##{@header_txt}"
373
- block = ""
374
- elsif described?(BLOCK_ID)
375
- header = ""
376
- block = "\#\^#{@block_id}"
377
- elsif !described?(FILENAME)
378
- Jekyll.logger.error "Invalid link level in 'md_link_str'. See WikiLink's 'md_link_str' for details"
379
- end
380
- label_ = labelled? ? "\|#{@label_txt}" : ""
381
- return "#{embed}#{link_type}\[\[#{filename}#{header}#{block}#{label_}\]\]"
382
- end
383
-
384
- def md_link_regex
385
- regex_embed = embedded? ? REGEX_LINK_EMBED : %r{}
386
- regex_link_type = typed? ? %r{#{@link_type}#{REGEX_LINK_TYPE}} : %r{}
387
- filename = described?(FILENAME) ? @filename : ""
388
- if described?(HEADER_TXT)
389
- header = %r{#{REGEX_LINK_HEADER}#{@header_txt}}
390
- block = %r{}
391
- elsif described?(BLOCK_ID)
392
- header = %r{}
393
- block = %r{#{REGEX_LINK_BLOCK}#{@block_id}}
394
- elsif !described?(FILENAME)
395
- Jekyll.logger.error "Invalid link level in regex. See WikiLink's 'md_link_regex' for details"
147
+ Jekyll.logger.error("Jekyll-Wikilinks: Invalid wikilink level")
396
148
  end
397
- label_ = labelled? ? %r{#{REGEX_LINK_LABEL}#{clean_label_txt}} : %r{}
398
- return %r{#{regex_embed}#{regex_link_type}#{REGEX_LINK_LEFT}#{filename}#{header}#{block}#{label_}#{REGEX_LINK_RIGHT}}
399
- end
400
-
401
- def describe
402
- return {
403
- 'level' => level,
404
- 'labelled' => labelled?,
405
- 'embedded' => embedded?,
406
- 'typed_link' => typed?,
407
- }
408
- end
409
-
410
- def labelled?
411
- return !@label_txt.nil? && !@label_txt.empty?
412
- end
413
-
414
- def typed?
415
- return !@link_type.nil? && !@link_type.empty?
416
- end
417
-
418
- def embedded?
419
- return !@embed.nil? && @embed == "!"
420
- end
421
-
422
- def is_img?
423
- # github supported image formats: https://docs.github.com/en/github/managing-files-in-a-repository/working-with-non-code-files/rendering-and-diffing-images
424
- return SUPPORTED_IMG_FORMATS.any?{ |ext| ext == File.extname(@filename).downcase }
425
- end
426
-
427
- def is_img_svg?
428
- return File.extname(@filename).downcase == ".svg"
429
- end
430
-
431
- def described?(chunk)
432
- return (!@filename.nil? && !@filename.empty?) if chunk == FILENAME
433
- return (!@header_txt.nil? && !@header_txt.empty?) if chunk == HEADER_TXT
434
- return (!@block_id.nil? && !@block_id.empty?) if chunk == BLOCK_ID
435
- Jekyll.logger.error "There is no link level '#{chunk}' in WikiLink Struct"
436
- end
149
+ return '<a class="' + $wiki_conf.css_name("wiki") + link_type_txt + '" href="' + lnk_doc_rel_url + '">' + inner_txt + '</a>'
150
+ end
437
151
 
438
- def level
439
- return "file" if described?(FILENAME) && !described?(HEADER_TXT) && !described?(BLOCK_ID)
440
- return "header" if described?(FILENAME) && described?(HEADER_TXT) && !described?(BLOCK_ID)
441
- return "block" if described?(FILENAME) && !described?(HEADER_TXT) && described?(BLOCK_ID)
442
- return "invalid"
152
+ # helpers
153
+
154
+ def sort_typed_first
155
+ # sorting inline wikilinks is necessary so when wikilinks are replaced,
156
+ # longer strings are replaced first so as not to accidentally overwrite
157
+ # substrings
158
+ # (this is especially likely if there is a matching wikilink that
159
+ # appears as both untyped and typed in a document)
160
+ temp = @wikilink_inlines.dup
161
+ @wikilink_inlines.clear()
162
+ typed_wikilinks = temp.select { |wl| wl.is_typed? }
163
+ untyped_wikilinks = temp.select { |wl| !wl.is_typed? }
164
+ @wikilink_inlines = typed_wikilinks.concat(untyped_wikilinks)
443
165
  end
444
166
  end
445
167
 
@@ -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