Skip to content

Latest commit

 

History

History
99 lines (80 loc) · 5.58 KB

File metadata and controls

99 lines (80 loc) · 5.58 KB

GLOSSARY.md

The core vocabulary of the Muse codebase — enough to read the source and AGENTS.md without getting lost. For the architecture, boot order, and the do-not-break rules, go to AGENTS.md.

Mental model. Muse renders one preview: a chosen font × theme × language, highlighted by Shiki. Everything selectable is an asset with a stable id, sourced either from the repo (data/*.json, listed in the catalog) or uploaded at runtime (kept in localStorage). A pub/sub state store holds the selection, mirrors it to localStorage and the URL hash, and notifies subscribers that re-render. That's the whole app.


Core

  • Asset — anything selectable: a font, theme, or language. Each has a unique id and shows up as a pill.
  • Font / Theme / Language — the three asset kinds. A theme is VSCode theme JSON (colors + tokenColors). A language pairs a manifest with a sample code file.
  • Preview — the rendered code block in the center pane (renderPreview() in src/preview.js). The app's single visual output.

Identity & data

  • id / canonical id / filename stem — the one identifier for an asset: the JSON filename stem === the id field inside it, and that id is what lives in the URL hash, localStorage, and Shiki's registry. rebuild-index.mjs enforces the match.
  • Manifest — the small JSON describing a font or language. Font: id, name, stack, optional cssUrl/ligatures. Language: id, label, shikiLang, sample, summary. (Themes have no manifest — the theme JSON is the asset.)
  • catalog — the in-memory set of valid ids ({fonts, themes, languages}) in state.js. Every setState validates against it; an unknown id falls back to a default with a console.error. Runtime adds/removes must keep it in sync (extendCatalog/ removeFromCatalog) or a freshly uploaded selection bounces back to default.
  • data/_index.json — the catalog on disk: the auto-generated list of repo asset ids, fetched at boot. Never hand-editrebuild-index.mjs / CI regenerate it.

Where an asset comes from

  • Repo asset — backed by a committed data/ file, listed in _index.json, travels in shared URLs.
  • Runtime asset — uploaded in-browser, persisted in localStorage only. A shared URL pointing at one falls back to defaults on another device.
  • Built-in theme — a theme Shiki ships (names in data/themes/_builtin.json); available with no repo file. The committed repo themes are currently light themes Shiki doesn't ship.
  • Installed / found font — a font already on the visitor's machine: either auto-detected from the LOCAL_FONTS probe (fonts.js, via a canvas-width trick) or found by the user typing its name. No download needed.
  • Custom font / theme — a runtime upload (URL, @font-face, or theme JSON). Its id gets a custom- prefix (slugify() in ui/uploaders.js) so it can't shadow a repo id — repo files must never use that prefix (CI rejects them). For themes there are two layers: the persisted custom theme vs its live in-memory runtime theme (runtimeThemes / getRuntimeTheme).

State

  • State store — the pub/sub store in src/state.js: getState (read a copy), setState (write + persist + notify), subscribe (fires immediately, then on change). Defaults: jetbrains-mono / one-dark-pro / python.
  • State precedenceURL hash > localStorage > defaults. On load the hash wins; on change, localStorage and the hash update together.
  • URL hash — the shareable serialization of the setup. The app writes it via history.replaceState (no feedback loop); a pasted hash applies live via hashchange.
  • localStorage keysmuse:state (selection), muse:custom-fonts, muse:custom-themes, muse:found-fonts. All JSON; corrupt data falls back to defaults rather than crashing.

Rendering

  • Highlighter — the Shiki instance (src/themes.js), created once and reused via the cached getHighlighter() promise. Loaded from esm.sh.
  • Theme name override — before handing a custom theme to Shiki, do { ...raw, name: id } so Shiki, the hash, and localStorage agree on the canonical id. Critical invariant.
  • Render token / race guardrenderToken in preview.js: each render grabs a token and bails if a newer one started, so out-of-order async renders never paint.

UI

  • Pill — a selectable chip: a font/theme in a sidebar (fonts left, themes right) or a language in the lang tabs. Custom pills are removable; search.js fuzzy-filters them.
  • Uploader dialog — the Add Font / Add Theme modals that create runtime assets. Theme colors are validated hex-only to block CSS injection through Shiki's inline styles.
  • Export — turns the current setup into a paste-ready VS Code settings.json (ui/export.js).

Build & deploy

  • No-build-step — plain HTML + vanilla ES modules + JSON. No bundler/tests/linter; Shiki loads at runtime from esm.sh. Deployed as GitHub Pages from the repo root.
  • rebuild-index.mjs — the only script: validates every asset and regenerates _index.json. --check validates without writing (PR CI). Node 18+, zero deps.
  • .nojekyll — the empty root file that stops Jekyll dropping _-prefixed files (_index.json, _builtin.json). Without it the app won't boot.

Words live here; the "do not break this" rules live in AGENTS.md under Critical invariants.