nav.xhtml had one entry per placed story, labelled with its first
paragraph (body text too), and always the title "Contents".
- Headings (h1-h6) get an id in the EPUB, and the navigation lists the
h1-h3 headings of the stories in reading order, nested by level and
linked to them. A document without headings keeps one entry per
story (its first paragraph).
- The navigation's title follows the language (Inhoud, Inhalt, Table
des matières, Índice, Indice, 目次, 目录; Contents otherwise), and
file.exportEpub takes tocTitle to set it.
Fixes#769Fixes#770
Table cell paragraphs go through the same run and inline path as body paragraphs, so deleted and moved-from text and field instructions stay out of cells, and field results, tabs and breaks come in.
Word's Normal imports as a paragraph style named Normal whose definition is w:docDefaults with Normal's own properties on top; paragraphs without a style use Word's default paragraph style. A styleMap entry can still map Normal to [Basic Paragraph].
to_bytes returns a Result and every caller propagates it, so a document
that can't be written is an error: the existing file, the unsaved state
and the recovery checkpoint stay. Asset entries near or over 4 GiB are
written with zip64 sizes. On the web, Save marks the document saved only
after the browser download has started.
Fields, buttons and video or sound are collected with the page content's
inclusion rule: the item's layer is visible and printable, and neither the
item nor any group around it is hidden or non-printing.
story_html wrote every paragraph on its own, so li paragraphs had no
list around them and each line of a pre style was its own <pre>.
Consecutive li paragraphs now share one list: ol for a numbered style,
ul for a bulleted one, and an unmarked ul (list-style:none) when the
style has no list type of its own (typed bullets). Consecutive pre
paragraphs of one style (and direction) become one <pre> with their
lines separated by newlines.
Fixes#767
Czech for Step and Repeat (Repeat, Count:, Rows:, Create as a grid),
transparency (Isolate Blending, Knockout Group, Object:, Group:),
fill/stroke commands, Reverse Path, Set Anchor, Sample Color, the
Presentation view mode and Invalid value. Removes Type/Proof Setup,
Type/Rotate Spread and Type/Separations Preview, which main no longer
uses (czech_catalog_has_no_stale_keys).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
story_html left out each anchored object's mark and the object with it,
and reading_order only sees page items, so an image anchored in a story
was in neither the EPUB nor the HTML export. The story's text is now
split at the object marks, and each anchored graphic is written in
place: inline in the paragraph, an above-line object as a block span
with its alignment. The graphic markup (and image or media file
registration) is shared with free graphics (graphic_html).
Fixes#766
InDesign draws a radial gradient in the object's bounding box: on a
non-square frame it's an ellipse reaching the frame's sides, and a
Gradient Swatch tool drag keeps those proportions. LYH Studio episode 6
(3:16) gives the left page's background a radial gradient: magenta in
the middle, cyan out to every edge. DesignCraft drew a circle reaching
only the longer side, so a portrait page stayed purple at its sides.
- doc: `Fill::radial_ellipse(bounds)`: centre and radii (default: the
box's centre and half its width and height; with a tool vector, its
start, and its length measured with the box made square).
- render: the radial paint is that circle, stretched by the paint
transform; PDF: the shading's transform does the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Swatches panel New Swatch takes what is current: a gradient
built in the Gradient panel becomes "New Gradient Swatch" (applied, and
listed), an unnamed colour a listed swatch, a selected named swatch a
"… copy". DesignCraft's button always added the same orange swatch, and
gradient swatches could not be created at all (LYH Studio episode 6,
2:12: "this is our Swatch … create a new swatch for it").
- engine: `swatch.new {swatch?, target?}` does the above for the
selection's fill (or stroke) or a named swatch; `swatch.create` also
takes `gradient: {kind?, stops: [{location, swatch | color, opacity?,
midpoint?}]}`, its stops taking colour swatches by name, as swatches
dragged onto the Gradient panel's stops.
- Swatches panel: New Swatch runs `swatch.new`, and with nothing
selected still adds a colour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The two ink passes run over the area the spread's transparent objects
(opacity, blend, effects, knockout, nested or anchored) and their
effects' reach can change, not the whole view; the rest is drawn once,
through the ordinary renderer, clipped out of that area. Objects the
area touches join it whole, so no object is drawn partly through each
colour conversion (no seam). A transparent parent-page item still
takes the whole view.
- The ink passes get the render threads (effects keep their backdrop:
with_blended_filters composites the offscreen filters with the blend).
- The view is kept in the 64 MiB cache only when the ink passes ran.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The window drags from any empty part of the bar: the gap between the
menus and the tools, and the 7 pt lower band, which is always there,
so at the 900 px minimum width (menus and tools filling the row) the
window can still be moved. Menu titles and tools keep their clicks; a
menu title pressed and dragged doesn't move the window.
- The Close button's hover fill and glyph are Tokens::caption_close and
caption_close_text instead of fixed RGB values.
- BAR_H and LOWER_BAND replace the literal 36 (drag area, caption
buttons, title centre).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening or saving a document moves it to the front of File › Open Recent
(no duplicates; Save a Copy and exports don't count). The submenu lists the
files by name with the full path as tooltip, then Clear Recent Files; the
start screen shows the last eight with their folders. A file that is gone is
dimmed and, when chosen, says so in an alert and stays listed (a disk that
isn't connected comes back). Preferences › File Handling sets how many are
kept (default 20, 0–100).
Engine: Prefs.recent_files / recent_files_max (saved in prefs.json),
file.openRecent {index}, file.recentFiles, file.clearRecent. UI:
app.openRecent; the macOS menu bar rebuilds the submenu when the list
changes.
On layouts with a dedicated + key (German) or Shift+= (US), Zoom In's
Cmd+= arrives as Key::Plus. No shortcut matched it, so egui's built-in
keyboard zoom scaled the whole UI, and the UI-scale preference reset it
on the next frame. Plus now counts as = for shortcuts, and egui's
keyboard zoom is off since the UI scale is a preference.
set() sliced `&path[..path.len() - 1]`, which panics on an empty path;
split_last() returns early instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Text Frame Options has a section list (General, Baseline
Options, Column Rules, ...). General holds Columns (Fixed Number / Fixed
Width with Number, Width, Gutter), Balance Columns, Inset Spacing as a
2x2 grid with a link button, Vertical Justification and Ignore Text
Wrap; Baseline Options holds First Baseline Offset and Min. DesignCraft
showed one flat list without the columns type, width, balance, link,
ignore-wrap or baseline settings, although the model keeps them.
- dialogs: a section list (General, Baseline Options, Column Rules);
General as above (Width shows what Fixed Number columns get, editable
for Fixed Width; a side typed while linked sets all four insets);
Baseline Options; Column Rules as before. Enum captions translated.
- OK sends the new fields only when edited, as before.
- engine: `object.textFrameOptions` takes `columnWidth` (Fixed Width)
and `firstBaselineMin`, which compose already honours.
LYH Studio episode 14 sets two columns (9:45) and a 0.1875 in inset
(10:57) here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InDesign's Text Wrap panel has the five wrap buttons with Invert, then
Top, Left, Bottom and Right offsets around a link button that makes them
all the same. DesignCraft's panel had a single Offset field that always
showed 0 (the object's offset was never read), and Invert only in
Properties.
- SelInfo carries the wrap offsets; the panel shows each side's value
in the document's units and sets one side, or all four while linked
(linked by default when they're equal).
- Invert sits next to the wrap buttons; fields are disabled without a
wrap.
LYH Studio episode 14 (11:13) opens Window › Text Wrap to give the quote
a Jump Object wrap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- designcraft-color: ICC profiles (built-in RGB working spaces, user .icc files) go through
craft-cms from storytold/craft-libs. The default CMYK working space is craft-cms's Coated
FOGRA39; CMYK swatches show relative colorimetric with the settings' black point
compensation. Generic CMYK and Device CMYK stay selectable. A CMYK profile name resolves
through Builtin::stand_in_for; a name with no stand-in is an UnknownProfile error.
ColorSettings::with_known_profiles replaces unavailable saved names with the defaults; the UI
uses it when it restores saved settings at startup. Lab, gamut error and proofing of ICC CMYK
spaces use craft-cms transforms. The Generic CMYK output profile is encoded by craft-cms.
- designcraft-pdf: the PDF/X output intent is the working CMYK space's profile: the FOGRA39
built-in with identifier FOGRA39, user profiles as loaded, Generic CMYK otherwise.
- moxcms is no longer a direct dependency of designcraft-color.