Commit Graph
1442 Commits
Author SHA1 Message Date
skylartaylor d9584410af ci: retain FigCraft package and metadata checks 2026-10-16 05:24:23 +02:00
Skyfuller1303 c4536f412b M1: import labels of straight connectors from .fig files
Straight connectors saved with a manual routing snapshot (connector and derived-frame version 1) now come in as an editable vector plus their label text layers, instead of an empty frame. Label placement composes the saved background and text transforms, and label paints and text styles use the existing import path. Connectors of other versions or line styles keep the existing fallback with their compatibility notes. At the layer depth or node limit the saved vector is kept without extra label layers, and skipped labels are reported once. Live endpoint bindings and routing are not retained.
2026-10-16 05:08:37 +02:00
Skyfuller1303 7fd44641f2 M1: keep paragraph options from .fig files
Text layers, text styles and instance overrides in .fig files can carry list spacing, hanging list, hanging punctuation and leading trim. The importer now reads them from the highest layer with a valid value, so an invalid instance override row falls through to the valid value below it, while explicit zero, false and NONE values stay resets. Both text layers and text styles share one mapping. The native text data stores these options once per text node, so differing values on separate runs are not represented, and the experimental .fig exporter keeps its existing note that these settings are left out.
2026-10-16 05:03:38 +02:00
Skyfuller1303 3723fcffbd M1: keep text decoration skip ink from .fig files
Text layers, styled runs and text styles in .fig files carry a skip-ink boolean for their decoration. The importer now reads it into the native decoration look: an omitted run value inherits the layer's, a local value overrides a linked shared text style without changing the style itself, and instance overrides keep an explicit false over a true main. A malformed value counts as unset. The exporter writes the actual value of the layer and of each styled run instead of a constant true, and a decoration look that differs from the default only in skip ink no longer triggers the unsupported-decoration note, so default native text exports its real false value.
2026-10-16 05:03:34 +02:00
Skyfuller1303 120b6830ff M1: import editable text on a path from .fig files
Supported TEXT_PATH layers import as editable native text on their vector path, including mixed text styles, a start inside a later segment and reversed text direction. The importer converts the segment parameter stored in the file to the native distance along the complete path.

The mapping accepts a connected, unbranched path with one recognized start-segment marker and the default placement above the path. Damaged or unsupported path data keeps the text readable off its path and adds an import note. Other vertical placements, multiline text and ambiguous or disconnected networks are not converted. Underline and strikethrough remain a native path-rendering limitation and are reported. Public REST TEXT_PATH layers and the experimental .fig writer are unchanged.
2026-10-16 05:03:29 +02:00
Skyfuller1303 a52e2bb6b3 M1: distinguish unresolved vector segment style metadata in .fig import
The vector network decoder now keeps each segment's style id. Import reports a segment style that names a row of the layer's style table as metadata that was not interpreted, and one that names no row as a reference to a missing style entry, each at most once per file. The earlier note claimed that stroke styles were left out, which overstated what is known about the metadata. Segment geometry, paint and width are unchanged, and the style ids are not kept in the native vector model.
2026-10-16 05:02:27 +02:00
Skyfuller1303 8408cc72b8 M1: import component slot content from .fig files
Slot properties of a component, the frames that reference them and the content that instances assign to them now come across from .fig files. A slot definition becomes a native slot property. The referencing frame of an expanded instance keeps following the frame of its main, and when the instance assigns slot content (including an explicitly empty slot) the frame carries that content as its own, independently owned children. Nested instances inside assigned content keep their own source links. An assignment on an outer instance wins over one made by an instance nested in the main, and a slot without an assignment keeps the default content of its main.

Assignments that are malformed, use the empty-GUID sentinel or point at a layer that is not slot content are skipped with an import note. Preferred component keys cannot be mapped to nodes of the file and are dropped with a note, as are slot settings the editor cannot represent. Public REST snapshots, the experimental .fig writer and property resources are not changed.
2026-10-16 04:59:11 +02:00
Skyfuller1303 0b40964202 M1: keep grid track sizes in .fig import
Grid columns and rows keep fixed pixel sizes, Hug sizing and fractional Fill weights when the minimum and maximum sizing definitions agree. Track GUIDs join the sizing records to the ordered tracks, so reordered records do not change cell placement. Unsupported min/max pairs, invalid sizes and duplicate records fall back with a reported note, and imports are bounded to 1,000 tracks per axis. Public REST snapshots ignore the private track metadata.
2026-10-16 04:58:11 +02:00
Dylan M. Taylor 3489e01a22 ci: delegate release, freebsd, windows-arm64, packaging-lint to craft-common-actions and add nix check 2026-10-15 21:39:02 -04:00
NetterSilverandClaude Haiku 5.5 8538dd740f Refuse edits that leave a layer with non-finite geometry
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>
2026-10-16 03:38:36 +02:00
Skyfuller1303 d2606b3f51 M1: let local text values and instance overrides win over a shared text style in .fig import
A text layer that links a shared text style keeps its own, possibly stale, copy
of the typography. The style's typography now beats that copy, a case,
decoration, paragraph spacing or paragraph indent set on the layer itself beats
the style (so "original", "none" and zero clear the style's value), and an
override row of an instance beats both. An explicit "no style" on a text layer
unlinks it even when the older style field still names one.

Letter spacing given as a percentage of the font size stays a percentage. A text
property value on an instance no longer inherits the character styles written
for the main's text, which count other characters.
2026-10-16 03:32:39 +02:00
Skyfuller1303 4b29d8c34d M1: apply instance overrides by key and order, settle bound paints, keep stroke outline styles
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.
2026-10-16 03:32:38 +02:00
Skyfuller1303 d331db00aa M1: keep explicit instance identity and cached library components in .fig import
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.
2026-10-16 03:32:36 +02:00
krinry b525fde8d1 M1: pop up colour picker when adding a fill or stroke (#404)
Clicking the + button to add a fill or stroke in the Design panel now
immediately opens the colour picker dialog for the newly added paint,
matching Figma's behaviour.
2026-10-16 06:45:40 +05:30
BFlat f40c600e67 Docs: roadmap rows for the community fixes from #478 up (#591, #598, #602) and #589 (#605) 2026-10-16 07:55:52 +07:00
BFlat 9c2d61f6ae Merge pull request #601 from Skyfuller1303/feat/drop-to-open
M7: drop files anywhere to open them
2026-10-16 07:41:02 +07:00
vxMacDev 9c1d65d924 fix(render): text strokes follow their alignment (#615)
The canvas renderer and PDF export stroked text with the alignment
forced to centre, so Inside and Outside on text did nothing (SVG export
already honoured them). Glyph outlines are closed, so text strokes now
go through stroke_area like other shapes' strokes, with the same fill
rule: inside clips to the glyphs, outside to around them.
2026-10-15 19:36:39 -05:00
skylar taylor-barrick e4fe308cdf Merge pull request #608 from Silvertree2010/fix/h1871-file-close-with-a-negative-index
Reject negative or fractional index in file.close
2026-10-15 18:28:25 -06:00
Marco Arnulfo 5d1c24d061 Contributors: add my name for the About window 2026-10-16 02:19:42 +02:00
Skyfuller1303 01daf92fc3 M1: show an import report after opening a file
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.
2026-10-16 02:18:50 +02:00
Skyfuller1303 d4394e87cc M1: save a copy as .fig
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.
2026-10-16 02:03:46 +02:00
vxMacDev c56a65f58b fix(format): keep vertical trim on .fig import (#466)
Figma's schema has leadingTrim on NodeChange (NONE, CAP_HEIGHT), and
the REST importer already reads style.leadingTrim, but the .fig mapping
never copied it, so text set to "Cap height to baseline" imported
untrimmed in its trimmed box. text_style now copies it with the other
text fields, from the layer or its text style.
2026-10-15 18:45:06 -05:00
Skyfuller1303 924310c124 M1: keep per-point stroke joins on .fig import
Vector points carry their own stroke join in a .fig file. Import now keeps each point's join as the point's own override instead of dropping it for the layer's join.

Joins equal to the layer join no longer force styled stroke runs, and an absent layer join counts as miter. Unresolved point styles, unknown joins, and joins that dashed or variable-width strokes cannot draw each produce a warning.
2026-10-16 01:34:52 +02:00
Skyfuller1303 0404448f74 M1: keep imported file bytes out of the command journal
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.
2026-10-16 01:34:29 +02:00
BFlat 4ee413acde Merge pull request #606 from storytold/community/batch-8
Community batch 8: drop files anywhere, duplicate fill tests
2026-10-16 06:18:07 +07:00
Edivan TeixeiraandClaude Opus 5.5 f05eecdaa0 node.set: test that a refused call changes nothing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:46:04 -03:00
Edivan TeixeiraandClaude Opus 5.5 8cccc48516 node.set: apply auto layout keys to the frames and name the rest; resolve fontStyle like text does
- 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>
2026-10-15 19:43:52 -03:00
Skyfuller1303 1f6010e07c M7: open dropped files that have no file on disk
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.
2026-10-16 00:22:14 +02:00
NetterSilverandClaude Haiku 5.5 90d7521840 Reject negative or fractional index in file.close
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>
2026-10-16 00:19:49 +02:00
Daniel Miguel c6a3f25224 M0.9: sync reviewed GNOME controls fix with upstream 2026-10-16 00:13:38 +02:00
bflatastic 665a578957 Merge branch 'fix-601' into batch/t8 2026-10-16 05:04:14 +07:00
bflatastic 44ac32db0c Merge branch 'pr-600' into batch/t8 2026-10-16 05:04:13 +07:00
bflatastic f948e08fbc Merge remote-tracking branch 'origin/main' into fix-601
# Conflicts:
#	ROADMAP.md
2026-10-16 05:04:09 +07:00
bflatastic 65f5771a6e Home: describe the drop target without naming other software 2026-10-16 05:04:00 +07:00
Daniel Miguel b83a0de7a8 M0.9: scope Wayland decorations and avoid bundled title fonts 2026-10-16 00:01:55 +02:00
BFlat 33d59932f9 Merge pull request #602 from storytold/community/batch-7
Community batch 7: Czech plurals and bounded canvas overscan
2026-10-16 04:51:25 +07:00
Edivan TeixeiraandClaude Opus 5.5 c8ba7b4a4b node.set: refuse auto layout keys off frames, and font styles the family lacks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:26:08 -03:00
bflatastic 049f97a4c3 Merge branch 'pr-597' into batch/t7
# Conflicts:
#	ROADMAP.md
2026-10-16 03:46:48 +07:00
bflatastic 62a291fcb8 Merge branch 'pr-596' into batch/t7 2026-10-16 03:46:43 +07:00
BFlat 7459cc7f86 Merge pull request #598 from storytold/community/batch-6
Community batch 6: 8 reviewed PRs
2026-10-16 03:45:01 +07:00
Ivan Shishkanov ce6726aad3 M1: merge current main and resolve PR #595 conflicts
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.
2026-10-15 23:12:40 +03:00
Ivan Shishkanov 692d52c514 M3: merge current main and resolve PR #575 conflicts
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.
2026-10-15 23:08:41 +03:00
Barzabel d27ae11d15 M1: a duplicate's fill stays its own (#586)
Regression test for #586: with the colour picker open on a red rectangle or
pen path, duplicating it (edit.duplicate, or copy and paste) and recolouring
the copy leaves the original red. The cause was the picker staying bound to
the original after the selection moved to the copy, fixed by #523; without
that fix this test fails. The duplicated paint is already independent data.
2026-10-15 23:06:31 +03:00
Patrik LermonandClaude Opus 5.5 0a5eceedf1 i18n(sv): translate 480 new strings
Brings the Swedish catalog up to date with upstream main (eb741a3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:05:47 +02:00
Skyfuller1303 b640069961 M7: drop files anywhere to open them
- Files dragged over the window show a "Drop to open" (home screen) or
  "Drop to import" (canvas) overlay.
- On the home screen each dropped file the app opens becomes a document of its
  own; any other file is turned away with a toast.
- On the canvas dropped files import as before, at the drop point.
- A small card ("Opening as a new file", "Adding to {document}") is on screen
  before a large file blocks the window; the files then open a frame later.
- A canvas import stays with the document and page that received the drop,
  keeps its placement, restores the page and selection chosen meanwhile, and is
  cancelled with a message if that document or page is gone.
- ui.inspect reports pendingOpens; every new string, including the cancel
  messages, goes through tr() with en, de and es entries.
2026-10-15 21:48:25 +02:00
bflatastic 9f935718fe Merge branch 'rb-578' into batch/t6
# Conflicts:
#	crates/text/src/fontdb_tests.rs
2026-10-16 02:37:43 +07:00
bflatastic 1c863aa9f5 Merge branch 'rb-568' into batch/t6 2026-10-16 02:36:56 +07:00
bflatastic 891f0acb3c Merge branch 'rb-560' into batch/t6 2026-10-16 02:36:56 +07:00
bflatastic 55c05338a1 Merge branch 'rb-554' into batch/t6 2026-10-16 02:36:55 +07:00
bflatastic 4e3fd82bd1 Merge branch 'rb-549' into batch/t6 2026-10-16 02:36:55 +07:00