Montilla Design's Flex Layout file names its body face "Regular " (with a
trailing space, as the designer's copy of Articulat CF did). Face lookup
already ignores spacing and case, so the text is drawn in Regular, but
font.list (Find Font) compared names exactly and reported the style
missing. It now uses the lookup's comparison (designcraft_fonts::same_style).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Flex Layout container is a frame holding its objects as nested items
(as Edit › Paste Into makes), with a `flex` record: direction, wrap,
justification, cross-axis alignment, Fixed/Auto width and height, padding
and horizontal/vertical spacing. designcraft_doc::flex lays the objects
out (a Flexbox subset: lines, justification, alignment, Auto sizing), and
the engine runs it after every edit, so the container keeps its objects
in place whatever changes.
Commands: flex.add (Add to Flex Layout; detects aligned objects: their
direction, Auto size, Space Between at their own spacing, as InDesign
does), flex.convert (a group or rectangle frame), flex.remove (objects
stay, grouped), flex.set (every panel setting, plus the alignment grid
cell), flex.reorder. Resizing a container by its handles or W/H changes
its box and makes that side Fixed instead of scaling its objects;
dragging an object inside one drops it in the nearest place.
UI: Object › Flex Layout (Add to, Convert to, Remove, Show Flex Controls),
a Flex Layout panel (Window › Panels) laid out as InDesign's (Create Flex
Layout; alignment grid, W/H with Auto/Fixed; justification menu, four
directions, wrap; padding with the link button; spacing, greyed as
InDesign does when the justification works it out or nothing wraps), and
the same section in Properties. Icons are new drawings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign sets a text line when its baseline fits in the frame; the
descenders may hang below the frame's bottom. DesignCraft required the
baseline plus the descent to fit, so a frame sized to a heading's caps
oversets: Zero2Graphic's magazine tutorial draws 2.7682 cm frames for
103 pt headings (control bar, 4:12–5:44), and all three were overset.
The keep-lines IDML fixture's frames are now 236 pt tall, so they hold the
same 19 lines under either rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guard restored only the active document's content and selection, so a
command that edited through a nested successful command and then panicked
left the nested edit's undo entry (and no redo) behind, and a command that
opened or switched documents restored nothing at all. The guard now
snapshots every open document with its history and selection, the active
index and the journal, and restores them on a panic.
Regression tests: a nested edit followed by a panic leaves the history and
redo exactly as they were, and a command that opens a second document and
panics leaves only the original open.
A script whose later step failed kept the successful prefix in the document
but truncated the prefix's undo entries (and returned before the command's
aggregate undo entry was recorded), so the edits could not be undone at all.
A failed script now restores the document, selection and history from before
it started: all-or-nothing.
Regression test: frame.create followed by an unknown command is an error, the
document has no frame, nothing is left to undo, and the next edit undoes
normally. The one-undo-step success path still holds.
parse() expanded parameter entities with up to eight passes of whole-string
replacement, each pass cloning the text and re-inserting the entities'
original values. A pass count is not an output bound: a few hundred bytes of
nested entities inflate multiplicatively (a 449-byte DTD reaches ~4 MB here,
and larger chains would go to gigabytes), so a small file could exhaust
memory and CPU. Expansion now stops once it has added more than 1 MiB over
the input.
Regression test: a nested-entity DTD under 500 bytes is rejected with the
budget error, and a small inline entity still parses.
The command removed the section at a nonzero start with retain() and only then
looked it up to keep its properties, so the lookup always fell back to the
defaults: editing one field (a marker, a start number) silently reset the
style, prefix, include-prefix flag and start number. The existing section is
now read before the list is rebuilt.
Regression test: a Roman-numbered page-2 section with prefix A- and marker
First, then marker Second keeps startNumber, style, prefix and includePrefix.
Measured in Zero2Graphic's video: InDesign's placeholder paragraphs run 5,
10 (at 18 pt), 6 and 8 lines in a 5.9 cm column, about 2, 2, 3 and 3 of
DesignCraft's filler sentences. The rhythm started 3, 4, 2, 5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The panel was a row of text buttons (Add, Subtract, …, Make Compound,
Release). InDesign's has four rows of icon buttons: Paths (Join, Open,
Close, Reverse), Pathfinder, Convert Shape and Convert Point. The icons are
new drawings in icons.rs. Two engine commands back the rows that had none:
path.join (close an open path, or join two open paths at their nearest
ends) and path.convertPoints (plain, corner, smooth, symmetrical, on the
selected points or whole paths).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>