jekyll-wikilinks 0.0.2 → 0.0.3

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.
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: