Add ESLint and Prettier, and close the node test gaps
Tooling: - Prettier as the single formatting authority (110 columns, single quotes, measured against the existing style); Markdown excluded because table-cell padding turns the README glossary into 1000-character lines. - Type-aware ESLint ending in eslint-config-prettier, so a rule always means "this is a bug", never "this looks different". - .editorconfig and an `npm run check` that runs typecheck, lint, format and tests in one go. Findings fixed on the first run: three more duplicate imports, four String(unknown) calls (parameter types narrowed instead of casts), two dead initialisers, two redundant casts, a console.log for a real error. Two warnings were false here and are disabled with a reason in place. Tests 132 -> 269: - node-catalog.test.ts covers every node with a run(), with a guard that fails when a new node has no row. - behavior-events.test.ts covers the ten event nodes through a running World, checking timing rather than existence. - Input's state machine (press/release/releaseAll) is reachable without DOM events now; the DOM handlers are thin adapters. Compare fell back to == without a configured operator although the schema default is <; aligned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f140c2fd77
commit
d54a620ebd
113 files changed
+5049
-666
No files matched your search
+15
-4
@@ -194,7 +194,10 @@ export class EditorState {
|
||||
|
||||
select(selection: Selection): void {
|
||||
// Test hooks pass the short form `{ kind: 'object', sceneId, objectId }` without `objectIds`.
|
||||
if (selection?.kind === 'object' && !selection.objectIds) selection = objectSelection(selection.sceneId, [selection.objectId]);
|
||||
// The type says `objectIds` is always there – untyped callers are exactly why this guard exists.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (selection?.kind === 'object' && !selection.objectIds)
|
||||
selection = objectSelection(selection.sceneId, [selection.objectId]);
|
||||
if (sameSelection(this.selection, selection)) return;
|
||||
this.selection = selection;
|
||||
this.emit('selection');
|
||||
@@ -204,7 +207,9 @@ export class EditorState {
|
||||
toggleObject(sceneId: string, objectId: string): void {
|
||||
const s = this.selection;
|
||||
const current = s?.kind === 'object' && s.sceneId === sceneId ? s.objectIds : [];
|
||||
const next = current.includes(objectId) ? current.filter((id) => id !== objectId) : [...current, objectId];
|
||||
const next = current.includes(objectId)
|
||||
? current.filter((id) => id !== objectId)
|
||||
: [...current, objectId];
|
||||
this.select(objectSelection(sceneId, next, current.includes(objectId) ? undefined : objectId));
|
||||
}
|
||||
|
||||
@@ -227,7 +232,8 @@ export class EditorState {
|
||||
const asset = findAsset(this.project, s.assetId);
|
||||
// Fall back to the behavior asset so the graph stays open when its node vanished (undo).
|
||||
if (!asset || asset.type !== 'behavior') this.select(null);
|
||||
else if (!asset.graph.nodes.some((n) => n.id === s.nodeId)) this.select({ kind: 'asset', assetId: s.assetId });
|
||||
else if (!asset.graph.nodes.some((n) => n.id === s.nodeId))
|
||||
this.select({ kind: 'asset', assetId: s.assetId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +268,12 @@ export function sameSelection(a: Selection, b: Selection): boolean {
|
||||
if (!a || !b || a.kind !== b.kind) return false;
|
||||
if (a.kind === 'asset' && b.kind === 'asset') return a.assetId === b.assetId;
|
||||
if (a.kind === 'object' && b.kind === 'object') {
|
||||
return a.sceneId === b.sceneId && a.objectId === b.objectId && a.objectIds.length === b.objectIds.length && a.objectIds.every((id, i) => id === b.objectIds[i]);
|
||||
return (
|
||||
a.sceneId === b.sceneId &&
|
||||
a.objectId === b.objectId &&
|
||||
a.objectIds.length === b.objectIds.length &&
|
||||
a.objectIds.every((id, i) => id === b.objectIds[i])
|
||||
);
|
||||
}
|
||||
if (a.kind === 'node' && b.kind === 'node') return a.assetId === b.assetId && a.nodeId === b.nodeId;
|
||||
return false;
|
||||
|
||||
Reference in new issue
Block a user