Summary
The README lists Browser / Node as a supported surface, but import "docxodus"
throws in plain Node. The barrel re-exports the browser editor, which imports
@atlaskit/pragmatic-drag-and-drop subpaths that only a bundler can resolve.
Everything the engine offers — initialize, convertDocxToHtml, docxDiff*,
the annotation overlay, openDocxSession — is defined in dist/index.js itself,
so there is no engine-only entry point to import instead.
Reproduction
mkdir repro && cd repro
npm init -y && npm pkg set type=module
npm install docxodus@12.3.0
node -e "import('docxodus').then(()=>console.log('OK')).catch(e=>console.log(e.code))"
ERR_UNSUPPORTED_DIR_IMPORT: Directory import
'/…/node_modules/@atlaskit/pragmatic-drag-and-drop/element/adapter'
is not supported resolving ES modules imported from
'/…/node_modules/docxodus/dist/editor.js'
Node v26.8.1, docxodus 12.3.0. Reproduces with npm and pnpm alike, so it is
not a package-manager artifact. Under tsx it surfaces differently
(ERR_MODULE_NOT_FOUND, resolving …/element/adapter/index.jsx).
Root cause
@atlaskit/pragmatic-drag-and-drop ships no exports map. Its subpath
directories contain only a legacy redirect:
module is a bundler convention; Node ESM does not read it, and directory
imports are unsupported. dist/index.js reaches this via
export { DocxEditor } from "./editor.js" (plus CommentGutter, ribbon), so
the failure happens on import, before any engine call.
exports currently publishes ., ./react, ./embed, ./worker,
./export-browser — none of which is engine-only.
Why it matters
Server-side is a real use case for this library: batch conversion, diffing in a
job queue, agent pipelines, indexing. Those never touch DocxEditor, but today
they cannot import the package at all without a bundler or a loader shim.
Suggested fix
Add an engine-only subpath that excludes the editor, e.g.:
exporting everything in index.js except DocxEditor, CommentGutter and
ribbon. index.js could then re-export ./core plus the editor, keeping the
current entry point unchanged for browser consumers.
A lazy await import("./editor.js") inside the editor factories would also work
and would fix the default entry point itself, though it changes DocxEditor to
an async acquisition.
Workaround, for anyone hitting this
A ~20-line Node loader hook that resolves @atlaskit/pragmatic-drag-and-drop* to
a stub with the seven named exports the editor imports (draggable,
dropTargetForElements, monitorForElements, autoScrollForElements,
autoScrollWindowForElements, pointerOutsideOfPreview,
setCustomNativeDragPreview). With that in place the engine loads and runs
correctly in Node (cold start around 100 ms), so this is purely a packaging
boundary and not an engine limitation.
Summary
The README lists Browser / Node as a supported surface, but
import "docxodus"throws in plain Node. The barrel re-exports the browser editor, which imports
@atlaskit/pragmatic-drag-and-dropsubpaths that only a bundler can resolve.Everything the engine offers —
initialize,convertDocxToHtml,docxDiff*,the annotation overlay,
openDocxSession— is defined indist/index.jsitself,so there is no engine-only entry point to import instead.
Reproduction
Node v26.8.1, docxodus 12.3.0. Reproduces with npm and pnpm alike, so it is
not a package-manager artifact. Under
tsxit surfaces differently(
ERR_MODULE_NOT_FOUND, resolving…/element/adapter/index.jsx).Root cause
@atlaskit/pragmatic-drag-and-dropships noexportsmap. Its subpathdirectories contain only a legacy redirect:
moduleis a bundler convention; Node ESM does not read it, and directoryimports are unsupported.
dist/index.jsreaches this viaexport { DocxEditor } from "./editor.js"(plusCommentGutter,ribbon), sothe failure happens on import, before any engine call.
exportscurrently publishes.,./react,./embed,./worker,./export-browser— none of which is engine-only.Why it matters
Server-side is a real use case for this library: batch conversion, diffing in a
job queue, agent pipelines, indexing. Those never touch
DocxEditor, but todaythey cannot import the package at all without a bundler or a loader shim.
Suggested fix
Add an engine-only subpath that excludes the editor, e.g.:
exporting everything in
index.jsexceptDocxEditor,CommentGutterandribbon.index.jscould then re-export./coreplus the editor, keeping thecurrent entry point unchanged for browser consumers.
A lazy
await import("./editor.js")inside the editor factories would also workand would fix the default entry point itself, though it changes
DocxEditortoan async acquisition.
Workaround, for anyone hitting this
A ~20-line Node loader hook that resolves
@atlaskit/pragmatic-drag-and-drop*toa stub with the seven named exports the editor imports (
draggable,dropTargetForElements,monitorForElements,autoScrollForElements,autoScrollWindowForElements,pointerOutsideOfPreview,setCustomNativeDragPreview). With that in place the engine loads and runscorrectly in Node (cold start around 100 ms), so this is purely a packaging
boundary and not an engine limitation.