Created
April 22, 2021 10:13
-
-
Save DivineDominion/83feb20f7a1fa059b915d6e5c412e1b9 to your computer and use it in GitHub Desktop.
Kramdown GFM Parser extension for [[wikilinks]]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'kramdown/parser/kramdown' | |
require 'kramdown-parser-gfm' | |
# Based on the API doc comment: https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown.rb | |
class Kramdown::Parser::GFMWikiLink < Kramdown::Parser::GFM | |
def initialize(source, options) | |
super | |
# Override existing Table parser to use our own start Regex which adds a check for wikilinks | |
@@parsers.delete(:table) #Data(:table, TABLE_START, nil, "parse_table") | |
self.class.define_parser(:table, TABLE_START) | |
@span_parsers.unshift(:wikilinks) | |
end | |
# Override Kramdown table pipe check so we can write `[[pagename|Anchor Text]]`. | |
# https://github.com/gettalong/kramdown/blob/master/lib/kramdown/parser/kramdown/table.rb | |
# Regex test suite: https://regexr.com/5rb9q | |
TABLE_PIPE_CHECK = /^(?:\|(?!\[\[)|[^\[]*?(?!\[\[)[^\[]*?\||.*?(?:\[\[[^\]]+\]\]).*?\|)/.freeze # Fail for wikilinks in same line | |
TABLE_LINE = /#{TABLE_PIPE_CHECK}.*?\n/.freeze # Unchanged | |
TABLE_START = /^#{OPT_SPACE}(?=\S)#{TABLE_LINE}/.freeze # Unchanged | |
WIKILINKS_MATCH = /\[\[(.*?)\]\]/.freeze | |
define_parser(:wikilinks, WIKILINKS_MATCH, '\[\[') | |
def parse_wikilinks | |
line_number = @src.current_line_number | |
# Advance parser position | |
@src.pos += @src.matched_size | |
wikilink = Wikilink.parse(@src[1]) | |
el = Element.new(:a, nil, {'href' => wikilink.url, 'title' => wikilink.title}, location: line_number) | |
add_text(wikilink.title, el) | |
@tree.children << el | |
el | |
end | |
# [[page_name|Optional title]] | |
# For a converter that uses the available pages, see: <https://github.com/metala/jekyll-wikilinks-plugin/blob/master/wikilinks.rb> | |
class Wikilink | |
def self.parse(text) | |
name, title = text.split('|', 2) | |
title = name if title.nil? | |
self.new(name, title) | |
end | |
attr_accessor :name, :title | |
attr_reader :match | |
def initialize(name, title) | |
@name = name.strip.gsub(/ +/, '-') | |
@title = title | |
end | |
def title | |
@title || @name | |
end | |
def url | |
"/wiki/#{@name.downcase}" | |
end | |
end | |
end |
Thanks! Question -- do you really need to redefine the Table regexes? Is there not a way to force the wikilinks regex match to happen first?
@rathboma I think no; but I'd be happy if you find a better way :) The table parser is block-level, the wikilink parser span level. You'd need to add a block level parser that detect a non-table block with wikilink inside and then prevent the table, maybe 🤔
Fair enough! FYI I got this working. It's great. thank you for posting!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm using this in a nanoc statically built website.
That option to select the flavor
GFMWikiLink
is all I needed to do.Didn't actually write anything on the wiki since figuring this out, but it's at https://christiantietze.de/wiki/ :)
The website repo isn't public so I don't have to worry if I ever committed a password -- but if you want to see anything, send me an email.