Add prepared build artifacts, browser host and the build and
purge commands for the CLJS renderer benchmarks.
Each preparation attempt gets a build ID and a retained directory with
its manifest, log, Node case catalog, browser bundle, renderer files
and host page. Ready builds load their matching catalog in process and
serve only their own directory through an owned loopback host.
Own Chromium through a bounded process group, verify the compiled build
identity before execution and retain failed preparations for diagnosis.
Wire the diagnostic pilot to the same build, catalog, server and
browser APIs.
Add real boundary tests for artifacts, processes, servers, browsers and
CLI parsing, and register them with the performance test runner. Rename
the benchmark lint and test scripts to match the suite.
AI-assisted-by: deepseek-flash
* 🐛 Create Plugin API shapes at the page root
Create component instances and SVG shapes at the page root so a board at
the page origin cannot capture them. Continue using the existing forced
frame option for component instances and an explicit parent frame for
SVG imports. Interactive placement retains its current behavior.
Cover component instances, SVG imports and SVG imports with images on
ordinary, flex and grid origin boards, including undo, redo, position
changes and explicit reparenting.
Closes#12086
AI-assisted-by: deepseek-v4.1-flash
Signed-off-by: choi junsoo <junsoo1172@gmail.com>
* 🐛 Preserve interactive creation placement
Cover component and SVG placement inside and outside an origin board.
Exercise the sidebar move lifecycle and verify parent preservation.
Correct the Plugin API changelog category.
AI-assisted-by: gpt-6
Signed-off-by: choi junsoo <junsoo1172@gmail.com>
* 🔧 Cover page-root creation in the Plugin API test suite
Check that LibraryComponent.instance(), createShapeFromSvg() and
createShapeFromSvgWithImages() create shapes at the page root when a
board covers the page origin. Each test removes the shape it creates,
since it lives outside the scratch board.
AI-assisted-by: claude-opus-5-5
---------
Signed-off-by: choi junsoo <junsoo1172@gmail.com>
Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
* ✨ Add unit tests for the token form and combobox helpers
Several helpers of the token forms and the token value combobox were
already pure but had no tests. Cover the reference under the cursor,
the order of the token tree, moving through the combobox options, the
shadow and typography form values and their validation, which value a
form tab validates, and that a token import needs a json file.
Signed-off-by: Florian Schroedl <flo.schroedl@gmail.com>
* ✨ Test the shadow and typography form rules
Add tests for the shadow and typography form schemas: a negative blur
is rejected, a negative spread and a blank blur or spread are accepted,
every shadow needs its offsets and color, a line height needs a font
size, and a token can't reference itself. A typography token submitted
without any field is rejected.
They replace the tests of the validator wrappers, the combobox focus
order and the import file check.
Signed-off-by: Florian Schroedl <flo.schroedl@gmail.com>
---------
Signed-off-by: Florian Schroedl <flo.schroedl@gmail.com>
The Integrations settings page labelled the MCP server as Beta, while
the MCP docs give no maturity status. Drop the badge, its style and the
unused translation key so the UI no longer presents it as beta.
Closes#12800
AI-assisted-by: claude-opus-5-5
The token pill worked out inside the component whether its token is
applied to the selection, whether it can apply to it at all and why
the token is invalid, so no test could reach that logic. Move it into
`pill-state`, and split the tooltip into `tooltip-info`, which decides
what it says, and `render-tooltip`, which renders it. Both are pure
and get unit tests for the applied, partial, disabled and error states
and each tooltip case.
The two chained `on-click` handlers become one. Nothing else changes
in behavior.
Signed-off-by: Florian Schroedl <flo.schroedl@gmail.com>
At some point the code around this changed, I believe this used to reduce over
file ids. However today it reduces over entire library maps, so it passes a map
instead of an id to `dm/get-in files`. This then hashes the library which
forces it to decode all of its shapes, and then it fails to lookup the data. So
the component/colors/typography counts were always returning 0.
Using reduce-kv fixes this, and we can just get the library data directly with
`(:data library)`.
On the backstage file in penpot-files this brings the time to the telemetry
snapshot down from 3.8s to 1.5s
AI-assisted-by: claude-5.5-sonnet
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
* ⚡ Avoid decoding the opened page twice for its frame index
The frame index was built over a with-meta copy, so pages got decoded again.
Read it from the page objects themselves and fix the with-meta identity check.
* ⚡ Intern keywords when decoding transit on the frontend
Each shape is decoded on its own, so every shape had its own key keywords.
Cache them in the read handler so all decoded data shares one instance.
* ⚡ Use an array map as the wasm shape proxy delegate
A hash map with ~35 keys costs ~3 KB of nodes per shape on large pages.
An array map holds the same entries in one array, at a small lookup cost.