Commit Graph
344 Commits
Author SHA1 Message Date
aiongg f33de8f4aa refactor(pdf): split export.rs into export/ 2026-10-26 21:00:23 +00:00
aiongg bec8800b62 refactor(idml): split export.rs into export/ 2026-10-26 21:00:23 +00:00
aiongg 2c0882c6e0 refactor(idml): split import.rs into import/ 2026-10-26 21:00:23 +00:00
aiongg 3c19a24e68 Merge pull request #1374 from aiongg/print-color
Print color: overprint, knockout, CMYK blending and spot gradients through craft-pdf
2026-10-25 21:58:20 -04:00
Dylan M. Taylor 63a4f687fb Reduce cognitive complexity in UI dialogs, canvas, chrome, shortcut import and IDML export (#1848)
* refactor(ui): split shortcut set import into sort, apply and conflict steps

Resolves SonarCloud rust:S3776 on import (ui-egui/src/shortcut_import.rs).

* refactor(ui): split drop caps and nested styles dialog into row helpers

Resolves SonarCloud rust:S3776 on drop_caps_and_nested_styles (ui-egui/src/dialogs.rs).

* refactor(ui): split draw_guides into bleed, grid, overlay and guide helpers

Resolves SonarCloud rust:S3776 on draw_guides (ui-egui/src/canvas.rs).

* refactor(ui): split control_paragraph into alignment, indent, drop cap and shading helpers

Resolves SonarCloud rust:S3776 on control_paragraph (ui-egui/src/chrome.rs).

* refactor(idml): move graphic layer option tree out of image_el

Resolves SonarCloud rust:S3776 on image_el (idml/src/export.rs).
2026-10-25 21:25:57 -04:00
aiongg 240dbcf731 Merge remote-tracking branch 'upstream/main' into print-color
# Conflicts:
#	Cargo.toml
#	crates/idml/src/export.rs
2026-10-26 01:10:39 +00:00
Dylan M. Taylor 0e83233c97 Merge pull request #1737 from storytold/sonar/idml-c
refactor(idml): import graphics and table cell helpers (Sonar S3776)
2026-10-25 16:31:14 -04:00
Dylan M. Taylor 6227c4f1c8 Merge pull request #1730 from storytold/sonar/idml-b
refactor(idml): graphic part and spread import helpers (Sonar)
2026-10-25 16:30:25 -04:00
Dylan M. Taylor 19bc14fe03 Merge pull request #1718 from storytold/sonar/s1612-b
chore: method paths for remaining closures (Sonar S1612)
2026-10-25 16:30:13 -04:00
aiongg 65c387732d Merge upstream/main into print-color
PDF/X and CMYK groups keep this branch's approach: krilla's serialize
settings (pdfx::print_settings) write the CMYK page and transparency
groups, the GTS_PDFX output intent and the PDF/X Info and XMP entries.
make_pdfx4 adds only the XMP dates, so main's title argument and its
output-intent, Info and pdfxid XMP edits are dropped, and both
cmyk_group_spaces calls after writer.finish() (Export PDF, Print
Booklet) stay removed. Main's new parts are kept: file_info_metadata
(also for Print Booklet, on top of the print settings), optional content
registration and layer errors, add_form_fields, and pdfx's fonts module.
Main's metadata panic test calls the two-argument make_pdfx4.

craft-libs and the krilla patch are pinned to storytold/craft-libs
e3b9e239; Cargo.lock is main's, relocked without updates.
2026-10-25 19:47:27 +00:00
dotCooCoo 0f037cb67e Merge main into feat/file-info 2026-10-24 18:14:03 -07:00
skylar taylor-barrick 0f1ff65e7a Merge pull request #1647 from andeecollard/codex/placed-graphic-layer-overrides
M6: preserve placed-graphic layer settings across IDML and native saves
2026-10-24 18:55:32 -06:00
aiongg b595f1b7d3 EPUB: Split Document (export option and per-style Export Tagging) (#1787)
* EPUB: Split Document in a paragraph style's Export Tagging

* EPUB: Split Document as a document setting (off, one style, or export tags)

The document stores EPUB Export Options › Split Document (DocSettings.epub_split):
off (one content file, the default), a single paragraph style, or the
paragraph styles' Export Tagging › Split Document flags. document.epubSplit sets
it as one undo step; file.exportEpub takes a split that overrides it for one
export. A Style setting follows a renamed style and a deleted style's
replacement. IDML reads and writes EPubExportPreference BreakDocument and
ParagraphStyleName. A split before a list item or preformatted line closes the
open list or block first, so each content file is balanced.

* EPUB Export Options dialog with Split Document before Export EPUB

File › Export EPUB… opens EPUB Export Options, seeded from the document's
Split Document setting: a Split Document checkbox with Single Paragraph Style
(and its style) or Based on Paragraph Style Export Tags. OK stores a changed
setting through document.epubSplit, then continues to the save dialog; Cancel
does nothing. app.exportEpub with a path skips the dialog. Docs and the
progress log describe the setting.

* EPUB: the navigation test exports one content file with Split Document off

* EPUB export from the menu passes its options (cover, split) to the engine

* EPUB: Split Document on a style's EPUB tag map counts when the style says false; a caller's cover: false stays
2026-10-24 17:56:49 -04:00
skylar taylor-barrick 9fc02f8f7b Merge contributor branch codex/placed-graphic-layer-overrides (PR #1647) into main
Conflict resolutions:
- crates/pdf/src/export.rs: keep main's `graphic(.., hidden)` signature from
  #1241 and report retained graphic-layer overrides that drawing cannot apply.
- docs/gaps.md: keep main's change list and add the graphic-layer entry.
2026-10-24 15:30:03 -06:00
dotCooCoo 6bc5ac36fb Merge main into feat/file-info 2026-10-24 11:30:55 -07: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
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
andeecollard b7e36bf616 M6: retain layer order when native parents reopen closed subtrees 2026-10-24 13:22:08 +01:00
andeecollard 3d362d0bdf M6: preserve nested graphic layers and retain export diagnostics 2026-10-24 13:22:08 +01:00
andeecollard 7074dc8a85 M6: preserve per-placement graphic layer options 2026-10-24 13:22:08 +01: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
Dylan M. TaylorandClaude Sonnet 5.5 04f0c55afb refactor(idml): extract graphics and table cell import helpers (Sonar S3776)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 08:52:41 +00:00
Dylan M. TaylorandClaude Sonnet 5.5 71d9386138 refactor(idml): split graphic part and spread import helpers (Sonar S107, S3776)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 08:52:11 +00:00
Dylan M. TaylorandClaude Sonnet 5.5 75d5b015d3 refactor(idml): extract helpers to cut cognitive complexity (Sonar S3776) (#1723)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 04:51:31 -04:00
Dylan M. TaylorandClaude Sonnet 5.5 9770002c5c chore: method paths for remaining trivial closures (Sonar S1612)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 08:32:21 +00:00
Dylan M. TaylorandClaude Sonnet 5.5 8299d26400 chore: replace trivial closures with method paths (Sonar S1612) (#1714)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 04:30:43 -04:00
dotCooCoo a525894355 File Info: PDF export writes the document's title, author, description and keywords
File › File Info… opens a dialog with Document Title, Author,
Description, Keywords, Copyright Notice and Copyright Info URL, and the
document saves them. The new file.info command reads them with {} and
sets the fields it is given; "" or null clears a field, and keywords
are a list or one line split at semicolons and commas. file.info.get
returns the fields without editing the document, so opening the dialog
does not end a Data Merge preview.

Export PDF, PDF/X-4 and Print Booklet write the title, author,
description and keywords into the PDF's document information and XMP.
EPUB export takes the title and author from File Info, and HTML export
takes the title. A title or author given to the export replaces File
Info's, and an empty Document Title leaves the document's name as the
title. Export PDF's dialog no longer sends the document's name as the
PDF title, so the PDF takes its title from File Info; the file name
still comes from the document's name.
2026-10-24 00:20:21 -07:00
aiongg e79da41ce9 Merge #1704: Text frames: a custom baseline grid keeps its start and increment through IDML
# Conflicts:
#	crates/compose/src/lib.rs
#	crates/idml/src/tests.rs
2026-10-24 05:52:12 +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 df6ba617d3 Text frames: a custom baseline grid keeps its start and increment through IDML 2026-10-24 04:58:04 +00: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
Brandon Thomas d45a7baf4c Merge storytold/main into fix/h1246-idml-round-trip-renames-styles-w
# Conflicts:
#	crates/idml/src/tests.rs
2026-10-23 17:29:40 -04:00
Brandon Thomas 8eb4f5590a Merge storytold/main into feat/cell-rotation-reported
# Conflicts:
#	crates/idml/src/tests.rs
2026-10-23 17:29:22 -04:00
Brandon Thomas 0092906ea8 Merge pull request #1664 from MarekSpodBiedry/issue-1623
idml: explicit zero cell edge weights hide the default table border (#1623)
2026-10-23 17:28:02 -04:00
Brandon Thomas b84f268430 Merge storytold/main into fix/1589-audit-dc-08-non-finite-idml-numb
# Conflicts:
#	crates/idml/src/tests.rs
2026-10-23 17:27:37 -04:00
NetterSilverandClaude Opus 5.5 913bce948f Keep non-finite IDML numbers out of imported documents
Fixes #1589

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:48:11 +00:00
MarekSpodBiedry 7b91a1eefc idml: explicit zero cell edge weights hide the default table border (#1623) 2026-10-23 17:35:51 +02:00
MarekSpodBiedry 5344faf9f0 IDML export: clip a table cell's graphic to the cell (#1551) 2026-10-23 16:08:12 +02:00
aiongg a30b71cd36 Merge remote-tracking branch 'upstream/main' into print-color
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	xtask/src/pdf_deps.rs
2026-10-23 05:40:13 +00:00
MarekSpodBiedry d292dd2acd IDML export: write the graphic placed in a table cell (#1551) 2026-10-22 21:06:54 +02:00
Hamza a473793c07 Rotated cell text is settable and reported, not silently flattened (#1468)
A cell's text rotation (Cell Options › Text › Rotation) was already read from
IDML and written back, but only 0 is composed, so an imported form's narrow
header columns of vertical labels came in horizontal and wrapped mid-word
("Eingela / ngt am") — and nothing anywhere said why. The reporter's file has
30 such cells.

Composing rotated cell text is a larger change than this. What this does is
stop it being silent, and let the value be set from the API:

- the IDML import reports it once per file: "2 table cell(s) have rotated text
  (Cell Options › Text › Rotation): the angle is kept and written back, but the
  text is composed horizontally";
- `table.setCell` takes `rotation` (0, 90, 180 or 270, any other angle refused,
  negatives and multiples normalised), which nothing could set before;
- `table.get` reports each cell's rotation, so a round trip can be checked.

Tests: the angle through an export and back with the warning counted once for
the file (and no warning when no cell is rotated), and the command's accepted
and refused angles. Each fails without its own part.
2026-10-22 15:59:33 +05:00
NetterSilverandClaude Opus 5.5 fa81009be2 Keep a literal ':' in style names through an IDML round trip
Found while testing crates/idml/src/names.rs:148-155

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 10:22:08 +02:00
aiongg d7b9f716f1 View: Lock Guides and Lock Column Guides are commands (#1096) (#1174)
* View: Lock Guides and Lock Column Guides are commands (#1096)

view.lockGuides {on?} (Cmd+Alt+;) sets the Lock Guides UI state the Properties panel and ruler-guide drags use. view.lockColumnGuides {on?} is a document setting, on by default, saved with the document, not an undo step, and read from and written to IDML ColumnGuideLocked. Both are in View > Grids & Guides with checkmarks.

* View: Lock Column Guides is translated wherever Lock Guides is (#1096)

* View: Lock Column Guides is undoable (#1096)

* ROADMAP: the progress line lands in one commit after the guide PRs
2026-10-22 02:12:42 -04:00
aionggandHamza 6f7fc7134a IDML: dragged column guides import, validated, and round-trip (#1096) (#1171)
* IDML: keep column guides that were dragged off centre (#1096)

InDesign records dragged column guides in `MarginPreference ColumnsPositions`,
as pairs of offsets from the margin box's left edge. The importer discarded them
and divided the columns evenly, so a page whose gutter the designer had moved
came back with it in the middle: on a 450 pt margin box, `0 150 170 450` was
read as columns at 215 and 235.

`Columns::positions` already existed, documented as "Custom column positions
(after dragging column guides)", but nothing set it and nothing read it. Now
`Page::column_rects` returns the custom rects when they are set — that one
method is what the canvas guides, snapping, threading and the first frame of a
placed story all go through, so they follow the dragged gutter — the importer
fills it, and the exporter writes the page's real positions instead of
recomputing an even split, so the round trip keeps them.

`layout.marginsAndColumns` clears them when a count or gutter is set, which is
what InDesign's Margins and Columns does. Without that the stale positions would
outrank the new value and the dialog would look broken.

Verified against InDesign-authored IDML rather than assumed, which settled two
things. The attribute is written whether or not anything was dragged — a real
page's values are exactly its even split — so an even set is dropped rather than
marking every imported page custom and freezing its columns; the tolerance for
that comparison only absorbs float noise, about 1e-14 pt on that page. And
`<Guide>` is a `<Page>` child, not a `<Spread>` one, which is where this
importer already looks: the reporter's missing ruler guide was 099fbd2, landed
the day the ticket was filed, not a second bug.

That commit left `lib.rs` still listing guides as ignored on import; corrected.

* IDML: custom column positions are validated and round-trip (#1096)

Columns::positions are used only when they are 2 x count finite edges,
ascending from 0 to the margin box width (within 0.01 pt); anything else
is the even split, in Page::column_rects, on IDML import (bounded parse,
checked against the page's margin box) and on IDML export.
Columns::with_gutter_moved moves one gutter's pair of guides between its
neighbours for the coming column-guide command.

ROADMAP: drop four progress-log lines the #1121 merge duplicated and move
its line to the top.

* IDML: a page without its own margins checks the default's column positions against its width (#1096)

* ROADMAP: the progress line lands in one commit after the guide PRs

---------

Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
2026-10-22 01:59:10 -04:00
aiongg 8a6f9725b0 IDML: test a ruler guide in a column gutter without facing pages (#1096) (#1170) 2026-10-22 01:25:12 -04:00
aiongg 99cb64a779 Print color: US spelling in the new code and docs 2026-10-20 13:36:14 +00:00
aiongg 6c9709e11f Print color: gradient stops keep the swatch they were given
A stop can name a colour swatch (spot, process, tint, [Paper]) next to its
display colour. swatch.create {gradient}, object.gradient, the Gradient panel
and IDML StopColor keep the reference; renames follow it, swatch edits refresh
the stop's colour and a deleted swatch leaves a plain colour. The field is
optional and omitted for plain stops, so saved documents load and save as
before.
2026-10-20 13:12:29 +00:00
Brandon Thomas 5442d648eb Merge pull request #1193 from Silvertree2010/fix/h2418-idml-import-accepts-nan-inf-in-s
Ignore NaN and infinite numbers when importing IDML
2026-10-19 02:50:02 -04:00
Brandon Thomas 54052d77f9 Merge pull request #1237 from aykutfirat/fix/cell-first-baseline
Tables: cell First Baseline offset (Cell Options › Text › First Baseline)
2026-10-19 02:49:33 -04:00