jekyll-wikilinks 0.0.5 → 0.0.6

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.
@@ -1,192 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
  require "jekyll"
3
3
 
4
- require_relative "jekyll-wikilinks/context"
5
- require_relative "jekyll-wikilinks/doc_manager"
6
- require_relative "jekyll-wikilinks/link_index"
7
- require_relative "jekyll-wikilinks/parser"
8
-
9
- require_relative "jekyll-wikilinks/filter"
10
4
  require_relative "jekyll-wikilinks/version"
11
5
 
12
- Liquid::Template.register_filter(JekyllWikiLinks::TypeFilters)
13
-
14
- module JekyllWikiLinks
15
- class Generator < Jekyll::Generator
16
- attr_accessor :site, :config, :md_docs, :doc_manager, :link_index, :parser, :graph_nodes, :graph_links
17
-
18
- # Use Jekyll's native relative_url filter
19
- include Jekyll::Filters::URLFilters
20
-
21
- CONVERTER_CLASS = Jekyll::Converters::Markdown
22
- # config
23
- CONFIG_KEY = "wikilinks"
24
- ENABLED_KEY = "enabled"
25
- EXCLUDE_KEY = "exclude"
26
- # graph config
27
- GRAPH_DATA_KEY = "d3_graph_data"
28
- ENABLED_GRAPH_DATA_KEY = "enabled"
29
- EXCLUDE_GRAPH_KEY = "exclude"
30
- GRAPH_ASSETS_LOCATION_KEY = "assets_rel_path"
31
-
32
- # identify missing links in doc via .invalid-wiki-link class and nested doc-text.
33
- REGEX_INVALID_WIKI_LINK = /invalid-wiki-link#{REGEX_NOT_GREEDY}\[\[(#{REGEX_NOT_GREEDY})\]\]/i
34
-
35
- def initialize(config)
36
- @config ||= config
37
- @testing ||= config['testing'] if config.keys.include?('testing')
38
- end
39
-
40
- def generate(site)
41
- return if disabled?
42
- self.old_config_warn()
43
- Jekyll.logger.debug "Excluded jekyll types: ", option(EXCLUDE_KEY)
44
- Jekyll.logger.debug "Excluded jekyll types in graph: ", option_graph(EXCLUDE_GRAPH_KEY)
45
-
46
- # setup site
47
- @site = site
48
- @context ||= JekyllWikiLinks::Context.new(site)
49
-
50
- # setup markdown docs
51
- docs = []
52
- docs += site.pages if !exclude?(:pages)
53
- docs += site.docs_to_write.filter { |d| !exclude?(d.type) }
54
- @md_docs = docs.filter {|doc| markdown_extension?(doc.extname) }
55
-
56
- # setup helper classes
57
- @doc_manager = DocManager.new(@md_docs, @site.static_files)
58
- @parser = Parser.new(@context, @markdown_converter, @doc_manager)
59
- @link_index = LinkIndex.new(@site, @doc_manager)
60
-
61
- # parse + populate index
62
- @md_docs.each do |doc|
63
- @parser.parse(doc.content)
64
- @link_index.populate_attributes(doc, @parser.typed_link_blocks)
65
- end
66
- @link_index.process
67
-
68
- # handle graph data
69
- @graph_nodes, @graph_links = [], []
70
- @md_docs.each do |doc|
71
- if !disabled_graph_data? && !self.excluded_in_graph?(doc.type)
72
- self.generate_graph_data(doc)
73
- end
74
- end
75
- if !disabled_graph_data?
76
- self.write_graph_data()
77
- end
78
- end
79
-
80
- # config helpers
81
-
82
- def disabled?
83
- option(ENABLED_KEY) == false
84
- end
6
+ # in order of expected execution
85
7
 
86
- def exclude?(type)
87
- return false unless option(EXCLUDE_KEY)
88
- return option(EXCLUDE_KEY).include?(type.to_s)
89
- end
90
-
91
- def has_custom_assets_path?
92
- return !!option_graph(GRAPH_ASSETS_LOCATION_KEY)
93
- end
94
-
95
- def markdown_extension?(extension)
96
- markdown_converter.matches(extension)
97
- end
98
-
99
- def markdown_converter
100
- @markdown_converter ||= site.find_converter_instance(CONVERTER_CLASS)
101
- end
102
-
103
- def option(key)
104
- config[CONFIG_KEY] && config[CONFIG_KEY][key]
105
- end
106
-
107
- # graph config helpers
108
-
109
- def disabled_graph_data?
110
- option_graph(ENABLED_GRAPH_DATA_KEY) == false
111
- end
8
+ # setup config
9
+ require_relative "jekyll-wikilinks/config"
10
+ Jekyll::Hooks.register :site, :after_init do |site|
11
+ # global '$wiki_conf' to ensure that all local jekyll plugins
12
+ # are reading from the same configuration
13
+ # (global var is not ideal, but is DRY)
14
+ $wiki_conf = Jekyll::WikiLinks::PluginConfig.new(site.config)
15
+ end
112
16
 
113
- def excluded_in_graph?(type)
114
- return false unless option_graph(EXCLUDE_KEY)
115
- return option_graph(EXCLUDE_KEY).include?(type.to_s)
116
- end
17
+ # setup docs (based on configs)
18
+ require_relative "jekyll-wikilinks/patch/doc_manager"
19
+ Jekyll::Hooks.register :site, :post_read do |site|
20
+ if !$wiki_conf.disabled?
21
+ site.doc_mngr = Jekyll::WikiLinks::DocManager.new(site)
22
+ end
23
+ end
117
24
 
118
- def option_graph(key)
119
- config[GRAPH_DATA_KEY] && config[GRAPH_DATA_KEY][key]
120
- end
25
+ # convert
26
+ require_relative "jekyll-wikilinks/plugins/converter"
121
27
 
122
- # graph helpers
28
+ # generate
29
+ require_relative "jekyll-wikilinks/plugins/generator"
123
30
 
124
- def generate_graph_data(doc)
125
- Jekyll.logger.debug "Processing graph nodes for doc: ", doc.data['title']
126
- # missing nodes
127
- missing_node_names = doc.content.scan(REGEX_INVALID_WIKI_LINK)
128
- if !missing_node_names.nil?
129
- missing_node_names.each do |missing_node_name_captures|
130
- missing_node_name = missing_node_name_captures[0]
131
- if graph_nodes.none? { |node| node[:id] == missing_node_name }
132
- Jekyll.logger.warn "Net-Web node missing: ", missing_node_name
133
- Jekyll.logger.warn " in: ", doc.data['slug']
134
- graph_nodes << {
135
- id: missing_node_name,
136
- url: '',
137
- label: missing_node_name,
138
- }
139
- end
140
- graph_links << {
141
- source: relative_url(doc.url),
142
- target: missing_node_name,
143
- }
144
- end
145
- end
146
- # existing nodes
147
- graph_nodes << {
148
- id: relative_url(doc.url),
149
- url: relative_url(doc.url),
150
- label: doc.data['title'],
151
- }
152
- # TODO: this link calculation ends up with duplicates -- re-visit this later.
153
- all_links = doc.data['attributed'] + doc.data['backlinks']
154
- all_links.each do |link|
155
- linked_doc = link['doc']
156
- if !excluded_in_graph?(linked_doc.type)
157
- graph_links << {
158
- source: relative_url(linked_doc.url),
159
- target: relative_url(doc.url),
160
- }
161
- end
162
- end
163
- end
31
+ # convert fores
32
+ # Jekyll::Hooks.register :documents, :pre_convert do |doc|
33
+ # Jekyll:WikiLinks::Parser.parse_blocks(doc)
34
+ # @site.link_index.populate_fores(doc, typed_link_blocks, md_docs)
35
+ # end
164
36
 
165
- def write_graph_data()
166
- assets_path = has_custom_assets_path? ? option_graph(GRAPH_ASSETS_LOCATION_KEY) : "/assets"
167
- if !File.directory?(File.join(site.source, assets_path))
168
- Jekyll.logger.error "Assets location does not exist, please create required directories for path: ", assets_path
169
- end
170
- # from: https://github.com/jekyll/jekyll/issues/7195#issuecomment-415696200
171
- static_file = Jekyll::StaticFile.new(site, site.source, assets_path, "graph-net-web.json")
172
- # TODO: make write file location more flexible -- requiring a write location configuration feels messy...
173
- File.write(@site.source + static_file.relative_path, JSON.dump({
174
- links: graph_links,
175
- nodes: graph_nodes,
176
- }))
177
- # tests fail without manually adding the static file, but actual site builds seem to do ok
178
- # ...although there does seem to be a race condition which causes a rebuild to be necessary in order to detect the graph data file
179
- if @testing
180
- @site.static_files << static_file if !@site.static_files.include?(static_file)
181
- end
182
- end
37
+ # convert backs
38
+ # Jekyll::Hooks.register :documents, :pre_convert do |doc|
39
+ # Jekyll:WikiLinks::Parser.parse_inlines(doc)
40
+ # @site.link_index.populate_backs(doc, typed_link_blocks, md_docs)
41
+ # end
183
42
 
184
- # !! deprecated !!
43
+ # generate metadata
44
+ # Jekyll::Hooks.register :documents, :post_convert do |doc|
45
+ # Jekyll:WikiLinks::Generator.generate(doc)
46
+ # end
185
47
 
186
- def old_config_warn()
187
- if config.include?("wikilinks_collection")
188
- Jekyll.logger.warn "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."
189
- end
190
- end
191
- end
192
- end
48
+ # hook up liquid filters
49
+ require_relative "jekyll-wikilinks/plugins/filter"
50
+ Liquid::Template.register_filter(Jekyll::WikiLinks::TypeFilters)
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-wikilinks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - manunamz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-03 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.12.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.12.3
13
41
  description:
14
42
  email:
15
43
  - manunamz@pm.me
@@ -18,20 +46,24 @@ extensions: []
18
46
  extra_rdoc_files: []
19
47
  files:
20
48
  - lib/jekyll-wikilinks.rb
21
- - lib/jekyll-wikilinks/context.rb
22
- - lib/jekyll-wikilinks/doc_manager.rb
23
- - lib/jekyll-wikilinks/filter.rb
24
- - lib/jekyll-wikilinks/jekyll_patch.rb
25
- - lib/jekyll-wikilinks/link_index.rb
26
- - lib/jekyll-wikilinks/naming_const.rb
27
- - lib/jekyll-wikilinks/parser.rb
49
+ - lib/jekyll-wikilinks/config.rb
50
+ - lib/jekyll-wikilinks/patch/context.rb
51
+ - lib/jekyll-wikilinks/patch/doc_manager.rb
52
+ - lib/jekyll-wikilinks/patch/site.rb
53
+ - lib/jekyll-wikilinks/plugins/converter.rb
54
+ - lib/jekyll-wikilinks/plugins/filter.rb
55
+ - lib/jekyll-wikilinks/plugins/generator.rb
56
+ - lib/jekyll-wikilinks/util/link_index.rb
57
+ - lib/jekyll-wikilinks/util/parser.rb
58
+ - lib/jekyll-wikilinks/util/regex.rb
28
59
  - lib/jekyll-wikilinks/version.rb
29
60
  homepage: https://github.com/manunamz/jekyll-wikilinks
30
61
  licenses:
31
- - MIT
62
+ - GPL3
32
63
  metadata:
33
64
  homepage_uri: https://github.com/manunamz/jekyll-wikilinks
34
65
  source_code_uri: https://github.com/manunamz/jekyll-wikilinks
66
+ changelog_uri: https://github.com/manunamz/jekyll-wikilinks/blob/main/CHANGELOG.md
35
67
  post_install_message:
36
68
  rdoc_options: []
37
69
  require_paths:
@@ -50,5 +82,5 @@ requirements: []
50
82
  rubygems_version: 3.2.17
51
83
  signing_key:
52
84
  specification_version: 4
53
- summary: Add jekyll support for [[wikilinks]] (in markdown).
85
+ summary: Add jekyll support for [[wikilinks]] (in markdown files).
54
86
  test_files: []
@@ -1,15 +0,0 @@
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
@@ -1,68 +0,0 @@
1
- require_relative "naming_const"
2
-
3
- module JekyllWikiLinks
4
- class DocManager
5
- attr_accessor :md_docs, :static_files
6
-
7
- # kramdown header regexes
8
- # atx header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L29
9
- REGEX_ATX_HEADER = /^\#{1,6}[\t ]*([^ \t].*)\n/i
10
- # setext header: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/header.rb#L17
11
- REGEX_SETEXT_HEADER = /^ {0,3}([^ \t].*)\n[-=][-=]*[ \t\r\f\v]*\n/i
12
- # obsidian-style
13
- REGEX_BLOCK = /.*\s\^#{REGEX_BLOCK_ID_TXT}^\n/i
14
-
15
- def initialize(md_docs, static_files)
16
- @md_docs ||= md_docs
17
- @static_files ||= static_files
18
- end
19
-
20
- def all
21
- return @md_docs
22
- end
23
-
24
- def get_doc_by_fname(filename)
25
- return nil if filename.nil? || @md_docs.size == 0
26
- docs = @md_docs.select{ |d| File.basename(d.basename, File.extname(d.basename)) == filename }
27
- return nil if docs.nil? || docs.size > 1
28
- return docs[0]
29
- end
30
-
31
- def get_doc_by_url(url)
32
- return nil if url.nil? || @md_docs.size == 0
33
- docs = @md_docs.select{ |d| d.url == url }
34
- return nil if docs.nil? || docs.size > 1
35
- return docs[0]
36
- end
37
-
38
- def get_doc_content(filename)
39
- return nil if filename.nil? || @md_docs.size == 0
40
- docs = @md_docs.select{ |d| File.basename(d.basename, File.extname(d.basename)) == filename }
41
- return docs[0].content if docs.size == 1
42
- return nil
43
- end
44
-
45
- # 'bname' -> 'basename' (filename with)
46
- def get_image_by_bname(filename)
47
- return nil if filename.nil? || @static_files.size == 0 || !SUPPORTED_IMG_FORMATS.any?{ |ext| ext == File.extname(filename).downcase }
48
- docs = @static_files.select{ |d| File.basename(d.relative_path) == filename }
49
- return nil if docs.nil? || docs.size > 1
50
- return docs[0]
51
- end
52
-
53
- def self.doc_has_header?(doc, header)
54
- return nil if header.nil?
55
- # leading + trailing whitespace is ignored when matching headers
56
- header_results = doc.content.scan(REGEX_ATX_HEADER).flatten.map { |htxt| htxt.strip }
57
- setext_header_results = doc.content.scan(REGEX_SETEXT_HEADER).flatten.map { |htxt| htxt.strip }
58
- return header_results.include?(header.strip) || setext_header_results.include?(header.strip)
59
- end
60
-
61
- def self.doc_has_block_id?(doc, block_id)
62
- return nil if block_id.nil?
63
- # leading + trailing whitespace is ignored when matching blocks
64
- block_id_results = doc.content.scan(REGEX_BLOCK).flatten.map { |bid| bid.strip }
65
- return block_id_results.include?(block_id)
66
- end
67
- end
68
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JekyllWikiLinks
4
- module TypeFilters
5
- # 'links' accepts both untyped links, typed links, and attributes; fore and back.
6
-
7
- # usage: {% assign note_links = page.links | doc_type = "notes" %}
8
- # "doc_type" is the jekyll type ("pages", "posts", "<collection-name>")
9
- def doc_type(links, doc_type)
10
- return if links.nil?
11
- target_links = []
12
- links.each do |l|
13
- target_links << l if self.to_string(l['doc'].type) == doc_type.to_str
14
- end
15
- return target_links.uniq
16
- end
17
-
18
- # usage: {% assign author_links = page.links | link_type = "author" %}
19
- # "link_type" is the wikilink's type, the string that appears before the link in `link-type::[[wikilink]]`.
20
- def link_type(links, link_type)
21
- return if links.nil?
22
- target_links = []
23
- link.each do |l|
24
- target_links << l if self.to_string(l['type'].to_str) == link_type.to_str
25
- end
26
- return target_links.uniq
27
- end
28
-
29
- def to_string(type)
30
- return type if type.is_a?(String)
31
- type = type.to_s
32
- begin
33
- String(type)
34
- rescue ::ArgumentError
35
- raise ArgumentError, "invalid type"
36
- end
37
- end
38
- end
39
- end
@@ -1,24 +0,0 @@
1
- # TODO: Would be nice to put LinkIndex-related data into real objects as opposed to sticking tons and tons of data into frontmatter...I think...
2
-
3
- # modelling off of 'related_posts': https://github.com/jekyll/jekyll/blob/6855200ebda6c0e33f487da69e4e02ec3d8286b7/lib/jekyll/document.rb#L402
4
- # module LinkLogic
5
- # attr_accessor :attributed, :attributes, :backlinks, :forelinks
6
-
7
- # # 'links' 'type' is 'nil' for untyped links.
8
- # # 'attributes' are block-level typed forelinks; their 'type' may not be 'nil'.
9
- # # 'attributed' are block-level typed backlinks; their 'type' may not be 'nil'.
10
- # # [{ 'type': str, 'doc': doc }, ...]
11
- # end
12
-
13
- # module Jekyll
14
- # class Page
15
- # # it would be nice if these would only exist if the page is guaranteed to be a markdown file.
16
- # include LinkLogic
17
- # end
18
- # end
19
-
20
- # module Jekyll
21
- # class Document
22
- # include LinkLogic
23
- # end
24
- # end
@@ -1,81 +0,0 @@
1
- module JekyllWikiLinks
2
- class LinkIndex
3
- attr_accessor :index
4
-
5
- # Use Jekyll's native relative_url filter
6
- include Jekyll::Filters::URLFilters
7
-
8
- REGEX_LINK_TYPE = /<a\sclass="wiki-link(\slink-type\s(?<link-type>([^"]+)))?"\shref="(?<link-url>([^"]+))">/i
9
-
10
- def initialize(site, doc_manager)
11
- @context ||= JekyllWikiLinks::Context.new(site)
12
- @doc_manager ||= doc_manager
13
- @index = {}
14
- @doc_manager.all.each do |doc|
15
- @index[doc.url] = LinksInfo.new()
16
- end
17
- end
18
-
19
- def process
20
- self.populate_links()
21
- # apply index info to each document
22
- @doc_manager.all.each do |doc|
23
- doc.data['attributed'] = @index[doc.url].attributed
24
- doc.data['backlinks'] = @index[doc.url].backlinks
25
- doc.data['attributes'] = @index[doc.url].attributes
26
- doc.data['forelinks'] = @index[doc.url].forelinks
27
- end
28
- end
29
-
30
- def populate_attributes(doc, typed_link_blocks)
31
- typed_link_blocks.each do |tl|
32
- attr_doc = @doc_manager.get_doc_by_fname(tl.filename)
33
- @index[doc.url].attributes << {
34
- 'type' => tl.link_type,
35
- 'doc' => attr_doc,
36
- }
37
- @index[attr_doc.url].attributed << {
38
- 'type' => tl.link_type,
39
- 'doc' => doc,
40
- }
41
- end
42
- end
43
-
44
- def populate_links()
45
- # for each document...
46
- @doc_manager.all.each do |doc|
47
- # ...process its forelinks
48
- doc.content.scan(REGEX_LINK_TYPE).each do |m|
49
- ltype, lurl = m[0], m[1]
50
- @index[doc.url].forelinks << {
51
- 'type' => ltype,
52
- 'doc' => @doc_manager.get_doc_by_url(lurl),
53
- }
54
- end
55
- # ...process its backlinks
56
- @doc_manager.all.each do |doc_to_backlink|
57
- doc_to_backlink.content.scan(REGEX_LINK_TYPE).each do |m|
58
- ltype, lurl = m[0], m[1]
59
- if lurl == relative_url(doc.url)
60
- @index[doc.url].backlinks << {
61
- 'type' => ltype,
62
- 'doc' => doc_to_backlink,
63
- }
64
- end
65
- end
66
- end
67
- end
68
- end
69
-
70
- class LinksInfo
71
- attr_accessor :attributed, :attributes, :backlinks, :forelinks
72
-
73
- def initialize
74
- @attributed = [] # (block-level typed forelinks)
75
- @attributes = [] # (block-level typed backlinks)
76
- @backlinks = []
77
- @forelinks = []
78
- end
79
- end
80
- end
81
- end
@@ -1,21 +0,0 @@
1
- # naming_const.rb
2
- # regex constants defining supported file types and valid names for files, variables, or text
3
- #
4
-
5
- module JekyllWikiLinks
6
- # TODO: Fix REGEX_NOT_GREEDY
7
- # REGEX_NOT_GREEDY = /[^(?!\]\])]+/i
8
- # REGEX_NOT_GREEDY = /(?!\]\]).*/i
9
- REGEX_NOT_GREEDY = /[^\]]+/i
10
- # <variables> only work with 'match' function, not with 'scan' function. :/
11
- # oh well...they are there for easier debugging...
12
- # valid naming conventions # capture indeces for WikiLinks class (0 is 'embed')
13
- REGEX_LINK_TYPE_TXT = /(?<link-type-txt>([^\n\s\!\#\^\|\]]+))/i # 1
14
- REGEX_FILENAME = /(?<filename>([^\\\/:\#\^\|\[\]]+))/i # 2
15
- REGEX_HEADER_TXT = /(?<header-txt>([^\!\#\^\|\[\]]+))/i # 3
16
- REGEX_BLOCK_ID_TXT = /(?<block-id>([^\\\/:\!\#\^\|\[\]]+))/i # 4
17
- REGEX_LABEL_TXT = /(?<label-txt>(#{REGEX_NOT_GREEDY}))/i # 5
18
-
19
- # from: https://docs.github.com/en/github/managing-files-in-a-repository/working-with-non-code-files/rendering-and-diffing-images
20
- SUPPORTED_IMG_FORMATS = Set.new(['.png', '.jpg', '.gif', '.psd', '.svg'])
21
- end