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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f6d8e47bdeb17eba9c47c70c35ed2622fe27ab4b6280fa1838d6c69f24723b9
4
- data.tar.gz: bfb12748858bd1c810b5613e1c2f516e64d65772082a680e24b3c796f37b6e80
3
+ metadata.gz: e65a8cc36608b07333b7fe02a0f37f100117c7ed94d0b2e0fa500520eee6a2aa
4
+ data.tar.gz: 8d28d1930fedbddfd17d13c431f42043cdfb3333493929f78977d8da122c0647
5
5
  SHA512:
6
- metadata.gz: 0e6483f4844cc0b0d8fd43be71040bce438b5357972e2139660ca1979a2b42843af2355577a46dc0f119902e281fb244b4fc53d8db7f8a3760889073be08db36
7
- data.tar.gz: 0af4216fa1fae8dbc086e785663d5ab4884afe83924c3b8fe5ef0ccb98fffa508dfc767b9c057b1dfec17efba36e3202eb494751ac53731209130c2108e43454
6
+ metadata.gz: bae180a6824ea1a646d9103a0e6701814e1792275ae1037119db819b91fc35a9d01d8fc5c4b64ea8ba689f9b799309fd662ce66e001fd89e1e83eb1114257fba
7
+ data.tar.gz: d9327ed183e0d9ade35f23633a70f01157b388cdb627de5890d63cfd151a0bf070ddf92313b92ca385f187b360b96fbaaa770b2dfc29cf9a28fc4ffdb45caa57
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+ require "jekyll"
3
+
4
+ module Jekyll
5
+ module WikiLinks
6
+
7
+ class PluginConfig
8
+
9
+ ATTR_KEY = "attributes"
10
+ CONFIG_KEY = "wikilinks"
11
+ ENABLED_KEY = "enabled"
12
+ EXCLUDE_KEY = "exclude"
13
+ # css-related
14
+ CSS_KEY = "css"
15
+ NAME_KEY = "name"
16
+ # names
17
+ ## valid
18
+ WEB_KEY = "web"
19
+ WIKI_KEY = "wiki"
20
+ ## invalid
21
+ INV_WIKI_KEY = "invalid_wiki"
22
+ # INV_WEB_KEY = "invalid_web"
23
+ ## embed
24
+ EMBED_WRAPPER_KEY = "embed_wrapper"
25
+ EMBED_TITLE_KEY = "embed_title"
26
+ EMBED_CONTENT_KEY = "embed_content"
27
+ EMBED_LINK_KEY = "embed_wiki_link"
28
+ EMBED_IMG_WRAPPER_KEY = "embed_image_wrapper"
29
+ EMBED_IMG_KEY = "embed_image"
30
+
31
+ def initialize(config)
32
+ @config ||= config
33
+ self.old_config_warn()
34
+ Jekyll.logger.debug "Excluded jekyll types: ", option(EXCLUDE_KEY) unless disabled?
35
+ end
36
+
37
+ # util
38
+
39
+ def css_name(name_key)
40
+ return option_css_name(name_key) if option_css_name(name_key)
41
+ # valid
42
+ return "wiki-link" if name_key == WIKI_KEY
43
+ # invalid
44
+ return "invalid-wiki-link" if name_key == INV_WIKI_KEY
45
+ # return "invalid-web-link" if name_key == INV_WEB_KEY
46
+ # embeds
47
+ return "embed-wrapper" if name_key == EMBED_WRAPPER_KEY
48
+ return "embed-title" if name_key == EMBED_TITLE_KEY
49
+ return "embed-content" if name_key == EMBED_CONTENT_KEY
50
+ return "embed-wiki-link" if name_key == EMBED_LINK_KEY
51
+ # img
52
+ return "embed-image-wrapper" if name_key == EMBED_IMG_WRAPPER_KEY
53
+ return "embed-image" if name_key == EMBED_IMG_KEY
54
+ end
55
+
56
+ def disabled?
57
+ option(ENABLED_KEY) == false
58
+ end
59
+
60
+ def disabled_attributes?
61
+ option_attributes(ENABLED_KEY) == false
62
+ end
63
+
64
+ def exclude?(type)
65
+ return false unless option(EXCLUDE_KEY)
66
+ return option(EXCLUDE_KEY).include?(type.to_s)
67
+ end
68
+
69
+ # options
70
+
71
+ def option(key)
72
+ @config[CONFIG_KEY] && @config[CONFIG_KEY][key]
73
+ end
74
+
75
+ def option_attributes(key)
76
+ @config[CONFIG_KEY] && @config[CONFIG_KEY][ATTR_KEY] && @config[CONFIG_KEY][ATTR_KEY][key]
77
+ end
78
+
79
+ def option_css(key)
80
+ @config[CONFIG_KEY] && @config[CONFIG_KEY][CSS_KEY] && @config[CONFIG_KEY][CSS_KEY][key]
81
+ end
82
+
83
+ def option_css_name(key)
84
+ option_css(NAME_KEY) && @config[CONFIG_KEY][CSS_KEY][NAME_KEY][key]
85
+ end
86
+
87
+ # !! deprecated !!
88
+
89
+ def option_exist?(key)
90
+ @config[CONFIG_KEY] && @config[CONFIG_KEY].include?(key)
91
+ end
92
+
93
+ def old_config_warn()
94
+ if @config.include?("wikilinks_collection")
95
+ 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."
96
+ end
97
+ if option_exist?("assets_rel_path")
98
+ Jekyll.logger.warn "As of 0.0.5, 'assets_rel_path' is now 'path'."
99
+ end
100
+ if @config.include?("d3_graph_data")
101
+ Jekyll.logger.warn "As of 0.0.6, 'd3_graph_data' and graph functionality have been moved to the 'jekyll-graph' plugin."
102
+ end
103
+ end
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module WikiLinks
5
+
6
+ class Context
7
+ attr_reader :site
8
+
9
+ def initialize(site)
10
+ @site = site
11
+ end
12
+
13
+ def registers
14
+ { :site => site }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+ require_relative "../util/regex"
3
+
4
+ module Jekyll
5
+ module WikiLinks
6
+
7
+ #
8
+ # this class is responsible for answering any questions
9
+ # related to jekyll markdown documents
10
+ # that are meant to be processed by the wikilinks plugin
11
+ #
12
+ class DocManager
13
+ CONVERTER_CLASS = Jekyll::Converters::Markdown
14
+
15
+ def initialize(site)
16
+ return if $wiki_conf.disabled?
17
+
18
+ markdown_converter = site.find_converter_instance(CONVERTER_CLASS)
19
+ # filter docs based on configs
20
+ docs = []
21
+ docs += site.pages if !$wiki_conf.exclude?(:pages)
22
+ docs += site.docs_to_write.filter { |d| !$wiki_conf.exclude?(d.type) }
23
+ @md_docs = docs.filter { |doc| markdown_converter.matches(doc.extname) }
24
+ if @md_docs.nil? || @md_docs.empty?
25
+ Jekyll.logger.debug("No documents to process.")
26
+ end
27
+
28
+ @static_files ||= site.static_files
29
+ end
30
+
31
+ # accessors
32
+
33
+ def all
34
+ return @md_docs
35
+ end
36
+
37
+ def get_doc_by_fname(filename)
38
+ return nil if filename.nil? || @md_docs.size == 0
39
+ docs = @md_docs.select{ |d| File.basename(d.basename, File.extname(d.basename)) == filename }
40
+ return nil if docs.nil? || docs.size > 1
41
+ return docs[0]
42
+ end
43
+
44
+ def get_doc_by_url(url)
45
+ return nil if url.nil? || @md_docs.size == 0
46
+ docs = @md_docs.select{ |d| d.url == url }
47
+ return nil if docs.nil? || docs.size > 1
48
+ return docs[0]
49
+ end
50
+
51
+ def get_doc_content(filename)
52
+ return nil if filename.nil? || @md_docs.size == 0
53
+ docs = @md_docs.select{ |d| File.basename(d.basename, File.extname(d.basename)) == filename }
54
+ return docs[0].content if docs.size == 1
55
+ return nil
56
+ end
57
+
58
+ def get_image_by_fname(filename)
59
+ return nil if filename.nil? || @static_files.size == 0 || !SUPPORTED_IMG_FORMATS.any?{ |ext| ext == File.extname(filename).downcase }
60
+ docs = @static_files.select{ |d| File.basename(d.relative_path) == filename }
61
+ return nil if docs.nil? || docs.size > 1
62
+ return docs[0]
63
+ end
64
+
65
+ def self.doc_has_header?(doc, header)
66
+ return nil if header.nil?
67
+ # leading + trailing whitespace is ignored when matching headers
68
+ header_results = doc.content.scan(REGEX_ATX_HEADER).flatten.map { |htxt| htxt.strip }
69
+ setext_header_results = doc.content.scan(REGEX_SETEXT_HEADER).flatten.map { |htxt| htxt.strip }
70
+ return header_results.include?(header.strip) || setext_header_results.include?(header.strip)
71
+ end
72
+
73
+ def self.doc_has_block_id?(doc, block_id)
74
+ return nil if block_id.nil?
75
+ # leading + trailing whitespace is ignored when matching blocks
76
+ block_id_results = doc.content.scan(REGEX_BLOCK).flatten.map { |bid| bid.strip }
77
+ return block_id_results.include?(block_id)
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require "jekyll"
3
+
4
+ # appending to built-in jekyll site object to pass data to jekyll-d3
5
+
6
+ module Jekyll
7
+
8
+ class Site
9
+ attr_accessor :doc_mngr, :link_index, :wiki_parser
10
+ end
11
+
12
+ end
@@ -0,0 +1,53 @@
1
+ require "jekyll"
2
+ require "nokogiri"
3
+
4
+ module Jekyll
5
+ module WikiLinks
6
+
7
+ class WebLinkConverter < Jekyll::Converter
8
+ priority :low
9
+
10
+ # config
11
+ CSS_KEY = "css"
12
+ CONFIG_KEY = "wikilinks"
13
+ EXCLUDE_KEY = "exclude"
14
+ # link types
15
+ # WEB_KEY = "web"
16
+ # WIKIL_KEY = "wiki"
17
+ # INVALID_KEY = "invalid"
18
+ # WIKI_EMBED_KEY = "wiki_embed"
19
+
20
+ def matches(ext)
21
+ ext =~ /^\.md$/i
22
+ end
23
+
24
+ def output_ext(ext)
25
+ ".html"
26
+ end
27
+
28
+ # add 'web-link' css class to links that aren't
29
+ # - wikilinks
30
+ # - contain an excluded css class
31
+ def convert(content)
32
+ excluded_classes = option_css(EXCLUDE_KEY)
33
+ if excluded_classes.nil? || excluded_classes.empty?
34
+ css_def = "a:not(.#{$wiki_conf.css_name("wiki")}):not(.#{$wiki_conf.css_name("embed_wiki_link")})"
35
+ else
36
+ css_def = "a:not(.#{$wiki_conf.css_name("wiki")}):not(.#{$wiki_conf.css_name("embed_wiki_link")}):not(.#{excluded_classes.join("):not(.")})"
37
+ end
38
+ parsed_content = Nokogiri::HTML::fragment(content)
39
+ parsed_content.css(css_def).each do |link|
40
+ link.add_class('web-link')
41
+ end
42
+ content = parsed_content.to_html
43
+ end
44
+
45
+ # config helpers
46
+
47
+ def option_css(key)
48
+ @config[CONFIG_KEY] && @config[CONFIG_KEY][CSS_KEY] && @config[CONFIG_KEY][CSS_KEY][key]
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module WikiLinks
5
+
6
+ module TypeFilters
7
+ # 'links' accepts untyped links, typed links, and attributes; fore and back.
8
+
9
+ # usage: {% assign note_links = page.links | doc_type = "notes" %}
10
+ # TODO: if you simply filter links against specific jekyll types, this filter is completely unecessary...
11
+ # // looping through backlinks:
12
+ # {% assign note_links = site.notes | where: "url", backlink.url | first %}
13
+ def doc_type(links, doc_type)
14
+ Jekyll.logger.error("'links' should not be nil") if links.nil?
15
+ return "No doc type given" if doc_type.empty?
16
+ return [] if links.empty?
17
+
18
+ site = @context.registers[:site]
19
+ links.each do |l|
20
+ # links
21
+ if l.keys.include?('url')
22
+ doc = site.documents.select{ |d| d.url == l['url'] && d.type.to_s == doc_type.to_s }
23
+ if !doc.nil? && doc.size != 1
24
+ links.delete(l)
25
+ end
26
+ # attributes
27
+ elsif l.keys.include?('urls')
28
+ l['urls'].each do |lurl|
29
+ doc = site.documents.select{ |d| d.url == lurl && d.type.to_s == doc_type.to_s }
30
+ if !doc.nil? && doc.size != 1
31
+ links['urls'].delete(lurl)
32
+ end
33
+ end
34
+ else
35
+ Jekyll.logge.error("In 'doc_type' filter, 'links' do not have 'url' or 'urls'")
36
+ end
37
+ end
38
+ return links.uniq
39
+ end
40
+
41
+ # usage: {% assign author_links = page.links | rel_type = "author" %}
42
+ def rel_type(links, link_type)
43
+ Jekyll.logger.error("'links' should not be nil") if links.nil?
44
+ return "No link type given" if link_type.empty?
45
+ return [] if links.empty?
46
+
47
+ site = @context.registers[:site]
48
+ links.each do |l|
49
+ if l.keys.include?('url')
50
+ if l['type'].to_s == link_type.to_s
51
+ docs = site.documents.select{ |d| d.url == l['url'] }
52
+ if !doc.nil? && doc.size != 1
53
+ links.delete(l)
54
+ end
55
+ end
56
+ elsif l.keys.include?('urls')
57
+ l['urls'].each do |lurl|
58
+ docs = site.documents.select{ |d| d.url == lurl }
59
+ if !doc.nil? && doc.size != 1
60
+ links['urls'].delete(lurl)
61
+ end
62
+ end
63
+ else
64
+ Jekyll.logge.error("In 'rel_type' filter, 'links' do not have 'url' or 'urls'")
65
+ end
66
+ end
67
+ return links.uniq
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ require "jekyll"
3
+
4
+ require_relative "../patch/context"
5
+ require_relative "../patch/doc_manager"
6
+ require_relative "../patch/site"
7
+ require_relative "../util/link_index"
8
+ require_relative "../util/parser"
9
+ require_relative "converter"
10
+
11
+ module Jekyll
12
+ module WikiLinks
13
+
14
+ class Generator < Jekyll::Generator
15
+
16
+ def generate(site)
17
+ return if $wiki_conf.disabled?
18
+
19
+ @site ||= site
20
+ @context ||= Jekyll::WikiLinks::Context.new(site)
21
+
22
+ # setup helper classes
23
+ @parser = Parser.new(@site)
24
+ @site.link_index = LinkIndex.new(@site)
25
+
26
+ @site.doc_mngr.all.each do |doc|
27
+ @parser.parse(doc.content)
28
+ @site.link_index.populate_forward(doc, @parser.wikilink_blocks, @parser.wikilink_inlines, @site.doc_mngr.all)
29
+ end
30
+ # wait until all docs are processed before assigning backward facing metadata,
31
+ # this ensures all attributed/backlinks are collected for assignment
32
+ @site.doc_mngr.all.each do |doc|
33
+ @site.link_index.populate_backward(doc, @site.doc_mngr.all)
34
+ @site.link_index.assign_metadata(doc)
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,112 @@
1
+ require_relative 'regex'
2
+
3
+ module Jekyll
4
+ module WikiLinks
5
+
6
+ class LinkIndex
7
+ attr_reader :index
8
+
9
+ def initialize(site)
10
+ @baseurl = site.baseurl
11
+ @index = {}
12
+ site.doc_mngr.all.each do |doc|
13
+ @index[doc.url] = LinksInfo.new()
14
+ end
15
+ end
16
+
17
+ def assign_metadata(doc)
18
+ doc.data['attributed'] = @index[doc.url].attributed.uniq
19
+ doc.data['attributes'] = @index[doc.url].attributes.uniq
20
+ doc.data['backlinks'] = @index[doc.url].backlinks.uniq
21
+ doc.data['forelinks'] = @index[doc.url].forelinks.uniq
22
+ doc.data['missing'] = @index[doc.url].missing.uniq
23
+ end
24
+
25
+ def populate_forward(doc, wikilink_blocks, wikilink_inlines, md_docs)
26
+ # attributes - blocks
27
+ wikilink_blocks.each do |tlbl|
28
+ urls = []
29
+ tlbl.list_items.each do |bullet_type, filename|
30
+ attr_doc = md_docs.detect { |d| File.basename(d.basename, File.extname(d.basename)) == filename }
31
+ if !attr_doc.nil?
32
+ urls << attr_doc.url
33
+ end
34
+ end
35
+ if !urls.nil? && !urls.empty?
36
+ @index[doc.url].attributes << {
37
+ 'type' => tlbl.link_type,
38
+ 'urls' => urls,
39
+ }
40
+ else
41
+ Jekyll.logger.warn("No documents found for urls: #{urls}")
42
+ end
43
+ end
44
+ # forelinks - inlines
45
+ wikilink_inlines.each do |wlil|
46
+ link_doc = md_docs.detect { |d| File.basename(d.basename, File.extname(d.basename)) == wlil.filename }
47
+ if !link_doc.nil?
48
+ @index[doc.url].forelinks << {
49
+ 'type' => wlil.link_type,
50
+ 'url' => link_doc.url,
51
+ }
52
+ end
53
+ end
54
+ # ...process missing links
55
+ doc.content.scan(REGEX_INVALID_WIKI_LINK).each do |m|
56
+ ltext = m[0]
57
+ @index[doc.url].missing << ltext
58
+ end
59
+ end
60
+
61
+ def populate_backward(doc, md_docs)
62
+ md_docs.each do |doc_to_link|
63
+ # attributed
64
+ @index[doc_to_link.url].attributes.each do |al|
65
+ urls = al['urls'].map { |url| self.remove_baseurl(url) }
66
+ if urls.include?(doc.url)
67
+ target_attr = @index[doc.url].attributed.detect { |atr| atr['type'] == al['type']}
68
+ # add
69
+ if !target_attr.nil?
70
+ target_attr['urls'] << doc_to_link.url
71
+ # create new
72
+ else
73
+ urls = @index[doc.url].attributed.detect { |a| a['type'] == al['type'] }
74
+ @index[doc.url].attributed << {
75
+ 'type' => al['type'],
76
+ 'urls' => [ doc_to_link.url ],
77
+ }
78
+ end
79
+ end
80
+ end
81
+ # backlinks
82
+ @index[doc_to_link.url].forelinks.each do |l|
83
+ if self.remove_baseurl(l['url']) == doc.url
84
+ @index[doc.url].backlinks << {
85
+ 'type' => l['type'],
86
+ 'url' => doc_to_link.url,
87
+ }
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def remove_baseurl(url)
94
+ return url.gsub(@baseurl, '') if !@baseurl.nil?
95
+ return url
96
+ end
97
+
98
+ class LinksInfo
99
+ attr_accessor :attributes, :attributed, :backlinks, :forelinks, :missing
100
+
101
+ def initialize
102
+ @attributed = [] # block typed backlinks; { 'type' => str, 'urls' => [ str ] }
103
+ @attributes = [] # block typed forelinks; { 'type' => str, 'urls' => [ str ] }
104
+ @backlinks = [] # inline typed and basic backlinks; { 'type' => str, 'url' => str }
105
+ @forelinks = [] # inline typed and basic forelinks; { 'type' => str, 'url' => str }
106
+ @missing = [] # missing forelinks; [ str ]
107
+ end
108
+ end
109
+ end
110
+
111
+ end
112
+ end