Eng-council sweep: export hygiene, dead code, helper dedup, declare vega-expression

This commit is contained in:
2026-06-12 19:39:54 +03:00
parent f26ac66633
commit 0e225d7d5c
26 changed files with 89 additions and 98 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ import type { VisualizationSpec } from 'vega-embed';
import type { Config } from 'vega-lite';
/** Options for `RenderHandle.toImageURL` (spec §08 → Per-chart export). */
export interface ImageExportOptions {
interface ImageExportOptions {
/**
* Pixel-density multiplier for the **PNG** raster, **relative to the device**.
* The image is drawn at `scale × devicePixelRatio` logical-pixel density, so
@@ -80,7 +80,7 @@ export interface RenderOptions {
* size against this (÷ dpr, since the backing store is dpr× the CSS size) and
* throws `ChartTooLargeError` rather than handing back a blank canvas.
*/
export const MAX_CANVAS_PX = 32767;
const MAX_CANVAS_PX = 32767;
/**
* Thrown by `renderSpec` when a **canvas**-backed chart resolves to a height larger
+24 -19
View File
@@ -110,12 +110,20 @@ export function runMergeChartTheme(editor: monaco.editor.IStandaloneCodeEditor):
});
}
/** Remove the draft's `config` block, copying it to the clipboard first. */
export async function runExtractConfig(editor: monaco.editor.IStandaloneCodeEditor): Promise<void> {
/**
* Shared prologue of the two extract actions: the model, the spec parsed off it,
* and the config split out — or null (after toasting) when any step has nothing
* to work with.
*/
function extractableConfig(editor: monaco.editor.IStandaloneCodeEditor): {
model: monaco.editor.ITextModel;
rest: Record<string, unknown>;
config: Record<string, unknown>;
} | null {
const model = editor.getModel();
if (!model) return;
if (!model) return null;
const spec = parseSpecObject(model);
if (!spec) return;
if (!spec) return null;
const { spec: rest, config } = extractConfigFromSpec(spec);
if (config === null) {
@@ -124,8 +132,16 @@ export async function runExtractConfig(editor: monaco.editor.IStandaloneCodeEdit
title: 'No config to extract',
message: 'This spec has no config block.',
});
return;
return null;
}
return { model, rest, config };
}
/** Remove the draft's `config` block, copying it to the clipboard first. */
export async function runExtractConfig(editor: monaco.editor.IStandaloneCodeEditor): Promise<void> {
const extracted = extractableConfig(editor);
if (!extracted) return;
const { model, rest, config } = extracted;
// Copy before removing — if the clipboard write fails, the spec keeps its
// config and nothing is lost.
@@ -157,20 +173,9 @@ export async function runExtractConfig(editor: monaco.editor.IStandaloneCodeEdit
* non-overlapping keys stop applying once the new theme replaces it.)
*/
export function runExtractConfigToTheme(editor: monaco.editor.IStandaloneCodeEditor): void {
const model = editor.getModel();
if (!model) return;
const spec = parseSpecObject(model);
if (!spec) return;
const { spec: rest, config } = extractConfigFromSpec(spec);
if (config === null) {
notify({
kind: 'info',
title: 'No config to extract',
message: 'This spec has no config block.',
});
return;
}
const extracted = extractableConfig(editor);
if (!extracted) return;
const { model, rest, config } = extracted;
const snippet = selectActiveSnippet(useSnippetStore.getState());
const theme = useCustomThemeStore
+2 -8
View File
@@ -27,6 +27,7 @@ import {
reassignCollidingSnippetIds,
} from '@core/import-normalize';
import { snippetSizeBytes } from '@core/snippet';
import { humanizeBytes } from '@core/storage-estimate';
import { downloadJson, readTextFile } from '../infrastructure/file-transfer';
import { deleteSnippet, saveSnippet, StorageQuotaError } from '../infrastructure/snippet-store';
import { notify } from '../stores/NotificationStore';
@@ -36,13 +37,6 @@ import { useSnippetStore } from '../stores/SnippetStore';
/** Practical snippet-storage budget (spec §02 storage monitor / §08). */
const SNIPPET_BUDGET_BYTES = 5 * 1024 * 1024;
/** Round bytes to a short KB/MB string for the overage warning. */
function formatBytes(bytes: number): string {
const kb = bytes / 1024;
if (kb < 1024) return `${Math.max(1, Math.round(kb))} KB`;
return `${Math.round(kb / 1024)} MB`;
}
/**
* Export the whole workspace to a downloaded JSON file (spec §08 → Export).
* Flushes the live editor buffer first so in-progress draft edits are included.
@@ -209,7 +203,7 @@ export async function importWorkspace(file: File): Promise<void> {
}
if (overage > 0) {
clauses.push(
`This puts snippet storage about ${formatBytes(overage)} over the ~5 MB budget; ` +
`This puts snippet storage about ${humanizeBytes(overage)} over the ~5 MB budget; ` +
`consider deleting some snippets.`,
);
}