651 Commits
Author SHA1 Message Date
Brandon Thomas 610792ed34 Merge storytold/main into feat/multi-automation-roots 2026-10-24 10:24:14 -04:00
Brandon Thomas 4b9b0a96f1 Merge storytold/main into feat/convert-variable-to-text
# Conflicts:
#	docs/gaps.md
2026-10-24 10:24:00 -04:00
Brandon Thomas 3ea6459651 Merge storytold/main into feat/layout-go-back-forward 2026-10-24 10:23:44 -04:00
Brandon Thomas 073287500f Merge storytold/main into feat/convert-to-note 2026-10-24 10:23:16 -04:00
aiongg 5def4a8c01 Story Optical Margin Alignment with a size, and Ignore Optical Margin (Story panel, engine and IDML) (#1705)
* Type: story Optical Margin Alignment with a size, and Ignore Optical Margin (engine, IDML)

A story's Optical Margin Alignment applies to every paragraph except those
with Ignore Optical Margin; hang amounts scale with the story's size.
story.options sets it, type.para and paragraph styles take
ignoreOpticalMargin. IDML imports and exports StoryPreference
OpticalMarginAlignment/OpticalMarginSize and IgnoreEdgeAlignment. The
per-paragraph opticalMargin switch keeps hanging at the text's own size.

Part of #947.

* Type: the Story panel, and Ignore Optical Margin in the Paragraph panel menu and Paragraph Style Options

Window > Type & Tables > Story sets Optical Margin Alignment and its size
for the stories of the text selection or the selected text frames through
story.options, and is disabled without either. type.selectionAttrs
reports the stories' values as storyOptions, null where they differ.
The Paragraph panel menu toggles ignoreOpticalMargin, and Paragraph Style
Options > Indents and Spacing has an Ignore Optical Margin checkbox.

Part of #947.

* ROADMAP: the story Optical Margin Alignment entry names its default and scope
2026-10-24 10:08:40 -04:00
Brandon Thomas b724698d98 Merge remote-tracking branch 'origin/main' into pr1678
# Conflicts:
#	apps/designcraft-cli/src/main.rs
2026-10-24 10:03:25 -04:00
Brandon Thomas b33224d692 Merge remote-tracking branch 'origin/main' into pr1639
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-24 10:02:54 -04:00
aiongg d767fcf41e Text frames: a custom baseline grid's Relative To (page, margin, frame or inset) (#1758) 2026-10-24 09:55:47 -04:00
aiongg d4c1322d97 Merge pull request #1709 from aiongg/w65-batch
Integration batch: book-chapter IDML baseline grids, hyphenation, and the Paragraph panel stack
2026-10-24 08:14:29 -04:00
dotCooCoo e51b2c6114 Type › Notes › Convert to Note: the selected text becomes a note, as in InDesign
The new command note.convertFromText removes the selected story text
and puts it into a new editorial note whose anchor sits where the text
was. It takes an optional author, and Convert Note to Text puts the text
back. DesignCraft refuses a selection in a table cell, or one that holds
a note, footnote, endnote, anchored object, index marker, text anchor,
cross-reference or table, and leaves the story unchanged. The item
follows New Note in Type › Notes, with translations in the catalogs that
already translate Convert Note to Text.
2026-10-24 04:18:18 -07:00
skylar taylor-barrick 7427a15863 M6: harden placed PDF layer variants (#1670)
Integrate current main (d8d78851) without rewriting the contributor's commits, retaining craft-libs 9f75d3dc.

Accept literal null trailer entries while rejecting actual or ambiguous encryption/hybrid markers. Structurally inspect bounded xref/trailer history instead of adopting trailer-looking comments. Preflight all selected source variants before editing/undo; preserve reset-to-defaults. Suppress stale unrewritable canvas overrides rather than revealing source content. Keep conservative all-content crop fallback without overcropping layerless/null stubs.

Validation: cargo xtask ci, all 9 gates passed; 3062 tests passed, 6 skipped; all 16 WASM-safe crates checked. 17 supported variants passed independent qpdf, logical preservation and Poppler pixel checks; 6 unsupported/repair-only cases refused. Direct-harness Claude Opus 5 reviewed the exact main-relative delta with no blocking findings.

No native-format changes or unrelated layer features. Synthetic regression fixtures are generated in test code.
2026-10-24 00:18:22 -06:00
aiongg 92c565e854 Merge #1570: Paragraph panel: InDesign's layout and panel menu
# Conflicts:
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
2026-10-24 06:02:06 +00:00
aiongg 6d4b1f797f Merge #1486: Control panel (¶): Bulleted and Numbered List, Shading and Border, as InDesign's
# Conflicts:
#	crates/ui-egui/src/chrome.rs
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
#	crates/ui-egui/src/panels/properties.rs
2026-10-24 06:01:20 +00:00
aiongg c428083d74 Merge #1483: Bulleted and Numbered List buttons give InDesign's default hanging indent
# Conflicts:
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/de.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ja.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
#	docs/target-app-parity.md
2026-10-24 06:00:59 +00:00
aiongg 3903519c80 Merge #1459: Control panel: the text controls have InDesign's Character (A) and Paragraph (¶) modes
# Conflicts:
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
2026-10-24 05:59:51 +00:00
aiongg 48ff7aa03e Merge #1457: Properties: ••• expands Character and Paragraph in place, as in InDesign
# Conflicts:
#	crates/ui-egui/src/i18n/ar.rs
#	crates/ui-egui/src/i18n/cs.rs
#	crates/ui-egui/src/i18n/it.rs
#	crates/ui-egui/src/i18n/ka.rs
#	crates/ui-egui/src/i18n/pl.rs
#	crates/ui-egui/src/i18n/pt_br.rs
#	crates/ui-egui/src/i18n/ru.rs
#	crates/ui-egui/src/i18n/uk.rs
2026-10-24 05:56:55 +00:00
aiongg 4cbeea2232 Merge #1572: Hyphenate Across Column: no column or frame ends in a hyphen when it's off 2026-10-24 05:52:41 +00:00
aiongg e11f9f6202 Merge #1703: Baseline grid: Relative To Top Margin starts the grid at each page's top margin
# Conflicts:
#	crates/compose/src/lib.rs
2026-10-24 05:51:57 +00:00
aiongg d8d7885172 Anchored objects: Relative to Spine mirrors custom positions on right-hand pages (#1702)
* Anchored objects: Relative to Spine mirrors custom positions on right-hand pages

* Anchored objects: page side from the frame's spread position; footnote cache keyed by page side
2026-10-24 01:34:05 -04:00
aiongg 14da000a35 Baseline grid: Relative To Top Margin starts the grid at each page's top margin
The setting was imported and editable but never read: the composer, the
canvas grid and baseline snapping measured the grid from the page top.
BaselineGrid::origin gives the first line on a page (start, plus the
page's top margin for Top Margin), and all three use it. The composition
cache tracks the setting and the pages' top margins.

Also adds a left-to-right facing-pages guard test for mirrored margins
and the right parent page's guides and running head.
2026-10-24 04:28:34 +00:00
aiongg 4823b59492 PDF: shared reader from craft-libs 9f75d3dc (input bounds and crash fixes) (#1701)
* PDF: craft-pdf, krilla and hayro from craft-libs main (input bounds and crash fixes)

* PDF: craft-libs 9f75d3dc, with hayro-cmap from its vendored copy
2026-10-23 23:03:36 -04:00
Brandon Thomas 058b369b53 Merge storytold/main into squad/pdfx-unembedded-fonts
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-23 17:30:20 -04:00
Brandon Thomas f0907d3831 Merge pull request #1665 from MarekSpodBiedry/issue-1624
find: search and change text inside table cells in document scope (#1624)
2026-10-23 17:27:58 -04:00
Brandon Thomas c882fd0f58 Merge storytold/main into feat/save-dialog-folder 2026-10-23 17:27:23 -04:00
Brandon Thomas f064aeed7f Merge pull request #1613 from MarekSpodBiedry/issue-1551
IDML export: write the graphic placed in a table cell (#1551)
2026-10-23 17:26:55 -04:00
Brandon Thomas dc968ecdff Merge pull request #1629 from marcoarnulfo/feat/autoflow-existing-pages
Autoflow: fill the pages that follow before adding pages at the end
2026-10-23 17:26:42 -04:00
moppeeer 3f1c847927 Merge remote-tracking branch 'origin/main' into paragraph-panel-indesign
# Conflicts:
#	ROADMAP.md
2026-10-23 22:16:55 +02:00
moppeeer db77b3c740 Merge remote-tracking branch 'origin/main' into hyphenate-across-column
# Conflicts:
#	ROADMAP.md
2026-10-23 22:16:36 +02:00
aiongg 1fd8463af9 i18n: missing translations are reported, never a failure (#1677)
A string without a translation shows in English, and an empty catalog row
counts as untranslated. Tests keep duplicate-key and placeholder checks and
the lookup, context, plural-caption and right-to-left mechanics; coverage,
stale-key, wording and per-language literal checks are removed.

`cargo xtask i18n-report`, also a `cargo xtask ci` step, runs the ignored
missing_translations_report test and prints the missing strings per language.
2026-10-23 15:39:24 -04:00
Marco Arnulfo b5342e48cd Save and export dialogs start in the document's folder, or the last one used (#1653) 2026-10-23 21:32:05 +02:00
Marco Arnulfo 7362530591 MCP: --automation-read-root and --automation-write-root may each be given more than once (#1552)
A path passes when it lies inside one of the roots of its kind. The roots'
common parent, a sibling named like a root, `..` or a link out of them and
the other kind's roots stay refused; a folder given twice counts once.
2026-10-23 20:30:07 +02:00
andeecollard 62a26d9e35 PDF: preserve catalogs and full references in layer variants 2026-10-23 17:47:18 +01:00
MarekSpodBiedry 708feab5cd find: search and change text inside table cells in document scope (#1624) 2026-10-23 17:37:45 +02:00
Marco Arnulfo e7d16aeaaa docs: autoflow drops the pages it added for unused frames; threading into grouped frames is no longer a gap 2026-10-23 11:40:25 +02:00
Marco Arnulfo 5539e28647 Layout: Go Back after Presentation returns to the last spread presented
Presentation's spreads now count as one jump in the window's history, and
leaving it as a jump back to the view it was entered from, at the place the
view was. Before, the history stayed on the last presented spread while the
view was put back, so Go Back couldn't reach it.

docs/gaps.md: Go Back and Go Forward are two of the missing menu items, 149.
2026-10-23 11:26:32 +02:00
Marco Arnulfo 0160b7af07 Convert to Text (all instances): a caret in a table cell or a footnote keeps its place after the converted value; gaps: 150 missing menu items 2026-10-23 10:56:22 +02:00
Marco Arnulfo 3cd235ee5c Type › Text Variables › Convert Variable to Text: the selected instances, or every instance of one variable, become the text they show on their page 2026-10-23 03:40:11 +02:00
Marco Arnulfo 86356d15be Layout: Go Back and Go Forward through the pages viewed, with InDesign's shortcuts 2026-10-23 03:19:47 +02:00
Marco Arnulfo 2caa39e130 Autoflow: fill the pages that follow before adding pages at the end
Autoflow (Shift-click, autoflow on Place, text.thread with autoflow) inserted
new pages right after the story's last frame, in front of the document's own
pages. As in InDesign, it now threads one frame per column on each page that
follows, whatever else the page holds, and only then adds pages at the end of
the document. It fills whole pages, so an estimate that stops inside a page
can't leave its later columns out of the thread. Frames it set past the end
of the text are removed again; the pages they were on stay. Smart Text Reflow
of the primary text frame keeps adding pages after the story's last page.

Shrinks gap 26: flowing into the primary text frame of the following pages
is left.
2026-10-22 23:28:22 +02:00
MarekSpodBiedry d292dd2acd IDML export: write the graphic placed in a table cell (#1551) 2026-10-22 21:06:54 +02:00
KnottyDyes bba31c17b6 PDF: report visible unembedded fonts in PDF/X-4 (#909)
Track text state through graphics saves and drawn forms; exempt invisible text. Report font names and pages in export warnings and validation without embedding or outlining placed fonts.
2026-10-22 10:31:21 -06:00
moppeeer 883bcddac1 Merge branch 'control-panel-lists-shading' into paragraph-panel-indesign 2026-10-22 17:32:39 +02:00
moppeeer daad84ac69 Merge branch 'list-buttons-hanging-indent' into control-panel-lists-shading 2026-10-22 17:30:19 +02:00
moppeeerandClaude Opus 5.5 b3896d8122 List buttons: track the hanging indent they set (listHang)
A paragraph attribute records that the Bulleted or Numbered List button set
the hanging indent; turning the list off takes the indent away only then
(and while it is still as applied), and clears the mark. A paragraph whose
own indents were 18/-18 before the list keeps them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 17:30:14 +02:00
moppeeer 66fcf3ddce Merge branch 'control-panel-lists-shading' into paragraph-panel-indesign
# Conflicts:
#	ROADMAP.md
2026-10-22 17:01:04 +02:00
moppeeer c427640726 Merge remote-tracking branch 'origin/main' into control-panel-lists-shading
# Conflicts:
#	crates/ui-egui/src/i18n/fr.rs
2026-10-22 16:53:56 +02:00
moppeeer 6bd8fe7c4a Merge remote-tracking branch 'origin/main' into control-panel-text-modes
# Conflicts:
#	crates/ui-egui/src/i18n/fr.rs
2026-10-22 16:52:21 +02:00
moppeeer a320b8888a Merge remote-tracking branch 'origin/main' into properties-more-options
# Conflicts:
#	crates/ui-egui/src/i18n/fr.rs
2026-10-22 16:51:06 +02:00
moppeeer 42d55734de Merge remote-tracking branch 'origin/main' into hyphenate-across-column
# Conflicts:
#	ROADMAP.md
2026-10-22 16:35:55 +02:00
aiongg 8f98f3dc8b Keyboard Shortcuts: import an InDesign shortcut set (#1296)
* #1180: import an InDesign keyboard shortcut set

Edit > Keyboard Shortcuts gets Import InDesign Set..., which reads the
.txt that InDesign's Show Set writes (window.importShortcuts {path|text}).
Matched commands take the set's Default shortcut, or lose theirs when
every occurrence says [none defined]; other commands give up keys the
set takes. The report lists changes, cleared conflicts, and the items
that could not be matched or read. Tool keys stay fixed.

* #1180: read the set file through the checked reader

* #1180: when two items want the same keys, the later one takes them
2026-10-22 09:28:11 -04:00