Format entire codebase with Prettier (mechanical, no behavior change)

This commit is contained in:
2026-06-05 01:43:28 +03:00
parent 939950b136
commit 0c7297624e
32 changed files with 1597 additions and 832 deletions
@@ -5,7 +5,7 @@ the preview pane. This covers four mechanics: **embedding** a spec via
`vega-embed`, **theming** so charts match the active UI theme, **debounced
re-rendering** so typing stays smooth, and **error handling** so a broken spec
produces a readable message and self-heals. It deliberately stops at the
embedding boundary — the *content* of the spec (resolving named-dataset
embedding boundary — the _content_ of the spec (resolving named-dataset
references, applying fit-mode sizing) is prepared upstream by a pure transform;
see §6.
@@ -63,9 +63,9 @@ export async function renderSpec(
config: Config,
): Promise<RenderHandle> {
const result: EmbedResult = await vegaEmbed(node, spec, {
actions: false, // no built-in export/source/editor menu — clean chart
renderer: 'svg', // crisp, inspectable, copyable output
config, // theme config (see §3)
actions: false, // no built-in export/source/editor menu — clean chart
renderer: 'svg', // crisp, inspectable, copyable output
config, // theme config (see §3)
});
return {
@@ -82,7 +82,7 @@ export async function renderSpec(
Every successful `vegaEmbed` returns a `result.view` (a live Vega `View`
instance). It owns timers, signal listeners, and DOM. If you embed a new spec
into the same node *without* finalizing the old view, the old one leaks — its
into the same node _without_ finalizing the old view, the old one leaks — its
listeners keep firing and resources accumulate over a long editing session.
The renderer that drives re-rendering must therefore hold the previous handle and
@@ -92,7 +92,7 @@ destroy it before (or while) creating the next:
let current: RenderHandle | null = null;
async function rerender(node: HTMLElement, spec: TopLevelSpec, config: Config) {
current?.destroy(); // tear down the previous view first
current?.destroy(); // tear down the previous view first
current = await renderSpec(node, spec, config);
}
```
@@ -181,7 +181,7 @@ re-rendering picks up the new config and the chart restyles automatically.
### Rules
- **Do** keep `chartConfigFor` as the *only* place that maps a UI theme to a Vega
- **Do** keep `chartConfigFor` as the _only_ place that maps a UI theme to a Vega
config. Adding a UI theme = adding one config and one map entry.
- **Do** set chart `background: 'transparent'` so the pane's own background shows
through and theme switches look seamless.
@@ -233,8 +233,8 @@ export function escapeVegaField(name: string): string {
encoding.x = { field: escapeVegaField(columnName), type: 'quantitative' };
```
This matters wherever Astrolabe *constructs* spec fragments from data-derived
column names — most notably the chart builder (see *Chart Builder* spec) and any
This matters wherever Astrolabe _constructs_ spec fragments from data-derived
column names — most notably the chart builder (see _Chart Builder_ spec) and any
helper that injects an encoding. For specs the user authored by hand, escaping is
the user's responsibility; Astrolabe does not rewrite hand-authored `field:`
values.
@@ -293,15 +293,21 @@ export function createDebouncedRenderer(opts: {
return {
schedule() {
if (timer) clearTimeout(timer); // cancel the pending render
if (timer) clearTimeout(timer); // cancel the pending render
timer = setTimeout(run, opts.delayMs());
},
flush() {
if (timer) { clearTimeout(timer); timer = null; }
if (timer) {
clearTimeout(timer);
timer = null;
}
void run();
},
cancel() {
if (timer) { clearTimeout(timer); timer = null; }
if (timer) {
clearTimeout(timer);
timer = null;
}
generation++; // abandon any in-flight result
},
};
@@ -330,7 +336,7 @@ useSettingsStore.subscribe((s, prev) => {
### Busy indicator
`setBusy(true/false)` toggles store state that the preview reads to overlay a
**subtle, non-blocking** spinner/shimmer. It sits *over* the existing chart so the
**subtle, non-blocking** spinner/shimmer. It sits _over_ the existing chart so the
last good render stays visible while the next one computes — the pane never goes
blank mid-edit.
@@ -366,8 +372,8 @@ It does two deterministic things, on a **deep copy** of the spec:
Vega-Lite's `"container"` keyword (Original = untouched; Width/Height/Full set
the corresponding dimension(s) to `"container"`), recursing the same way.
This is *content* preparation, not embedding, and it is fully covered by the
*Live Preview* spec. The only invariant this doc cares about:
This is _content_ preparation, not embedding, and it is fully covered by the
_Live Preview_ spec. The only invariant this doc cares about:
> `prepareSpecForRender` runs on a copy and returns a new spec. The renderer
> embeds that returned spec. **The user's stored spec is never mutated by
@@ -392,11 +398,11 @@ A spec that cannot be rendered must produce a **readable** message in the previe
area and recover on its own once the spec is valid again. Errors arise at three
stages, all funneled to one error field the preview reads:
| Stage | Failure | Surfaced as |
|---|---|---|
| Parse | Invalid JSON | "Invalid JSON: …" |
| Stage | Failure | Surfaced as |
| -------------------------------- | -------------------------------------- | ---------------------- |
| Parse | Invalid JSON | "Invalid JSON: …" |
| Prepare (`prepareSpecForRender`) | Referenced dataset missing/unfetchable | "Dataset not found: …" |
| Embed (`vega-embed`) | Vega-Lite compile / data error | "Rendering error: …" |
| Embed (`vega-embed`) | Vega-Lite compile / data error | "Rendering error: …" |
```ts
// inside render(), driven by the debounced renderer
@@ -427,10 +433,12 @@ async function render(): Promise<void> {
current = await renderSpec(node, prepared, config);
usePreviewStore.getState().setError(null); // success clears any prior error
} catch (e) {
usePreviewStore.getState().setError(
`Rendering error: ${(e as Error).message}. ` +
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
);
usePreviewStore
.getState()
.setError(
`Rendering error: ${(e as Error).message}. ` +
`Check your JSON syntax and that the spec is valid Vega-Lite.`,
);
}
}
```
@@ -457,12 +465,12 @@ manual retry, no reload.
## Summary
| Concern | Mechanism | Source of truth |
|---|---|---|
| Embedding | One `renderSpec` over `vega-embed`, `actions: false`, `renderer: 'svg'` | `src/app/services/chart-renderer.ts` |
| View teardown | `view.finalize()` before each re-render and on unmount | the renderer's `RenderHandle` |
| Theming | Vega `Config` per UI theme, applied at embed time | `chartConfigFor()` in `src/core/vega-themes.ts` |
| Field names | `escapeVegaField` on every data-derived `field:` | `src/core/rendering.ts` |
| Debounce | `createDebouncedRenderer`, delay from `renderDebounce` setting | `src/app/services/debounced-renderer.ts` |
| Spec prep | `prepareSpecForRender` (pure, on a copy) | `src/core/rendering.ts` (see *Live Preview*) |
| Errors | One error field, cleared on success, empty = nothing | `PreviewStore.error` |
| Concern | Mechanism | Source of truth |
| ------------- | ----------------------------------------------------------------------- | ----------------------------------------------- |
| Embedding | One `renderSpec` over `vega-embed`, `actions: false`, `renderer: 'svg'` | `src/app/services/chart-renderer.ts` |
| View teardown | `view.finalize()` before each re-render and on unmount | the renderer's `RenderHandle` |
| Theming | Vega `Config` per UI theme, applied at embed time | `chartConfigFor()` in `src/core/vega-themes.ts` |
| Field names | `escapeVegaField` on every data-derived `field:` | `src/core/rendering.ts` |
| Debounce | `createDebouncedRenderer`, delay from `renderDebounce` setting | `src/app/services/debounced-renderer.ts` |
| Spec prep | `prepareSpecForRender` (pure, on a copy) | `src/core/rendering.ts` (see _Live Preview_) |
| Errors | One error field, cleared on success, empty = nothing | `PreviewStore.error` |