jekyll-wikilinks 0.0.5 → 0.0.6

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