Dotfiles, utilities, and other apparatus.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

83 lines
2.9 KiB

#!/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)