Commit Graph
1131 Commits
Author SHA1 Message Date
aiongg d90881a8a9 Merge branch 'print-color' into print-color-separations
# Conflicts:
#	Cargo.toml
2026-10-26 01:11:35 +00: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. TaylorandClaude Sonnet 5.5 3eeab5aead refactor(engine): reduce complexity in path join and paragraph style apply (Sonar) (#1729)
* refactor(engine): split join_paths and apply_para (Sonar S3776)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(engine): use the resolved style types in apply_para_in_story

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Pass the resolved styles by reference at the call site

* Drop the range binding the call no longer uses

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 17:48:35 -04:00
Dylan M. Taylor 4322609d4b Merge pull request #1722 from storytold/sonar/engine-datamerge
refactor(engine): data merge complexity and parameter counts (Sonar)
2026-10-25 16:31:23 -04:00
Dylan M. Taylor a4143e031a Merge pull request #1735 from storytold/sonar/engine-d
refactor(engine): reduce complexity in find.change and used_fonts (Sonar)
2026-10-25 16:30:36 -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
Dylan M. Taylor 05e5f17913 Merge pull request #1717 from storytold/sonar/s2208-a
chore: explicit imports in test modules (Sonar S2208)
2026-10-25 16:29:55 -04:00
aiongg 9c977f41a6 Merge print-color (#1374 with main: egui 0.37, craft-libs e3b9e239) into print-color-separations
print_pdf, shared by Export PDF, File › Print and Separations Preview, takes main's two
changes to the inline export pipeline: rasterize_layered runs only for PDF/A-2b (other
standards keep hidden placed-PDF layers as optional content), and the report gets
GRAPHIC_LAYER_RENDERING_WARNING when the source document has graphic layer visibility
overrides and the writer did not report it. The Separations Preview command matches
craft_prepress::Conversion with a fallback arm, since the enum is non-exhaustive at
craft-libs e3b9e239.
2026-10-25 19:54:40 +00: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
skylar taylor-barrick bd4b9dd1d2 egui-037: reconcile shared window integration with main 2026-10-25 18:34:10 +01:00
Brandon Thomas 743eced7ba Merge pull request #1712 from dotCooCoo/feat/file-info
File Info: PDF export writes the document's title, author, description and keywords
2026-10-25 12:26:32 -04:00
Brandon Thomas 58402f01e2 Merge pull request #1783 from dotCooCoo/feat/split-note
Notes: Split Note splits a note in two at the insertion point in its text, as in InDesign
2026-10-25 12:26:26 -04:00
Brandon Thomas 019c1d9e67 Merge pull request #1785 from dotCooCoo/fix/editorial-note-keeps-caret
Notes: deleting a note or converting it to text keeps the caret on the same text
2026-10-25 12:26:20 -04:00
Brandon Thomas 94bf1bf7f9 Merge pull request #1780 from dotCooCoo/fix/note-delete-keeps-caret
Footnotes: deleting a footnote or endnote keeps the caret on the same text
2026-10-25 12:26:13 -04:00
Brandon Thomas bb45cdcc50 Merge pull request #1775 from dotCooCoo/fix/footnote-moves-drop-typing-format
Footnotes: moving the caret into or out of a footnote drops formatting not yet typed
2026-10-25 12:26:06 -04:00
Brandon Thomas f2b62c9473 Merge pull request #1778 from dotCooCoo/fix/link-tests-on-windows
Links: the folder relink and IDML link tests expect Windows paths on Windows
2026-10-25 12:25:54 -04:00
Brandon Thomas 564b3befc5 Merge pull request #1796 from dotCooCoo/fix/preflight-test-absolute-temp-dir
Preflight: the missing-link test makes the temporary folder absolute
2026-10-25 12:25:35 -04:00
skylartaylor 6bc2e25792 M0.37: fix accessible controls and simplify reviewed engine paths 2026-10-25 08:31:14 +01:00
skylartaylor b350488906 Reconcile current DesignCraft main with the egui 0.37 migration 2026-10-25 07:16:33 +01:00
skylar taylor-barrick 7ca39c6c10 Merge pull request #1806 from storytold/fix/idml-nested-pdf-layer-agreement
Keep nested placed-PDF layer choices in embedded IDML
2026-10-24 23:45:11 -06:00
skylar taylor-barrick 7417172663 M6: reject conflicting shared-id PDF layer choices in IDML 2026-10-24 22:59:09 -06:00
skylar taylor-barrick dae8a622eb Count distinct placement ids in the IDML layer-variant guard
A duplicated text frame holding an anchored placed PDF leaves two placements sharing one ItemId, so the raw update count exceeded the variant count and a correct export failed. The guard now checks that every mapped id was reached. Replaces the mismatch test with a duplicated-frame export regression.
2026-10-24 21:13:58 -06:00
skylar taylor-barrick 3bacb1b022 Text: reject malformed explicit Story Options targets 2026-10-24 21:06:21 -06:00
skylar taylor-barrick 21a54becce M6: guard IDML variant coverage and strengthen export tests 2026-10-24 20:45:22 -06:00
skylartaylor 8a6ed75d41 egui037: reconcile current DesignCraft main and qualify CI 2026-10-25 03:38:13 +01:00
skylar taylor-barrick 25218f3759 M6: preserve nested PDF layer choices in embedded IDML 2026-10-24 20:16:22 -06:00
skylar taylor-barrick 53d9b6d7f8 M6: merge current main and retain nested PDF/A placement traversal 2026-10-24 19:25:12 -06:00
dotCooCoo 0f037cb67e Merge main into feat/file-info 2026-10-24 18:14:03 -07:00
skylar taylor-barrick df526527cd Merge main into the explicit-visibility branch 2026-10-24 18:58:31 -06: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 befc2e0346 Styles: renaming a style keeps its Export Tagging (#1790)
* Styles: renaming a style keeps its Export Tagging

Renaming a paragraph or character style, or moving it into a style
group, moves its Export Tagging to the new name. Deleting a style drops
its tagging and leaves the replacement's own tagging unchanged.

* Styles: a paragraph style can't be renamed onto another style's name

* Styles: a refused rename says the name is taken and shows the General section

Renaming a paragraph or character style onto a name another style has
now says so ("a paragraph style named `Body` already exists"); empty
or bracketed names keep the generic message. The Paragraph Style Options
dialog switches to General, where the name field is, when the rename is
refused. Paragraph style names are trimmed like character style names,
and a renamed style never picks up an export tag left under its new name.

* Styles: the rename test's stale tagging takes the Split Document field

* ROADMAP: date the style rename line 2026-10-24
2026-10-24 20:37:21 -04:00
skylar taylor-barrick 9f6cb08591 M6: preserve nested placed-PDF layer choices in PDF/A export 2026-10-24 18:07:19 -06:00
skylar taylor-barrick 040e388e68 M6: let rustfmt lay out the anchored regression's item
Formatting only: the gate's `cargo fmt --check` rejected the three-argument layout.
2026-10-24 17:50:41 -06:00
skylar taylor-barrick 921fcc16d0 Merge current main (b595f1b7) into the #1647+#1671 pair 2026-10-24 17:45:15 -06:00
skylar taylor-barrick 2d81510d19 M6: keep an anchored placement's layer choice in a regression
The parent-page regression covers a placement a page inherits. The other placement the export
walks reach is an object anchored in a story: the IDML copy gets a variant that shows every
layer, an external-only copy is refused, and PDF/A-2b rasterises it and warns. The nested-story
regression that used to cover this case also asserted placements anchored inside a table cell and
a footnote, which this pass does not reach; this one keeps the anchored case alone.
2026-10-24 17:45:12 -06:00
skylar taylor-barrick dfba0a3f9d M6: leave placements nested in cells and notes out of the PDF layer pass
Both exports walk Document::placed_items: document and parent spreads, groups, and the objects
anchored in a story. That is the walk the parent-page and anchored fix introduced. The
nested-story traversal (table cells, notes, endnotes), Document::update_placed_items and the
fail-closed refusals that went with it are not part of it: that is the traversal change on its
own, not the placements this pass carries. update_items keeps its reach, so the two exports clear
the choice where the placement actually is again.

A choice anchored inside a table cell's or a note's text therefore stays on the document and is
not carried into the embedded IDML copy, as on main; the refusal that turned that silent
difference into an export error goes with the traversal it guarded, since asking the walk's own
predicate it could never fire. The stale-field half keeps: has_applicable_pdf_layer_overrides
still asks for a graphic whose asset is a PDF, so relinking a placed PDF to an image no longer
makes the package report name a choice that does not exist.

Tests: the nested-placement regression and the relink integration test of the removed refusal
go; the parent-page regression, the stale-field predicate test and the format 4 cell-only reader
test stay. The comments no longer claim every placement counts.
2026-10-24 17:44:02 -06:00
skylartaylor df9d51f4e2 egui037: Integrate DesignCraft main EPUB and PDF updates 2026-10-25 01:34:16 +02:00
skylar taylor-barrick ba8936e061 M6: keep the relink regression off the file guard's path
The workspace file guard scans test modules too when they are declared `pub(crate) mod` (it only
skips a plain `mod`), so a temp file written inside pdflayers.rs' tests failed
no_crate_touches_the_file_system_outside_the_checked_readers. The unit test now builds the state a
relink leaves behind - layer fields on an item whose asset is an image - and asserts the refusal
predicate ignores it while all three exports run. The user path (a real links.relink to a PNG) moves
to tests/pdf_optional_content.rs, where the guard exempts fixtures written by test files.
2026-10-24 17:05:13 -06:00
skylartaylor a2db858e7d egui037: Port DesignCraft to egui 0.37
Pin the final egui, winit and shared UI revisions and reconcile current main.
Preserve document-epoch input and screenshot boundaries, host action ordering,
and Windows path regression coverage. Add click/End batch characterization.

Validation: all nine Linux CI stages pass (3230 tests, zero failures); Windows
CI and bounded native editing workflows pass on the same production source.
2026-10-25 00:52:21 +02:00
dotCooCoo c1561f7ccf Preflight: the missing-link test makes the temporary folder absolute
a_missing_link_shown_by_its_preview_is_still_reported builds its link
under std::env::temp_dir(). On macOS and Linux that returns TMPDIR as
set, so a relative TMPDIR gave a relative link, which document_path
refuses in a document without a path, and the test failed with
"(the path is not valid)". The test now passes the temporary folder
through std::path::absolute first. The preflight code is unchanged.
2026-10-24 15:43:49 -07:00
skylar taylor-barrick 1731c95bad M6: say plainly that the export refusal is a tripwire
Comment-only: the refusal in both exports cannot fire while the walk and the predicate cover the
same placements, so the comments now say it is a tripwire for a future nesting construct and ask
nobody to narrow the walk to match it.
2026-10-24 16:12:40 -06:00
skylar taylor-barrick 08876e1868 M6: refuse an export only for a choice it could have applied
The refusal guard asked whether any item still had the layer fields, while the export walks
also require a graphic whose asset is a PDF. Relinking a placed PDF to an image keeps those
fields on the item (links.relink replaces the asset in place), so a stale field blocked IDML
and PDF/A-2b exports that used to work. The guard, and the package report, now ask the same
question the walks ask: has_applicable_pdf_layer_overrides requires the PDF asset too, so a
stale choice is simply ignored and the tripwire still fires if a future construct ever puts a
real choice where the walk cannot reach it.

Regression: a_stale_choice_on_a_relinked_image_does_not_block_exports places a layered PDF,
hides a layer, relinks that asset to a PNG and exports IDML, PDF/A-2b and plain PDF - all
succeed, and the document reports the stale field while the applicable helper does not.
2026-10-24 16:11:28 -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 1266ce8236 M6: cover every placement when PDF layer choices are applied
Kept separate from the parent-page fix and from the all-on export fix: this is the traversal
remediation on its own.

The detection helpers already walked parent spreads, groups and the stories in table cells,
notes and endnotes, while the two exports walked document spreads only, and the write side
(Document::update_items) did not reach placements nested in those stories either. So a choice
on a frame anchored in a cell's text or in a footnote asked for the newer file format and was
named by the package report, yet the IDML copy carried the file's defaults. The walk was
narrow on main as well (see the probe evidence), so this is pre-existing for the older
hidden-list state; it becomes a wrong claim only because the paired PR added the variants and
said every placement counts.

Document::placed_items recurses those stories (depth budget 64, like the detection side) and
a new Document::update_placed_items applies the change where the placement actually is,
copying only the branches holding a match. update_items is untouched, so unrelated commands
keep their reach. Both exports also refuse rather than fall back when a document has a choice
but the walk found no placement to carry it.

Regression: nested_placements_keep_their_layer_choices_in_saves_and_exports runs a placement
anchored in a table cell's text, then in a footnote: the save keeps the choice, the embedded
IDML copy shows every layer, external-only IDML is rejected, PDF/A-2b export succeeds.
2026-10-24 15:49:40 -06:00
skylar taylor-barrick 09f9ce50e7 Package: name the placed-PDF layer choices its IDML copy cannot carry
A package's IDML copy links the placed files, so a per-placement Object Layer Options
choice cannot travel in it, while the packaged DesignCraft document keeps the choice. The
report now says so instead of leaving the two copies to differ silently.
2026-10-24 15:37:14 -06:00
skylar taylor-barrick f09df5123e M6: keep placed-PDF layer choices for parent-page and anchored placements
The IDML layer-variant pass and the PDF/A-2b rasterisation pass both walked only
document-spread items, so a choice on a parent-page placement (or an anchored one) was
replaced by the file's defaults on export, and an external-only IDML export succeeded
when it could not carry the choice. Both now cover every placement through
Document::placed_items, and the choice is cleared where the placement actually is.

Regression: a parent-page placement with an explicit all-on choice keeps all layers in
embedded IDML, external-only IDML rejects it, and PDF/A-2b rasterises it.
2026-10-24 15:37:12 -06:00
skylar taylor-barrick faed705607 Merge contributor branch codex/pdf-layer-explicit-visibility (PR #1671) into the paired integration branch 2026-10-24 15:30:04 -06: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
skylar taylor-barrick 0e0ed78125 M6: integrate placed-PDF vector layer export with current main (#1241)
Preserve contributor commits and adapt optional-content registration and table-cell graphic calls to the current PDF exporter refactors. Keep current-main roadmap corrections.

All nine cargo xtask ci gates passed on tree d0c21f347e: 3209 tests passed, 6 skipped, 16 WASM-safe crates. The exact PR head also passed 118 PDF unit/integration tests. Independent production-export controls: 8 flat/null cases succeeded; 7 unreadable Prev values refused, 4 compatibility controls succeeded; all 12 emitted PDFs pass qpdf.

This PR is independent of the format-v4 pair (#1647/#1671), which remains held for a reproduced parent-placement IDML issue.
2026-10-24 14:38:11 -06:00
dotCooCoo 28d3c6b44f Notes: deleting a note or converting it to text keeps the caret on the same text
note.delete removes the note's anchor (3 bytes) from the story, and
note.convertToText replaces it with the note's text. Both left a caret or
selection in the story text at its old byte offsets. With "copy" selected
after a note in "Draft copy.", Delete Note left the selection at 9..13 in
an 11-byte story, and Convert Note to Text with the note's text "ab" left
"opy." selected.

Both commands now move a caret or selection in the story's own text by
the change in length when it comes after the anchor. A caret before the
anchor stays where it is, and a caret in a table cell or in another story
is unchanged.
2026-10-24 11:45:19 -07:00