Commit Graph
820 Commits
Author SHA1 Message Date
MortenHustedandClaude Opus 5.5 3567bef862 #1460: commands and tools that pass their params on list what they pass
file.placeImage runs image.place's code and file.exportSvg file.export's,
so their docs now list the names those read (width, height, target, mode;
scale or size and the export options). MCP's create_node passes points,
closed and select to node.create, and pointer and key read ctrl, so their
schemas list them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:35:23 +01:00
MortenHustedandClaude Opus 5.5 27c11858e1 M0.9: MCP tools and batch steps refuse names they don't take (#1413)
`run_command {"command": "inspect.code", "args": {...}}` ran the command
without its params, on the selection. MCP tool arguments are now checked
against each tool's input schema (and the objects it describes inside,
such as a batch's steps; open objects like `params` take anything), and
a step key other than `command`, `params` and `as` is refused in
command.batch, figcraft-cli scripts and the MCP batch tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:06:59 +01:00
MortenHustedandClaude Opus 5.5 ff4fe00294 M0.9: commands refuse parameter names they don't take (#1413)
A misspelt parameter name was ignored and the command reported success,
answering as if the parameter hadn't been given (`comment.list
{"filterr": "open"}` listed resolved threads). `Session::execute` now
refuses names the command's params doc doesn't list, naming them and
what the command takes, before the command runs, so every path into a
command (CLI, batches, control channel, MCP, plugins, the UI) gets the
check.

The names come from the existing docs, parsed once with the registry:
each top-level item's first word and the words joined to it by `|`, `/`
or `+`, bracketed text and what follows `:`, `=` or `→` being
description, alternative groups (`{x, y} | {points}`) included. `ids`
and `id` are always taken (`params::targets` reads either); node.set,
whose doc is its props list, keeps its own check.

The junk sweep runs each junk object as given and cut down to the names
a command takes, so the junk values still reach the parsers. Tests that
passed names their command never read (comment.resolve's author,
collab.host's link, node.get's depth) pass only what it takes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:06:58 +01:00
MortenHustedandClaude Opus 5.5 64e648ae7e M0.9: command docs list every parameter their commands read
Before commands can refuse names their docs don't list (#1413), the docs
have to list what the code reads. These are the top-level names the run
code (and every helper it hands the params to) reads that its doc left
out, all checked against the code; nothing changes behaviour:

- creation: node.create (characters, points, closed), frame.create,
  shape.*, text.create and vector.create (index, name, select),
  image.place (name)
- aliases the code already took: comment.* (id | link), annotation.add
  and annotation.edit (label | text), text.set (characters | text),
  text.listStyle (style | list), fill.add and stroke.add (paint | color),
  proto.interaction.add/set (durationMs | duration_ms, delayMs | delay_ms)
- options: file.export and export.update (contentsOnly,
  includeBoundingBox, svgOutlineText, svgSimplifyStroke), comment.next
  (frame, resolved), layout.suggest (direction), variable.create
  (description), vector.edit.widthPoint (side), collab.share (key),
  collab.manageFile (access, label, link, name), fill.pattern (visible,
  blend)
- docs whose shape hid a name: proto.interaction.add (a stray `}` closed
  the object before delayMs; dest was only in a trailer),
  proto.interaction.set (patch fields in a second object), collab.join
  (a top-level comma inside the link examples), pref.uiScale (commas in
  the value's description)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:06:33 +01:00
NetterSilverandClaude Opus 5.5 adb1b43033 Speed up raster export: faster blur and spread passes
Shadows and layer blurs dominated PNG/JPG/WebP export time (gdb stack
sampling of the example files: about 45% in fx::box_blur_h, 13% in
fx::morph). Both now produce the same bytes, faster:

- fx::blur runs its three box passes per row while the row is in cache,
  works on whole pixels instead of bounds-checked bytes, skips fully
  transparent rows, transposes in cache-friendly column blocks, and
  splits rows and transposes across rayon on desktop for pixmaps of
  64K pixels and more, only when not already on a rayon worker (a band
  of render_view stays on its thread: no nested parallelism).
- fx::morph (shadow spread on layers that aren't one outline) uses the
  van Herk / Gil-Werman running max/min: constant work per pixel instead
  of 2r + 1.

Integer arithmetic and pass order are unchanged; new tests compare both
against the previous implementations byte for byte, including sizes on
the parallel path.

An ignored timing test exports every top-level frame of examples/ as
PNG, JPG and WebP at 2x through export_file:
cargo test --release -p figcraft-engine --lib export_timings -- --ignored --nocapture

Ryzen, 16 threads, Linux; median of 7 (min):
  PNG   2195 ms (2182) ->  992 ms (989)   -55%
  JPG   2880 ms (2560) -> 1550 ms (1535)  -46%
  WebP  1964 ms (1901) -> 1022 ms (1018)  -48%
  total 7035 ms (6677) -> 3567 ms (3555)  -49%
All 80 exported files (PNG, JPG, WebP, PDF, SVG) are byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:43:23 +01:00
aiongg 0330a7cc85 refactor(engine): move assets/components test files to assets/components/ 2026-10-26 20:36:51 +00:00
aiongg 2576e646a1 refactor(engine): move sharing/background test files to sharing/background/ 2026-10-26 20:36:51 +00:00
aiongg 7d70e0bfe5 refactor(engine): move assets/library test files to assets/library/ 2026-10-26 20:36:51 +00:00
aiongg 9c97cb6e17 refactor(engine): move assets/library_server test files to assets/library_server/ 2026-10-26 20:36:51 +00:00
aiongg 32bd9dc35a refactor(engine): move fonts test files to fonts/ 2026-10-26 20:36:51 +00:00
aiongg 3398ec3c8c refactor(engine): move automation/file_access test files to automation/file_access/ 2026-10-26 20:36:50 +00:00
aiongg f664a82093 refactor(engine): move assets/library_swap test files to assets/library_swap/ 2026-10-26 20:36:50 +00:00
aiongg a9d93f8310 refactor(engine): split cmd/file.rs into file/ 2026-10-26 20:17:48 +00:00
aiongg 96423f5a6e refactor(engine): move cmd/file.rs zip_cap_tests to file/zip_cap_tests.rs 2026-10-26 20:17:48 +00:00
aiongg 13855cfabe refactor(engine): move cmd/file.rs staging_write_tests to file/staging_write_tests.rs 2026-10-26 20:17:48 +00:00
aiongg 47c807f209 refactor(engine): move cmd/file.rs rest_import_tests to file/rest_import_tests.rs 2026-10-26 20:17:48 +00:00
aiongg f0f1c2003d refactor(engine): move cmd/file.rs tab_order_tests to file/tab_order_tests.rs 2026-10-26 20:17:48 +00:00
aiongg 1e9e0a4e75 refactor(engine): split session.rs into session/ 2026-10-26 20:17:48 +00:00
aiongg c4bd0dd542 refactor(engine): move Session state, prefs, errors and methods out of lib.rs 2026-10-26 20:17:48 +00:00
aiongg 0b9fcb7f4e refactor(engine): split cmd/component.rs into component/ 2026-10-26 20:17:48 +00:00
aiongg cea90cf935 refactor(engine): split cmd/edit.rs into edit/ 2026-10-26 20:17:48 +00:00
aiongg 688eeccc7a refactor(engine): split boards/board.rs into board/ 2026-10-26 20:17:48 +00:00
aiongg ad4ba1ae9b refactor(engine): split dev/codegen.rs into codegen/ 2026-10-26 20:17:48 +00:00
aiongg c631450b0c refactor(engine): split sharing/live.rs into live/ 2026-10-26 20:17:48 +00:00
aiongg 0bc49705bd refactor(engine): split assets/components.rs into components/ 2026-10-26 20:17:48 +00:00
aiongg 2e7790b58b refactor(engine): split canvas/tools.rs into tools/ 2026-10-26 20:17:48 +00:00
aiongg e1b0ea2c1d refactor(engine): move batch, params, inspect, file_access, doc_urls to automation/ 2026-10-26 20:17:48 +00:00
aiongg 2cf15106e1 refactor(engine): move datafill, textfit, templates, synthetic, synthetic_ds to content/ 2026-10-26 20:17:48 +00:00
aiongg 53b04cc784 refactor(engine): move plugins, plugin_directory, widgets to extensions/ 2026-10-26 20:17:48 +00:00
aiongg fa8e917ede refactor(engine): move collab, live, online, branches, invite_links, background to sharing/ 2026-10-26 20:17:48 +00:00
aiongg 9452ec1ada refactor(engine): move annotations, code_connect, codegen, component_codegen, tailwind, devcompare, devinspect, dev_measurements, dev_resources to dev/ 2026-10-26 20:17:48 +00:00
aiongg e466f4a03a refactor(engine): move components, library, library_server, library_swap, style_vars, playground, token_roles to assets/ 2026-10-26 20:17:48 +00:00
aiongg a587d964c9 refactor(engine): move selection_colors, selection_reorder, selection_spacing, rename to selection/ 2026-10-26 20:17:47 +00:00
aiongg 094b01e501 refactor(engine): move tools, snap, distance, guides, drop, arc_handles, shape_handles, rotation_origin, al_keys, booleans, shapebuilder, textedit, textpreview, vectoredit to canvas/ 2026-10-26 20:17:47 +00:00
aiongg 5d1b826f7a refactor(engine): move board, board_table, board_templates to boards/ 2026-10-26 20:17:47 +00:00
aiongg a3179236f3 refactor(engine): move textedit.rs inline tests to crates/engine/src/textedit/tests.rs 2026-10-26 20:17:47 +00:00
aiongg 71524803d1 refactor(engine): move crates/engine/src/templates/mod.rs to crates/engine/src/templates.rs 2026-10-26 20:17:47 +00:00
aiongg d853eee820 refactor(engine): move crates/engine/src/cmd/mod.rs to crates/engine/src/cmd.rs 2026-10-26 20:17:47 +00:00
BFlat cac54fd552 Merge pull request #840 from StrajnarFilip/feat/vector-drawable-export
M6: export as Android Vector Drawable (XML)
2026-10-27 01:06:21 +07:00
BFlat 740cc2a2c6 Merge pull request #726 from ijashuzain/feat/variables-dart-export
M6: export variables as Dart constants for Flutter
2026-10-27 00:53:10 +07:00
BFlat 29c89f7d5b Merge pull request #650 from JimKnoxx/overlay-anchor-trigger
M5: overlay positions relative to the layer that opens them
2026-10-27 00:49:52 +07:00
bflatastic 2aae395310 Merge main into #840 2026-10-27 00:31:32 +07:00
bflatastic fd0f4d8b60 Merge main into #664
Main's class_name takes the node kind (#1372); Vue's slot names pass slot.
2026-10-27 00:30:42 +07:00
BFlat 83c7940293 Merge pull request #1384 from muamerETS/fix/1370-drag-unfilled-selection
M1: a selected unfilled shape drags over a filled layer stacked below it (#1370)
2026-10-27 00:25:59 +07:00
BFlat 7cb369db8c Merge pull request #1372 from lileeei/1235-transliterate-class-names
Transliterate non-ASCII layer names into code-export class names
2026-10-27 00:23:36 +07:00
BFlat 8583588839 Merge pull request #1366 from Silvertree2010/fix/h2716-px-to-rem-conversion-rounds-to-2
Keep full precision when converting px to rem in code export
2026-10-27 00:13:42 +07:00
BFlat ad9abe7ce6 Merge pull request #1133 from g1obalworlds/fix-batch-rollback-closed-tabs
engine: restore tabs closed inside a failed command group
2026-10-27 00:13:37 +07:00
BFlat dd5b5c0dc0 Merge pull request #1374 from Ridzzz0Alam/fix/1330-save-disk-changes
fix: Issue #1330 Save no longer overwrites changes another app made to the open file
2026-10-27 00:13:15 +07:00
bflatastic 632f2cef4b Merge main into #840
# Conflicts:
#	docs/roadmap.md
2026-10-27 00:12:27 +07:00
bflatastic 15c6834114 Merge main into #1384 2026-10-27 00:10:34 +07:00