Skip to content

Commit e711cca

Browse files
committed
feat: use panflute which is way more sane
1 parent 9f5689e commit e711cca

File tree

2 files changed

+106
-8
lines changed

2 files changed

+106
-8
lines changed

interlinks/example.qmd

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
title: "Interlinks Example"
33
filters:
4-
- interlinks
4+
- interlinks.py
55
interlinks:
66
sources:
77
siuba:
8-
url: https://siuba.org
8+
url: https://siuba.org/
99
inv: null
1010
fallback: objects_siuba.json
1111
vetiver:
12-
url: https://vetiver.rstudio.com
12+
url: https://vetiver.rstudio.com/
1313
inv: null
1414
fallback: objects_vetiver.json
1515
---
@@ -20,10 +20,11 @@ interlinks:
2020

2121
Tilde means don't display module:
2222

23-
* `vetiver.SKLearnHandler`{.ref}
24-
* `~vetiver.SKLearnHandler`{.ref}
25-
* `siuba:siuba.dply.verbs.mutate`{.ref}
23+
* :ref:`vetiver.SKLearnHandler`
24+
* :ref:`~vetiver.SKLearnHandler`
25+
* :ref:`siuba.dply.verbs.mutate`
2626
- TODO: should be able to use `domain:...` to use a specific inventory file.
27-
* `some explanation <mutate>`{.ref}
27+
* :refzzz:`some explanation <mutate>`
2828
- TODO: this syntax let's you change the text of the link.
29-
* [some explanation](vetiver.SKLearnHandler)
29+
* [some explanation](`vetiver.SKLearnHandler`)
30+
* [](`vetiver.SKLearnHandler`)

interlinks/interlinks.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import json
2+
import panflute as pf
3+
4+
from plum import dispatch
5+
6+
7+
inventory = {}
8+
9+
10+
def ref_to_anchor(ref, text):
11+
# TODO: for now we just mutate el
12+
is_shortened = ref.startswith("~")
13+
14+
stripped = ref.lstrip("~")
15+
16+
try:
17+
entry = inventory[stripped]
18+
dst_url = entry["full_uri"]
19+
except KeyError:
20+
raise KeyError(f"Cross reference not found in an inventory file: {stripped}")
21+
22+
if not text:
23+
if is_shortened:
24+
# shorten names from module.sub_module.func_name -> func_name
25+
name = pf.Str(entry["name"].split(".")[-1])
26+
else:
27+
name = pf.Str(entry["name"])
28+
else:
29+
# when the element is an Link, content is a ListContainer, but it has to be
30+
# *splatted back into Link?
31+
return pf.Link(*text, url=dst_url)
32+
33+
return pf.Link(name, url=dst_url)
34+
35+
36+
@dispatch
37+
def visit(el, doc):
38+
return el
39+
# raise TypeError(f"Unsupported type: {type(el)}")
40+
41+
42+
@dispatch
43+
def visit(el: pf.MetaList, doc):
44+
meta = doc.get_metadata()
45+
46+
for doc_name, cfg in meta["interlinks"]["sources"].items():
47+
json_data = json.load(open(cfg["fallback"]))
48+
49+
for item in json_data["items"]:
50+
# TODO: what are the rules for inventories with overlapping names?
51+
# it seems like this is where priority and using source name as an
52+
# optional prefix in references is useful (e.g. siuba:a.b.c).
53+
full_uri = cfg["url"] + item["uri"].replace("$", item["name"])
54+
enh_item = {**item, "full_uri": full_uri}
55+
inventory[item["name"]] = enh_item
56+
57+
return el
58+
59+
60+
@dispatch
61+
def visit(el: pf.Doc, doc):
62+
return el
63+
64+
65+
@dispatch
66+
def visit(el: pf.Code, doc):
67+
# TODO: also need to remove ref. Should handle in parent?
68+
left_el = el.prev
69+
70+
if left_el == pf.Str(":ref:"):
71+
return ref_to_anchor(el.text, None)
72+
73+
return el
74+
75+
76+
@dispatch
77+
def visit(el: pf.Link, doc):
78+
if el.url.startswith("%60") and el.url.endswith("%60"):
79+
pf.debug("In a markdown link ref")
80+
81+
url = el.url[3:-3]
82+
83+
# Get URL ----
84+
85+
# TODO: url can be form external+invname:domain:reftype:target
86+
# for now, assume it's simply <target>. e.g. siuba.dply.verbs.mutate
87+
return ref_to_anchor(url, el.content)
88+
89+
return el
90+
91+
92+
def main(doc=None):
93+
return pf.run_filter(visit, doc=None)
94+
95+
96+
if __name__ == "__main__":
97+
main()

0 commit comments

Comments
 (0)