On a device, a presented frame bigger than the screen now scrolls through
its whole size whatever its overflow, as Figma documents for top-level
frames. Before, "No scrolling" frames only clipped, so the landing page
template's long Phone frame couldn't be scrolled in Present. Content past
a frame's own edges still scrolls only on the axes its overflow allows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Board files (File > New board) with sticky notes, shapes with text, connectors that follow what they join (straight or elbow, arrowheads, labels), marker, highlighter and eraser, and stamps; a board toolbar and a contextual bar; the Design panel hidden on boards, Prototype and Dev Mode refused there. Boards are ordinary FigCraft files built from ordinary layers, so saving, undo, export, MCP and live sessions work unchanged. File tabs, recent files and Open files show a pen nib for design files and a note for boards (original icons drawn in code).
Import lines for connected components inside generated layer trees; Compare changes against any saved version; a Dev Mode behaviour suite with an inspect-only canvas (menus, shortcuts, paste and Revert to saved refuse design edits; a drag under way is dropped on entering), Changed in the ready list, statuses only on top-level frames and sections; read-only plugins' panels from the Inspect tab.
* CI: run the gate through craft-common-actions' shared gate.yml; FreeBSD nightly and on release
ci.yml calls the shared workflow (cached apt packages, nextest, main-only cache saves, Cargo.lock check). FreeBSD runs nightly and on pushes to release instead of on pull requests. Depends on storytold/craft-common-actions#69.
* CI: build the shared gate without craft-fonts, as before
* CI: build the shared gate with release.yml's craft-fonts pin
* Packaging: pin the Windows signing client and check its hash
* Packaging: pin appimagetool and check its hash
* Reject AppImage download for architectures without a pinned appimagetool
* Pin the AppImage runtime
* Dev profile: line tables for workspace crates, no debug info for dependencies
* Tests: one integration-test binary per crate with several test files
* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
SonarCloud flags every bare [ conditional in bash scripts under packaging/ as a reliability smell (rule S7688). Convert the flagged [ ... ] tests to [[ ... ]]: safer word-splitting and no glob surprises, same semantics for these string and file tests.
- Use [[ ]] instead of [ ] for conditional tests in the bash packaging scripts (S7688). Every
converted test compares quoted values to literals, so no pattern-matching change.
- Name positional parameters with locals inside functions (S7679).
- End the env.sh helpers with an explicit return that keeps their exit status (S7682).
- Give case statements a default branch (S131).
- Send the check-app-specific.sh error to stderr (S7677).
packaging/freebsd/package.sh is left alone while #1158 rewrites it.
read() returns Result<Message>, not a lock guard; these test loops
deliberately ignore what the client sent first.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
With points selected only on another edited layer, a press inside the
combined box over an unselected filled region of the active layer picked
the region instead of dragging the box. Other layers' selections now count
in the same priority check; a press on an already selected region still
drags the regions.
With points selected in more than one edited layer the transform box now
wraps them all, in the page's axes since the layers can be turned
differently. Its corners and edges scale them, outside a corner rotates
them and inside drags them; each layer's points are mapped in its own
coordinates and the whole drag is one undo step. A click inside clears
every layer's points.
Review: after a Save as, closing called request_close, which asked the
question again while another file still had changes. It now carries on
with save_then_close. Save is the default answer: Enter picks it when no
button has the keyboard.
Closing a window with unsaved changes asked "Close the window and lose
them?" with only Close without saving and Cancel. It now asks
Don't Save / Cancel / Save, as PhotoCraft and VectorCraft do. Save saves
each file of the window with unsaved changes and closes; a file without
a path (or saved as .fig) gets Save as first, and closing goes on once
that saved it. A failed save or a cancelled Save as keeps the window
open with its changes. The two changed strings are updated in every
catalog.
With the keyboard in a Design panel field (X, W, a colour…), the
shortcut handler returned before looking at any key, so Cmd/Ctrl+S and
Shift+Cmd/Ctrl+S did nothing: no save, no message, the tab kept its
unsaved dot. Those two now work from a field: the field lets go of the
keyboard, which commits what was typed as clicking away does, and the
save runs the next frame.
Review: `mcp --bogus --help` stopped at --bogus with exit 2. The parser
now keeps the first bad option and reports it only when no --help or -h
follows.
Review: " . .name. . " kept inner dots at the edges; trim spaces and dots
in one pass. docs/cli.md and safe_file_name's comment give the 100 and
200 character limits.
`figcraft-cli mcp --help` failed with "unknown option --help" and
exit code 2; only a leading --help worked. The argument parser now
returns CliError::Help for --help or -h among a subcommand's options
(not as an option's value), and main prints the usage on stdout with
exit code 0. docs/cli.md says so.
export into a folder replaced every character outside letters, digits,
'-', '_', space and '.' with '_', so a frame called
"Homepage - desktop (live + verbeteringen)" became
"Homepage - desktop _live _ verbeteringen_.png". The app's
file.exportLayers keeps those names and only replaces what file systems
refuse. The CLI now uses the engine's safe_file_name, and docs/cli.md
says which characters are replaced.
Also adds my own entry to contributors/people.toml.
node.create, node.set and the other prop appliers map fill/stroke
"none" (either case) and null to an empty fills/strokes list, as
fills: [] already did (undocumented), so an outline-only shape is one
call - agents write "none" for no paint. KEYS and docs/mcp.md
document it; the error names the accepted forms. fill_none_tests
covers create, set, undo, text and the error.