Add CI workflow, render snapshots, and keyboard apply shortcuts
Some checks are pending
CI / test (push) Waiting to run
Some checks are pending
CI / test (push) Waiting to run
This commit is contained in:
parent
bfb8275b2f
commit
9ce07c860b
34
.gitea/workflows/ci.yml
Normal file
34
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,34 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install deps
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Static syntax checks
|
||||
run: |
|
||||
node --check src/server.js
|
||||
node --check src/mcp-server.js
|
||||
node --check src/layout.js
|
||||
node --check src/compile.js
|
||||
node --check frontend/app.js
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
@ -38,6 +38,9 @@ Docs:
|
||||
- `docs/release-checklist.md`
|
||||
- `docs/operations-runbook.md`
|
||||
|
||||
CI:
|
||||
- `.gitea/workflows/ci.yml` runs syntax checks + full test suite on push/PR.
|
||||
|
||||
## REST API
|
||||
|
||||
### `POST /compile`
|
||||
@ -157,3 +160,9 @@ Tools:
|
||||
- Selected panel editors for component properties, full pin properties, full symbol body/pin editing, and net connect/disconnect operations
|
||||
- Click diagnostics to jump/flash focused net/component/pin
|
||||
- Auto Layout and Auto Tidy actions
|
||||
- Keyboard shortcuts:
|
||||
- `Ctrl/Cmd+Z` undo
|
||||
- `Ctrl/Cmd+Shift+Z` or `Ctrl/Cmd+Y` redo
|
||||
- `Space` rotate selected components (or pan when no selection)
|
||||
- `Alt+Enter` apply current selection editor (component/pin/net)
|
||||
- `Alt+C` connect selected pin to chosen net
|
||||
|
||||
@ -2990,6 +2990,28 @@ function setupEvents() {
|
||||
el.canvasViewport.classList.add("dragging");
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
||||
if (evt.altKey && evt.key === "Enter") {
|
||||
evt.preventDefault();
|
||||
if (state.selectedPin) {
|
||||
el.applyPinPropsBtn.click();
|
||||
return;
|
||||
}
|
||||
if (state.selectedNet) {
|
||||
el.updateNetBtn.click();
|
||||
return;
|
||||
}
|
||||
if (state.selectedRefs.length === 1 && state.selectedRef) {
|
||||
el.updatePlacementBtn.click();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (evt.altKey && evt.key.toLowerCase() === "c" && state.selectedPin) {
|
||||
evt.preventDefault();
|
||||
el.connectPinBtn.click();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("keyup", (evt) => {
|
||||
|
||||
@ -13,12 +13,12 @@
|
||||
<p>AI-Native Schematic Workspace</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button id="newProjectBtn">New</button>
|
||||
<button id="loadSampleBtn">Load Sample</button>
|
||||
<button id="importBtn">Import JSON</button>
|
||||
<button id="exportBtn">Export JSON</button>
|
||||
<button id="autoLayoutBtn">Auto Layout</button>
|
||||
<button id="autoTidyBtn">Auto Tidy</button>
|
||||
<button id="newProjectBtn" aria-label="Create new project">New</button>
|
||||
<button id="loadSampleBtn" aria-label="Load sample project">Load Sample</button>
|
||||
<button id="importBtn" aria-label="Import Schemeta JSON file">Import JSON</button>
|
||||
<button id="exportBtn" aria-label="Export Schemeta JSON file">Export JSON</button>
|
||||
<button id="autoLayoutBtn" aria-label="Run automatic layout">Auto Layout</button>
|
||||
<button id="autoTidyBtn" aria-label="Run automatic tidy layout">Auto Tidy</button>
|
||||
<button id="undoBtn" title="Undo (Ctrl/Cmd+Z)">Undo</button>
|
||||
<button id="redoBtn" title="Redo (Ctrl/Cmd+Shift+Z)">Redo</button>
|
||||
<label class="inlineSelect">
|
||||
@ -54,10 +54,10 @@
|
||||
|
||||
<section class="pane center">
|
||||
<div class="canvasTools">
|
||||
<button id="zoomOutBtn">-</button>
|
||||
<button id="zoomResetBtn">100%</button>
|
||||
<button id="zoomInBtn">+</button>
|
||||
<button id="fitViewBtn">Fit</button>
|
||||
<button id="zoomOutBtn" aria-label="Zoom out">-</button>
|
||||
<button id="zoomResetBtn" aria-label="Reset zoom">100%</button>
|
||||
<button id="zoomInBtn" aria-label="Zoom in">+</button>
|
||||
<button id="fitViewBtn" aria-label="Fit schematic to viewport">Fit</button>
|
||||
<label class="inlineCheck"><input id="showLabelsInput" type="checkbox" checked /> Labels</label>
|
||||
<span id="compileStatus">Idle</span>
|
||||
</div>
|
||||
|
||||
19
tests/render-regression.test.js
Normal file
19
tests/render-regression.test.js
Normal file
@ -0,0 +1,19 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { compile } from "../src/compile.js";
|
||||
import fixture from "../examples/esp32-audio.json" with { type: "json" };
|
||||
|
||||
function svgHash(svg) {
|
||||
return createHash("sha256").update(String(svg ?? "")).digest("hex");
|
||||
}
|
||||
|
||||
test("render output for reference fixture remains deterministic", () => {
|
||||
const outA = compile(fixture, { render_mode: "schematic_stub", show_labels: true });
|
||||
const outB = compile(fixture, { render_mode: "schematic_stub", show_labels: true });
|
||||
|
||||
assert.equal(outA.ok, true);
|
||||
assert.equal(outB.ok, true);
|
||||
assert.equal(outA.svg, outB.svg);
|
||||
assert.equal(svgHash(outA.svg), "c7a3cd161b6129b53e335d689e13b5425ccca6692f263245e3bf2d7b37aab06a");
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user