Commit Graph

415 Commits

Author SHA1 Message Date
jahala c614e0ab9e
Docs, About: the Illustrator-class sibling is VectorCraft (#59) (#139)
DrawCraft was renamed VectorCraft, and its repository is now
storytold/vectorcraft. Three places still used the old name:

- AGENTS.md and CLAUDE.md told contributors and agents that the sibling
  checkout lives at ../drawcraft. A clone made from the README link lands
  in ../vectorcraft, so that path does not exist.
- The About window's sibling list used the app-page slug "drawcraft".
  getartcraft.com/apps/drawcraft still redirects to /apps/vectorcraft,
  so the link worked, but the README (which the list says it matches)
  uses /apps/vectorcraft.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 01:14:05 -04:00
jahala d323b4e702
Web: AltGr and other named keys no longer type their names (#134) (#138)
In the browser, pressing AltGr while editing text on the canvas inserted
the word "AltGraph" into the story.

eframe's web backend (0.36.2, web/input.rs text_from_keyboard_event)
turns a keydown into a text event unless the key is on a fixed list of
names. Browsers report many more named keys than that list holds:
AltGraph, Dead, Unidentified, the media keys. Each one arrived as text.
Panel text fields are not affected, because a focused egui text field
takes its text from the browser's input events instead of keydown.

The web shell now drops a text event that is a key name (ASCII letters
and digits, starting with a capital, longer than one character) unless
an egui text field has the keyboard. One key press never types such a
word; a text field's input events can, so they are left alone.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 01:13:59 -04:00
jahala ce3deb651a
Commands: huge row and column counts can't exhaust memory (#137)
Three commands took a count from their parameters and used it unchecked.
Parameters come from MCP, the control channel and scripts, so the count
is hostile input (never-crash: cap input-sized allocations, checked
arithmetic).

- layout.createGuides made one or two guides per row and column with no
  upper limit: 30 million rows took 1.2 GB, and 2^32 - 1 would exhaust
  memory, which aborts the process past the command guard. A count over
  2^32 wrapped to a small one. Both counts are now capped at 100.
- edit.stepAndRepeat multiplied rows by columns as usize. In debug builds
  the overflow panicked; in release builds 2^32 x 2^32 wraps to 0, passes
  the 1000-copy limit and starts a grid of 2^64 copies. The product is
  now checked, and a grid that large falls back to `count` copies like
  any other grid over 1000.
- file.new stored any column count in the page (4 billion, or a wrapped
  value past 2^32). Page::column_rects builds one rect per column each
  time the columns are laid out. The count is now clamped to 1..=216,
  the range layout.marginsAndColumns already uses.

Each case has a regression test that failed before the fix.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 01:13:54 -04:00
aiongg fe16e00e37
PDF/A keeps placed images; right-to-left tables and columns (#128)
* PDF: PDF/A exports keep placed PNG, JPEG, GIF and WebP images by writing them without interpolation (#71)

* Tables: new tables take their paragraph's direction, and the Table panel sets a table's direction (#100)

* Text: stories made in a right-to-left-bound document fill their columns from the right (#100)
2026-10-10 01:13:48 -04:00
aiongg 3033c8cc64
CLI: export options after the last export are an error; MCP and README docs match the code (#127)
* CLI: run rejects an export option with no export after it (#67)

--page, --scale and --pdf-options apply to the exports that follow them; one
given after the last --export or --all-pages did nothing and said nothing.
The usage text and docs/agents.md say so.

* MCP: document that text offsets and story lengths are UTF-8 bytes (#68)

* MCP: docs name the UI-only commands precisely; app.links works headless (#62)

* README: PDF and EPUB export ship (#60)
2026-10-10 01:13:42 -04:00
skylar taylor-barrick 691d0de183
#72: preserve typed generic dialog values (#120) 2026-10-10 01:13:35 -04:00
skylar taylor-barrick fc2739a8cd
#61: honor MCP typing, story and page contracts (#118) 2026-10-10 01:13:29 -04:00
skylar taylor-barrick 4c6aa4cd4b
browser-correctness: fix print, startup flags, and document MIME (#117) 2026-10-10 01:13:23 -04:00
Haseom Shin 788e0eac66
Images: set SVG text in the shared fonts when the bundled ones lack it (#116) 2026-10-10 01:13:17 -04:00
aiongg d730d8fa27
UI: toolbars that don't fit the window switch to two columns or scroll (#57) (#112)
* UI: toolbars that don't fit the window switch to two columns or scroll (#57)

In a short window the Tools panel lays its tools out in two columns,
without changing the single/double-column preference, which comes back
when the window grows again. While the window forces two columns the
column toggle is disabled. Whatever two columns can't fit scrolls
vertically.

The Control panel and the application bar scroll sideways when their
controls are wider than the window. The Control panel keeps its height.
In the application bar the workspace controls follow the menus instead of
overlapping them. A plain mouse wheel scrolls these one-direction bars,
and a thin floating scroll bar shows only when something overflows, so
nothing changes while everything fits.

Tool buttons, icon buttons and the Fill proxy carry accessibility
labels, which the new window-size tests use to find them.

* UI: captions in a sideways-scrolled bar stay on one line

The last group of a scrolled Control bar row got only the width left
over, so a caption like Columns wrapped one letter per line.
2026-10-10 01:09:52 -04:00
aiongg 4564ec6707
UI: text fields take Select All, Copy, Cut, Paste, Undo and Redo from the Mac menu (#30) (#111)
The macOS menu bar takes Cmd+A, Cmd+C, Cmd+X, Cmd+V, Cmd+Z and Cmd+Shift+Z
before the window sees them, so in a panel, dialog or search field they ran
the document's commands: Select All selected every frame, Paste pasted into
the layout, Undo undid the last document change.

While a text field has keyboard focus, these Edit items now act on the field,
whether chosen by shortcut or from the menu: Select All, Undo and Redo reach
it as their keys, Copy and Cut as clipboard events, and Paste asks the
window for the system clipboard. The items stay enabled for the field even
when the document has nothing to copy or undo. With no field focused, and
for every other item, the menu works as before.
2026-10-10 01:09:47 -04:00
aiongg 9fbd6d2402
Show an alert when a file can't be opened or placed (#80)
* Opening an InDesign document says to export IDML (#21)

.indd and .indt files (recognised by their published 16-byte signature)
failed to open or place with a confusing format error. They now explain
that the format is closed and how to export IDML from InDesign instead.

File › Open offers .indd and .indt files (desktop and web), and dropping
one on the window opens it like a .designcraft or .idml file. A file that
can't be opened or placed from File › Open, Place, a drop, the command
line or the control channel's app.open shows an alert with the reason, as
well as the status line.

* File open: an .indd file is an unreadable file like any other

Remove the INDD signature check and message, and .indd/.indt from the
Open filters and drop routing. The alert tests use a generic unreadable
file.

* Control channel: a failed app.open answers with the error and opens no alert

An alert waits for a click that a control client can't give. app.open
reports the error in its response, as engine.execute does; File › Open,
drops and the command line still show the alert.
2026-10-10 01:09:41 -04:00
Haseom Shin 07b95eb7b3
Compose: don't panic when a hyphenated paragraph starts with a no-break letter (#115) 2026-10-10 01:09:36 -04:00
jahala aeabc82ca6
Images: PSD decode passes clippy on Rust 1.98 (#136)
Rust 1.98 adds the clippy lint chunks_exact_to_as_chunks. It flags two
loops in the PSD decoder, so `cargo xtask ci` stops at the clippy step on
unmodified main for anyone on current stable.

Both loops now use as_chunks / as_chunks_mut (stable since 1.88, below the
workspace rust-version 1.90). The chunks are arrays, so the try_from that
could never fail goes away too. Decoded pixels are unchanged; the existing
PSD tests cover both paths.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 01:09:30 -04:00
Brandon Thomas 4e0e3949f1 Bump version to 0.5.0 (from 0.4.0) for release; refresh contributors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:02:05 -04:00
Brandon Thomas 66c7ce7e96
Merge pull request #131 from XusBadia/dmg-background
macOS DMG: branded window background and icon layout
2026-10-09 09:20:37 -04:00
Xus Badia ec42e542e9 macOS DMG: branded window background and icon layout
The DMG opened as a plain Finder window. It now shows the app icon's figure on
the DesignCraft colour, with DesignCraft.app and the Applications link side by side.
Same approach as PhotoCraft's and VectorCraft's (storytold/photocraft#1201,
storytold/vectorcraft#493).

- packaging/macos/dmg/: background.svg (source; text outlined, no paper grain,
  the figure an <image> of assets/app-icon), background.tiff (1x + 2x HiDPI,
  16-colour palette, Deflate, sRGB; ~90 KB)
  and dmg-layout.DS_Store (Finder view settings: window, icon size 128,
  positions, background).
- generate.py writes the TIFF and the layout on any OS, byte-for-byte
  reproducible, with nothing from the machine that ran it (no paths, users,
  disk names or volume UUIDs).
- package.sh copies them into the staging folder; the image is still built with
  hdiutil makehybrid. Nothing extra runs in the signing job.
- The volume name drops the version: the layout finds the background through
  an alias that includes the volume name. The DMG file name keeps the version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:43:40 +02:00
Brandon Thomas 14e677b242 Bump version to 0.4.0 (from 0.3.0) for release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 10:02:08 -04:00
Brandon Thomas d26b91335c
README Downloads: where to get it first, then builds with Windows before macOS (#135)
Co-authored-by: Brandon Thomas <shared2@storyteller.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 09:50:30 -04:00
Brandon Thomas 865640b70a
Release: FreeBSD x86_64, Flatpak x86_64/aarch64, AppImage zsync updates; README Downloads (#132)
- freebsd job: builds packaging/freebsd/package.sh in a FreeBSD 14.3 VM (same image and
  packages as freebsd.yml) into designcraft-<ver>-freebsd-x86_64.tar.gz.
- flatpak jobs (x86_64 on ubuntu-24.04, aarch64 on ubuntu-24.04-arm): repackage the Linux
  tarball with packaging/linux/flatpak-bundle.sh and a new bundle manifest; runtime and
  finish-args shared with the from-source manifest (checked by packaging-lint).
- AppImages embed gh-releases-zsync update information and ship a .zsync beside them.
- version, linux, web, flatpak and freebsd no longer use the release environment (they read
  no secrets), so a workflow_dispatch on a branch dry-runs them; the signing jobs and the
  draft release stay environment-gated.
- nfpm package description described an image editor; now describes DesignCraft.
- README: Downloads section listing every build.

Co-authored-by: Brandon Thomas <shared2@storyteller.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 09:38:16 -04:00
Brandon Thomas 5382fd4fb7 Bump version to 0.3.0 (from 0.2.1) for release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:13:12 -04:00
Brandon Thomas f4a4c9709b
Merge pull request #76 from CameronGilroy/pr/data-merge
Data merge: linked source, placeholders, preview, and tiled merge
2026-10-07 22:53:41 -04:00
Brandon Thomas b05fe0aed4
Merge pull request #78 from ShaoWenbinSaleh/multi-language-fix
Complete Arabic translations, refine Chinese terminology, and cache RTL label layouts
2026-10-07 22:46:52 -04:00
Brandon Thomas 8d2d180062 Merge origin/main into multi-language-fix
Resolve i18n conflicts: keep this branch's revised zh/ar wording plus
main's new rows (font-name, missing-glyph, Korean line-break labels).
Brazilian Portuguese (#103) now uses the same cached HashMap lookup as
Arabic; the cached-lookup test covers pt-br too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:32:13 -04:00
Brandon Thomas 48dfbcfd19 Merge origin/main into data-merge
Resolve conflicts keeping both sides: doc gains both `cjk` and
`datamerge` modules; file.open resolves data-merge sources and loads the
document's fonts; DocState keeps preview_stash/preview_record and fonts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:28:15 -04:00
Brandon Thomas 8e2a5b1fc3
Merge pull request #55 from EthanSuquet/fix/cmyk-tiff-pdf-export
PDF: placed CMYK TIFFs keep their inks
2026-10-07 22:13:56 -04:00
Brandon Thomas 2c8ea6d167 Merge remote-tracking branch 'origin/main' into r55
# Conflicts:
#	Cargo.toml
2026-10-07 22:13:23 -04:00
Brandon Thomas e97d98977f
Merge pull request #103 from RicSchonfelder/i18n-pt-br
i18n: add Brazilian Portuguese (pt-br) UI translation
2026-10-07 22:13:15 -04:00
Brandon Thomas 9f2f61bfbf
Merge pull request #82 from aiongg/fix/psd-channels
Images: PSD composites decode by colour mode
2026-10-07 22:13:10 -04:00
Brandon Thomas 84f2eadb39 Release CI: macOS job on macos-15-xlarge
Custom macOS larger runners in a runner group do not pick up jobs; the
built-in M2 Pro label does. Only release.yml uses it, and the
actions_macos_xl budget caps the monthly spend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:08:05 -04:00
Brandon Thomas a39c8893b9 Merge remote-tracking branch 'origin/main' into fix/cmyk-tiff-pdf-export
# Conflicts:
#	crates/pdf/Cargo.toml
#	crates/pdf/src/tests.rs
2026-10-07 22:05:52 -04:00
Brandon Thomas 1c2aa451cf
Merge pull request #85 from aiongg/feat/cjk-and-fonts
CJK: language-aware shaping and fallback, vertical metrics, document fonts, missing-glyph boxes (builds on #75)
2026-10-07 22:05:01 -04:00
Brandon Thomas aee756d604 Merge remote-tracking branch 'origin/main' into feat/cjk-and-fonts
# Conflicts:
#	crates/ui-egui/Cargo.toml
2026-10-07 22:04:42 -04:00
Brandon Thomas 625e6b0e01
Merge pull request #58 from EthanSuquet/feat/pdfx4-flag-rgb-under-cmyk-intent
PDF/X-4: flag device RGB under the CMYK output intent
2026-10-07 22:04:21 -04:00
Brandon Thomas dd8d3037b1
Merge pull request #75 from ShaoWenbinSaleh/arabic-chinese-typesetting-rules-fix
Preserve and compose Chinese and Arabic typesetting rules
2026-10-07 22:04:16 -04:00
Brandon Thomas 27909c6cbb
Merge pull request #66 from Luskish/fix/control-close-on-malformed-input
Control: close the connection on input that isn't a request
2026-10-07 22:04:11 -04:00
Brandon Thomas feb3808029
Merge pull request #56 from storybored379/fix/guide-layer-locks
Guides: honor layer protection in move and delete commands
2026-10-07 22:04:06 -04:00
Brandon Thomas 864d0b6008
Merge pull request #53 from epfabian/middle-mouse-pan
Canvas: middle-mouse drag pans the view
2026-10-07 22:04:01 -04:00
Brandon Thomas a42bd84e89
Merge pull request #79 from aiongg/fix/34-transform-dialogs
Transform: Rotate and Shear open their dialogs (#34)
2026-10-07 22:03:56 -04:00
Brandon Thomas 3b8a58fcc4
Merge pull request #97 from denizkoekden/feat/office-fonts-macos
Fonts: read Microsoft Office's bundled fonts on macOS
2026-10-07 22:03:51 -04:00
Brandon Thomas 45866e6037
Merge pull request #101 from skylartaylor/fix/idml-packaged-link-resolution
IDML: resolve nested packaged image links after relocation
2026-10-07 22:03:46 -04:00
Brandon Thomas 8d828f6efb
Merge pull request #104 from skylartaylor/fix/render-outside-stroke
Render: keep outside-aligned strokes out of closed interiors
2026-10-07 22:03:41 -04:00
Brandon Thomas 08b6e335dd
Merge pull request #102 from skylartaylor/fix/idml-cell-edge-priority
IDML: honor explicit cell edges at table borders
2026-10-07 22:03:36 -04:00
Brandon Thomas fd0e801968
Merge pull request #105 from skylartaylor/fix/idml-scalar-inset-spacing
IDML: import scalar InsetSpacing property values
2026-10-07 22:03:31 -04:00
Brandon Thomas fdffbb4b23 M9: distinct zh label for Revert; translations are our own
Revert no longer shares Undo's Simplified Chinese label. Drop the
comments and ROADMAP wording that tied terminology to a vendor's help.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:01:57 -04:00
Brandon Thomas 330b8c18f2 Images: PSD checks the image data is present before allocating
Header dimensions are untrusted: a tiny file claiming a ~460 MiB composite
allocated it before finding the data missing. ImageData::holds verifies
raw planes fit in the data, or that RLE row counts each reach a full row
and sum to no more than the data, before the RGBA buffer is allocated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:59:39 -04:00
Brandon Thomas 211589a80a Release CI: macOS job on the org macos-release runner
The standard macOS runners are shared with all CI and queue for an hour or
more. The macos-release runner (GitHub-hosted M2 Pro) is in a runner group
usable only by release.yml on the release branch, with a monthly spend cap
on the actions_macos_xl SKU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:54:59 -04:00
Brandon Thomas 2531f039fe Data merge: review fixes (bounded reads, no truncation, safe links, docs)
- Remove the docs/superpowers planning spec.
- textimport: cap decompressed zip parts at 64 MiB (protects Place and
  xlsx data sources); oversized part is an error. Regression test.
- datamerge: refuse data files over 256 MiB and skip image candidates
  over 256 MiB by metadata before reading.
- datamerge: assign_page uses get_mut instead of indexing spreads.
- datamerge: one/limit over u32 are errors, not truncated.
- select_records dedupes with a HashSet (was O(n^2)), order kept.
- Hyperlink cells: only http, https, ftp and mailto schemes link.
- Document data.* commands and data.merge creating a new document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:54:38 -04:00
Brandon Thomas a79351e249 Glyph outlines: minimal boolean form (clippy 1.96 nonminimal_bool)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:49:48 -04:00
Brandon Thomas 730d598d48 Kinsoku::allows: minimal boolean form (clippy 1.96 nonminimal_bool)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:48:33 -04:00