jekyll-wikilinks 0.0.3 → 0.0.7
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 +4 -4
- data/lib/jekyll-wikilinks/config.rb +109 -0
- data/lib/jekyll-wikilinks/patch/context.rb +19 -0
- data/lib/jekyll-wikilinks/patch/doc_manager.rb +82 -0
- data/lib/jekyll-wikilinks/patch/site.rb +12 -0
- data/lib/jekyll-wikilinks/plugins/converter.rb +53 -0
- data/lib/jekyll-wikilinks/plugins/filter.rb +73 -0
- data/lib/jekyll-wikilinks/plugins/generator.rb +41 -0
- data/lib/jekyll-wikilinks/util/link_index.rb +112 -0
- data/lib/jekyll-wikilinks/util/parser.rb +463 -0
- data/lib/jekyll-wikilinks/util/regex.rb +66 -0
- data/lib/jekyll-wikilinks/version.rb +7 -3
- data/lib/jekyll-wikilinks.rb +46 -267
- metadata +50 -13
- data/lib/jekyll-wikilinks/context.rb +0 -15
- data/lib/jekyll-wikilinks/filter.rb +0 -28
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 861b1b580036bacff2ddf67c3080e21ec36adfe550944fb637ee07ce6afa5b58
         | 
| 4 | 
            +
              data.tar.gz: 62380a8fbc94fdb4646055999b1deaf339a561bf3fbdfb8f858b0b8e993573fb
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fa76884a4da7bdca8ec6d389140a8c7f0b193563bba676abe81ea683b6932444abcfe1fb619c0e6186450f38eb81cced6067c154c275854fd73bc81b932c4455
         | 
| 7 | 
            +
              data.tar.gz: 4e2ffa8675e1a6d5066f472d3b021d1d8c20a11104c1802b0dd451c45d92120b410aea44c8bf8b6af6a42b0d9d3bb287cb4469382e8c66d7e03448cff650c0da
         | 
| @@ -0,0 +1,109 @@ | |
| 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 | 
            +
                  TYPED_KEY = "typed"
         | 
| 19 | 
            +
                  WEB_KEY = "web"
         | 
| 20 | 
            +
                  WIKI_KEY = "wiki"
         | 
| 21 | 
            +
                  ## invalid
         | 
| 22 | 
            +
                  INV_WIKI_KEY = "invalid_wiki"
         | 
| 23 | 
            +
                  # INV_WEB_KEY = "invalid_web"
         | 
| 24 | 
            +
                  ## embed
         | 
| 25 | 
            +
                  EMBED_WRAPPER_KEY = "embed_wrapper"
         | 
| 26 | 
            +
                  EMBED_TITLE_KEY = "embed_title"
         | 
| 27 | 
            +
                  EMBED_CONTENT_KEY = "embed_content"
         | 
| 28 | 
            +
                  EMBED_LINK_KEY = "embed_wiki_link"
         | 
| 29 | 
            +
                  EMBED_IMG_WRAPPER_KEY = "embed_image_wrapper"
         | 
| 30 | 
            +
                  EMBED_IMG_KEY = "embed_image"
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def initialize(config)
         | 
| 33 | 
            +
                    @config ||= config
         | 
| 34 | 
            +
                    self.old_config_warn()
         | 
| 35 | 
            +
                    Jekyll.logger.debug "Excluded jekyll types: ", option(EXCLUDE_KEY) unless disabled?
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # util
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def css_name(name_key)
         | 
| 41 | 
            +
                    return option_css_name(name_key) if option_css_name(name_key)
         | 
| 42 | 
            +
                    return "typed" if name_key == TYPED_KEY
         | 
| 43 | 
            +
                    # valid
         | 
| 44 | 
            +
                    return "wiki-link" if name_key == WIKI_KEY
         | 
| 45 | 
            +
                    # invalid
         | 
| 46 | 
            +
                    return "invalid-wiki-link" if name_key == INV_WIKI_KEY
         | 
| 47 | 
            +
                    # return "invalid-web-link" if name_key == INV_WEB_KEY
         | 
| 48 | 
            +
                    # embeds
         | 
| 49 | 
            +
                    return "embed-wrapper" if name_key == EMBED_WRAPPER_KEY
         | 
| 50 | 
            +
                    return "embed-title" if name_key == EMBED_TITLE_KEY
         | 
| 51 | 
            +
                    return "embed-content" if name_key == EMBED_CONTENT_KEY
         | 
| 52 | 
            +
                    return "embed-wiki-link" if name_key == EMBED_LINK_KEY
         | 
| 53 | 
            +
                    # img
         | 
| 54 | 
            +
                    return "embed-image-wrapper" if name_key == EMBED_IMG_WRAPPER_KEY
         | 
| 55 | 
            +
                    return "embed-image" if name_key == EMBED_IMG_KEY
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  def disabled?
         | 
| 59 | 
            +
                    option(ENABLED_KEY) == false
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def disabled_attributes?
         | 
| 63 | 
            +
                    option_attributes(ENABLED_KEY) == false
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def exclude?(type)
         | 
| 67 | 
            +
                    return false unless option(EXCLUDE_KEY)
         | 
| 68 | 
            +
                    return option(EXCLUDE_KEY).include?(type.to_s)
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  # options
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  def option(key)
         | 
| 74 | 
            +
                    @config[CONFIG_KEY] && @config[CONFIG_KEY][key]
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def option_attributes(key)
         | 
| 78 | 
            +
                    @config[CONFIG_KEY] && @config[CONFIG_KEY][ATTR_KEY] && @config[CONFIG_KEY][ATTR_KEY][key]
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def option_css(key)
         | 
| 82 | 
            +
                    @config[CONFIG_KEY] && @config[CONFIG_KEY][CSS_KEY] && @config[CONFIG_KEY][CSS_KEY][key]
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def option_css_name(key)
         | 
| 86 | 
            +
                    option_css(NAME_KEY) && @config[CONFIG_KEY][CSS_KEY][NAME_KEY][key]
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  # !! deprecated !!
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def option_exist?(key)
         | 
| 92 | 
            +
                    @config[CONFIG_KEY] && @config[CONFIG_KEY].include?(key)
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def old_config_warn()
         | 
| 96 | 
            +
                    if @config.include?("wikilinks_collection")
         | 
| 97 | 
            +
                      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."
         | 
| 98 | 
            +
                    end
         | 
| 99 | 
            +
                    if option_exist?("assets_rel_path")
         | 
| 100 | 
            +
                      Jekyll.logger.warn "As of 0.0.5, 'assets_rel_path' is now 'path'."
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                    if @config.include?("d3_graph_data")
         | 
| 103 | 
            +
                      Jekyll.logger.warn "As of 0.0.6, 'd3_graph_data' and graph functionality have been moved to the 'jekyll-graph' plugin."
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
            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,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
         |