forked from meewgumi/green-web-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbidirectional_links_generator.rb
124 lines (105 loc) · 4.33 KB
/
bidirectional_links_generator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# frozen_string_literal: true
class BidirectionalLinksGenerator < Jekyll::Generator
def generate(site)
graph_nodes = []
graph_edges = []
all_notes = site.collections['notes'].docs
all_pages = site.collections['pages'].docs
all_docs = all_notes + all_pages
link_extension = !!site.config["use_html_extension"] ? '.html' : ''
all_docs.each do |current_note|
# Convert all Wiki/Roam-style double-bracket link syntax to plain HTML
# anchor tag elements (<a>) with "internal-link" CSS class
all_docs.each do |note_potentially_linked_to|
title_from_filename = File.basename(
note_potentially_linked_to.basename,
File.extname(note_potentially_linked_to.basename)
).gsub('_', ' ').capitalize
external_href = note_potentially_linked_to.data["source"]
new_href = external_href ||= "#{note_potentially_linked_to.url}#{link_extension}"
anchor_tag = "<a class='internal-link' href='#{new_href}'>\\1</a>"
# Replace double-bracketed links with label using note title
# [[A note about cats|this is a link to the note about cats]]
current_note.content = current_note.content.gsub(
/\[\[#{title_from_filename}\|(.+?)(?=\])\]\](?!.*?[\r\n]+[`{3,}|~{3,}])/i,
anchor_tag
)
# Replace double-bracketed links with label using note filename
# [[cats|this is a link to the note about cats]]
current_note.content = current_note.content.gsub(
/\[\[#{note_potentially_linked_to.data['title']}\|(.+?)(?=\])\]\](?!.*?[\r\n]+[`{3,}|~{3,}])/i,
anchor_tag
)
# Replace double-bracketed links using note title
# [[a note about cats]]
current_note.content = current_note.content.gsub(
/\[\[(#{note_potentially_linked_to.data['title']})\]\](?!.*?[\r\n]+[`{3,}|~{3,}])/i,
anchor_tag
)
# Replace double-bracketed links using note filename
# [[cats]]
current_note.content = current_note.content.gsub(
/\[\[(#{title_from_filename})\]\](?!.*?[\r\n]+[`{3,}|~{3,}])/i,
anchor_tag
)
end
# At this point, all remaining double-bracket-wrapped words are
# pointing to non-existing pages, so let's turn them into disabled
# links by greying them out and changing the cursor
# Still need to find a way to exclude from codeblocks with ```
current_note.content = current_note.content.gsub(
/\[\[(.+?)\|(.+?)\]\]/,
<<~HTML.chomp # replace with this HTML (\\1 is what was inside the brackets)
<span title='There is no note that matches this link.' class='invalid-link'>\\1</span>
HTML
)
# current_note.content = current_note.content.gsub(
# /
# (?:^\[{2}.|\s{1}\[{2}) # Starting with [[ on newline or preceded by space
# ([^\]]+) # Capture entire filename
# \]{2} # Make sure it ends in ]]
# (?!.*?[\r\n]+[`{3,}|~{3,}]) # Exclude codeblocks
# /x, # match on the remaining double-bracket links
# <<~HTML.chomp # replace with this HTML (\\1 is what was inside the brackets)
# <span title='There is no note that matches this link.' class='invalid-link'>
# \\1
# </span>
# HTML
# )
end
# Identify note backlinks and add them to each note
all_notes.each do |current_note|
# Nodes: Jekyll
notes_linking_to_current_note = all_notes.filter do |e|
e.content.include?(current_note.url) and !e.data['source']
end
# Nodes: Graph
graph_nodes << {
id: note_id_from_note(current_note),
path: "#{current_note.url}#{link_extension}",
label: current_note.data['title'],
} unless current_note.path.include?('_notes/index.html')
# Edges: Jekyll
current_note.data['backlinks'] = notes_linking_to_current_note
# Edges: Graph
notes_linking_to_current_note.each do |n|
graph_edges << {
source: note_id_from_note(n),
target: note_id_from_note(current_note),
}
end
end
File.write('_includes/notes_graph.json', JSON.dump({
edges: graph_edges,
nodes: graph_nodes,
}))
end
def note_id_from_note(note)
note.data['title']
.dup
.gsub(/\W+/, ' ')
.delete(' ')
.to_i(36)
.to_s
end
end