My theme for forester (+plugins)
1import 'ninja-keys';
2import 'katex';
3
4import autoRenderMath from 'katex/contrib/auto-render';
5
6function partition(array, isValid) {
7 return array.reduce(([pass, fail], elem) => {
8 return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]];
9 }, [[], []]);
10}
11
12window.addEventListener("load", (event) => {
13 autoRenderMath(document.body)
14
15 const openAllDetailsAbove = elt => {
16 while (elt != null) {
17 if (elt.nodeName == 'DETAILS') {
18 elt.open = true
19 }
20
21 elt = elt.parentNode;
22 }
23 }
24
25 const jumpToSubtree = evt => {
26 if (evt.target.tagName === "A") {
27 return;
28 }
29
30 const link = evt.target.closest('span[data-target]')
31 const selector = link.getAttribute('data-target')
32 const tree = document.querySelector(selector)
33 openAllDetailsAbove(tree)
34 window.location = selector
35 }
36
37
38 [...document.querySelectorAll("[data-target^='#']")].forEach(
39 el => el.addEventListener("click", jumpToSubtree)
40 );
41
42 const ninja = document.querySelector('ninja-keys');
43 const baseUrl = document.querySelector('html').getAttribute('data-base-url')
44 const jsonUrl = `${baseUrl}forest.json`
45
46 fetch(jsonUrl)
47 .then((res) => res.json())
48 .then((trees) => {
49 const items = []
50
51 const editIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 -960 960 960" width="20"><path d="M480-120v-71l216-216 71 71-216 216h-71ZM120-330v-60h300v60H120Zm690-49-71-71 29-29q8-8 21-8t21 8l29 29q8 8 8 21t-8 21l-29 29ZM120-495v-60h470v60H120Zm0-165v-60h470v60H120Z"/></svg>'
52 const bookmarkIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 -960 960 960" width="20"><path d="M120-40v-700q0-24 18-42t42-18h480q24 0 42.5 18t18.5 42v700L420-167 120-40Zm60-91 240-103 240 103v-609H180v609Zm600 1v-730H233v-60h547q24 0 42 18t18 42v730h-60ZM180-740h480-480Z"/></svg>'
53
54 if (window.sourcePath) {
55 items.push({
56 id: 'edit',
57 title: 'Edit current tree in Visual Studio Code',
58 section: 'Commands',
59 hotkey: 'cmd+e',
60 icon: editIcon,
61 handler: () => {
62 window.location.href = `vscode://file/${window.sourcePath}`
63 }
64 })
65 }
66
67 const isTopTree = (item) => {
68 return item.tags ? item.tags.includes('top') : false
69 }
70
71 const addItemToSection = (item, section, icon) => {
72 const title =
73 item.taxon
74 ? (item.title ? `${item.taxon}. ${item.title}` : item.taxon)
75 : (item.title ? item.title : "Untitled")
76 const fullTitle = `${title} [${item.uri}]`
77 items.push({
78 id: item.uri,
79 title: fullTitle,
80 section: section,
81 icon: icon,
82 handler: () => {
83 window.location.href = item.route
84 }
85 })
86 }
87
88 const [top, rest] = partition(trees, isTopTree)
89 top.forEach((item) => addItemToSection(item, "Top Trees", bookmarkIcon))
90 rest.forEach((item) => addItemToSection(item, "All Trees", null))
91
92 ninja.data = items
93 });
94});
95
96