4 hours ago
etherpad

v3.3.2

3.3.2

3.3.2 is a bug-fix and dependency-hardening follow-up to 3.3.1. It rounds out the pad-deletion UX rework (suppressing the recovery token for durable identities, keeping the token-less Delete button reachable, and closing a read-only deletion hole), restores the saved-revision markers that went missing from in-pad history mode in 3.3.x, and adds env-var overrides so air-gapped installs can switch off Etherpad's outbound calls without editing the image. It also fixes the migrateDB / importSqlFile / migrateDirtyDBtoRealDB CLI scripts against the promise-based ueberdb2 API, rejects unreachable ./.. pad ids, and clears a batch of dependency security advisories (including CVE-2026-54285). On the CI side it unblocks the installer smoke test (which had been hanging the full 6-hour job ceiling since 3.2.0) and pins ueberdb2 past a startup-exit regression in the packaged boot.

Security

  • Force @opentelemetry/core ≥ 2.8.0 (GHSA-8988-4f7v-96qf / CVE-2026-54285, #7975). The transitive dep (pulled in via @elastic/elasticsearch@elastic/transport) had a W3CBaggagePropagator.extract() that did not enforce W3C size limits on inbound baggage headers, allowing unbounded memory allocation. Pinned via a pnpm-workspace.yaml override; satisfies the existing 2.x range with no parent bump.
  • Resolve open Dependabot security alerts (#7967). Refreshes stale override floors and adds new ones via pnpm-workspace overrides: form-data ≥ 4.0.6, ws ≥ 8.21.0, esbuild ≥ 0.28.1, basic-ftp ≥ 5.3.1 (capped <6.0.0 to avoid a surprise major on the plugin-install path), tar ≥ 7.5.16, js-yaml ≥ 4.2.0, qs ≥ 6.15.2, ip-address ≥ 10.1.1, and @babel/core ≥ 7.29.6.
  • Reject read-only deletion via token-less paths (part of #7959 / #7960). Under allowPadDeletionByAllUsers a read-only viewer was granted canDeletePad=true, and the server's flagOk/creatorOk branches never checked session.readonly — so a read-only link holder could delete a pad without a token. Read-only sessions are now excluded from both the client var and the server's token-less authorization paths; a valid recovery token stays sufficient regardless of session mode.

Notable enhancements

  • Pad deletion — suppress the recovery token for durable identities and relabel the action (#7926 / #7930). Building on the allowPadDeletionByAllUsers suppression, a creator's deletion token is now also withheld when they have a durable identity — authenticated (req.session.user with a username) and the deployment pins that identity to a stable authorID via a getAuthorId hook — since only then does the creator survive a cookie clear or a different device, making the token redundant. This tightens the previous "require authentication ⇒ always suppress" rule: without getAuthorId the authorID still comes from the per-browser cookie, so an authenticated user on a second device is not the creator and keeps getting a token. A new canDeleteWithoutToken client var hides the whole recovery-token disclosure (label, field, submit) when no token is needed, and the recovery form now renders for all sessions (hidden by default) so an authenticated creator without a durable mapping still has UI to enter their token. API.createPad returns a null deletionToken under allowPadDeletionByAllUsers, matching the socket/UI path.
  • Offline/air-gapped installs — env-var overrides for the update check, plugin catalog, and updater (#7917, addresses #7911). Firewalled deployments could not disable Etherpad's outbound calls without editing settings.json inside the image. The relevant keys are now wired through the ${ENV:default} substitution in settings.json.docker and settings.json.template: PRIVACY_UPDATE_CHECK, PRIVACY_PLUGIN_CATALOG, UPDATES_TIER (off = no calls), UPDATE_SERVER, plus the docker-only UPDATES_SOURCE / UPDATES_CHANNEL / UPDATES_CHECK_INTERVAL_HOURS / UPDATES_GITHUB_REPO / UPDATES_REQUIRE_ADMIN_FOR_STATUS. A new "Updates & privacy" section in doc/docker.md documents the set; backend tests parse the shipped configs and fail if the ${ENV} placeholders are dropped. Config, docs, and tests only — no runtime code change.

Notable fixes

  • Pad — keep the token-less Delete button reachable without pad-wide settings (#7959 / #7960). The token-less #delete-pad button was nested inside the enablePadWideSettings-gated section, so disabling pad-wide settings removed the only no-token deletion path — and combined with #7926 hiding the token disclosure when no token is needed, a user allowed to delete could be left with no deletion UI at all. The button is now always rendered (hidden by default) and driven by a canDeletePad client var (creator or allowPadDeletionByAllUsers, excluding read-only sessions), so the plain button and the recovery-token disclosure are mutually coherent and neither depends on pad-wide settings.
  • History mode — restore the saved-revision markers (#7946 / #7948). When #7659 moved the timeslider into the pad as an embedded iframe, the user-facing control became the outer #history-slider-input, but the saved-revision stars were still drawn into the now-hidden iframe #ui-slider-bar, so "Save Revision" appeared to do nothing in in-pad history mode (a 3.3.x regression). pad_mode.ts now bridges the embedded slider's saved revisions onto the outer slider as percentage-positioned, aria-hidden star markers (with click-to-seek for mouse users), and the server's SAVE_REVISION handler broadcasts NEW_SAVEDREV to the pad room so a revision saved by a collaborator appears live on an already-open history slider. A single revision saved at rev 0 now renders too. Adds Playwright coverage for both the single-client and two-client live paths.
  • Import dialog — correct the outdated "no converter" help message (#7988 / #7989). The notice claimed only plain text and HTML could be imported and linked to the legacy AbiWord wiki, prompting LibreOffice installs for formats that already work natively. Etherpad imports .txt, .html, .docx (via mammoth) and .etherpad without LibreOffice; only .pdf/.odt/.doc/.rtf still need it. The message now says so and points at the documentation site.
  • PadManager — reject unreachable . and .. pad ids (#7962). isValidPadId accepted ids consisting only of URL dot-segments, but per the WHATWG URL standard a browser normalises /p/. to /p/ and /p/.. to /, so such a pad could be created in the database yet never opened or exported. These ids are now rejected, and the admin deletePad handler falls back to a raw key purge when getPad() throws so any legacy ./.. pad can still be removed.

Internal / contributor-facing

  • CLI — fix the database migration/import scripts against the ueberdb2 promise API (#7982 / #7983). migrateDB.ts opened source and target databases, copied all keys, then resolved without closing either — so under ueberdb2 6.1.x the keep-alive timer kept the process hanging after "Done syncing dbs", and buffered target writes were only guaranteed flushed on close(). It now closes both databases (flushing writes, clearing the timer) on success and error paths and exits with an explicit status. importSqlFile.ts and migrateDirtyDBtoRealDB.ts were ported off the pre-v6 callback API to await db.init() / db.set(k, v) / db.close(), removing two @ts-ignores that hid broken calls and fixing an undefined length in a progress log; tsc --noEmit on the bin package is now clean.
  • CI — stop the installer smoke test hanging the 6-hour job ceiling (#7981). The "Installer test" had hung on every ubuntu/macOS run since 3.2.0: pnpm run prod is a nested launcher, so kill "$PID"; wait "$PID" only signalled the outer pnpm and blocked forever if the node server didn't exit on SIGTERM. Teardown now runs the launcher in its own process group, kills the whole group (SIGTERM then SIGKILL), drops the blocking wait, and adds an 8-minute timeout-minutes backstop to both smoke steps.
  • CI — run the Debian-package smoke test on PRs (#7969). The packaged-boot smoke test previously ran only on push to develop — i.e. after merge — which is why the ueberdb2 startup-exit regression turned develop red instead of being blocked at PR time. A pull_request trigger (scoped to production-footprint paths) now runs the build+smoke job on PRs; the release/apt-publish jobs stay tag-guarded.
  • Release — park the non-functional ep_etherpad npm publish (#7922). The releaseEtherpad workflow republished ./src as ep_etherpad, a package with zero dependents that nothing in the repo or any deployment path consumes, and it had been failing with E404 (no OIDC trusted publisher configured). The job is now gated behind an explicit confirm: true dispatch input so a stray run fails fast with a clear message, with the status documented in the workflow header and AGENTS.MD.
  • Tests — port the orphaned legacy timeslider specs to Playwright (#7949). The src/tests/frontend/specs/ mocha suite is run by no CI workflow, so its timeslider coverage was dead — which is how the #7946 history-mode regression reached a release. The still-meaningful cases (revision labels, export links, deep-link entry) were ported to frontend-new Playwright specs re-targeted at the real in-pad UI, and the three now-ported legacy specs were deleted.

Dependencies

  • ueberdb2 pinned to 6.1.13. 6.1.10 rewrote the cache/buffer layer to lazily arm an .unref()'d flush timer only when there are dirty keys, so on a fresh empty dirty DB nothing anchored Node's event loop and the packaged (.deb/systemd) boot could exit cleanly (code 0) before server.listen() bound the port — failing the Debian-package health check. The dep was pinned back to the last green release (6.1.9, #7969) and then rolled forward to the now-fixed 6.1.13 (#7979), pinned exactly rather than with a caret.
  • nodemailer 8.x → 9.0.1 (#7965 / #7950 / #7976), mongodb 7.1.1 → 7.3.0 (#7941), pg 8.21.0 → 8.22.0 (#7985), undici → 8.5.0 (#7980 etc.), oidc-provider 9.8.4 → 9.8.5 (#7973), pdfkit 0.19.0 → 0.19.1 (#7945), semver 7.8.3 → 7.8.4 (#7943), and @radix-ui/react-switch 1.3.0 → 1.3.1 (#7974).
  • Dev/build dependency group updates (#7964, #7970, #7978, #7987, #7944, #7951, #7952, and others), including @types/node 25 → 26, esbuild 0.28.0 → 0.28.1, eslint 10.4.1 → 10.5.0, @playwright/test 1.60 → 1.61, vitest 4.1.8 → 4.1.9, and actions/checkout 6 → 7 (#7977).
4 hours ago
etherpad-lite

v3.3.2

3.3.2

3.3.2 is a bug-fix and dependency-hardening follow-up to 3.3.1. It rounds out the pad-deletion UX rework (suppressing the recovery token for durable identities, keeping the token-less Delete button reachable, and closing a read-only deletion hole), restores the saved-revision markers that went missing from in-pad history mode in 3.3.x, and adds env-var overrides so air-gapped installs can switch off Etherpad's outbound calls without editing the image. It also fixes the migrateDB / importSqlFile / migrateDirtyDBtoRealDB CLI scripts against the promise-based ueberdb2 API, rejects unreachable ./.. pad ids, and clears a batch of dependency security advisories (including CVE-2026-54285). On the CI side it unblocks the installer smoke test (which had been hanging the full 6-hour job ceiling since 3.2.0) and pins ueberdb2 past a startup-exit regression in the packaged boot.

Security

  • Force @opentelemetry/core ≥ 2.8.0 (GHSA-8988-4f7v-96qf / CVE-2026-54285, #7975). The transitive dep (pulled in via @elastic/elasticsearch@elastic/transport) had a W3CBaggagePropagator.extract() that did not enforce W3C size limits on inbound baggage headers, allowing unbounded memory allocation. Pinned via a pnpm-workspace.yaml override; satisfies the existing 2.x range with no parent bump.
  • Resolve open Dependabot security alerts (#7967). Refreshes stale override floors and adds new ones via pnpm-workspace overrides: form-data ≥ 4.0.6, ws ≥ 8.21.0, esbuild ≥ 0.28.1, basic-ftp ≥ 5.3.1 (capped <6.0.0 to avoid a surprise major on the plugin-install path), tar ≥ 7.5.16, js-yaml ≥ 4.2.0, qs ≥ 6.15.2, ip-address ≥ 10.1.1, and @babel/core ≥ 7.29.6.
  • Reject read-only deletion via token-less paths (part of #7959 / #7960). Under allowPadDeletionByAllUsers a read-only viewer was granted canDeletePad=true, and the server's flagOk/creatorOk branches never checked session.readonly — so a read-only link holder could delete a pad without a token. Read-only sessions are now excluded from both the client var and the server's token-less authorization paths; a valid recovery token stays sufficient regardless of session mode.

Notable enhancements

  • Pad deletion — suppress the recovery token for durable identities and relabel the action (#7926 / #7930). Building on the allowPadDeletionByAllUsers suppression, a creator's deletion token is now also withheld when they have a durable identity — authenticated (req.session.user with a username) and the deployment pins that identity to a stable authorID via a getAuthorId hook — since only then does the creator survive a cookie clear or a different device, making the token redundant. This tightens the previous "require authentication ⇒ always suppress" rule: without getAuthorId the authorID still comes from the per-browser cookie, so an authenticated user on a second device is not the creator and keeps getting a token. A new canDeleteWithoutToken client var hides the whole recovery-token disclosure (label, field, submit) when no token is needed, and the recovery form now renders for all sessions (hidden by default) so an authenticated creator without a durable mapping still has UI to enter their token. API.createPad returns a null deletionToken under allowPadDeletionByAllUsers, matching the socket/UI path.
  • Offline/air-gapped installs — env-var overrides for the update check, plugin catalog, and updater (#7917, addresses #7911). Firewalled deployments could not disable Etherpad's outbound calls without editing settings.json inside the image. The relevant keys are now wired through the ${ENV:default} substitution in settings.json.docker and settings.json.template: PRIVACY_UPDATE_CHECK, PRIVACY_PLUGIN_CATALOG, UPDATES_TIER (off = no calls), UPDATE_SERVER, plus the docker-only UPDATES_SOURCE / UPDATES_CHANNEL / UPDATES_CHECK_INTERVAL_HOURS / UPDATES_GITHUB_REPO / UPDATES_REQUIRE_ADMIN_FOR_STATUS. A new "Updates & privacy" section in doc/docker.md documents the set; backend tests parse the shipped configs and fail if the ${ENV} placeholders are dropped. Config, docs, and tests only — no runtime code change.

Notable fixes

  • Pad — keep the token-less Delete button reachable without pad-wide settings (#7959 / #7960). The token-less #delete-pad button was nested inside the enablePadWideSettings-gated section, so disabling pad-wide settings removed the only no-token deletion path — and combined with #7926 hiding the token disclosure when no token is needed, a user allowed to delete could be left with no deletion UI at all. The button is now always rendered (hidden by default) and driven by a canDeletePad client var (creator or allowPadDeletionByAllUsers, excluding read-only sessions), so the plain button and the recovery-token disclosure are mutually coherent and neither depends on pad-wide settings.
  • History mode — restore the saved-revision markers (#7946 / #7948). When #7659 moved the timeslider into the pad as an embedded iframe, the user-facing control became the outer #history-slider-input, but the saved-revision stars were still drawn into the now-hidden iframe #ui-slider-bar, so "Save Revision" appeared to do nothing in in-pad history mode (a 3.3.x regression). pad_mode.ts now bridges the embedded slider's saved revisions onto the outer slider as percentage-positioned, aria-hidden star markers (with click-to-seek for mouse users), and the server's SAVE_REVISION handler broadcasts NEW_SAVEDREV to the pad room so a revision saved by a collaborator appears live on an already-open history slider. A single revision saved at rev 0 now renders too. Adds Playwright coverage for both the single-client and two-client live paths.
  • Import dialog — correct the outdated "no converter" help message (#7988 / #7989). The notice claimed only plain text and HTML could be imported and linked to the legacy AbiWord wiki, prompting LibreOffice installs for formats that already work natively. Etherpad imports .txt, .html, .docx (via mammoth) and .etherpad without LibreOffice; only .pdf/.odt/.doc/.rtf still need it. The message now says so and points at the documentation site.
  • PadManager — reject unreachable . and .. pad ids (#7962). isValidPadId accepted ids consisting only of URL dot-segments, but per the WHATWG URL standard a browser normalises /p/. to /p/ and /p/.. to /, so such a pad could be created in the database yet never opened or exported. These ids are now rejected, and the admin deletePad handler falls back to a raw key purge when getPad() throws so any legacy ./.. pad can still be removed.

Internal / contributor-facing

  • CLI — fix the database migration/import scripts against the ueberdb2 promise API (#7982 / #7983). migrateDB.ts opened source and target databases, copied all keys, then resolved without closing either — so under ueberdb2 6.1.x the keep-alive timer kept the process hanging after "Done syncing dbs", and buffered target writes were only guaranteed flushed on close(). It now closes both databases (flushing writes, clearing the timer) on success and error paths and exits with an explicit status. importSqlFile.ts and migrateDirtyDBtoRealDB.ts were ported off the pre-v6 callback API to await db.init() / db.set(k, v) / db.close(), removing two @ts-ignores that hid broken calls and fixing an undefined length in a progress log; tsc --noEmit on the bin package is now clean.
  • CI — stop the installer smoke test hanging the 6-hour job ceiling (#7981). The "Installer test" had hung on every ubuntu/macOS run since 3.2.0: pnpm run prod is a nested launcher, so kill "$PID"; wait "$PID" only signalled the outer pnpm and blocked forever if the node server didn't exit on SIGTERM. Teardown now runs the launcher in its own process group, kills the whole group (SIGTERM then SIGKILL), drops the blocking wait, and adds an 8-minute timeout-minutes backstop to both smoke steps.
  • CI — run the Debian-package smoke test on PRs (#7969). The packaged-boot smoke test previously ran only on push to develop — i.e. after merge — which is why the ueberdb2 startup-exit regression turned develop red instead of being blocked at PR time. A pull_request trigger (scoped to production-footprint paths) now runs the build+smoke job on PRs; the release/apt-publish jobs stay tag-guarded.
  • Release — park the non-functional ep_etherpad npm publish (#7922). The releaseEtherpad workflow republished ./src as ep_etherpad, a package with zero dependents that nothing in the repo or any deployment path consumes, and it had been failing with E404 (no OIDC trusted publisher configured). The job is now gated behind an explicit confirm: true dispatch input so a stray run fails fast with a clear message, with the status documented in the workflow header and AGENTS.MD.
  • Tests — port the orphaned legacy timeslider specs to Playwright (#7949). The src/tests/frontend/specs/ mocha suite is run by no CI workflow, so its timeslider coverage was dead — which is how the #7946 history-mode regression reached a release. The still-meaningful cases (revision labels, export links, deep-link entry) were ported to frontend-new Playwright specs re-targeted at the real in-pad UI, and the three now-ported legacy specs were deleted.

Dependencies

  • ueberdb2 pinned to 6.1.13. 6.1.10 rewrote the cache/buffer layer to lazily arm an .unref()'d flush timer only when there are dirty keys, so on a fresh empty dirty DB nothing anchored Node's event loop and the packaged (.deb/systemd) boot could exit cleanly (code 0) before server.listen() bound the port — failing the Debian-package health check. The dep was pinned back to the last green release (6.1.9, #7969) and then rolled forward to the now-fixed 6.1.13 (#7979), pinned exactly rather than with a caret.
  • nodemailer 8.x → 9.0.1 (#7965 / #7950 / #7976), mongodb 7.1.1 → 7.3.0 (#7941), pg 8.21.0 → 8.22.0 (#7985), undici → 8.5.0 (#7980 etc.), oidc-provider 9.8.4 → 9.8.5 (#7973), pdfkit 0.19.0 → 0.19.1 (#7945), semver 7.8.3 → 7.8.4 (#7943), and @radix-ui/react-switch 1.3.0 → 1.3.1 (#7974).
  • Dev/build dependency group updates (#7964, #7970, #7978, #7987, #7944, #7951, #7952, and others), including @types/node 25 → 26, esbuild 0.28.0 → 0.28.1, eslint 10.4.1 → 10.5.0, @playwright/test 1.60 → 1.61, vitest 4.1.8 → 4.1.9, and actions/checkout 6 → 7 (#7977).
5 hours ago
react-image-crop

11.1.2

6 hours ago
axios

v1.18.1

v1.18.1 — June 21, 2026

This release focuses on Node HTTP adapter fixes, safer AxiosError serialisation, runtime/type correctness fixes, documentation updates, and dependency maintenance.

🐛 Bug Fixes

  • AxiosError Serialisation: Made AxiosError#cause non-enumerable to prevent circular JSON serialisation failures when errors include nested causes. (#10913)
  • Node HTTP Adapter: Guarded socket.setKeepAlive for proxy agent streams, accepted path-only URLs when socketPath is configured, deferred environment proxy handling to Node, and explicitly passed maxBodyLength through to follow-redirects. (#10917, #10930, #10942, #10993)
  • Runtime and Type Correctness: Fixed several runtime crashes, type definition mismatches, and incorrect error handling paths. (#10959, #11021)
  • AxiosURLSearchParams: Switched the encoder callback to an arrow function so encoder.call(this) receives the AxiosURLSearchParams instance correctly. (#11019)

🔧 Maintenance & Chores

  • Documentation: Documented sensitive headers and status transition behaviour, prepared cleaned-up docs, added Deno install instructions, and clarified that request data is request-specific (#11007, #11010, #11023, #11025)

  • Dependencies: Bumped vite, rollup, form-data, js-yaml, and multer across the root project, docs, smoke tests, and module test workspaces. (#11011, #11012, #11013, #11014, #11015, #11016, #11017, #11026)

🌟 New Contributors

We are thrilled to welcome our new contributors. Thank you for helping improve axios:

  • @webdevelopersrinu (#10913)
  • @sijie-Z (#10993)
  • @bartlomieju (#11023)
  • @JSap0914 (#11019)

Full Changelog

7 hours ago
docx-editor

@eigenpal/docx-editor-i18n@1.9.0

Patch Changes

  • 28876a2: Make regular expressions over file- and library-supplied strings run in linear time and escape quoted font names completely. The variable-detection, plural-message, and core-properties date regexes no longer backtrack polynomially on hostile input, and font family names are now backslash-escaped before being wrapped in a quoted CSS string so a crafted DOCX font name cannot break out of it.
7 hours ago
docx-editor

@eigenpal/docx-editor-react@1.9.0

Patch Changes

  • f61435b: Harden openPrintWindow to build the print window via DOM APIs instead of document.write, so a crafted document title cannot break out into executable markup. The framework-agnostic print helpers are now exported from @eigenpal/docx-editor-core as the single source of truth, and the React package re-exports them unchanged.
  • 791b132: Remove two potential slow-input denial-of-service paths in the React adapter. The data URL MIME parser now uses index math instead of a backtracking regex, and the toolbar test-id helper no longer scans across unmatched parentheses, so neither degrades on long crafted input.
  • Updated dependencies [4b47daf]
  • Updated dependencies [9144b69]
  • Updated dependencies [826aa32]
  • Updated dependencies [826aa32]
  • Updated dependencies [12c1f87]
  • Updated dependencies [7839ee9]
  • Updated dependencies [826aa32]
  • Updated dependencies [9454c9a]
  • Updated dependencies [f61435b]
  • Updated dependencies [28876a2]
    • @eigenpal/docx-editor-core@1.9.0
    • @eigenpal/docx-editor-i18n@1.9.0
    • @eigenpal/docx-editor-agents@1.9.0
7 hours ago
docx-editor

@eigenpal/docx-editor-vue@1.9.0

Patch Changes

  • Updated dependencies [4b47daf]
  • Updated dependencies [9144b69]
  • Updated dependencies [826aa32]
  • Updated dependencies [826aa32]
  • Updated dependencies [12c1f87]
  • Updated dependencies [7839ee9]
  • Updated dependencies [826aa32]
  • Updated dependencies [9454c9a]
  • Updated dependencies [f61435b]
  • Updated dependencies [28876a2]
    • @eigenpal/docx-editor-core@1.9.0
    • @eigenpal/docx-editor-i18n@1.9.0
    • @eigenpal/docx-editor-agents@1.9.0
7 hours ago
docx-editor

@eigenpal/nuxt-docx-editor@1.9.0

Patch Changes

  • @eigenpal/docx-editor-vue@1.9.0
7 hours ago
docx-editor

@eigenpal/docx-editor-core@1.9.0

Minor Changes

  • 826aa32: Add an { all: true } option to setContentControlContent, setContentControlValue, and removeContentControl to apply the change to every content control matching the filter — across headers and footers with { includeHeadersFooters: true } — instead of only the first. This covers one logical value that recurs under a shared tag (e.g. a name in the body, a running header, and several table cells). The default stays first-match. An { all: true } run is atomic: if any matched control is refused by a lock, type, or data-binding guard, nothing is written unless { force: true }.

  • 826aa32: Add createContentControl to wrap a text span (including inside a table cell) in a new content control, returning a new document plus the created control with an auto-assigned unique w:id. setContentControlValue now sets dropdown/date/checkbox values on inline controls too, including inside table cells and — with { includeHeadersFooters: true } — headers and footers. Date controls serialize their format to <w:dateFormat>.

  • 826aa32: Content-control addressing now covers inline (w:sdt-in-paragraph) controls, including inside table cells: findContentControls, findContentControl, setContentControlContent, setContentControlValue, and removeContentControl discover and edit them, and { includeHeadersFooters: true } also reaches headers and footers. Results carry kind and location. The live-editor DocxEditorRef methods (React and Vue) gain the same inline support.

    Because of this, findContentControls now returns inline controls in the body that earlier versions skipped — code relying on the old block-only results (counts, first match) should re-check.

Patch Changes

  • 4b47daf: Chinese, Korean, and Japanese documents now render and measure with the matching Noto webfont instead of a system fallback. CJK theme typefaces — by their native or romanized name (e.g. SimSun, Malgun Gothic, PMingLiU, MS Mincho) — map to the corresponding Noto Sans/Serif SC/TC/KR/JP family, and the font loader fetches that family rather than the unresolvable raw name.
  • 9144b69: Harden clipboard HTML paste against script injection and slow-input denial of service. Pasted HTML is now sanitized (via DOMPurify) and parsed into an inert document instead of being assigned to innerHTML, so embedded scripts, event handlers, and javascript: URLs cannot run. Word comment stripping and Office/Word namespace-tag removal now use linear scans that cannot backtrack on hostile input or leave a stray comment opener behind.
  • 12c1f87: Fix export corruption for comments overlapping tracked changes.
  • 7839ee9: Fix CJK text overflowing the right margin when a document's theme leaves the East Asian font slot empty. The East Asian theme font is now resolved from the document's w:themeFontLang (e.g. Japanese → MS Mincho), so line breaking and rendering use the correct font and wrap within the page.
  • 9454c9a: Preserve explicit nil/none borders on export. A cell that hides the table's default grid by setting <w:tcBorders> sides to nil no longer loses that override on save, so hidden gridlines stay hidden after a round-trip instead of re-inheriting the table's grid. The same applies to paragraph (w:pBdr) and page (w:pgBorders) borders, which had the identical bug. Fixes #947.
  • f61435b: Harden openPrintWindow to build the print window via DOM APIs instead of document.write, so a crafted document title cannot break out into executable markup. The framework-agnostic print helpers are now exported from @eigenpal/docx-editor-core as the single source of truth, and the React package re-exports them unchanged.
  • 28876a2: Make regular expressions over file- and library-supplied strings run in linear time and escape quoted font names completely. The variable-detection, plural-message, and core-properties date regexes no longer backtrack polynomially on hostile input, and font family names are now backslash-escaped before being wrapped in a quoted CSS string so a crafted DOCX font name cannot break out of it.