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

View file

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

View file

@ -42,7 +42,7 @@
<script> <script>
{% filter indent(6) %} {% filter indent(6) %}
{%+ include_raw "main.js" %} {%+ include "main.js.jinja" %}
{% endfilter %} {% endfilter %}
</script> </script>
</head> </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", () => { 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("details.spell-collapsible").forEach(hookLoad);
document.querySelectorAll("a.toggle-link").forEach(hookToggle); document.querySelectorAll("a.toggle-link").forEach(hookToggle);
document.querySelectorAll(".spoilered").forEach(hookSpoiler); document.querySelectorAll(".spoilered").forEach(hookSpoiler);
function tick(prevTime, time) { function tick(prevTime, time) {
const dt = time - prevTime; const dt = time - prevTime;
for (const q of rfaQueue) { for (const q of rfaQueue) {

View file

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

View file

@ -3,13 +3,18 @@ import shutil
from argparse import ArgumentParser from argparse import ArgumentParser
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import Self, Sequence from typing import Self, Sequence, TypedDict
from hexdoc.hexdoc import MARKER_NAME, SitemapMarker from hexdoc.hexdoc import MARKER_NAME, SitemapMarker
from hexdoc.utils import HexdocModel from hexdoc.utils import HexdocModel
from hexdoc.utils.path import write_to_path from hexdoc.utils.path import write_to_path
class SitemapItem(TypedDict):
defaultPath: str
langPaths: dict[str, str]
def strip_empty_lines(text: str) -> str: def strip_empty_lines(text: str) -> str:
return "\n".join(s for s in text.splitlines() if s.strip()) 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) shutil.copytree(args.src, args.dst, dirs_exist_ok=True)
# crawl the new tree to rebuild the sitemap # 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): for marker_path in args.dst.rglob(MARKER_NAME):
marker = SitemapMarker.load(marker_path) 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)) write_to_path(args.dst / "meta" / "sitemap.json", json.dumps(sitemap))