WE GOT DROPDOWNS

This commit is contained in:
object-Object 2023-09-01 01:33:46 -04:00
parent f2cbe48d88
commit fcb808fe63
6 changed files with 78 additions and 18 deletions

View file

@ -29,11 +29,7 @@
aria-haspopup="true"
aria-expanded="false"
>{{ version }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
</ul>
<ul class="dropdown-menu" id="version-dropdown"></ul>
</li>
<li class="dropdown">
<a
@ -44,11 +40,7 @@
aria-haspopup="true"
aria-expanded="false"
>{{ lang }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
</ul>
<ul class="dropdown-menu" id="lang-dropdown"></ul>
</li>
</ul>
</div>

View file

@ -141,6 +141,12 @@ canvas.spell-viz {
.dropdown-menu {
background-color: #402a40;
min-width: 120px;
}
.dropdown-menu-ltr {
left: 0;
right: auto;
}
.dropdown-menu > li > a {

View file

@ -42,7 +42,7 @@
<script>
{% filter indent(6) %}
{%+ include_raw "main.js" %}
{%+ include "main.js.jinja" %}
{% endfilter %}
</script>
</head>

View file

@ -292,10 +292,62 @@ function hookSpoiler(elem) {
}
}
// these are filled by Jinja
const ROOT_URL = "{{ props.url }}";
const PAGE_URL = "{{ page_url }}";
const VERSION = "{{ version }}";
const LANG = "{{ lang }}";
function dropdownItem(text, href) {
let a = document.createElement("a");
a.href = href;
a.textContent = text;
let li = document.createElement("li");
li.appendChild(a);
return li;
}
function fillDropdowns(sitemap) {
let versionDropdown = document.getElementById("version-dropdown");
let langDropdown = document.getElementById("lang-dropdown");
// versions, linking to the current lang if possible
for (const version of Object.keys(sitemap).sort().reverse()) {
let {defaultPath, langPaths} = sitemap[version];
// link to the current language if available, else link to the default language
let path;
if (langPaths.hasOwnProperty(LANG)) {
path = langPaths[LANG];
} else {
path = defaultPath;
}
let item = dropdownItem(version, ROOT_URL + path);
versionDropdown.appendChild(item);
}
// langs for the current version
let langPaths = sitemap[VERSION].langPaths;
for (const lang of Object.keys(langPaths).sort()) {
let item = dropdownItem(lang, ROOT_URL + langPaths[lang]);
langDropdown.appendChild(item);
}
}
document.addEventListener("DOMContentLoaded", () => {
// fetch the sitemap from the root and use it to generate the navbar
fetch(`${ROOT_URL}/meta/sitemap.json`)
.then(r => r.json())
.then(fillDropdowns)
.catch(e => console.error(e))
document.querySelectorAll("details.spell-collapsible").forEach(hookLoad);
document.querySelectorAll("a.toggle-link").forEach(hookToggle);
document.querySelectorAll(".spoilered").forEach(hookSpoiler);
function tick(prevTime, time) {
const dt = time - prevTime;
for (const q of rfaQueue) {

View file

@ -105,7 +105,7 @@ class SitemapMarker(HexdocModel):
version: str
lang: str
path: str
lang_in_path: bool
is_default_lang: bool
@classmethod
def load(cls, path: Path):
@ -223,14 +223,13 @@ def main(args: Args | None = None) -> None:
for version in versions:
for lang, book in books.items():
is_default_lang = lang == props.default_lang
lang_in_path = not is_default_lang
# /index.html
# /lang/index.html
# /v/version/index.html
# /v/version/lang/index.html
parts = ("v", version) if version else ()
if lang_in_path:
if not is_default_lang:
parts += (lang,)
output_dir = args.output_dir / Path(*parts)
@ -261,7 +260,7 @@ def main(args: Args | None = None) -> None:
version=version,
lang=lang,
path="/" + "/".join(parts),
lang_in_path=lang_in_path,
is_default_lang=is_default_lang,
)
(output_dir / MARKER_NAME).write_text(marker.model_dump_json())

View file

@ -3,13 +3,18 @@ import shutil
from argparse import ArgumentParser
from collections import defaultdict
from pathlib import Path
from typing import Self, Sequence
from typing import Self, Sequence, TypedDict
from hexdoc.hexdoc import MARKER_NAME, SitemapMarker
from hexdoc.utils import HexdocModel
from hexdoc.utils.path import write_to_path
class SitemapItem(TypedDict):
defaultPath: str
langPaths: dict[str, str]
def strip_empty_lines(text: str) -> str:
return "\n".join(s for s in text.splitlines() if s.strip())
@ -63,11 +68,17 @@ def main():
shutil.copytree(args.src, args.dst, dirs_exist_ok=True)
# crawl the new tree to rebuild the sitemap
sitemap = defaultdict[str, dict[str, bool]](dict)
sitemap = defaultdict[str, SitemapItem](
lambda: SitemapItem(defaultPath="", langPaths={})
)
for marker_path in args.dst.rglob(MARKER_NAME):
marker = SitemapMarker.load(marker_path)
sitemap[marker.version][marker.lang] = marker.lang_in_path
version_item = sitemap[marker.version]
version_item["langPaths"][marker.lang] = marker.path
if marker.is_default_lang:
version_item["defaultPath"] = marker.path
write_to_path(args.dst / "meta" / "sitemap.json", json.dumps(sitemap))