Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

#143

Load a Prism grammar only when a blob names it

merged · by keenan 8d ago · merged into main at 1b8675b1 by keenan 8d ago

keenan opened this 8d ago

Why

static/prism-worker.js imported prism-languages.min.js — every grammar Prism ships — on every code page. That is 546 KB the browser evaluates before it can colour the first line, and a page showing one Go file paid for all 293 components. The server still carries no lexer; only the amount of JavaScript the browser parses changes.

What

  • static/prism-languages/<component>.js holds one Prism component per file, byte for byte as cdnjs serves it.
  • static/prism-manifest.js maps a language name to the files that define it, in dependency order (php → markup-templating, php; scala → java, scala).
  • The worker starts with prism.min.js and the manifest, and imports a language’s files the first time a job names it. A file that has been run is never imported again, because a second insertBefore would insert the same grammar twice.
  • scripts/vendor-prism.py generates all of it and --check compares the committed bytes with cdnjs. It refuses to generate if a component ends up imported by no entry, so a language Prism adds cannot silently go missing.

A Go blob now loads 30 KB instead of 564 KB; php 37 KB, csharp 36 KB, and .tsx 49 KB over 8 files, the widest common entry.

Behaviour to review

Five components register no language of their own but change one: css-extras, js-extras, js-templates, php-extras, xml-doc. The manifest carries them in the entries that inherit the grammar they rewrite, placed right after it. That makes one deliberate difference from the old bundle, whose order handed js-extras to some languages that extend javascript and not others: actionscript, coffee, coffeescript, flow, ts, tsx and typescript gain arrow/control-flow/maybe-class-name tokens. Comparing all 395 language names old against new, those seven gain token classes and nothing loses any.

js-templates decides which languages it can embed inside a template string when it loads, so the grammars it embeds (sql, graphql, markdown) are loaded just before it. Without that the highlighting of a sql`…` literal would depend on what else the page had read first.

Checks

  • vole workflow run verify — all steps pass, including go test -race ./..., the license and link checks, and packaging.
  • python3 scripts/vendor-prism.py --check — the vendored grammars and manifest match Prism 1.30.0 on cdnjs (387 names, 293 components).
  • Every manifest entry was loaded and tokenised in a Node harness that stubs importScripts, with no exceptions and no entry answering plain.

Not in this change

Markdown fenced code blocks are the reason to want the manifest, but wiring class="language-…" through the sanitizer and app.js is a separate change. A SharedWorker is also deferred: with grammars loaded on demand, the remaining per-navigation cost is one small import.

Discussion (0)

No discussion yet.