@@ -47,39 +47,61 @@ def prefixed_url(url, base_url)
47
47
return url
48
48
end
49
49
50
+ def is_modifiable_markdown_part? ( part )
51
+ # NOTE: This allows usage of our custom markdown notation in the other (h2-h6) headings as well.
52
+ # Unlike in the case of the page titles (h1), the (lunr) search will work nicely for the text parts.
53
+ return part . start_with? ( '[[' ) || part . start_with? ( '#' )
54
+ end
55
+
50
56
def make_tooltip ( page , page_links , id , url , match )
51
- match_parts = match . split ( /\| / )
57
+ match_parts = match . split ( /(?<!\\ )\| / )
58
+
52
59
# If the text has an '|' it means it comes from our special autolink/tooltip [[text|id]] markdown block
53
60
# We have to reparse it a bit and get the id we must use
54
61
if match_parts . length > 1
55
62
#puts "match_parts: #{match_parts}"
56
- match = match_parts [ 0 ]
63
+ title = match_parts [ 0 ]
64
+ if title . length <= 0
65
+ puts "Error: Empty title in matching part: '#{ match } ' -> #{ match_parts } "
66
+ # nil means, show the original markdown part, instead of a half rendered one
67
+ return nil
68
+ end
57
69
id = match_parts [ 1 ]
70
+ # This is a special use case [[title|-]] that protects the given title from further processing
71
+ if id == '-'
72
+ # Just use the original title text
73
+ return title
74
+ end
58
75
link_data = page_links [ id ]
59
76
if link_data != nil
60
77
url = link_data [ "url" ]
61
78
url = prefixed_url ( url , page . site . config [ "baseurl" ] )
62
79
else
63
- puts "Error: Unknown ID in matching part: #{ match_parts } "
64
- return match
80
+ puts "Error: Unknown ID in matching part: '#{ match } ' -> #{ match_parts } "
81
+ # nil means, show the original markdown part, instead of a half rendered one
82
+ return nil
65
83
end
84
+ else
85
+ title = match
66
86
end
67
87
68
88
if id == nil or id . length <= 0
69
- puts "Error: Empty ID in matching part: #{ match } "
70
- return match
89
+ puts "Error: Empty ID in matching part: '#{ match } ' -> #{ match_parts } "
90
+ # nil means, show the original markdown part, instead of a half rendered one
91
+ return nil
71
92
end
72
93
if url == nil or url . length <= 0
73
- puts "Error: Empty URL for ID: #{ id } in matching part: #{ match } "
74
- return match
94
+ puts "Error: Empty URL for ID: '#{ id } ' in matching part: '#{ match } ' -> #{ match_parts } "
95
+ # nil means, show the original markdown part, instead of a half rendered one
96
+ return nil
75
97
end
76
98
77
99
# NOTE: Now we treat every link that has protocol prefix part as an external one
78
100
# that allows usage of direct links anywhere if needed (not recommended, plz use external_links.yml instead)
79
101
# but, at the same time requires e.g. all the really external links to be fully qualified (even in external_links.yml as well)
80
102
external_url = is_prefixed_url? ( url )
81
- match = save_from_markdownify ( match )
82
- replacement_text = '<a href="' + url + '" class="nav-link content-tooltip"' + ( external_url ? ' target="_blank"' : '' ) + '>' + match + '</a>'
103
+ title = save_from_markdownify ( title )
104
+ replacement_text = '<a href="' + url + '" class="nav-link content-tooltip"' + ( external_url ? ' target="_blank"' : '' ) + '>' + title + '</a>'
83
105
# puts "replacement_text: " + replacement_text
84
106
85
107
return replacement_text
@@ -101,11 +123,15 @@ def process_markdown_part(page, markdown_part, page_links, full_pattern, id, url
101
123
left_separator = $1
102
124
matched_text = $2
103
125
right_separator = $3
104
- #puts "\nmatch: #{match}\nleft_separator: #{left_separator}\nmatched_text: #{matched_text}\nright_separator: #{right_separator}"
126
+ # puts "\nmatch: #{match}\nleft_separator: #{left_separator}\nmatched_text: #{matched_text}\nright_separator: #{right_separator}"
105
127
106
128
replacement_text = make_tooltip ( page , page_links , id , url , matched_text )
107
- if add_separator
108
- replacement_text = left_separator + replacement_text + right_separator
129
+ if replacement_text != nil
130
+ if add_separator
131
+ replacement_text = left_separator + replacement_text + right_separator
132
+ end
133
+ else
134
+ replacement_text = markdown_part . gsub ( /(?<!\\ )\| / , "\\ \| " )
109
135
end
110
136
replacement_text
111
137
end
@@ -120,10 +146,26 @@ def process_markdown_parts(page, markdown)
120
146
# Regular expression pattern to match special Markdown blocks
121
147
# Unlike the others this needs grouping as we use do |match| for enumeration
122
148
# NOTE: Use multi line matching partially as e.g. code blocks can span to multiple lines
123
- special_markdown_blocks_pattern = /((?m:````.*?````|```.*?```|``.*?``|`.*?`)|\[ \[ .*?\] \] |\[ .*?\] \( .*?\) \{ \: .*?\} |\[ .*?\] \( .*?\) |\[ .*?\] \{ .*?\} |^#+\s .*?$)/
149
+ markdown_blocks_pattern = /((?m:````.*?````|```.*?```|``.*?``|`.*?`)|\[ \[ (?:[^\] ^\[ ]|\\ \[ |\\ \] )*?\] \] |\[ [^\] ^\[ ]*?\] \( .*?\) \{ \: .*?\} |\[ [^\] ^\[ ]*?\] \( .*?\) |\[ [^\] ^\[ ]*?\] :.*?$|\[ [^\] ^\[ ]*?\] \s *\[ .*?\] |^#+\s .*?$)/
150
+ # TODO: Always sync the bellow with the one-liner version for readability
151
+ # FIXME: Check why the /x version bellow is not working the same way
152
+ # markdown_blocks_pattern = /( # Either Code blocks
153
+ # (?m: # Even Multiline ones
154
+ # ````.*?```` | # Code block with 4 backticks
155
+ # ```.*?``` | # Code block with 3 backticks
156
+ # ``.*?`` | # Code block with 2 backticks
157
+ # `.*?` # Inline code with 1 backtick
158
+ # ) | #
159
+ # \[\[(?:[^\]^\[]|\\\[|\\\])*?\]\] | # or Our special, custom markdown notation
160
+ # \[[^\]^\[]*?\]\(.*?\)\{\:.*?\} | # or Link with attribute
161
+ # \[[^\]^\[]*?\]\(.*?\) | # Link without attribute
162
+ # \[[^\]^\[]*?\]:.*?$ | # Link reference label declaration
163
+ # \[[^\]^\[]*?\]\s*\[.*?\] | # Link using reference label
164
+ # ^#+\s.*?$ # or Headers
165
+ # )/x
124
166
125
167
# Split the content by special Markdown blocks
126
- markdown_parts = markdown . split ( special_markdown_blocks_pattern )
168
+ markdown_parts = markdown . split ( markdown_blocks_pattern )
127
169
#puts markdown_parts
128
170
markdown_parts . each_with_index do |markdown_part , markdown_index |
129
171
# puts "---------------\nmarkdown_index: " + markdown_index.to_s + "\n" + (markdown_index.even? ? "NOT " : "") + "markdown_part: " + markdown_part
@@ -144,27 +186,36 @@ def process_markdown_parts(page, markdown)
144
186
#puts "searching for #{title} with pattern #{pattern}"
145
187
146
188
if markdown_index . even?
147
- # Content outside of special Markdown blocks, aka. pure text (NOTE: Also excludes the reqursively self added <a ...>title</a> tooltips/links)
189
+ # Content outside of Markdown blocks, aka. pure text
148
190
149
191
# Search for known link titles
150
192
# NOTE: Using multi line matching here will not help either if the pattern itself is in the middle broken/spaned to multiple lines, so
151
193
# using whitespace replacements now inside the patter to handle this, see above!
194
+ # NOTE: Also excludes the reqursively self added <a ...>title</a> tooltips/links
152
195
full_pattern = /(^|[\s .,;:&'"(])(#{ pattern } )([\s .,;:&'")]|\z )(?![^<]*?<\/ a>)/
153
196
markdown_part = process_markdown_part ( page , markdown_part , page_links , full_pattern , id , url , true )
154
197
else
155
- # Content inside of special Markdown blocks
198
+ # Content inside of Markdown blocks
156
199
157
- # Handle own auto\tooltip links [[title]], but NOT [[title|id]], see bellow why
158
- full_pattern = /(\[ \[ )(#{ pattern } )(\] \] )/
159
- markdown_part = process_markdown_part ( page , markdown_part , page_links , full_pattern , id , url , false )
200
+ # Handle our special markdown notation autolink/tooltip links [[title]], but NOT [[title|id]], see bellow why
201
+ if is_modifiable_markdown_part? ( markdown_part )
202
+ full_pattern = /(\[ \[ )(#{ pattern } )(\] \] )/
203
+ markdown_part = process_markdown_part ( page , markdown_part , page_links , full_pattern , id , url , false )
204
+ end
160
205
end
161
206
end
162
207
208
+ # Handle our special markdown notation autolink/tooltip links [[title|id]]
209
+ # This must be a separate run, as independent from the given title, if ID is presented it will always override the title, and the title exclusion as well
163
210
if markdown_index . odd?
164
- # Handle own auto\tooltip links [[title|id]]
165
- # This must be a separate run, as independent from the given title, if ID is presented it will always override title, and title exclusion as well
166
- full_pattern = /(\[ \[ )(.+\| .+)(\] \] )/
167
- markdown_part = process_markdown_part ( page , markdown_part , page_links , full_pattern , nil , nil , false )
211
+ # Content inside of Markdown blocks
212
+
213
+ if is_modifiable_markdown_part? ( markdown_part )
214
+ # puts "\nmarkdown_index: " + markdown_index.to_s + "\n" + (markdown_index.even? ? "NOT " : "") + "markdown_part: " + markdown_part
215
+ # NOTE: The differences in the patter is intentional, allowing empty part on both sides of | allows the same flow inside process_markdown_part
216
+ full_pattern = /(\[ \[ )(.*?(?<!\\ )\| .*?)(\] \] )/
217
+ markdown_part = process_markdown_part ( page , markdown_part , page_links , full_pattern , nil , nil , false )
218
+ end
168
219
end
169
220
170
221
#puts "new markdown_part: " + markdown_part
@@ -293,7 +344,7 @@ def gen_page_link_data(links_dir, link_files_pattern)
293
344
page_id = yaml_content [ 'id' ]
294
345
page_url = yaml_content [ 'url' ]
295
346
page_title = yaml_content [ 'title' ]
296
- chars_to_remove = %{"'} #!?.:;}
347
+ chars_to_remove = %{"'}
297
348
page_title = page_title . gsub ( /\A [#{ Regexp . escape ( chars_to_remove ) } ]+|[#{ Regexp . escape ( chars_to_remove ) } ]+\z / , '' )
298
349
#puts "page_title: " + page_title
299
350
if page_title . length == 0
0 commit comments