refactor(web): rebuild the frontend on SvelteKit, TypeScript and Tailwind

The app was a single-entry React SPA: one index.html that the assembler
copied to every dataset path, with a hand-rolled router resolving the
dataset from window.location and the title patched in at runtime because
one file had to serve every route.

SvelteKit prerenders a real page per route instead. The entry generator
in routes/[dataset]/+page.ts reads the same datasets.json the assembler
does, so the set of pages and the set of databases cannot drift apart,
and each dataset page ships its own <title> and description.

Everything framework-free moved across unchanged in behaviour and became
typed: the admission blocks, subject list, query classifier and SQL
presets. `Student` now mirrors the 22-column table, so a mistyped column
name fails the build rather than rendering blank.

Tailwind replaces the stylesheet. Theme tokens are CSS variables, which
keeps dark mode a single block of overrides rather than a `dark:` variant
on every class. The score tiers stay hand-written CSS: the class is
chosen at runtime from a score, and no utility generator can see that.

Adds the tests the frontend never had, over the three modules where a
silent wrong answer is possible — most importantly that toAscii here
folds exactly as ToAscii does in the parser, which is what makes
accent-insensitive search find anything.

The assembler stops copying index.html per dataset and checks that the
build prerendered each one instead. The database presence, raw-artifact
and idempotence guards are untouched.

Verified: 25 tests, ESLint and svelte-check clean, and a full
`assemble site` producing /thptqg/, /thptqg/2016/, /thptqg/2017/ and
404.html with absolute asset URLs. Not verified in a browser — this
machine has none.
This commit is contained in:
tiennm99 committed 2026-08-14 11:38:29 +07:00
1 parent e2112fdb38
commit 3fd137a233
49 files changed
+4432 -3112

No files matched your search

+6
View File
@@ -66,6 +66,12 @@ jobs:
- name: Test assembler
run: go -C assembler test ./...
# Lint covers ESLint and svelte-check; the tests cover the framework-free
# modules, including the ASCII fold that has to match the Go parser.
- name: Test web
working-directory: web
run: npm test
- name: Lint web
working-directory: web
run: npm run lint