3 hours ago
astryx

v0.4.2

Astryx 0.4.2 — all @astryxdesign/* packages ship at this version.

npx astryx upgrade --apply

@astryxdesign/core

New Features

  • AvatarGroup: expose size on the avatar-group-overflow theming target so themes can style the "+N" overflow chip per size (matching avatar-fallback); the default chip font is unchanged (#5046).

  • Chat: ChatMessageBubble accepts a width prop (numbers are pixels, strings pass through, e.g. width="100%"), following the sizing convention on Card and other containers. When set it replaces the bubble's default max(80%, 280px) width cap; when unset nothing changes. Combined with variant="ghost", custom in-message content (an artifact card, attachment chips, a standalone ChatMessageMetadata) can now align with the bubble's text column at the full message-column width — previously the only workaround was hardcoding the bubble's private padding token at every call site. (#2574)

  • astryx theme template writes an annotated theme template into your project (#5048). New sibling of theme add: where add starts you from a theme we ship, template starts you from a blank annotated one. astryx init --features theme calls the same leaf, so project setup writes it too — it previously printed a one-line hint and wrote nothing, which is the weakest form of the help a theme author needs, since the first problem is not knowing the command but not knowing what the theme surface contains. The file is theme.template.ts: every defineTheme field with a note on when to reach for it, the token families, the component override syntax, and the consumption steps (providing the theme, loading the fonts you name, building for SSR), each section naming the CLI command that prints its authoritative reference. An existing file is never clobbered.

    This came out of a vibe test (#5047): agents given an annotated template reached twice as far into the theme surface as agents given only the docs (17 component targets vs 8, and the only arm to use interaction states, custom variants and onDark), and shipped a third of the contrast defects.

    A template that lies is worse than no template, so its claims are machine-checked against live sources rather than trusted: scripts/check-theme-template.test.mjs fails when a defineTheme field is added and left undocumented, when a token family is missing from the inventory, when a CSS variable or component key it names does not exist, when it cites a docs topic that does not, or when a theme source drops its SYNC reference. theme build compiles it warning-free in CI, and the CLI typecheck now covers it.

Fixes

  • Avatar: put the avatar box on the element that carries the astryx-avatar theme target, so a theme rule on the documented size axis resizes the whole avatar instead of growing the wrapper around a fixed-size circle; treat a whitespace-only name or alt as absent, so it falls through to the default icon rather than rendering an empty plate behind a blank accessible name; warn through the shared useDevWarning hook rather than a bare console.warn in the render body; and replace the phantom <OnlineIndicator /> in the JSDoc example with the real AvatarStatusDot (#5030)

  • CommandPaletteFooter: wire default keyboard-hint strings through useTranslator so they resolve from the locale catalog instead of being hardcoded English (#4506)

  • context-menu component overrides now drive the menu's internal radius and padding vars. ContextMenu.doc.mjs has always documented derived entries mapping borderRadius--_dropdown-menu-radius and padding--_dropdown-menu-padding, but derivedVarRegistry had no context-menu key, so the mapping was dead: components: {'context-menu': {base: {borderRadius: '12px'}}} emitted border-radius alone and the menu kept reading its own var(--_dropdown-menu-radius). The registry entry now matches the doc, as it already does for dropdown-menu (#4783).

  • useFocusTrap: a modal surface with no tabbable controls keeps its programmatic focus target instead of letting Tab escape into the page behind it. A dialog that places initial focus on a tabIndex={-1} heading or panel had nowhere to advance to, so Tab walked straight out of the trap. @astryxdesign/core/hooks also exports hasActiveFocusTrapEscape and isImeKeyEvent, which coordinate nested traps and skip IME composition keys (#5023).

  • Heading's type is a documented theming target, and the docs stop teaching a CSS variable that does not exist (#5016). Heading reflects type as a theme selector — typography.scale generates heading: {'type:display-1' …} rules for it — but theming.targets listed only level and color, so astryx theme build warned Unknown prop "type" on component "heading" on every theme that sets a type scale, including the shipped neutralTheme. The drift guard missed it twice over: it read a conditional spread ({level, color, ...(type && {type})}) as an unknown bag, and it only checked a component against a doc file in its own directory, so Heading/ — documented from Text/Text.doc.mjs — was never checked at all. Both are fixed, which brings three more previously unchecked directories under the guard.

    Separately, the theme docs' component-override example set --button-press-scale, which no component defines: copying it produces CSS that silently never applies. It now sets a real public var, and the example no longer declares the same button key twice.

  • DateTimeInput: the focused-and-empty time placeholder hints ("e.g., 2:30 PM" / "e.g., 14:30") now route through the i18n translator so they localize with the rest of the component. Adds @astryx.dateTimeInput.timeHint12h and @astryx.dateTimeInput.timeHint24h to the en catalog. The live-region "Invalid date" / "Invalid time" announcements this PR also covered landed first in #4363 and now reuse that PR's @astryx.dateInput.invalidDate and @astryx.timeInput.invalidTime keys. (#4546)

  • Floating layers now declare their own body type instead of inheriting it. The layer container already set font-family; it now sets font-size and line-height from --text-body-size / --text-body-leading alongside it. A layer is hosted wherever its trigger sits, so any content that did not set its own size took the ambient one — the same Tooltip, Popover or HoverCard rendered at 13px from a caption and at 20px from a lede. Content that goes through Text, or sets a size itself (Tooltip's label, DropdownMenu items, NavMenu headings), is unaffected: those already declared their own and still win. Anything that was relying on inheriting a non-body size now renders at the body size and should set one explicitly (#5064).

  • Added a @astryx.listInput.* catalog namespace to packages/core/locales/en.json so the lab ListInput component's action labels, empty state, reorder instructions, and live announcements can be translated. ListInput previously hardcoded every visible and assistive-technology-facing string (#4967).

  • Layer: use an inert <template> marker to find each context layer's actual JSX position. Safe positions stay inline; positions inside a paragraph, link, button, inline formatting, or a structurally restricted container portal to the nearest safe ancestor. Corrective portals keep CSS custom properties inheriting from that nearby host while preserving direction and writing mode, and show() passes the trigger as the popover's invoker source. The new lazyMount option waits until opening to resolve and mount content; HoverCard uses it so rich content never enters an invalid paragraph during initial render and unmounts again when hidden. Other context layers keep their existing closed-content behavior (#5039).

  • Two guards left failing on main by their own landings, so every PR since has been red through no fault of its own. #4963 gave Thumbnail's remove button a coarse-pointer hit-area var and did not document it, which the derived-var guard reads as an undocumented private var; the var is an inset on a ::after overlay, so it is documented as private and listed alongside the other vars no standard CSS property maps onto. #5026 moved borderDefaults into CoreTokenName — the landing the theme-template guard was explicitly waiting for (its comment says "when #5017 lands, this guard starts requiring the template to cover it") — so the template's token inventory now names --border-width.

  • Menus that open on hover no longer close when you click them. A hover-opened menu is already open under the cursor by the time the pointer arrives, so the click that naturally follows was dismissing it — fixed for TopNavMegaMenu in #4555, and now shared: the hover→click guard lives in useMenuHover, so TopNavMenu, TopNavHeading, SideNavHeading and DropdownMenuSubMenu get it too, and TopNavMegaMenu runs on the shared machine instead of its own copy. Also from the consolidation: opening a menu moves focus into it synchronously rather than a frame later, closing one returns focus to its trigger instead of dropping it to the document, and keyboard activation always opens rather than toggling an open menu shut (#3121)

  • SideNav: a hardening pass over the family, driven by the component audit. Accessibility, theming, passthrough and code-health defects across SideNavItem, SideNavHeading, SideNavSection, SideNavCollapseButton and the navItemStyles module the TopNav drawer modes share — the motion guards, the untranslated flyout name, the hand-rolled visually-hidden block, the dropped ...rest, the missing theming state, the uncleaned timers, and the hand-rolled hover intent, which is now the shared useMenuHover. Nav rows also adopt the shared focus outline from #4654, so a keyboard-focused row is ringed with the system's 2px --color-accent at 3px offset in every theme instead of falling through to the browser's own ring; in a split-action row the link and the chevron toggle are ringed individually, since they are separate tab stops. Three visual fixes came out of review. The collapsed submenu flyout was painting a second, square-cornered surface inside the popover's rounded one, and insetting its own content by 4px instead of standing off the rail — both gone, with the gap moved to the positioned layer where DropdownMenu keeps it. The selected row now survives forced-colors: active: it marked the current page with a 6% background tint, which forced colors flatten away entirely, and it now paints Highlight/HighlightText like ToggleButton and SegmentedControlItem. And the footer icon row comes out one size, with the collapse chevron centred rather than seated 2.42px high on a stray text baseline.

    Four changes are visible to a consumer. Hover on a collapsed item's flyout is now gated on (hover: hover) and only closes on mouseleave if hover opened it, and a click-to-dismiss no longer springs back open under a stationary pointer. The footer icon rows cascade a sm size through SizeContext, so an unsized Button passed to footerIcons now matches the built-in collapse button instead of rendering a size larger — pass an explicit size to opt out. SideNavCollapseButton takes a size, for placements outside the nav that have no row to inherit from. And SideNavCollapseButton takes the controlled collapsible config — the same {isCollapsed, onCollapsedChange} object handed to SideNav — which is how a button rendered outside the sidenav now stays in step with it. handleRef on both components is deprecated in its favour: the state the consumer already owns reaches the button through props, with no imperative handle in between.

  • Slider: the thumb no longer overhangs the component's own box at min and max. It was centred on the container edge at either extreme, leaving half of it (10px) outside the control, where a tight container clipped it or it overlapped the next element. Thumb travel is now inset by half a thumb at each end — the geometry a native input[type=range] uses — and the fill, the marks and the pointer-to-value mapping share that inset, so the thumb also stays under the pointer that grabbed it instead of jumping by up to half its width. Vertical sliders and both thumbs of a range slider are fixed the same way (#5051).

  • Interactive controls meet the WCAG 2.5.8 AA 24px minimum on touch. The Slider track (20px tall, and clickable along its whole length) floors its block size to 24px, Thumbnail's remove button grows its tappable area through a ::after overlay, and sm CheckboxInput, RadioListItem and Switch floor to a 24px target centred on the control. All of it is gated on @media (pointer: coarse), and only the invisible tappable area changes — rails, thumbs and glyphs stay exactly where they were, and fine-pointer rendering is untouched (#4963, #4964).

Documentation

  • Ten private (--_*) component theming vars are now documented in their owning component's theming.vars[]: --_avatar-group-overlap, --_card-elevation, --_card-ring, --_codeblock-gutter-width, --_item-label-color, --_item-description-color, --_tab-indicator-bottom, --_tree-indent (plus --_dropdown-menu-radius/--_dropdown-menu-padding, which Breadcrumbs sets on a child menu). They were declared in source and described nowhere, because the drift guard skipped the --_ prefix outright (#4783).

@astryxdesign/cli

New Features

  • astryx theme build warns when a theme names fonts it does not load. The resolved --font-family-* tokens and component-override fontFamily values are checked against CSS generics and known system families; anything else gets one warning per family in the receipt and, after the install instructions, the <link>/@font-face snippet to add. astryx docs typography gains a Loading Custom Fonts section (Google Fonts and self-hosted recipes, font-display: swap, real fallback stacks), and the theme docs' production-build section points at it (#5015).

  • astryx theme template writes an annotated theme template into your project (#5048). New sibling of theme add: where add starts you from a theme we ship, template starts you from a blank annotated one. astryx init --features theme calls the same leaf, so project setup writes it too — it previously printed a one-line hint and wrote nothing, which is the weakest form of the help a theme author needs, since the first problem is not knowing the command but not knowing what the theme surface contains. The file is theme.template.ts: every defineTheme field with a note on when to reach for it, the token families, the component override syntax, and the consumption steps (providing the theme, loading the fonts you name, building for SSR), each section naming the CLI command that prints its authoritative reference. An existing file is never clobbered.

    This came out of a vibe test (#5047): agents given an annotated template reached twice as far into the theme surface as agents given only the docs (17 component targets vs 8, and the only arm to use interaction states, custom variants and onDark), and shipped a third of the contrast defects.

    A template that lies is worse than no template, so its claims are machine-checked against live sources rather than trusted: scripts/check-theme-template.test.mjs fails when a defineTheme field is added and left undocumented, when a token family is missing from the inventory, when a CSS variable or component key it names does not exist, when it cites a docs topic that does not, or when a theme source drops its SYNC reference. theme build compiles it warning-free in CI, and the CLI typecheck now covers it.

Fixes

  • Heading's type is a documented theming target, and the docs stop teaching a CSS variable that does not exist (#5016). Heading reflects type as a theme selector — typography.scale generates heading: {'type:display-1' …} rules for it — but theming.targets listed only level and color, so astryx theme build warned Unknown prop "type" on component "heading" on every theme that sets a type scale, including the shipped neutralTheme. The drift guard missed it twice over: it read a conditional spread ({level, color, ...(type && {type})}) as an unknown bag, and it only checked a component against a doc file in its own directory, so Heading/ — documented from Text/Text.doc.mjs — was never checked at all. Both are fixed, which brings three more previously unchecked directories under the guard.

    Separately, the theme docs' component-override example set --button-press-scale, which no component defines: copying it produces CSS that silently never applies. It now sets a real public var, and the example no longer declares the same button key twice.

  • Two guards left failing on main by their own landings, so every PR since has been red through no fault of its own. #4963 gave Thumbnail's remove button a coarse-pointer hit-area var and did not document it, which the derived-var guard reads as an undocumented private var; the var is an inset on a ::after overlay, so it is documented as private and listed alongside the other vars no standard CSS property maps onto. #5026 moved borderDefaults into CoreTokenName — the landing the theme-template guard was explicitly waiting for (its comment says "when #5017 lands, this guard starts requiring the template to cover it") — so the template's token inventory now names --border-width.

Documentation

  • MobileNavToggle preview simulates a mobile AppShell instead of an empty stage: new playground.appShellMobile for components that render nothing without AppShell mobile context (#4983)

@astryxdesign/theme-butter

Fixes

  • --radius-none no longer overrides to 0.125rem. --radius-none and --radius-full are documented as always fixed (never scaled by a theme), matching @astryxdesign/core's own defaults — each of these themes' radius group bumps swept --radius-none along with it by mistake, the same bug fixed for theme-neutral in #4856. Anything opting out of rounding via --radius-none under these themes now renders with a true 0px radius again, instead of a silent 2px.

@astryxdesign/theme-chocolate

Fixes

  • --radius-none no longer overrides to 0.125rem. --radius-none and --radius-full are documented as always fixed (never scaled by a theme), matching @astryxdesign/core's own defaults — each of these themes' radius group bumps swept --radius-none along with it by mistake, the same bug fixed for theme-neutral in #4856. Anything opting out of rounding via --radius-none under these themes now renders with a true 0px radius again, instead of a silent 2px.

@astryxdesign/theme-gothic

Fixes

  • --radius-none no longer overrides to 0.125rem. --radius-none and --radius-full are documented as always fixed (never scaled by a theme), matching @astryxdesign/core's own defaults — each of these themes' radius group bumps swept --radius-none along with it by mistake, the same bug fixed for theme-neutral in #4856. Anything opting out of rounding via --radius-none under these themes now renders with a true 0px radius again, instead of a silent 2px.

@astryxdesign/theme-stone

Fixes

  • --radius-none no longer overrides to 0.125rem. --radius-none and --radius-full are documented as always fixed (never scaled by a theme), matching @astryxdesign/core's own defaults — each of these themes' radius group bumps swept --radius-none along with it by mistake, the same bug fixed for theme-neutral in #4856. Anything opting out of rounding via --radius-none under these themes now renders with a true 0px radius again, instead of a silent 2px.

Contributors

Thanks to everyone who contributed to this release:

@AKnassa @cixzhang @freddymeta @HelloOjasMutreja @imdreamrunner @is-jain @jiunshinn @rubyycheung

Full Changelog: https://github.com/facebook/astryx/compare/v0.4.1...v0.4.2

5 hours ago
fast-xml-parser

v5.11.0

What's Changed

New Contributors

Full Changelog: https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.10.1...v5.11.0

10 hours ago
next.js

v16.3.1-canary.20

Misc Changes

  • Wait for back-before-hydration recoveries in the browser: #97321
  • Extract metadata resolution primitives: #97388
  • test: update React 18 redbox snapshot: #97415
  • Turbopack: retain conditions when replacing resolve request keys: #97372
  • Remove server route matcher stack: #94157

Credits

Huge thanks to @gaearon, @gnoff, @timneutkens, and @mischnic for helping!

13 hours ago
officeParser

v7.6.2

v7.6.2: 🔁 Lossless Markdown Round-Trips for Code Blocks, Inline Code, Line Breaks & Tables

I am pleased to announce the release of officeParser v7.6.2! This patch closes four Markdown/HTML round-trip fidelity bugs found while driving a real editor's save → load → save cycle through officeParser: a single-line code block losing its language, inline code losing its backticks, a raw <br> being escaped, and a table header emitting invalid HTML. Each was a case where officeParser's own output did not reparse into what produced it; all four now round-trip cleanly.

These are corrections, not new behavior to guard against: the only output that moves is content that was previously lost, escaped, or emitted as invalid markup, so upgrading fixes those cases rather than disturbing working ones. If you built a workaround for any of them, you can drop it.


🔧 What's Fixed

1. Single-line code blocks keep their language

MarkdownGenerator chose fenced-vs-inline purely by whether the code text contained a newline, ignoring the language, so a one-line code block (const x = 1; tagged js) or a one-line mermaid diagram collapsed to an inline `code` span. That silently dropped both the language and its block-ness, and re-imported as an inline code mark rather than a code block. A code node is always block-level (genuinely inline code is a monospace text node), so a code node with a language now always emits as a fenced block regardless of newlines. A tagged `const x = 1;` becomes a proper js block again.

2. Inline code keeps its backticks

Inline code parses to a monospace text node, but the generator's text-node path had no backtick emission for it, so every inline `code` (and inline <code> from HTML) degraded to plain text on md → md and html → md. Monospace text is now re-wrapped in backticks, fence-sized so an embedded backtick can't close the span early, with emphasis wrapping the span so **`code`** round-trips.

3. Raw <br> round-trips symmetrically

MarkdownGenerator emits a raw <br> for a line break inside a table cell (a GFM pipe cell cannot hold a newline), but MarkdownParser did not read it back. It escaped <br> to &lt;br&gt;, destroying the break on the md → html hop, in cells and paragraphs alike. The parser now recognises <br> / <br/> / <br /> as a hard line break, symmetric with what the generator writes, so a <br> survives the round trip. A table-cell line break, ubiquitous in Word-imported forms and exams, is now preserved.

4. Valid, self-idempotent table headers

generate('html') emitted a table's header cells directly under <thead> (<thead><th>…) with no wrapping <tr>, which is invalid HTML that officeParser's own HtmlParser could not read back as a table, so a md → HTML → md round trip lost the header (its cells came back empty). The header row is now wrapped in a <tr> (<thead><tr><th>…), which is valid and self-idempotent.


📝 Also

  • Heading anchors are already toggleable. generate('md') appends a kramdown/Pandoc {#slug} suffix to headings (# Title {#title}), which GFM/CommonMark render as literal text. The existing top-level generateIds: false omits it (and the HTML heading ids). It is a generator-wide option, not under mdConfig, which made it easy to miss. Now documented in the README.

🛠 Getting Started

npm install officeparser@7.6.2

🔗 Full Changelog: View v7.6.2 details 🔗 Documentation & Visualizer: officeparser.harshankur.com

13 hours ago
embed-pdf-viewer

Release Next v3.0.0-next.4

@cloudpdf/engine@3.0.0-next.4

Minor Changes

  • #749 by @bobsingoropen({ kind: 'share' }): the engine resolves public share tokens itself.
    • The share arm exchanges shr_… for a session JWT on the engine's own transport (baseUrl + configured fetch) and delegates to the token arm, so the handle binds to a self-renewing source — revoking or editing the share retargets the open at the next renewal. Works on an engine constructed with no engine-level token at all.
    • Exchange failures surface as EngineErrors — on open() and on every later renewal (RPCs, SSE reconnects) — never as raw ShareExchangeErrors. Protected grants reject with the new EngineErrorCode.SharePasswordRequired; the wire code and HTTP status ride in details, the original error in cause. The mapping is exported as engineErrorFromShareExchange.
    • shareSessionSource now declares its concrete return type (() => Promise<string>) instead of the TokenSource union; HttpClient exposes baseUrl and fetchImpl getters.

@cloudpdf/viewer@3.0.0-next.4

Minor Changes

  • #749 by @bobsingor – Share sources pass through to the engine; the viewer-only share vocabulary is retired.
    • { kind: 'share' } is a standard OpenInput kind now, resolved by engine.open() itself — resolveCloudConfig no longer lowers share entries into token sources, and no longer re-threads baseUrl/fetch into the exchange.
    • BREAKING (prerelease line): on share sources the grant passphrase field is sharePassword (was password, which now means the PDF's own encryption password — the same slot every other kind uses). The top-level shareToken/sharePassword shorthands are unchanged.
    • CloudShareSource and CloudInitialDocument remain as deprecated aliases of OpenInputShare and InitialDocument.

@embedpdf/core-annotation@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Model carets anchored to rotated text as oriented box geometry.

    • Add caretGeomFromAnchor, which places the caret at the trailing glyph edge and derives its authoring rotation from the text baseline while preserving the previous byte-identical upright geometry.
    • Carry optional rotation on caret geometry, apply it to local-frame hit testing, and expose an oriented selection outline without enabling caret rotate or resize gestures.
  • #755 by @bobsingor – Models text-markup annotations with semantic text quads and adds oriented caret anchors, allowing highlight, underline, strikeout, squiggly, caret, and replace-text geometry to follow the selected text frame.

@embedpdf/core-geometry@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Adds semantic TextQuad geometry with corner-named transforms, bounds, rectangle conversion, positional PDF quad conversion, and resilient normalization for imported /QuadPoints.

@embedpdf/engine-core@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Add the canonical affine-aware text layout engine under text/layout: buildPageTextLayout, textGlyphAt, expandTextRangeToWord/Line, textGlyphQuad, and textSegmentsForRange, producing PdfTextSegment { quad, rect, advance }.

    Orientation frames are derived from the semantic edges of glyph quads and keyed by baseline direction and ascent handedness. Rotated and mirrored text become upright inside their frame, while shear remains an in-frame variation so mixed roman and italic text stays in one segment. Every run in a cluster uses the same canonical frame, and upright documents retain a byte-identical fast path.

  • #755 by @bobsingor – Extend the caret annotation contract with box-family rotation metadata.

    Caret DTOs, drafts, patches, and schemas now carry optional rotation and unrotatedRect fields with the same tri-state semantics as other box-family annotations. Rotation-stripped appearance documentation now includes carets.

  • #749 by @bobsingor – Adds share to the OpenInput union and a SharePasswordRequired engine error code.

    • OpenInputShare ({ kind: 'share', shareToken, sharePassword?, password? }) is the third cloud reference form, alongside id and token: a public share token from the dashboard's embed snippet, resolved by the cloud engine itself. Rejected by @embedpdf/engine, like the other cloud kinds.
    • sharePassword is the grant's passphrase (checked at exchange); password stays the PDF's own encryption password, same slot as every other kind.
    • EngineErrorCode.SharePasswordRequired is the prompt-and-retry signal for protected grants — the share sibling of DocPasswordRequired.
  • #755 by @bobsingor – Extends page geometry snapshots with an upright/rotated run union, oriented glyph cells, rotation and ascent-flip metadata, uniform quad and bounds helpers, wire schemas, and orientation conformance coverage.

@embedpdf/engine@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Returns orientation-aware page text geometry from the local engine so consumers can select and annotate rotated, sheared, and mirrored text without collapsing glyph cells into axis-aligned boxes.

Patch Changes

  • #751 by @bobsingor – Export the shared document types (OpenInput, OpenOptions, DocumentHandle, PageHandle, DocumentCapabilities, TokenSource, …) from the package root, mirroring @cloudpdf/engine, so code driving the engine directly can name them without importing from the transitive @embedpdf/engine-core dependency.

@embedpdf/engine-runtime@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Generate rotated caret appearances in the EmbedPDF PDFium runtime.

    The caret appearance generator now consumes the shared rotation metadata pair, draws in the logical unrotated box, and emits the form transform needed for the baked caret to follow its text baseline.

  • #755 by @bobsingor – Updates the EmbedPDF PDFium runtime with oriented per-character geometry and orientation-aware text-markup appearance generation for rotated, sheared, and mirrored text, while retaining safe fallbacks for malformed quads.

@embedpdf/engine-services@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Replace the parallel rects[] and quads[] geometry on SearchMatch with canonical segments: PdfTextSegment[], validated by PdfTextSegmentSchema.

    Search tokens now always encode format=segments1, preventing newer clients from consuming stale CDN-cached responses with the old geometry shape; old tokens fail decoding instead.

  • #755 by @bobsingor – Persist and render caret rotation through the engine annotation services.

    • Read and write the caret rotation and unrotatedRect metadata pair during create, patch, and list operations.
    • Treat caret subtype 14 as box-family when rendering annotation appearances, returning a rotation-stripped raster placed by the logical box so consumers do not double-rotate it after reload.
  • #755 by @bobsingor – Reads boxes, oriented cells, flags, and text orientation through the new runtime geometry call, preserving the compact upright wire shape while emitting rotated runs for non-upright glyphs. Native page-redaction failures are now reported instead of being mistaken for pages without redaction annotations.

@embedpdf/react@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Render search and selection highlights from canonical text segments. Axis-aligned lines retain their classic appearance, while rotated lines render their true oriented cells.

  • #755 by @bobsingor – Render live caret annotations with their text-baseline rotation.

    The React annotation painter now treats caret SVGs as box-family visuals, applying the caret's authoring rotation about its centre while continuing to leave vertex-geometry rotation advisory.

Patch Changes

  • #755 by @bobsingor – Renders text-selection highlights from oriented segment polygons so the React selection layer follows rotated, sheared, and mirrored text.

@embedpdf/plugin-annotation@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Round-trip rotated caret geometry through the annotation repository.

    Rotated carets now lower their logical box and content-space tilt into /Rect, rotation, and unrotatedRect, and reconstruct that geometry when engine annotations are ingested. Upright writes explicitly clear stale transform metadata.

  • #755 by @bobsingor – Creates, previews, imports, and persists text-markup annotations with oriented quads and places caret and replace-text annotations at the selected glyph's trailing edge.

@embedpdf/plugin-search@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Represent search-hit geometry as canonical segments: TextSegment[] with a precomputed bounds envelope. Search reveal now passes that envelope directly to stage.reveal(hit.pageIndex, { rect: hit.bounds }) instead of manually folding rectangles.

@embedpdf/plugin-selection@3.0.0-next.4

Minor Changes

  • #755 by @bobsingor – Use the engine's canonical text segmentation while keeping selection gestures and state in the plugin coordinate seam.

    SelectionSnapshot.pages now carries segments only, with boxes exposed as derived views through segment.rect and rectsForPage(). Public geometry exports are now buildSelectionPageGeometry, contentPointToPdf, toContentSegment, and toContentTextQuad.

  • #755 by @bobsingor – Builds selections as oriented line segments, exposes their semantic quads and reading direction, and anchors selection endpoints to glyph cells while retaining AABB access for scrolling and conservative regions.

@cloudpdf/server@3.0.0-next.4

Patch Changes

  • #750 by @bobsingor – Preserves configured CORS response headers on the hijacked server-sent events stream, allowing browser clients on permitted origins to subscribe to document layer events.

@embedpdf/plugin-redaction@3.0.0-next.4

Patch Changes

  • #755 by @bobsingor – Preserves oriented selection quads through text-redaction marks, previews, and native apply so rotated, sheared, and mirrored text can be redacted without expanding the mark to its axis-aligned bounds.

@cloudpdf/contract@3.0.0-next.4

@cloudpdf/sdk@3.0.0-next.4

@cloudpdf/viewer-react@3.0.0-next.4

@embedpdf/core-acrojs@3.0.0-next.4

@embedpdf/core-js-sandbox@3.0.0-next.4

@embedpdf/core@3.0.0-next.4

@embedpdf/core-stage@3.0.0-next.4

@embedpdf/core-ui@3.0.0-next.4

@embedpdf/engine-runtime-darwin-arm64@3.0.0-next.4

@embedpdf/engine-runtime-darwin-x64@3.0.0-next.4

@embedpdf/engine-runtime-linux-arm64@3.0.0-next.4

@embedpdf/engine-runtime-linux-x64@3.0.0-next.4

@embedpdf/engine-runtime-linuxmusl-arm64@3.0.0-next.4

@embedpdf/engine-runtime-linuxmusl-x64@3.0.0-next.4

@embedpdf/engine-runtime-wasm32@3.0.0-next.4

@embedpdf/engine-runtime-win32-arm64@3.0.0-next.4

@embedpdf/engine-runtime-win32-x64@3.0.0-next.4

@embedpdf/angular@3.0.0-next.4

@embedpdf/web@3.0.0-next.4

@embedpdf/plugin-commands@3.0.0-next.4

@embedpdf/plugin-form@3.0.0-next.4

@embedpdf/plugin-i18n@3.0.0-next.4

@embedpdf/plugin-interaction@3.0.0-next.4

@embedpdf/plugin-link@3.0.0-next.4

@embedpdf/plugin-metadata@3.0.0-next.4

@embedpdf/plugin-page-edit@3.0.0-next.4

@embedpdf/plugin-render@3.0.0-next.4

@embedpdf/plugin-shell@3.0.0-next.4

@embedpdf/plugin-stage@3.0.0-next.4

@embedpdf/plugin-stamp@3.0.0-next.4

@embedpdf/plugin-view-manager@3.0.0-next.4

@embedpdf/viewer-chrome@3.0.0-next.4

@embedpdf/viewer@3.0.0-next.4

@embedpdf/viewer-react@3.0.0-next.4

14 hours ago
plate

v53.3.6

@platejs/core

Patch Changes

  • #5098 by @NoiceHax – Fix editor.api.html.deserialize returning unwrapped text nodes at the root for inline-only HTML

@platejs/utils

Patch Changes

  • Updated @platejs/core.

platejs

Patch Changes

  • Updated @platejs/core, @platejs/utils.

Contributors

Thanks to everyone who contributed to this release:

@NoiceHax

Full changelog: v53.3.5...v53.3.6

16 hours ago
docx-editor

@docx-editor.dev/react@2.4.1

Patch Changes

  • @docx-editor.dev/i18n@2.4.1
16 hours ago
docx-editor