Commit Graph
1043 Commits
Author SHA1 Message Date
aiongg d380fca0d0 DES-10: link placed files at once; saves make missing proxies, never hashes
A file placed from a path becomes a link immediately, with its size and
time as the fingerprint and its bytes kept resident. The background job
adds the content hash and proxy to the live document, undo history and
saved state without changing storage. Saves (file.save, saveACopy,
serialize, recovery snapshots) make the proxies still missing and write
links without a hash. An open hashes a no-hash link whose file matches by
size and time. embed:true placements hash while placing. The embed-until-
hashed path (settle_pending, settle_copy, keep_embedded) is gone.
2026-11-14 13:10:36 +00:00
aiongg c9c0f6deb4 DES-10 review: placing returns before proxies and hashes are made
Placing from files (file.place, place.load, table and media posters)
embeds each graphic with its link record and queues its content hash
and proxy on the link-check thread; the poll links it under the same
key, in the live document, the undo history and the saved state. A
save before then hashes the pending graphics from their bytes and
writes them embedded. crop_pdf checks the crop choice and mime before
reading, and place and relink pass the bytes they already hold.
2026-11-14 12:51:26 +00:00
aiongg 0fc62ec30b DES-10 review: package warnings in the file-format parity doc 2026-11-14 12:47:11 +00:00
aiongg 3bd9332a6c DES-10 review: export linked graphics in EPUB/HTML, PPTX, IDML and packages; cache output bytes in PDF export 2026-11-14 12:47:03 +00:00
aiongg b8be148b4c DES-10 review: link status after open, preflight without reading originals
- Open queues every linked file's lookup (stat, then hash) for the background
  check instead of stating candidates on the UI thread.
- links.list, links.update and relinkFolder use the open's status only while
  its check is still running; afterwards the file is looked at as it is now.
- Preflight tells Modified from size, time and the remembered hash checks
  (the worker keeps them between passes) and the vector test from the mime
  type; it never loads a linked original.
- A modification time of 0 never vouches for a file's bytes.
- Migration keeps an unsettled time as UNVERIFIED_MTIME; recovery snapshots
  keep images not yet saved as links embedded.
- Links panel test fixture has real files, so its Embedded assertions hold.
2026-11-14 12:46:23 +00:00
aiongg 18e1ba14b3 DES-10 T11: docs for linked artwork and multi-image placement 2026-11-14 12:28:58 +00:00
aiongg 39cb508cca Place: a single dropped image is placed where it lands; several load the cursor 2026-11-14 06:11:51 +00:00
aiongg 7c34fce67c Docs: place.skip, place.cycle, and Undo leaving the cursor as it is 2026-11-14 05:56:51 +00:00
aiongg c8f105dd65 Merge pr-2308 (place contact sheet) into multi-place 2026-11-14 05:49:47 +00:00
aiongg 62f70cc03c Merge branch 'pr-2309' into multi-place 2026-11-14 05:49:14 +00:00
aiongg 2ee301bd4b Merge pr-2302 (place cursor queue) into multi-place 2026-11-14 05:49:14 +00:00
aiongg 1a156fa564 Merge remote-tracking branch 'upstream/main' into image-perf
# Conflicts:
#	crates/images/src/jpeg.rs
#	crates/images/src/lib.rs
2026-11-14 04:29:08 +00:00
aiongg eefdfbb688 Docs: image cache keeps the levels drawn; canvas decodes in the background 2026-11-14 03:32:18 +00:00
jayzed80 c509445ed0 IDML export: keep endnote reference numbers (#2753) (#2764)
The IDML story writer skipped the endnote reference character, so an
exported body story lost every endnote's place: "an endnote here. End."
with nothing between "here" and the full stop. The endnote frame's
story was written with its numbers as text, so nothing linked the
listed endnote back to where it was referenced.

Each reference is now written as its own superscript character range
holding the endnote's number, formatted by Endnote Options (start,
style, prefix and suffix) as the endnote frame lists it. IDML's
Endnote / EndnoteRange elements are not written yet.
2026-11-14 00:34:31 +00:00
.CooCooandDylan M. Taylor 5fb75aaefc Properties: Text Frame section shows inset spacing and vertical justification (#2661)
* Properties: Text Frame section shows inset spacing and vertical justification

Properties › Text Frame now shows the frame's inset spacing under the
columns: Top and Bottom, a link that makes all four the same, then Left
and Right. A non-rectangular frame shows one Inset, the distance its text
keeps from the outline. Four buttons set Vertical Justification to Top,
Center, Bottom or Justify. Type on a path shows neither.

The section also shows with the Type tool in a frame. There it changes
the frame that shows the insertion point, or every frame that holds part
of the selected text, as Object › Text Frame Options does.

* Properties: one Inset for a non-rectangular frame keeps the other sides

The single Inset sets only the top inset, the one kept from the
outline. A rectangular frame that holds part of the same selected text
keeps its own sides.

* Properties: the one Inset field and the composer share the frame outline test

FrameOutline::of_item builds an item's outline with its corner options
applied. The composer uses it to keep the top inset from the outline,
and the Properties panel uses it to decide whether a frame shows one
Inset, so the two give the same answer for every frame.

* Text Frame Options: frames taken while typing stay with their document

OK is refused when another document became active after the dialog opened, so the saved frame ids do not change frames in that document.

* Properties: the inset link starts linked again after Revert

The link's state is kept per document state instead of per document, so
a frame with equal insets in the reverted document starts linked.

* Text Frame Options: frames taken while typing are refused after Revert

Revert keeps the document's id but replaces its state, so a new frame
can reuse a saved frame id. The dialog now ties the frames to the
document state, and OK is refused after Revert as it is in another
document.

* Properties: the one Inset of a non-rectangular frame sets all four sides

The composer bounds a shaped frame's text by its rectangle less all four
insets as well as by the outline, so a single Inset that changed only the
top left hidden sides in place: lowering a uniform 96 pt inset to 0 kept
text overset. When every frame the field changes is shaped, it now sets
all four sides. With a rectangular frame among them, only the top inset
changes and each frame keeps its other sides.

* Fix text frame dialog merge resolution

* Keep text frame preview targets fixed

* Fix target field key inference

* Tests: Text Frame Options show four sides for text through an oval and a rectangle

With the Type tool and text selected through an oval and a threaded
rectangle, with the oval as the caret's stored frame, the dialog shows
the four inset sides, a changed Top leaves the rectangle's other sides
as they were, and the link stays off while the rectangle's sides are
uneven.

* Properties: the inset link starts off when another frame has uneven sides

With selected text that runs through several frames, the link of Text
Frame > Inset Spacing started linked when the frame the section shows had
four equal insets, and a changed Top then set all four sides of every
frame. The link now starts linked only when every frame the field changes
has four equal insets. Its state is kept for that set of frames, so a link
turned on for one frame does not carry over to selected text that also
runs through a frame with uneven sides.

---------

Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
2026-11-12 17:27:08 -05:00
Dylan M. Taylor e6ab0d263e Merge branch 'main' into feat/duplicate-layer 2026-11-12 16:43:33 -05:00
Dylan M. Taylor 076e653ac3 Merge remote-tracking branch 'upstream/main' into codex/integrate-2658b 2026-11-12 16:27:39 -05:00
Dylan M. Taylor 520aeeefe1 Merge pull request #2652 from dotCooCoo/feat/text-frame-options-type-tool
Text: Text Frame Options open from the Type tool and change the frame holding the caret
2026-11-12 16:09:26 -05:00
Dylan M. Taylor 9fe0dd5197 Merge pull request #2666 from dotCooCoo/fix/recovery-off-interface-thread
Recovery: the timer writes recovery data on a background thread
2026-11-12 16:01:55 -05:00
dotCooCoo ba4f45e522 Merge main into feat/text-frame-options-type-tool 2026-11-12 12:45:20 -08:00
Dylan M. Taylor 1f2900fb50 Merge main into baseline grid justification PR 2026-11-12 15:29:33 -05:00
Dylan M. Taylor 3ebeb2ac96 Merge pull request #2669 from dotCooCoo/feat/object-style-text-frame-options
Object styles: a style sets its frames' paragraph styles and Text Frame General Options
2026-11-12 15:25:59 -05:00
dotCooCoo 963dc57d3b Merge main into feat/text-frame-options-type-tool 2026-11-12 12:23:08 -08:00
dotCooCoo b1ca9dd97d Merge main into feat/duplicate-layer 2026-11-12 12:23:07 -08:00
dotCooCoo 07728ede66 Merge main into fix/recovery-off-interface-thread 2026-11-12 11:26:06 -08:00
Codex 2a2d73ead9 Merge main preserving incremental composition and alpha-wrap caching 2026-11-12 19:41:39 +01:00
FredApps 17b74601fb Merge pull request #2663 from dotCooCoo/feat/alpha-channel-text-wrap
Text Wrap: Alpha Channel contours follow a transparent image's visible pixels
2026-11-12 19:38:50 +01:00
dotCooCoo 5662fefdaf Merge main into feat/duplicate-layer 2026-11-12 10:27:44 -08:00
dotCooCoo 6446622464 Merge main into feat/object-style-text-frame-options 2026-11-12 10:14:11 -08:00
dotCooCoo d9afe26fc8 Merge main into feat/type-shortcuts-carry 2026-11-12 10:10:51 -08:00
autocraft-bot[bot] 99da9632b3 Merge main into feat/text-frame-options-type-tool 2026-11-12 18:05:59 +00:00
FredApps fa671a104c Preserve latest incremental-composition documentation 2026-11-12 18:15:44 +01:00
FredApps 2348380198 Merge main and preserve PR #2663 behavior 2026-11-12 18:14:28 +01:00
FredApps 268f432385 Merge main and preserve PR #2699 behavior 2026-11-12 18:14:28 +01:00
Codex 7f8b352196 Merge main and retain shortcut and preflight documentation 2026-11-12 18:13:30 +01:00
Codex e81b2ea99e Merge main and preserve table query options and ID guidance 2026-11-12 18:13:30 +01:00
dotCooCoo 970e98fcc5 Compose: say where reuse resumes after an edit that moves lines
An edit that moves lines into other frames composes on until a paragraph
starts in the same frame and place as before, or to the story's end, as
an_edit_that_moves_lines_composes_up_to_the_next_frame_the_text_starts_in
shows. The ROADMAP line no longer cites an issue about selection lag.
2026-11-12 09:12:05 -08:00
dotCooCoo 78c06c9701 Merge main into feat/duplicate-layer 2026-11-12 09:08:34 -08:00
FredApps a5be0905dd Merge pull request #2649 from dotCooCoo/fix/merge-image-fields
Data merge: an image field in text places the image, not its path
2026-11-12 18:05:02 +01:00
FredApps 31d4c7f7f4 Merge pull request #2665 from dotCooCoo/feat/paste-clipboard-image
Paste: images on the system clipboard paste as embedded images
2026-11-12 18:03:55 +01:00
FredApps e8276337a3 Merge pull request #2354 from dotCooCoo/fix/table-story-target
Reject ambiguous table IDs across stories
2026-11-12 18:02:30 +01:00
FredApps b70472bc52 Merge pull request #2647 from dotCooCoo/feat/non-rectangular-frame-inset
Text Frame Options: a non-rectangular frame shows one Inset field
2026-11-12 18:00:15 +01:00
FredApps b7321d31b8 Merge pull request #2659 from dotCooCoo/feat/justification-auto-leading-single-word
Justification: the dialog sets Auto Leading and Single Word Justification
2026-11-12 17:58:12 +01:00
FredApps 6e50ee3974 Merge pull request #2650 from dotCooCoo/feat/paragraph-value-checks
Text: paragraph spacing and justification values are checked
2026-11-12 17:57:35 +01:00
autocraft-bot[bot] af298fadce Merge main into fix/recovery-off-interface-thread 2026-11-12 16:00:29 +00:00
dotCooCoo 329806477e Data merge: an explicit QR role in text is refused, and the caret follows each field
data.placeholder.add with role qr and the insertion point in text bound
the QR code to the first selected frame, which the caret was not in. It
now returns "qr placeholders bind to a frame", as a QR field there does.

A field inserted at the insertion point left the caret before its
marker, so a second field went in front of the first. The caret now
moves past the marker, as after typing.

Docs: docs/agents.md.
2026-11-12 07:45:10 -08:00
Adithya Shankaran 92043b4c48 Automation roots: refuse COM¹ to LPT³ and a device name before a colon (#2383)
* Automation roots: refuse COM¹ to LPT³ and a device name before a colon

is_device_name missed COM¹, COM², COM³ and LPT¹, LPT², LPT³, which Windows reserves as it does COM1.
It also cut the name only at a period, so COM1: and NUL:x were not seen as device names.

* Credit my name in the About window

* Automation roots: document the device-name tests

CodeRabbit's docstring check counts the touched tests. same_component stays without a doc comment, because #2205 deletes that function and a doc line above it conflicts.

* Automation roots: record the device-name refusal

The MCP roots description and the roadmap now name COM¹ to LPT³ and a device name before a colon.
2026-11-12 15:09:39 +00:00
dotCooCoo e22a6362cc Compose: list every case that composes a story whole in gap 20
docs/gaps.md now lists the same cases as docs/architecture.md and
reuse::plain. A doc comment on rejoin says that a run style an edit uses
for the first time stops the reuse until the old composition reaches the
same style at the same index.
2026-11-12 06:53:12 -08:00
dotCooCoo ba81cb05e9 Compose: an edit composes only the paragraphs it can change
Every edit of a story composed it from its first paragraph, so a typed
character in a long threaded story cost as much as laying out the whole
story: 456 ms in a story threaded over 300 pages.

A composition that lays every paragraph once keeps its state before each
paragraph. After an edit, composing starts one paragraph above the first
changed one, in the kept state and with the lines above copied. It stops
at the first unchanged paragraph it reaches in the state kept for that
paragraph, and copies the lines from there on with their story offsets
moved by the length of the edit.

- The cache does this when only the story differs from its entry.
- Composed whole as before: stories with footnotes, endnotes, tables,
  anchored objects, named lists, tracked deletions, balanced columns,
  vertical justification other than Top, column rules, type on a path,
  spanning or split paragraphs, paragraph borders or shading, and a
  layout that goes back over a paragraph (keep options).
- An edit that moves lines into other frames is composed to the end of
  the story.

In a 240-paragraph story a typed character composes 3 paragraphs
(240 before).

Docs: docs/architecture.md, docs/gaps.md (gap 20), ROADMAP.

Refs #2298
2026-11-12 06:21:26 -08:00
dotCooCoo fad00dd646 Data merge: an image field in a table cell or a note is refused by name
With the insertion point in a table cell or a note, data.placeholder.add
with an image field returned "a hyperlink field can't go in a table cell
or a note". It now returns a message about image fields that names the
two ways on: bind the field to a frame, or pass role text to merge its
path. Nothing is inserted on the error, and role text still puts the
marker in the cell.

Docs: docs/agents.md and the command's params text.
2026-11-12 05:58:02 -08:00