Commit Graph
1054 Commits
Author SHA1 Message Date
midasmatterhorn e45bb864ed math: cap LaTeX expression nesting depth so hostile input can't overflow the stack
`math.svg` and `math.insert` take an unbounded `latex` string, and the parser's
arg/atom/list/list_until_right recursive descent recursed once per group: 100k
nested braces, `\frac`s or `\left(`s overflowed the stack (an abort the command
guard cannot catch). Past MAX_NESTING (256) groups stop descending, so the rest
of the input is consumed iteratively.

Regression test: 100k nested braces, `\frac`s and `\left(`s typeset to an SVG;
the old code aborted with a stack overflow.
2026-10-14 22:52:56 +03:00
moppeeerandClaude Opus 5.5 bb96f1455f Fill with Placeholder Text in paragraphs, as InDesign does
InDesign's placeholder text comes in paragraphs; Zero2Graphic's magazine
tutorial styles its second paragraph as an 18 pt lead (2:16). DesignCraft
filled the frame with one paragraph, and the last filler sentence ran into
the first ("interit.Ovid"). Paragraphs now hold 2 to 5 sentences, and an
overset fill is trimmed to the last whole sentence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:32:57 +02:00
moppeeerandClaude Opus 5.5 d5d8621780 Pathfinder keeps the frontmost object, as InDesign does
InDesign's Pathfinder result takes the attributes (and content) of the
frontmost object, except Subtract, which keeps the backmost. DesignCraft
kept the backmost for every op but Minus Back, so a photo placed over
strips and intersected with them was deleted and the black strips stayed
(Zero2Graphic's magazine tutorial, 7:19).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:22:17 +02:00
NetterSilverandClaude Haiku 5.5 8b834d0533 Fix overflow in layout.pages.insert when after is u64::MAX
Found while testing crates/doc/src/build.rs:377 (Document::insert_pages), called from crates/engine/src/cmd/layout.rs:91

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 19:17:09 +00:00
zydvc26s67-webandCopilot App 4516989e51 Type: let a blank line's hidden paragraph mark take leading immediately
Selecting an empty paragraph (a blank line) puts a collapsed caret on its
hidden paragraph mark, the only character on that line. Previously
type.char either deferred the formatting to the next typed character (in
a non-empty story) or dropped it on the floor for composition, so there
was no way to change a blank line's height — matching InDesign's ability
to select the pilcrow and adjust leading.

- engine/cmd/text.rs: recognize an empty paragraph's own caret position
  (empty_para_mark) and apply character attributes straight to that
  byte's run instead of deferring to typing format.
- compose/lib.rs: an empty paragraph has no glyphs of its own, so resolve
  the hidden mark's run (if overridden) for the paragraph's base leading
  instead of always falling back to the paragraph's plain default.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-14 12:05:35 -07:00
zydvc26s67-webandCopilot App bfcd6ef71f Style delete: redirect every reference, validate name and replacement
delete_para and delete_char previously reassigned only the story text
runs/paragraphs using the deleted style, leaving other styles' Based
On, paragraph styles' nested/nested-line/GREP style refs, the drop cap
style, and the footnote reference style pointed at a name that no
longer exists.

Extract redirect_style_refs() from rename_style() (everything it does
except updating the registry entry's own name) and reuse it from both
delete commands, so deleting a style now redirects every reference
type to the replacement style before removing the registry entry.
Also teach rename_char_refs() about drop_cap_style, which it missed
even for renames.

Add validation: name must be non-empty and refer to an existing
style, and replaceWith (if given) must refer to an existing style and
can't be the style being deleted.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-14 11:33:35 -07:00
zydvc26s67-web 7c5b248dfc Merge remote-tracking branch 'origin/main' into pr171-fix 2026-10-14 11:11:42 -07:00
moppeeer 9327a55100 Merge origin/main into #468 (layout-parent-guides-units)
Main restructured the dialog dispatch; #468's Create Guides and Margins and Columns arms moved into it unchanged.
2026-10-14 19:24:45 +02:00
moppeeerandClaude Opus 5.5 11b1566c09 Type tool: a press over a locked empty frame draws a new text frame instead of converting it
Adobe's "Set up a modern magazine layout" (Brian Wood, 2:12–4:23) locks a
page frame drawn round the spread (Cmd+L), then draws the text frames on
top of it with the Type tool. In DesignCraft the press landed in the
locked frame, which the Type tool turned into a text frame, putting the
caret in it; no new frame was drawn.

- The Type tool takes a hit only on text frames (locked or not, as
  InDesign lets you edit their text) and unlocked empty frames; over a
  locked empty frame, the press starts a new text frame.
- text.placeCaret refuses to convert a locked empty frame (or one on a
  locked layer).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:22:54 +02:00
Jeffrey Thayne 999d0583a3 Merge remote-tracking branch 'origin/main' into linked-docx
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/dialogs.rs
2026-10-14 11:21:54 -06:00
zydvc26s67-web 117429085b Merge remote-tracking branch 'origin/main' into zydvc26s67-web-paragraph-styles-save-delete
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/dialogs.rs
2026-10-14 10:12:29 -07:00
aiongg a112a20c23 Merge upstream main 11a51d5b (0.8.0) 2026-10-14 17:09:42 +00:00
aiongg d72307ec02 Merge remote-tracking branch 'upstream/main' into place-loads-cursor
# Conflicts:
#	crates/engine/src/cmd/file.rs
2026-10-14 17:01:12 +00:00
Brandon Thomas 0df9238c73 Merge PR #850 2026-10-14 12:56:09 -04:00
Davit MatchakhelidzeandClaude Opus 5.5 5d4ed2a663 text: Georgian document language; no initial capitals for Georgian
Georgian is a Properties text language (IDML "Georgian" maps to ka). Georgian has no initial capitals: Mtavruli is only for all-caps text, so Change Case title and sentence case and index section heads leave Mkhedruli as it is (doc::capitalizes); upper case still gives Mtavruli.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-10-14 20:55:04 +04:00
Brandon Thomas 4f193834bd Merge PR #870 (with #869) 2026-10-14 12:40:07 -04:00
Brandon Thomas 50a6b60072 Merge PR #868 2026-10-14 12:39:59 -04:00
Brandon Thomas b8d975b094 Merge PR #866 2026-10-14 12:39:59 -04:00
Brandon Thomas 23aeddb354 Merge PR #864 2026-10-14 12:39:58 -04:00
Brandon Thomas c1a1970168 Merge PR #862 2026-10-14 12:39:58 -04:00
Brandon Thomas a6e7e2a0c7 Merge PR #838 2026-10-14 12:39:58 -04:00
Brandon Thomas 6ceb57d4f5 Merge PR #845 2026-10-14 12:39:58 -04:00
Marco Arnulfo 52eac14f2c PDF: a placed PDF 1.7 with /Version /1.7 in its catalog goes into PDF/X-4 exports (fixes #907) 2026-10-14 16:48:52 +02:00
KnottyDyes 0d77f39443 Docs: explain hyphenation defaults and image fitting modes to agents
Command descriptions left the new-text hyphenation default and image fitting outcomes implicit. State the default and each fitting mode's semantics, and add an MCP example that disables hyphenation. No behavior changes.
2026-10-14 08:39:00 -06:00
Marco Arnulfo b12e94c11d Package: a missing link stays missing, with no empty file in Links/ (fixes #908) 2026-10-14 16:37:55 +02:00
Marco Arnulfo 455442615b Color parsing: bare CMYK is always 0..100, so C 1 is a 1 % tint (fixes #910) 2026-10-14 16:29:10 +02:00
moppeeerandClaude Opus 5.5 188c4f7007 Facing pages take their side from their section's page numbers
Chris Nielsen's "Numbering Page Sections" (7:03): starting a section at
page 1 on a left page (the spread 8–9 selected) turns it into a lone
right-hand page 1 in InDesign, and the pages after it shuffle. DesignCraft
kept the page on the left, so odd page numbers sat on left pages.

- Document::repaginate gives each facing page the side of its number in
  its section (odd: right, or left bound right to left). Document Setup's
  Start Page # is one case of it.
- layout.section repaginates when a section starts, changes or is removed;
  objects go with their pages, in one undo step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:03:58 +02:00
sanyamsingh001andCodex 44485e08da Merge tested main 0f4f382b0e into PR #845
Preserve the reviewed PR behavior and tested upstream base.

Co-Authored-By: Codex <codex@openai.com>
2026-10-14 19:33:57 +10:00
Andres TorresiandClaude Opus 5.5 53374aab24 Type tool: dead keys and input-method composition on the canvas
Typing into a text frame never turned on the OS input method, so macOS
dead keys didn't compose: ⌥E then I typed "ei" instead of "í" (same for
⌥N, ⌥U and Japanese/Chinese input). The canvas now asks for the input
method while the Type tool has a caret and handles its events.

The text being composed shows in the story as an interaction preview
(new `text.compose` command), so it takes the format the next typed
character gets, drawn on a yellow box. On commit it's dropped and the
result typed with `text.insert` (one undo step); any other edit, tool
change or drag drops it first and tells the input method to forget it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:31:32 +01:00
moppeeerandClaude Opus 5.5 38b770230a docs: object.fit leaves locked objects and objects on locked layers as they are
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:31:30 +02:00
Gert Pellin 592e6026f4 EPUB fonts: skip bitmap-only fonts, and write the face's numeric weight
A font whose fsType allows embedding bitmaps only (bit 9, 0x0200) was
packaged with its outlines; it is now refused like a restricted one.
char_css wrote font-weight: bold for any style containing "bold", so
Semibold showed as Bold and Light as Regular; it now writes the numeric
weight (100-900) and style from the face's style name. Same approach as
aiongg's integration branch (#259, 8f54d1cc), with his test.
2026-10-14 11:19:31 +02:00
Gert Pellin 6e60bbccbe EPUB: read the cover image through a capped reader (256 MiB)
coverImage was read with an uncapped std::fs::read, so a huge file or a
device like /dev/zero could exhaust memory. Read it through the data
merge's capped reader, which now also stops the read itself at the cap
(a device reports no length), as in aiongg's integration branch (#259,
6eae3620), with /dev/zero as a test.
2026-10-14 11:09:11 +02:00
moppeeerandClaude Opus 5.5 64c99b18d5 Merge origin/main into codex/handle-double-click-fit
Main moved double-click handling to the second press (click_count 2, from the mouse or the control channel); the handle double-click that fits the frame now sits there too, before main's text-frame edit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:43:58 +02:00
a2c0cb79ce A radial gradient on a box with no width or height is a circle across it
Review fix from aiongg (6db40bdb, the radial_ellipse part), ported to this
branch: a straight line's box has no ellipse, so its stroke's radial
gradient showed only the last stop once #823's gradient strokes land.

Co-authored-by: aiongg <aiongtaigi@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:39:03 +02:00
f69601b0ff A linear gradient across a straight line runs along its length, on screen and in PDF alike
Review fix from aiongg (72d7ea2e, with the line tests of 6db40bdb), ported
to this branch: Fill::linear_axis gives screen and PDF one gradient axis,
and a box with no extent along the gradient's angle takes its longer side.

Co-authored-by: aiongg <aiongtaigi@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:36:45 +02:00
moppeeer 5f00aa7bb3 Merge remote-tracking branch 'origin/main' into codex/gradient-strokes
# Conflicts:
#	crates/engine/src/cmd/style.rs
#	crates/idml/src/tests.rs
2026-10-14 10:33:30 +02:00
moppeeer 52e0aaa2d6 Merge remote-tracking branch 'origin/main' into codex/radial-gradient-ellipse
# Conflicts:
#	crates/engine/src/cmd/style.rs
2026-10-14 10:32:47 +02:00
moppeeerandClaude Opus 5.5 23e1680e7d feat(ui): Swatches panel header like InDesign's; swatches go to the fill or stroke in front
LYH Studio episode 6 colours the "1969" headline (8:28) and the loop's
stroke (9:15) from the Swatches panel, whose header holds InDesign's
Fill/Stroke proxy, Formatting Affects Container/Text and the Tint field.

- Header: a Fill/Stroke proxy showing the colours of what colour edits
  apply to (panels::color_target; a click brings the other to the front,
  as X does), the container/text buttons (app.formattingAffectsText) and
  the tint of the colour in front.
- The Tint field sends only the tint, so each selected object (or run of
  text) keeps its own swatch: object.fill takes a tint without a swatch,
  and a stroke tint alone doesn't give a stroke-less object a stroke.
- Clicking a swatch applies it to the fill or stroke in front
  (panels::apply_swatch, to the text when colours affect text); that row
  is highlighted.
- Bottom row: New Color Group, New Swatch, Delete Swatch (the swatch last
  clicked). Rows and the proxy are named for accessibility (and tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:27:38 +02:00
Andres TorresiandClaude Haiku 5.5 be98657a22 feat(text): Typography panel lists and sets the OpenType features of the selection
A Typography panel (Window ▸ Show Panel, and the icon column) lists the
features of the selected text's fonts, merged over those fonts, grouped as
Ligatures, Alternates, Stylistic Sets (named by the font), Figure Style,
Figure Width, Figure Position and Capitals. A section or choice appears only
when a font offers it.

Each feature is a checkbox: checked when all of the selection has it, a dash
when only some of it does, empty when none does. A feature only some of the
selection's fonts offer is italic. Mutually exclusive choices are checkboxes
too, and choosing one turns the others off.

type.openTypeFeatures reports each feature's applied and available state over
the selection. type.feature turns features on or off across the selection,
keeping each run's other features. The fonts crate reads GSUB and GPOS
feature lists and stylistic set names.

The Character panel's OpenType menu is now a button that opens or focuses the
Typography panel.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-14 08:46:28 +01:00
aiongg f4efb7cc5c Integration: #869 Alt-drag copies a page in one command and one undo step (layout.pages.duplicateSpread takes to)
(cherry picked from commit 7889b25a37)
2026-10-14 09:43:06 +02:00
moppeeer 15fccae6b8 Merge remote-tracking branch 'origin/main' into codex/pages-panel-duplicate
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:39:45 +02:00
moppeeer 2a9e29f6ff Merge branch 'codex/page-tool-control-panel' into codex/liquid-object-pins
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:39:24 +02:00
moppeeer 3f1eb00bb3 Merge branch 'codex/page-tool' into codex/page-tool-control-panel
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:38:16 +02:00
moppeeer 65dbf3c3a2 Merge remote-tracking branch 'origin/main' into codex/page-tool
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-14 09:37:32 +02:00
moppeeerandClaude Opus 5.5 bf22391581 Gradient text test: make the cell's gradient swatch with object.gradient (swatch.create's gradient form is #763's)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:33:07 +02:00
aiongg 57c997634f Integration: #825 PDF table-cell and footnote text lays a gradient across its own lines, as on screen
(cherry picked from commit 14e98419ad)
2026-10-14 09:18:00 +02:00
moppeeer 16d8027d89 Merge remote-tracking branch 'origin/main' into codex/page-tool-liquid-guides 2026-10-14 09:13:24 +02:00
moppeeer 1faaebef25 Merge remote-tracking branch 'origin/main' into codex/gradient-text 2026-10-14 09:12:03 +02:00
moppeeer 7f1d9f2b2e Merge remote-tracking branch 'origin/main' into codex/copy-placed-graphic 2026-10-14 09:10:24 +02:00
moppeeer 69f77874e7 Merge remote-tracking branch 'origin/main' into codex/outlines-per-line 2026-10-14 09:09:16 +02:00