|
#!/usr/bin/env python3
|
|
|
|
# Fuck off, pylint:
|
|
# pylint: disable=all
|
|
|
|
"""
|
|
Pandoc filter to add a self-link below headers.
|
|
|
|
I hacked this out based on the Pandoc filter documentation here:
|
|
|
|
https://pandoc.org/filters.html
|
|
|
|
And the source of pandocfilters:
|
|
|
|
https://github.com/jgm/pandocfilters
|
|
|
|
You can look at a view of the AST generated by Pandoc with something like:
|
|
|
|
pandoc -s -t native index.md | less
|
|
|
|
Or get JSON output to feed directly to the filter for easier testing like so:
|
|
|
|
pandoc -s -t json index.md | ./filter.py
|
|
|
|
It wasn't super obvious to me how to go about what I wanted to do, but by
|
|
messing around with the above output I was able to get a general sense of
|
|
what was required.
|
|
|
|
Headers and Links look like these in the native output format:
|
|
|
|
Header 2 ("resources-discussed",[],[]) [Str "resources",Space,Str "discussed"]
|
|
|
|
Link ("",[],[]) [Str "wrote",Space,Str "about",Space,Str "adopting",Space,Str "Vimwiki"] ("/2017/1/22","")
|
|
|
|
I'm not sure what each of the value slots there do, but you can tell what some
|
|
of them are.
|
|
"""
|
|
|
|
from pandocfilters import toJSONFilter, Header, Str, Link, Space, Para, attributes, Div
|
|
|
|
def linkify_headers(key, value, format, meta):
|
|
"""Walk the AST for the document, replace Header elements with
|
|
a self-linking version."""
|
|
|
|
if key == 'Header':
|
|
|
|
# version 1: Puts the link inside the header, but messes with table of
|
|
# contents formatting:
|
|
|
|
# This should be the text contents of the header (consisting of a series
|
|
# of Str and Space objects):
|
|
# header_contents = value[2]
|
|
|
|
# Make a new list starting with a Link and a space:
|
|
# text_with_link = [Link(("", [], []), [ Str('#') ], ["#" + value[1][0], ""]), Space()]
|
|
# ...then put it in front of the header's text:
|
|
# text_with_link.extend(header_contents)
|
|
# return Header(value[0], value[1], text_with_link)
|
|
|
|
# version 2: Tacks a div after the header with a paragraph link. The
|
|
# explicitly-defined link prefix here (matching the one given in the
|
|
# Makefile) is necessary because the filtering happens before the ToC
|
|
# is generated, so the id of the headers gets mutated in the meanwhile.
|
|
#
|
|
# The div is just for styling purposes.
|
|
#
|
|
# This is all pretty silly, and honestly I kind of view this whole
|
|
# thing as a failed experiment.
|
|
|
|
div_attr = attributes({'class': 'header-and-link'})
|
|
link = Link(("", [], []), [Str('#' + value[1][0])], ["#" + value[1][0], ""])
|
|
contents_link = Link(("", [], []), [Str('#toc')], ["#toc", ""])
|
|
para = Para([link, Str(" | "), contents_link])
|
|
div = Div(div_attr, [para])
|
|
header = Header(value[0], value[1], value[2])
|
|
|
|
# For some fucking reason, things explode if you try putting the header
|
|
# inside the div.
|
|
|
|
return [header, div]
|
|
|
|
if __name__ == "__main__":
|
|
toJSONFilter(linkify_headers)
|