Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
eb6ab5f
chore: update benchmarks for v0.2
ryanatkn Jun 26, 2026
f9c6f65
Merge branch 'main' into update-benchmarks
ryanatkn Jun 29, 2026
5a6d6c5
Merge branch 'main' into update-benchmarks
ryanatkn Jul 3, 2026
2192078
run benchmarks
ryanatkn Jul 3, 2026
a5814d7
chore: upgrade dev deps
ryanatkn Jul 3, 2026
cb11f52
remove files from prettier comparison
ryanatkn Jul 3, 2026
9f5a331
fairer size groups
ryanatkn Jul 3, 2026
14ddc2f
downgrade to vite7
ryanatkn Jul 3, 2026
ae0d0fe
improvements
ryanatkn Jul 3, 2026
660e981
improvements
ryanatkn Jul 4, 2026
7c4f4da
deps
ryanatkn Jul 4, 2026
7ad464e
better negative display
ryanatkn Jul 4, 2026
18342ed
qualify
ryanatkn Jul 4, 2026
78e1156
biome
ryanatkn Jul 4, 2026
cd115ff
tweaks
ryanatkn Jul 4, 2026
facaf59
hover to set baseline
ryanatkn Jul 4, 2026
35916d8
cleanup
ryanatkn Jul 4, 2026
55c28a4
benchmark conformance
ryanatkn Jul 4, 2026
e8be447
wip
ryanatkn Jul 5, 2026
ca88293
wip
ryanatkn Jul 5, 2026
062a281
wip
ryanatkn Jul 5, 2026
7686c61
update-benchmarks
ryanatkn Jul 5, 2026
20f97ad
wip
ryanatkn Jul 6, 2026
8105c16
add no-locations variants
ryanatkn Jul 6, 2026
ea99405
merge main
ryanatkn Jul 6, 2026
09cfd55
wip
ryanatkn Jul 6, 2026
71a3ffb
wip
ryanatkn Jul 6, 2026
c950f7e
wip
ryanatkn Jul 6, 2026
14846b6
docs
ryanatkn Jul 6, 2026
1bb5fa3
rerun benchmarks
ryanatkn Jul 6, 2026
474b9da
tweaks
ryanatkn Jul 7, 2026
34b6ebc
wip
ryanatkn Jul 7, 2026
b0f794b
fix links
ryanatkn Jul 7, 2026
be379be
wip
ryanatkn Jul 7, 2026
b671332
merge main
ryanatkn Jul 7, 2026
c362038
merge main
ryanatkn Jul 7, 2026
00dc844
wip
ryanatkn Jul 7, 2026
bb01070
wip
ryanatkn Jul 7, 2026
a1e3965
bench
ryanatkn Jul 7, 2026
eb303ca
wip
ryanatkn Jul 7, 2026
d06882f
wip
ryanatkn Jul 7, 2026
7ca31ef
wip
ryanatkn Jul 7, 2026
b5db679
wip
ryanatkn Jul 7, 2026
fda95e3
wip
ryanatkn Jul 7, 2026
a576267
https://biomejs.dev/formatter/
ryanatkn Jul 7, 2026
763915f
wip
ryanatkn Jul 8, 2026
dc9cdb8
docs
ryanatkn Jul 8, 2026
63cf59a
rerun benchmarks
ryanatkn Jul 8, 2026
599a3a4
wip
ryanatkn Jul 8, 2026
47c2be4
wip
ryanatkn Jul 8, 2026
dee9096
Merge branch 'main' into update-benchmarks
ryanatkn Jul 15, 2026
b4259d2
wip
ryanatkn Jul 16, 2026
4eaa914
update
ryanatkn Jul 16, 2026
c7e46f7
update docs and add other benchmarks
ryanatkn Jul 16, 2026
a2864c8
updates
ryanatkn Jul 16, 2026
fc7a00d
wip
ryanatkn Jul 16, 2026
d5f81c4
updates
ryanatkn Jul 16, 2026
e16f7ce
wip
ryanatkn Jul 16, 2026
1b93aa6
wip
ryanatkn Jul 16, 2026
5e01a85
wip
ryanatkn Jul 16, 2026
8425f25
wip
ryanatkn Jul 16, 2026
1555f00
wip
ryanatkn Jul 16, 2026
9392014
wip
ryanatkn Jul 16, 2026
a2dc5e9
wip
ryanatkn Jul 16, 2026
11de1bd
wip
ryanatkn Jul 16, 2026
e6dc140
wip
ryanatkn Jul 16, 2026
cf0c815
wip
ryanatkn Jul 16, 2026
7ae6aa9
wip
ryanatkn Jul 16, 2026
7006cb3
wip
ryanatkn Jul 16, 2026
2543607
wip
ryanatkn Jul 16, 2026
dc025b0
clarify
ryanatkn Jul 16, 2026
e5f1323
wip
ryanatkn Jul 16, 2026
2857cf2
wip
ryanatkn Jul 16, 2026
3de0651
wip
ryanatkn Jul 16, 2026
dc15dcc
wip
ryanatkn Jul 16, 2026
0bf7dea
wip
ryanatkn Jul 16, 2026
b9a8300
updates
ryanatkn Jul 16, 2026
fe18e29
wip
ryanatkn Jul 16, 2026
416f77f
wip
ryanatkn Jul 16, 2026
e994c44
wip
ryanatkn Jul 16, 2026
2b4691f
wip
ryanatkn Jul 16, 2026
e95a518
wip
ryanatkn Jul 16, 2026
99a9a4d
modularity and reusability
ryanatkn Jul 17, 2026
57df1b5
dprint
ryanatkn Jul 19, 2026
bcac785
oxc-benchmark-formatter
ryanatkn Jul 19, 2026
33f617a
cleanup
ryanatkn Jul 19, 2026
a370a32
refactor
ryanatkn Jul 19, 2026
4f6cb79
update benchmarks
ryanatkn Jul 22, 2026
6ea9f2b
wip
ryanatkn Jul 22, 2026
ac84422
wip
ryanatkn Jul 22, 2026
377a9b0
wip
ryanatkn Jul 22, 2026
8150d8d
wip
ryanatkn Jul 22, 2026
22168d9
wip
ryanatkn Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
push:
branches: [main]
pull_request:
branches: ['**']
branches: ["**"]
# Allow manually re-running the check from the Actions tab.
workflow_dispatch:

Expand All @@ -28,7 +28,7 @@ jobs:

strategy:
matrix:
node-version: ['24.14']
node-version: ["24.14"]

steps:
# persist-credentials: false keeps the GITHUB_TOKEN out of .git/config, so a
Expand Down
70 changes: 57 additions & 13 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@ IMPORTANT for AI agents: Do NOT run `gro dev` - the developer will manage the de

- Svelte 5 - component framework with runes
- SvelteKit - application framework with static adapter
- fuz_css (`@fuzdev/fuz_css`) - CSS framework and design system
- fuz_css (`@fuzdev/fuz_css`) - semantic-first CSS framework and design system
- fuz_ui (`@fuzdev/fuz_ui`) - UI components, theming, docs system
- fuz_util (`@fuzdev/fuz_util`) - utility functions
- fuz_code (`@fuzdev/fuz_code`) - syntax highlighting
- Gro (`@fuzdev/gro`) - build system and task runner
- prettier + prettier-plugin-svelte - code formatting
- tsv (via Gro) - code formatting
- mdz (`@fuzdev/mdz`) - markdown preprocessor wired into `svelte.config.js`
- `@fuzdev/tsv_wasm` - tsv's formatter + parser as WASM; powers the playground, loaded lazily in the browser

Note: `@fuzdev/tsv_wasm` is loaded only on `/docs/playground` via a browser-only dynamic `import()`, so the ~900KB WASM never weighs down `/docs` or the prerendered pages.
Note: `@fuzdev/tsv_wasm` is loaded only on `/docs/playground` via a browser-only dynamic `import()`, so the ~900KB-gzipped WASM (~2.9MB decoded) never weighs down `/docs` or the prerendered pages.

Note: several devDependencies — `@webref/css` (CSS spec data), `zimmerframe` (AST traversal), `@sveltejs/acorn-typescript`, `zod`, and `@fuzdev/blake3_wasm` — are *optional peer dependencies* of `@fuzdev/fuz_css`'s `vite_plugin_fuz_css`, declared here so its build-time CSS generation resolves them (e.g. `css_literal.ts` imports `@webref/css`, `css_class_extractor.ts` walks ASTs with `zimmerframe`). They aren't imported by this app's own source, so don't mistake them for dead deps.

Note: `vite` is deliberately held at 7.x (with `@sveltejs/vite-plugin-svelte` 6.x) — vite 8 + plugin-svelte 7 was buggy with this app or SvelteKit's integration. Don't upgrade to vite 8 without deliberately re-verifying the site works.

## Scope

tsv.fuz.dev is the public face of the tsv tool:
Expand All @@ -56,8 +58,6 @@ tsv.fuz.dev is the public face of the tsv tool:

```
src/
├── lib/
│ └── sample.ts # placeholder constant (not yet wired up)
├── routes/
│ ├── +page.svelte # Home: hero, links to docs and benchmarks
│ ├── +layout.svelte # Root layout: fuz_css/fuz_code CSS, ThemeRoot, SiteState
Expand All @@ -81,30 +81,74 @@ src/
Benchmark data comes from `tsv`. Full workflow to update:

```bash
# 1. In ~/dev/tsv — run benchmarks (builds ffi + wasm automatically)
# 1. In ~/dev/tsv — run benchmarks across deno/node/bun (builds artifacts automatically)
deno task bench

# 2. In ~/dev/tsv.fuz.dev — copy the latest result
# 2. In ~/dev/tsv.fuz.dev — copy the latest results
npm run update-benchmarks
```

Step 1 writes `benches/deno/results/report.json` (committed to tsv).
Step 2 copies it to `src/routes/docs/benchmarks/benchmarks.json`.
The JSON format matches `BenchmarkBaseline` in `benchmark_data.ts`.
Step 1 writes the per-runtime `benches/js/results/report.<runtime>.{json,md}`
siblings, the composed cross-runtime `report.{json,md}`, and the conformance
coverage report `report.conformance.node.json` (committed to tsv).
Step 2 copies three of them — `report.node.json` → `benchmarks.json`, the
composed `report.json` → `benchmarks_cross_runtime.json`, and
`report.conformance.node.json` → `benchmarks_conformance.json` — then runs
`gro format` over the copies. Note the script's source paths are hardcoded to
`../tsv` — if the reports were generated in a different worktree, copy them
into `~/dev/tsv` (or copy manually) first.
The JSON formats match the types in `benchmark_data.ts`.

The end-to-end CLI comparison against Prettier, Biome, and Oxfmt comes from a
separate harness, a fork of Oxc's `bench-formatter` that adds tsv
(../oxc-bench-formatter). It publishes no JSON — its numbers live only as the
hyperfine console dump in its README, between the
`<!-- BENCHMARK_RESULTS_START -->` / `END` markers, plus a `## Versions` list
and a `_Measured on: …_` machine line. To update:

```bash
# 1. In ~/dev/oxc-bench-formatter — re-run and rewrite its README (needs a built ../tsv)
pnpm run update-readme

# 2. In ~/dev/tsv.fuz.dev — reparse the README into JSON
gro gen
```

`benchmarks_formatters.gen.json.ts` parses that README and writes
`benchmarks_formatters.json`, keeping only the scenarios tsv participates in
(it has no JSX/TSX parser, so the harness runs it on the JSX-free corpora
only).

A **missing** sibling checkout is the one tolerated case — generation is
skipped, the committed JSON stands, and `gro gen --check` passes on any machine
or CI that has only this repo (CI never checks out the harness, so it always
takes this path; no `--no-gen` needed). A README that **is** present but has
drifted fails the task loudly, naming the scenario and the section that stopped
parsing, rather than publishing stale or scenario-stripped numbers. A drift that
still parses but renames a scenario is caught on the site side instead: every
key in `benchmarks_cli.ts`'s `SCENARIO_COPY` must resolve to generated data, and
a test asserts it.

Key files in `src/routes/docs/benchmarks/`:

- `benchmarks.json` — raw benchmark data (copied from tsv)
- `benchmarks.json` — per-runtime Node report (copied from tsv)
- `benchmarks_cross_runtime.json` — composed cross-runtime report (copied from tsv)
- `benchmarks_conformance.json` — conformance parse-coverage report (copied from tsv)
- `benchmarks_formatters.json` — formatter CLI comparison, generated from the sibling harness's README
- `benchmark_data.ts` — TypeScript types matching the JSON format
- `benchmarks.ts` — re-exports the JSON with types
- `formatter_benchmark_data.ts` — types plus `parse_formatter_benchmarks`, the README parser
- `benchmarks_cli.ts` — shapes `benchmarks_formatters.json` for `BenchmarksCli.svelte` and owns the per-scenario prose; the numbers are all generated
- `benchmarks.ts`, `benchmarks_cross_runtime.ts`, `benchmarks_conformance.ts`, `benchmarks_formatters.ts` — re-export the JSON with types
- `BenchmarksBar.svelte`, `BenchmarksGroup.svelte`, etc. — visualization components
- `BenchmarksBaselineGroup.svelte` — shared interactive column behind the format, parse, and binary-size groups: hovering a row re-baselines that group's ratios (each of the three groups per section is independent), restoring the default anchor (the canonical reference — Prettier for format, the JS baseline for parse — and the smallest build for size) on mouseleave. `benchmark_data.ts`'s `compute_baseline_ratio`/`format_baseline_ratio`/`baseline_ratio_color` carry the per-`BaselineDirection` (`speed`/`size`) formulas it and the derivations share

## Architecture

- Static SvelteKit app (`adapter-static`), deploys to GitHub Pages
- Uses fuz_ui tome system for docs navigation
- `docs/tomes.ts` defines the doc sections: introduction, playground, benchmarks
- Benchmark data lives in `src/routes/docs/benchmarks/benchmarks.json` (see [Benchmarks](#benchmarks))
- The benchmarks page quotes no hand-written ratios — its prose computes them from the same reports the charts render, via `benchmark_data.ts`'s `benchmark_speedup`/`format_ratio_approx`/`format_ratio_range` and `benchmarks_cli.ts`'s `cli_speedup_vs_tsv`/`cli_memory_ratio_range`. A test gates that every pair the copy names still resolves
- `library.ts` builds component metadata at runtime from the `virtual:svelte-docinfo` module (provided by the `svelte-docinfo` Vite plugin); the docs index passes it to `DocsContent`
- The playground (`/docs/playground`) loads `@fuzdev/tsv_wasm` via a browser-only dynamic `import()` inside `Playground.svelte`, so the WASM code-splits into its own chunk fetched only on that route — the same lazy discipline `library.ts` uses for the heavy svelte-docinfo data, keeping `/docs` and the prerendered pages WASM-free. `@fuzdev/tsv_wasm` is in `vite.config.ts` `optimizeDeps.exclude` (like `blake3_wasm`)
- The playground's editor is fuz_code's `CodeTextarea` (live syntax highlighting via the experimental CSS Custom Highlight API). It needs `@fuzdev/fuz_code/theme_highlight.css`, imported inside `Playground.svelte` rather than the root layout so it stays on this route only; `supports_css_highlight_api()` drives a graceful-degradation note where the API is unavailable (the editor still works, unstyled)
Expand All @@ -117,7 +161,7 @@ Deploys to `https://tsv.fuz.dev/` via `gro deploy` (builds and pushes to deploy

- TypeScript strict mode
- Svelte 5 with runes API
- Prettier with tabs, 100 char width
- tsv with tabs, 100 char width
- Node >= 24.14
- Private package (not published to npm)

Expand Down
Loading