Commit Graph
2850 Commits
Author SHA1 Message Date
bflatastic 5adcf3cf83 Merge main into #1657 2026-10-30 20:19:47 +07:00
BFlat 6cf1ed1dd7 Merge pull request #1652 from nine-codes/claude/sharp-feynman-me8n1o
bs: Bosnian (bs) interface catalog
2026-10-30 20:18:36 +07:00
bflatastic f20e474d7e Merge main into #1652 2026-10-30 20:06:28 +07:00
bflatastic ed6a078854 Merge main into #1657 2026-10-30 20:05:52 +07:00
BFlat 22be27fb2a Merge pull request #1655 from lileeei/1102-style-dedupe-buckets
Text style dedupe is O(spans)
2026-10-30 20:03:38 +07:00
BFlat 4a9a5084bb Merge pull request #1651 from Carbocode/fix/sidebar-input-focus
M1: keep sidebar field text in place on focus
2026-10-30 20:01:24 +07:00
bflatastic cd95894f84 Merge main into #1652 2026-10-30 19:50:13 +07:00
bflatastic 60cb106eb6 Merge main into #1655 2026-10-30 19:49:39 +07:00
bflatastic a55854955d Merge main into #1651 2026-10-30 19:49:02 +07:00
bflatastic 6b35fd80cf Merge main into #1657 2026-10-30 19:48:25 +07:00
BFlat 01b07af55a M6: a pasted image the clipboard doesn't carry shows as missing and is named (#1648)
* M6: a pasted image the clipboard doesn't carry shows as missing and is named (#1646)

The placeholder an import stores for an image it lacks is now striped, not flat grey; the fill keeps the image's name; .fig and paste give a fixed, translated note per image; edit.pasteDesignLayers returns missingImages, the paste's message names those layers, and a paste with notes opens the import report.

* M6: the missing-image placeholder's stripes stay clean when scaled, and a .fig gives one note (#1646)
2026-10-30 19:34:24 +07:00
BFlat 4965620d77 M6: pasted layers keep the colours of their shared paint styles (#1647)
* M6: pasted layers keep the colours of their shared paint styles (#1638)

A clipboard links a style by the guid it has in its library, which it doesn't hold, and by its library asset, whose copy it does hold. Mapper::resource_id now takes a guid only when the file holds a node by it, else the asset, so .fig import and paste agree; a link to a style that really isn't there keeps the layer's stored colours, with a note.

* M6: Swedish catalog: keep both new import notes after the merge
2026-10-30 18:54:24 +07:00
BFlat dd2a9fd013 Docs: one copy of each row and status item, and a check that keeps it so (#1658)
* Docs: one copy of each row and status item, and a check that keeps it so

Merge resolutions that kept both sides had left progress-doc rows (the .fig row four times, co-editing, live cursors, Windows, M0.9) and status-line items (302 in all) twice or more. The rows are merged keeping every distinct fact, the newest wording winning (#1649's connector routing included); repeated status items are removed, the first kept. cargo xtask docs, run by ci, fails on a repeated table row or status item.

* Docs: remove the status items the merge of main brought back

Merging main into #1658 rebuilt the status lines from main's copies, which still listed items twice: ROADMAP 2, docs/roadmap.md 5, docs/gaps.md 43 and docs/target-app-parity.md 190, whose unclosed parenthesis also came back and hid them from cargo xtask docs. They are removed again, the first copy kept, and the parenthesis closed; every distinct item is still present against main.
2026-10-30 18:36:00 +07:00
c23f233446 M8: a font's damaged table offsets are skipped instead of wrapping on 32-bit targets (#1125)
normal_track read the trak size table at a file-controlled u32 offset with unchecked additions,
which wrap on 32-bit targets such as wasm32 (a debug panic, or reads at the wrong offset). Its
reads are now checked, and an incomplete normal track is dropped entirely, never returned in part.

index_bytes was already bounded by fill(), which checks each range before the flagged additions
run; this makes those bounds explicit, still skipping damaged faces and reading later faces' name
tables without their outlines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-30 14:08:32 +03:00
BFlat e4a7e89f39 M3: typed and stored variable, collection and mode ids find exactly that object (#1613) (#1635)
Builds on #1618. Variables::get and Variables::collection take an exact id before a name; stored mode ids go through Collection::mode_by_id (expressions, the prototype's mode switch); font family variables and the colour picker, prototype editor and panels read stored ids exactly. Ported from fix/stored-ids-exact.
2026-10-30 18:00:34 +07:00
Claude b0dbcc80a7 M10: Bosnian catalog follows main's string changes
Main renamed the connector-import note and added Add a connected shape,
Detach calculation and the calculated-variable hint; bs.toml follows
(1,901 UI strings) and the counts in ROADMAP.md and the localization
parity doc are updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z
2026-10-30 10:58:04 +00:00
Claude 876d458414 Merge main into claude/sharp-feynman-me8n1o
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z
2026-10-30 10:45:10 +00:00
BFlat f0abe51a84 M6: plugin widgets have hover styles (gap 6) (#1634) 2026-10-30 17:33:04 +07:00
lileeei 2e9212d902 M8: text style dedupe is O(spans) (#1102)
shape_text deduped spans into styles by scanning the styles already
collected - O(spans x styles), so a styled text's dedupe grew with the
square of its runs. Now the last two styles again (spans run in
blocks), then buckets keyed by a cheap fingerprint (family and style
bytes, size bits with -0.0 folded onto 0.0, the enums, fill count and
solid colours, variation count), each bucket resolved with the full
equality: the result is the scan's, never worse than it, and O(spans)
when names and sizes differ. The fingerprint seed comes from the
address space, so document-supplied names can't precompute collisions;
the worst an adversarial document does is fall back to the scan it
started with. The font-db write lock is untouched: find() loads faces,
which needs the write. layout_dedupe_tests covers blocks, excluded
fields (links, style ids, gradient stops), -0.0 and pathological
alternation.
2026-10-30 18:20:43 +08:00
Carbocode ca3caf8ee8 M1: cover typography field position on focus 2026-10-30 11:11:38 +01:00
BFlat 9099f1d5ae M6: .fig elbowed and curved connectors without a saved path are routed, not drawn straight (#1649)
The board connector router moves, unchanged, from the engine into figcraft-doc (route_points, RouteEnd) so the .fig importer can use it: an elbowed or curved connector saved without its path runs in right angles or one curve from the side of each layer it joins (the file's magnet, else the edge its point is on, else the side facing the other end). Straight connectors are unchanged. Gap 1.
2026-10-30 17:11:22 +07:00
Claude b352eb866b M10: Bosnian (bs) interface catalog
Adds a Bosnian (Bosanski) catalog in Latin script with ijekavian forms. It covers
every UI string (1,898), command label (629) and menu wording (31). It is
machine-drafted and marked as a draft until a native speaker reviews it.

Bosnian plural rule in i18n::plural: one for 1, 21, 31… (not 11), few for
2–4, 22–24… (not 12–14), other otherwise. Because one covers 21, every form
keeps {n}. Test: bosnian_tags_and_integer_plurals.

Docs: translating.md (conventions and plural rule), localization-parity.md,
README, ROADMAP, mcp.md and the pref.language param doc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw548pu8zRqLH3HjGHN
2026-10-30 09:49:32 +00:00
Carbocode 6f7236f17d M1: leave ROADMAP unchanged in the sidebar focus fix 2026-10-30 10:47:11 +01:00
BFlat 3d7ca30d51 M6: plugin panels take a slider control (gap 6) (#1637) 2026-10-30 16:45:33 +07:00
Carbocode 0daecb7022 M1: keep sidebar field text in place on focus 2026-10-30 10:44:38 +01:00
BFlat 84e5278209 M6: figcraft-cli connect publish publishes code connect mappings to a design file (#1643)
* M6: figcraft-cli connect publish publishes code connect mappings to a design file

figcraft-cli connect publish <file.figcraft> [--mappings figcraft.connect.json] [--dry-run] links each entry's component or set by name through codeConnect.import, warns about and skips links that don't fit, saves the file in place through the engine's file.save, and exits 1 when nothing links. Gap 16.

* M6: the generated man pages include connect and connect publish
2026-10-30 16:31:25 +07:00
BFlat 10c66678c3 Merge pull request #1641 from ChristopherLinnett/feat/1280-color-calculations
M3: colour variables can be calculated from others, faded or mixed per mode (#1280)
2026-10-30 16:16:23 +07:00
BFlat 99440fa9ff M8: a drag that only moves the selection shifts what was worked out at its start (#1571) (#1640)
The engine notes when a drag has only moved the selected layers by one offset (Interaction::moved_by); the canvas keeps the outlines, box and slots from the drag's start document and shifts them, the selection spacing and the Design panel's values (but the position fields) come from that document, and the Export section's values are kept. Dragging 648 layers: UI pass 2.10 to 1.44 ms a frame.
2026-10-30 16:13:55 +07:00
Christopher Linnett 8d5bad2afc M3: CSS export never names a calculation it leaves out either (#1280)
The CSS export left out a colour calculation that resolves to nothing but still wrote an alias to
it as var(--name); where no block defines that property, whatever reads the alias is invalid.
CSS (and Tailwind) and Penpot now share one rule, Variables::flattener: an alias that leads to a
calculation some mode of its collection leaves out goes out as the value it shows in the mode,
or is left out when it shows nothing.
2026-10-30 16:59:19 +08:00
BFlat 34fce9bfcf M12: create the next board shape already connected (#1631)
* M12: create the next board shape already connected (#1597)

A selected sticky or shape shows a + beside each side; hovering one previews where the next goes, clicking makes one of the same kind, size and colour there, joined by a connector, and starts typing in it, in one undo step. board.addConnected {id?, side?, edit?} does it from commands.

* M12: the connected-shape handle and command in every full catalog (#1597)

* M12: Shift+Cmd/Ctrl+Enter on a board shape adds the next one already connected (#1597)
2026-10-30 15:59:13 +07:00
bflatastic 68450a6a0e Merge main into #1641 2026-10-30 15:57:31 +07:00
BFlat d17de284da Tests: read the docs' examples whatever the checkout's line endings (#1645)
inspect_fields::compact_examples_run_verbatim_from_the_docs split docs/mcp.md and docs/control-protocol.md on text ending in a newline, so on a Windows checkout with core.autocrlf (CRLF docs) it panicked and cargo xtask ci failed locally. The test now reads both with LF line ends. Found while gating on Windows.
2026-10-30 15:53:33 +07:00
BFlat 74b69125b7 Merge pull request #1642 from kler/swedish-ui-2026-10-30
i18n(sv): translate 36 new strings
2026-10-30 15:50:39 +07:00
BFlat c1451fecd5 M4: an imported file finds an installed family under the other names its fonts give it (#1292) (#1628)
Fonts name a family by its typographic name and by a legacy name per weight; fonts without typographic names are installed under the legacy ones only. FontDb::resolve finds either from the other, and matches names across case, spaces, hyphens and underscores; every lookup (import, paste, REST import, rendering, missing fonts, the font report) uses it. A weight-number style goes by that weight, and .fig and REST imports wait for the installed fonts to be indexed.
2026-10-30 15:44:09 +07:00
BFlat 328bb6e269 Merge pull request #1609 from avhn/fix/1085-grouped-panic-rollback
M8: a grouped command whose closure panics leaves the document as before (#1085)
2026-10-30 15:27:30 +07:00
Christopher Linnett 55e5f31eb5 M3: document the colour-calculation functions this change touches (#1280)
Why type_of gives references no type, what display shows, how resolve_memo bounds one resolve,
and what variable.create and variable.set check before anything changes.
2026-10-30 16:25:26 +08:00
Christopher Linnett 1784567497 M3: Penpot tokens never reference a calculation a set leaves out (#1280)
A colour calculation that resolves to nothing in a mode is left out of that mode's token set, but
an alias to it still went out as a {name} reference to the missing token. Such an alias, and any
alias leading to one, now goes out as the colour it shows in the mode, or is left out with the
calculation's warning when it shows nothing. A calculation left out in only one mode of its
collection counts too: a reference to it from another collection would dangle whenever that
mode's theme is active.
2026-10-30 16:25:26 +08:00
Christopher Linnett bc76665c65 M3: colour variables can be calculated from others, faded or mixed per mode (#1280)
A colour variable's value in a mode can now be {"alpha": {"variable", "opacity"}} - that
variable's colour with its alpha replaced - or {"mix": {"from", "to", "t"}}, a per-channel blend
of two colour variables or literals over the stored values (in the document's colour profile),
alpha included. Calculations resolve lazily like aliases, so bound layers, mode switches,
instances and undo follow their sources; they compose, and a loop, or a calculation that reads
more than 32 variables in its collection's modes (other collections in their default modes), is
refused when it is set. Operands are stored by id and read by exact id, as stored references
are. Files keep them; REST, CSS, Penpot and .fig exports write the colour they show in each mode;
deleting a source leaves its readers on the colour they showed; library import and swap
re-point their operands. The Variables panel shows them with their formula and can swap one for
an alias or detach it to its colour.
2026-10-30 16:25:26 +08:00
BFlat 1772ecefb0 Merge pull request #1636 from ChristopherLinnett/fix/574-fig-import-large
M8: .fig import budgets four values per compressed canvas byte instead of one (#574)
2026-10-30 15:22:58 +07:00
Patrik LermonandClaude Opus 5.5 8dd69797af i18n(sv): translate 36 new strings
Brings the Swedish catalog up to date with upstream main (e94350a7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:19:45 +01:00
bflatastic 955f101221 Merge main into #1609 2026-10-30 15:12:01 +07:00
BFlat e110f23d8c Merge pull request #1615 from avhn/fix/1396-cli-completions-man-pages
M0.9: generate shell completions and man pages for figcraft-cli (part of #1396)
2026-10-30 15:09:34 +07:00
BFlat e94350a778 Merge pull request #1630 from samhyun/perf/partial-damage-margin
M8: an edit renders where the changed layer paints, its effects' margin once
2026-10-30 15:07:13 +07:00
bflatastic 027a0bbf92 Merge main into #1636 2026-10-30 15:06:33 +07:00
BFlat c44f382d71 Merge pull request #1633 from samhyun/fix/partial-backdrop-at-view-edge
M8: a patch reads no backdrop past the view's edge
2026-10-30 15:05:08 +07:00
bflatastic 7c8f2a929a Merge main into #1609 2026-10-30 14:52:57 +07:00
bflatastic 4acbb1f7db Merge main into #1615 2026-10-30 14:52:23 +07:00
BFlat cb5f047fbd Merge pull request #1616 from avhn/fix/1076-fig-image-budget
M8: .fig ZIP image reads share a total byte budget (part of #1076)
2026-10-30 14:50:02 +07:00
bflatastic e5a5da9e62 Merge main into #1609 2026-10-30 14:35:19 +07:00
bflatastic 83c6947e23 Merge main into #1615 2026-10-30 14:34:35 +07:00