jekyll-wikilinks 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaacfcf7a6de57c6c9d002a59c332521c0883cafafc0d724b6df45bee5be3053
4
- data.tar.gz: adebf54d3556e767e8c96c5d083b7dd444b9ba5747b86be28f6724b59aca9881
3
+ metadata.gz: 5221a2c4f1d84db636f09d707f0d55891b17be4e35946d1bad55ed743083fde1
4
+ data.tar.gz: c5b64c09bab070d24a6a1e4af2461e3f09b996211cb4fdff89bd2d624ca4d0b5
5
5
  SHA512:
6
- metadata.gz: afc278ad86c5cae713715435216b4514d28b81d62132394ed7703eefa17794171197ddaeeb306cecef5aa111e511c14d3923fe2e5404ba4a4064305bc1f53746
7
- data.tar.gz: 1357f4c985b87fc762020001acc3eed0cb6a7e900e89127690606749a6b9063349d6ed75c36a133be964256993ba0e2ea081dc88a1bc58ceb0c2ac737a131ab9
6
+ metadata.gz: 6732b84944cbe73c21c87bb43dbdf9006929c2110c9980507e1739df270098a8aa1f6c0f80998160189440b5bb7f5df52193cdd0af4b41c7e1e6e6d825379517
7
+ data.tar.gz: 1718789738c86cdb00094070a470758c60f248af37c6e0c70b34701bc5c331fdc480f64e01a04350ddd4ac6859c59d808e6afa800bb1400357987229c4671330
@@ -1,68 +1,271 @@
1
1
  # frozen_string_literal: true
2
2
  require "jekyll"
3
+ require_relative "jekyll-wikilinks/context"
4
+ require_relative "jekyll-wikilinks/filter"
3
5
  require_relative "jekyll-wikilinks/version"
4
6
 
5
- # can't use converters because it does not have access to jekyll's 'site'
6
- # object -- which we need to build a element's href attribute.
7
- class JekyllWikilinks < Jekyll::Generator
8
7
 
9
- def generate(site)
10
- wikilinks_collection = site.config["wikilinks_collection"]
11
- wikilinks_collection = "notes" if wikilinks_collection.nil? || wikilinks_collection.empty?
12
- all_notes = site.collections[wikilinks_collection].docs
13
- # i like the idea, but the solution style isn't robust enough yet...
14
- # all_pages = site.pages
15
- all_docs = all_notes # + all_pages
16
- link_extension = !!site.config["use_html_extension"] ? '.html' : ''
8
+ module JekyllWikiLinks
9
+ class Generator < Jekyll::Generator
10
+ attr_accessor :site, :config, :md_docs, :graph_nodes, :graph_links
17
11
 
18
- all_docs.each do |cur_note|
19
- parse_wiki_links(site, all_docs, cur_note, link_extension)
12
+ # Use Jekyll's native relative_url filter
13
+ include Jekyll::Filters::URLFilters
14
+
15
+ CONFIG_KEY = "wikilinks"
16
+ CONVERTER_CLASS = Jekyll::Converters::Markdown
17
+ ENABLED_KEY = "enabled"
18
+ ENABLED_GRAPH_DATA_KEY = "enabled"
19
+ EXCLUDE_KEY = "exclude"
20
+ EXCLUDE_GRAPH_KEY = "exclude"
21
+ GRAPH_DATA_KEY = "d3_graph_data"
22
+
23
+ def initialize(config)
24
+ @config = config
25
+ end
26
+
27
+ def generate(site)
28
+ return if disabled?
29
+ Jekyll.logger.debug "Excluded jekyll types: ", option(EXCLUDE_KEY)
30
+ Jekyll.logger.debug "Excluded jekyll types in graph: ", option_graph(EXCLUDE_GRAPH_KEY)
31
+
32
+ @site = site
33
+ @context = context
34
+
35
+ documents = []
36
+ documents += site.pages if !exclude?(:pages)
37
+ included_docs = site.docs_to_write.filter { |d| !exclude?(d.type) }
38
+ documents += included_docs
39
+ @md_docs = documents.select {|doc| markdown_extension?(doc.extname) }
40
+
41
+ old_config_warn()
42
+
43
+ # build links
44
+ md_docs.each do |document|
45
+ parse_wiki_links(document)
46
+ end
47
+
48
+ # backlinks data handling
49
+ @graph_nodes, @graph_links = [], []
50
+ md_docs.each do |document|
51
+ document.data['backlinks'] = get_backlinks(document)
52
+ if !disabled_graph_data? && !exclude_graph?(document.type)
53
+ generate_graph_data(document)
54
+ end
55
+ end
56
+
57
+ if !disabled_graph_data?
58
+ write_graph_data()
59
+ end
60
+ end
61
+
62
+ def old_config_warn()
63
+ if config.include?("wikilinks_collection")
64
+ Jekyll.logger.warn "Deprecated: As of 0.0.3, 'wikilinks_collection' is no longer used for configs. jekyll-wikilinks will scan all markdown files by default. Check README for details: https://shorty25h0r7.github.io/jekyll-wikilinks/"
65
+ end
66
+ end
67
+
68
+ def parse_wiki_links(note)
69
+ # Convert all Wiki/Roam-style double-bracket link syntax to plain HTML
70
+ # anchor tag elements (<a>) with "wiki-link" CSS class
71
+ md_docs.each do |note_potentially_linked_to|
72
+ title_from_filename = File.basename(
73
+ note_potentially_linked_to.basename,
74
+ File.extname(note_potentially_linked_to.basename)
75
+ )
76
+
77
+ note_url = relative_url(note_potentially_linked_to.url) if note_potentially_linked_to&.url
78
+
79
+ # Replace double-bracketed links using note title
80
+ # [[feline.cats]]
81
+ regex_wl, cap_gr = regex_wiki_link(title_from_filename)
82
+ render_txt = note_potentially_linked_to.data['title'].downcase
83
+ note.content = note.content.gsub(
84
+ regex_wl,
85
+ "<a class='wiki-link' href='#{note_url}'>#{render_txt}</a>"
86
+ )
87
+
88
+ # Replace double-bracketed links with alias (right)
89
+ # [[feline.cats|this is a link to the note about cats]]
90
+ regex_wl, cap_gr = regex_wiki_link_w_alias_right(title_from_filename)
91
+ note.content = note.content.gsub(
92
+ regex_wl,
93
+ "<a class='wiki-link' href='#{note_url}'>#{cap_gr}</a>"
94
+ )
95
+
96
+ # Replace double-bracketed links with alias (left)
97
+ # [[this is a link to the note about cats|feline.cats]]
98
+ regex_wl, cap_gr = regex_wiki_link_w_alias_left(title_from_filename)
99
+ note.content = note.content.gsub(
100
+ regex_wl,
101
+ "<a class='wiki-link' href='#{note_url}'>#{cap_gr}</a>"
102
+ )
103
+ end
104
+
105
+ # At this point, all remaining double-bracket-wrapped words are
106
+ # pointing to non-existing pages, so let's turn them into disabled
107
+ # links by greying them out and changing the cursor
108
+ # vanilla wiki-links
109
+ regex_wl, cap_gr = regex_wiki_link()
110
+ note.content = note.content.gsub(
111
+ regex_wl,
112
+ "<span title='There is no note that matches this link.' class='invalid-wiki-link'>[[#{cap_gr}]]</span>"
113
+ )
114
+ # aliases -- both kinds
115
+ regex_wl, cap_gr = regex_wiki_link_w_alias()
116
+ note.content = note.content.gsub(
117
+ regex_wl,
118
+ "<span title='There is no note that matches this link.' class='invalid-wiki-link'>[[#{cap_gr}]]</span>"
119
+ )
120
+ end
121
+
122
+ def get_backlinks(doc)
123
+ backlinks = []
124
+ md_docs.each do |backlinked_doc|
125
+ if backlinked_doc.content.include?(doc.url)
126
+ backlinks << backlinked_doc
127
+ end
128
+ end
129
+ return backlinks
130
+ end
131
+
132
+ def invalid_wiki_links(doc)
133
+ regex, _ = regex_invalid_wiki_link()
134
+ return doc.content.scan(regex)[0]
135
+ end
136
+
137
+ def generate_graph_data(doc)
138
+ Jekyll.logger.debug "Processing graph nodes for doc: ", doc.data['title']
139
+ # missing nodes
140
+ missing_node_names = invalid_wiki_links(doc)
141
+ if !missing_node_names.nil?
142
+ missing_node_names.each do |missing_node_name|
143
+ if graph_nodes.none? { |node| node[:id] == missing_node_name }
144
+ Jekyll.logger.warn "Net-Web node missing: ", missing_node_name
145
+ Jekyll.logger.warn " in: ", doc.data['slug']
146
+ graph_nodes << {
147
+ id: missing_node_name,
148
+ url: '',
149
+ label: missing_node_name,
150
+ }
151
+ end
152
+ graph_links << {
153
+ source: relative_url(doc.url),
154
+ target: missing_node_name,
155
+ }
156
+ end
157
+ end
158
+ # existing nodes
159
+ graph_nodes << {
160
+ id: relative_url(doc.url),
161
+ url: relative_url(doc.url),
162
+ label: doc.data['title'],
163
+ }
164
+ get_backlinks(doc).each do |b|
165
+ if !exclude_graph?(b.type)
166
+ graph_links << {
167
+ source: relative_url(b.url),
168
+ target: relative_url(doc.url),
169
+ }
170
+ end
171
+ end
172
+ end
173
+
174
+ def write_graph_data()
175
+ # from: https://github.com/jekyll/jekyll/issues/7195#issuecomment-415696200
176
+ static_file = Jekyll::StaticFile.new(site, site.source, "/assets", "graph-net-web.json")
177
+ File.write(@site.source + static_file.relative_path, JSON.dump({
178
+ links: graph_links,
179
+ nodes: graph_nodes,
180
+ }))
181
+ end
182
+
183
+ def context
184
+ @context ||= JekyllWikiLinks::Context.new(site)
185
+ end
186
+
187
+
188
+ def exclude?(type)
189
+ return false unless option(EXCLUDE_KEY)
190
+ return option(EXCLUDE_KEY).include?(type.to_s)
191
+ end
192
+
193
+ def exclude_graph?(type)
194
+ return false unless option_graph(EXCLUDE_KEY)
195
+ return option_graph(EXCLUDE_KEY).include?(type.to_s)
196
+ end
197
+
198
+ def markdown_extension?(extension)
199
+ markdown_converter.matches(extension)
200
+ end
201
+
202
+ def markdown_converter
203
+ @markdown_converter ||= site.find_converter_instance(CONVERTER_CLASS)
204
+ end
205
+
206
+ def option(key)
207
+ config[CONFIG_KEY] && config[CONFIG_KEY][key]
208
+ end
209
+
210
+ def option_graph(key)
211
+ config[GRAPH_DATA_KEY] && config[GRAPH_DATA_KEY][key]
212
+ end
213
+
214
+ def disabled?
215
+ option(ENABLED_KEY) == false
216
+ end
217
+
218
+ def disabled_graph_data?
219
+ option_graph(ENABLED_GRAPH_DATA_KEY) == false
220
+ end
221
+
222
+ # regex
223
+ # returns two items: regex and a target capture group (text to be rendered)
224
+ # using functions instead of constants because of the need to access 'wiki_link_text'
225
+ # -- esp. when aliasing.
226
+
227
+ def regex_invalid_wiki_link()
228
+ # identify missing links in note via .invalid-wiki-link class and nested note-name.
229
+ regex = /invalid-wiki-link[^\]]+\[\[([^\]]+)\]\]/i
230
+ cap_gr = "\\1" # this is mostly just to remain consistent with other regex functions
231
+ return regex, cap_gr
232
+ end
233
+
234
+ def regex_wiki_link(wiki_link_text='')
235
+ if wiki_link_text.empty?
236
+ regex = /(\[\[)([^\|\]]+)(\]\])/i
237
+ cap_gr = "\\2"
238
+ return regex, cap_gr
239
+ else
240
+ regex = /\[\[#{wiki_link_text}\]\]/i
241
+ cap_gr = wiki_link_text
242
+ return regex, cap_gr
243
+ end
244
+ end
245
+
246
+ def regex_wiki_link_w_alias()
247
+ regex = /(\[\[)([^\]\|]+)(\|)([^\]]+)(\]\])/i
248
+ cap_gr = "\\2|\\4"
249
+ return regex, cap_gr
250
+ end
251
+
252
+ def regex_wiki_link_w_alias_left(wiki_link_text)
253
+ raise ArgumentError.new(
254
+ "Expected a value for 'wiki_link_text'"
255
+ ) if wiki_link_text.nil?
256
+ regex = /(\[\[)([^\]\|]+)(\|)(#{wiki_link_text})(\]\])/i
257
+ cap_gr = "\\2"
258
+ return regex, cap_gr
259
+ end
260
+
261
+ def regex_wiki_link_w_alias_right(wiki_link_text)
262
+ raise ArgumentError.new(
263
+ "Expected a value for 'wiki_link_text'"
264
+ ) if wiki_link_text.nil?
265
+ regex = /(\[\[)(#{wiki_link_text})(\|)([^\]]+)(\]\])/i
266
+ cap_gr = "\\4"
267
+ return regex, cap_gr
20
268
  end
21
- end
22
269
 
23
- def parse_wiki_links(site, all_notes, note, link_extension)
24
- # some regex taken from vscode-markdown-notes: https://github.com/kortina/vscode-markdown-notes/blob/master/syntaxes/notes.tmLanguage.json
25
- # Convert all Wiki/Roam-style double-bracket link syntax to plain HTML
26
- # anchor tag elements (<a>) with "internal-link" CSS class
27
- all_notes.each do |note_potentially_linked_to|
28
- namespace_from_filename = File.basename(
29
- note_potentially_linked_to.basename,
30
- File.extname(note_potentially_linked_to.basename)
31
- )
32
-
33
- # Replace double-bracketed links using note title
34
- # [[feline.cats]]
35
- # ⬜️ vscode-markdown-notes version: (\[\[)([^\|\]]+)(\]\])
36
- note.content = note.content.gsub(
37
- /\[\[#{namespace_from_filename}\]\]/i,
38
- "<a class='wiki-link' href='#{site.baseurl}#{note_potentially_linked_to.data['permalink']}#{link_extension}'>#{note_potentially_linked_to.data['title'].downcase}</a>"
39
- )
40
-
41
- # Replace double-bracketed links with alias (right)
42
- # [[feline.cats|this is a link to the note about cats]]
43
- # ✅ vscode-markdown-notes version: (\[\[)([^\]\|]+)(\|)([^\]]+)(\]\])
44
- note.content = note.content.gsub(
45
- /(\[\[)(#{namespace_from_filename})(\|)([^\]]+)(\]\])/i,
46
- "<a class='wiki-link' href='#{site.baseurl}#{note_potentially_linked_to.data['permalink']}#{link_extension}'>\\4</a>"
47
- )
48
-
49
- # Replace double-bracketed links with alias (left)
50
- # [[this is a link to the note about cats|feline.cats]]
51
- # ✅ vscode-markdown-notes version: (\[\[)([^\]\|]+)(\|)([^\]]+)(\]\])
52
- note.content = note.content.gsub(
53
- /(\[\[)([^\]\|]+)(\|)(#{namespace_from_filename})(\]\])/i,
54
- "<a class='wiki-link' href='#{site.baseurl}#{note_potentially_linked_to.data['permalink']}#{link_extension}'>\\2</a>"
55
- )
56
- end
57
-
58
- # At this point, all remaining double-bracket-wrapped words are
59
- # pointing to non-existing pages, so let's turn them into disabled
60
- # links by greying them out and changing the cursor
61
- note.content = note.content.gsub(
62
- /\[\[(.*)\]\]/i, # match on the remaining double-bracket links
63
- <<~HTML.chomp # replace with this HTML (\\1 is what was inside the brackets)
64
- <span title='There is no note that matches this link.' class='invalid-wiki-link'>[[\\1]]</span>
65
- HTML
66
- )
67
270
  end
68
- end
271
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllWikiLinks
4
+ class Context
5
+ attr_reader :site
6
+
7
+ def initialize(site)
8
+ @site = site
9
+ end
10
+
11
+ def registers
12
+ { :site => site }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllWikiLinks
4
+ module BackLinkTypeFilters
5
+ # usage:
6
+ # {% assign note_backlinks = page.backlinks | backlink_type = "notes" %}
7
+ def backlink_type(backlinks, type)
8
+ return if backlinks.nil?
9
+ target_backlinks = []
10
+ backlinks.each do |bl|
11
+ target_backlinks << bl if self.to_string(bl.type) == type
12
+ end
13
+ return target_backlinks
14
+ end
15
+
16
+ def to_string(type)
17
+ return type if type.is_a?(String)
18
+ type = type.to_s
19
+ begin
20
+ String(type)
21
+ rescue ::ArgumentError
22
+ raise ArgumentError, "invalid type"
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Liquid::Template.register_filter(JekyllWikiLinks::BackLinkTypeFilters)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Jekyll
4
- module Wikilinks
5
- VERSION = "0.0.2"
6
- end
7
- end
3
+ module JekyllWikiLinks
4
+ VERSION = "0.0.3"
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-wikilinks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - shorty25h0r7
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-07 00:00:00.000000000 Z
11
+ date: 2021-05-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -18,6 +18,8 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - lib/jekyll-wikilinks.rb
21
+ - lib/jekyll-wikilinks/context.rb
22
+ - lib/jekyll-wikilinks/filter.rb
21
23
  - lib/jekyll-wikilinks/version.rb
22
24
  homepage: https://github.com/shorty25h0r7/jekyll-wikilinks
23
25
  licenses: