typograph-editor-documentation
    Preparing search index...

    Release Notes - Version 1.0.0-20260902

    • Text frames from InDesign showed the overflow marker on text that fits. A frame that InDesign had sized snugly around its own text — a heading, a label, a price — arrived here just barely too short for it, and the exclamation mark appeared on a frame that looked, and was, perfectly full. Frames sized generously were never affected, which is why it read as intermittent rather than as one fault.
    • The cause was the first line sitting lower in the frame than InDesign puts it. The distance from the top of the frame down to the first line is the font's ascent, and there are two numbers in a font that answer to that name. The browser hands over the taller one, which includes the room a font reserves above its capitals for accents; InDesign uses the other. The gap is about a sixth of the type size — for 16pt text, close to a millimetre — and it pushed the last line of a snug frame just past the bottom edge.
    • The first line is now placed with the same measurement InDesign uses, taken from the font file itself rather than from the browser.
    • Text moves up when a document is opened, by that same amount. This is the second time this measurement has changed: the 2026-08-27 notes said text would move down, and it did, by more than it should have. This release settles it where InDesign has it. A frame that was nudged by hand to compensate for either shift — vertical alignment changed, or the frame dragged — wants that nudge looked at again.
    • A frame sized to exactly fit its text no longer flags at random. Where a frame's height and its text came out to the same measurement by two different routes, the two numbers could differ in the last decimal place and the frame was called overfull on a difference far smaller than a pixel. A Georgia heading at 120pt was doing this. Frames that genuinely overflow are unaffected — they run past their bottom edge by whole lines, not by fractions of nothing.
    • A font that cannot supply the measurement still works and now says so in the browser console, naming the font. Its first line keeps the old placement, so it will sit slightly low; nothing else about it changes.
    • Comments. A reviewer can be given comment access to a document and leave feedback pinned to a spot on a page — a reply thread per pin, resolve when it is dealt with, reopen if it was not, and edit or delete their own words. Pins stay on the spot they were placed as the page is zoomed, scrolled and panned, and follow the page they belong to rather than appearing on every one.
    • A mode control in the top bar next to Share, reading Editing or Commenting, with the alternative behind it. It replaces the access chip that used to sit beside the document name: both answered the same question — what am I allowed to do here — and one control answers it where it can be acted on. Someone with comment access sees a label rather than a menu, and a reader with view access sees "View only". Someone with comment access sees it locked to Commenting, with a tooltip saying so, and the drawing and text tools are gone rather than present and inert — a toolbar that is there but does nothing reads as a broken editor.
    • The commenting surface follows Google Drive, which is the version of this most reviewers have already used. Each pin carries the author's face; the panel lists the threads as cards, with the open one expanded and the rest showing two lines and their reply count. Pointing at a pin lights up its card, and pointing at a card lights up its pin, so it is always clear which remark belongs to which spot on the page.
    • Clicking the page drops the pin straight away and opens the box to type in, rather than waiting for the text to be sent. Escape removes the draft and the pin with it, ⌘/Ctrl + Enter sends, and ⌘/Ctrl + Alt + M starts a comment in the middle of the page currently on screen.
    • The comment panel stays closed until it is asked for, through the Comments button beside the mode control, by clicking a pin, or by starting a comment. It carries the number of open threads, so a page with feedback says so without spending canvas on it. Escape or the ✕ closes it again.
    • Resolve is the tick on an open thread; edit and delete sit behind its ⋮ menu and appear only on the reader's own comment or reply. The filter at the top of the panel switches between the open threads and all of them.
    • A read-only reader now gets a document that behaves like one: the canvas does not respond to editing, the drawing tools, the page properties panel and the add-page tile are all gone, and the toolbar reads "View only". Previously a reader with view access saw a fully live editor whose changes could never be saved.
    • Resolved threads leave the panel and their pins disappear. "Show resolved" brings them back, greyed, with a Reopen next to each.
    • Nothing changes for a host that does not ask for any of this. The mode control is not drawn and no comment interface exists until the embedding application turns it on.
    • The value is OS/2.sTypoAscender from the font binary, read as the face loads. Every path that builds a font face records it, so a font arrives measured the same way whether it came with a document or from the font library.
    • fontBoundingBoxAscent is not merely the wrong one of the two — the browser also rounds it to a whole pixel, so a single font reports a different ratio at different point sizes. Nothing that needs to agree with InDesign should be derived from it.
    • The fits-in-the-frame comparisons carry a millionth-of-a-pixel guard. It is a floating point equality guard and not a typographic tolerance: the smallest real overflow is a fraction of a line, several orders of magnitude above it. It is applied to the drawing clip as well as to the overflow test, because a frame that reported it fits while its last line was clipped would lose text with nothing to say so.
    • PDFs need no change. The generator draws from the baselines stored in the document rather than computing its own, and those come from the same calculation, so the page and the PDF cannot disagree.
    • A stored document keeps the layout it was saved with. An existing template renders as it did until it is opened and saved again, at which point it takes the corrected placement.
    • Comments are additive to the EditorUI API and off by default. set_available_modes() decides whether the mode control is drawn at all — its default, ['editing'], draws nothing — and set_comment_source() decides whether any comment interface exists. An embedder that calls neither gets the previous bundle's behaviour exactly.
    • set_available_modes() takes { render: false } for a host that draws the mode control itself, and set_comments_open() / get_comments_open() / toggle_comments() drive the rail from outside. typograph_comments_toggled reports the rail's state and its thread count so a host button can follow it. An embedder that passes neither keeps the widget-drawn control.
    • 'viewing' is a third mode, for a host whose user may only read. It mutes the canvas and hides the authoring surface without offering any comment interface. The parameter bar and the add-page tile are hidden by container rather than by key, because both rebuild themselves on selection and would otherwise reappear. An empty mode list still means "editing", so nothing changes for an embedder that passes one.
    • The comment interface carries a typograph-comments class on each of its three roots, and every rule in the stylesheet is written through it. A host that resets colour across the editor — the Typograph portal does, with main.main > .content * { color: inherit }, to keep its own theme out — outranks a single-class rule, and the panel rendered with black buttons and black pin initials until the widget's own rules were given the higher specificity they need.
    • select_comment(id) no longer needs the threads to have arrived. An id the widget does not know yet is remembered and opened when the first list() resolves, which is what a deep link from a notification needs — a host timeout raced the network.
    • The editor still knows nothing about files. It performs no requests of its own for comments: the host registers eight async functions and owns every read and write, the same division that keeps saving out of this repo. There is no URL and no access token anywhere in the bundle.
    • A comment is anchored to a page uuid plus x/y in native millimetres, not to an element and not to screen pixels. Millimetres are what make a pin survive a zoom change; the page uuid is what makes it survive a page being inserted or reordered ahead of it. A pin does not follow an element that moves underneath it — that is Figma's behaviour rather than Google Docs', and it is deliberate: it also allows commenting on empty space, which anchoring to an element would not.
    • Pins are positioned from canvas_view on an animation frame, because canvas fires no event when the view moves. Zoom, scroll, pan and a window resize all move the pins and none of them announce themselves. The loop compares the view against the last one it drew and writes nothing when they match, so an idle editor does no layout work.
    • Writes are optimistic and roll back. A pin is drawn before the host has acknowledged it and removed again if the host rejects it, which is why every mutator snapshots its state first.
    • See docs/API-EditorUI.md for the full surface: set_available_modes, set_mode, get_mode, set_comment_source, set_current_user, refresh_comments, select_comment, and the typograph_mode_changed / typograph_comment_* events.