Found while testing crates/engine/src/cmd/arrange.rs:132
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Override rows of an instance can name a layer of its main by the key the layer
had before the main was edited. The key now resolves to the layer's current id
when it is unambiguous and the current id does not exist already. Rows of an
enclosing instance win over those of the instances nested in it, whatever order
the wire lists them in, and an explicit "no style" on an override detaches the
style instead of falling back to the older field.
Paints bound to variables take the colours of the active modes when a document
loads, before the first edit, without touching other pending changes.
A stroke-only vector that imports as the outline of its stroke now moves the
stroke's shared style and colour variables to the fill it becomes, and vectors
whose single segments carry their own stroke style say so in a warning.
A .fig import now links the layers of an instance to the layers of the
component they came from by the ids the file stores, instead of leaving it to
the engine to guess from names and places. Renamed slots and layers, siblings
that share a name and swapped mains keep their source link and the override
they carry.
Components that live only on the file's hidden internal pages (cached copies of
library components) are kept in the hidden library store when a visible layer
uses them, so their instances stay instances. The read-only guard for library
copies now compares the copies themselves rather than the dirty set, which an
import leaves full until the first edit.
Rebasing an instance (after detaching an outer instance or restoring a main)
follows the source chain inside the right enclosing instance, so contextual
links survive it. The last change of a GUID wins and a removed change deletes
it. Ordinary file JSON never reads the private provenance.
Importing such a file into an open document, or pasting its layers into another one, copies the cached components along (import) or leaves them behind as a missing main (paste), so no link points at a layer of the target.
Opening or importing a .fig or REST JSON file, or an SVG that has notes,
from the app (File > Open or Import, a recent file, a drop, a paste, the
system's open event) now shows an Import report window with the
document's name, its page, layer and image counts and the compatibility
notes the importer collected, instead of leaving them only in the command
result. Commands sent over the control channel or MCP never open it.
file.open and file.import return the counts as `summary`; ui.inspect
reports the open report as `importReport`. The fixed notes the importers
emit are translated (German and Spanish) and shown with a capital first
letter; other notes, such as SVG's, show as written. The report goes
away with its document. Escape or Close dismisses it.
Save as now offers .figcraft and .fig as separate file types. A .fig
destination, chosen in the dialog or passed to file.saveAs and file.save,
writes the existing experimental .fig export of the document that is shown
and reports how much was left out. The file's own path, unsaved changes,
versions, branches and undo history are not touched, and a shown earlier
version stays shown while the copy is written or a Save as choice is
pending.
Plain Save no longer writes over a file whose saved path ends in .fig;
earlier builds could write native data under that name. It asks for a
destination instead.
Pasting or dropping a file runs file.import with the whole file as Base64
data, and every successful command was journaled with its parameters, so
each imported file stayed in memory a second time for the session. Byte
imports, including ones wrapped in command.batch, are no longer journaled.
Imports by path and all other commands are unchanged.
- Several ids: auto layout keys go to the frame-like layers, the others get the remaining keys
and are named in `warnings`. Refused only when no target can have auto layout.
- fontStyle is never refused: it draws in the nearest face, as a text layer resolves it.
`warnings` says so when that face's weight or slant differs from what the name asks for.
- set_properties passes `warnings` on to the agent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A home-screen drop that carries only bytes queued file.open with data and name, which file.open rejected because it requires a path. file.open now also takes base64 data with a name and opens it as a new document without a save path.
Found while testing crates/engine/src/cmd/file.rs:1283
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Preserve the upstream behaviour and regression tests alongside this feature. Align the control-server connection-limit test with main closing invalid JSON connections: assert EOF instead of shutting down an already closed socket on macOS.
Preserve the upstream behaviour and regression tests alongside this feature. Align the control-server connection-limit test with main closing invalid JSON connections: assert EOF instead of shutting down an already closed socket on macOS.
page.duplicate copies every layer with duplicate_all_into (navigation between
copied frames points at the copies) and builds the old-to-new list for flows
from that copy, instead of copying each layer separately.
Main's case-insensitive replace loop (from an earlier PR) took the place of the
loop this change edited, so the replacement text is normalised once, where
the parameter is read.