fix(image): markdown export of nested images + HTML round-trip (alignment, dimensions)#15
Merged
Merged
Conversation
Image markdown export only worked for top-level images. Lexical applies `element` transformers only to direct children of the root during export; images nested inside another element (e.g. inside a paragraph after HTML import or when placed inline with text) were routed through `exportChildren`, which only runs `text-match` transformers and otherwise falls back to a decorator's empty `getTextContent()` — so the image was silently dropped. - Add IMAGE_TEXT_MATCH_TRANSFORMER (text-match) to handle nested/inline images, alongside the existing element transformer for block images. - Share the export + node-creation logic between both transformers so output is identical regardless of tree position. - Inline images can now also be imported from markdown (e.g. "text  text"). - Export ImageNode, $createImageNode, $isImageNode, ImageTranslator and the image transformers from the package root for discoverability. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
) ImageTranslator.importDOM dropped intrinsic dimensions and mis-read alignment, so an HTML round-trip (getHTML -> injectHTML) lost image size and reset alignment to center. - #10: the `img` conversion now reads width/height from the `width`/`height` attributes and from `px` inline styles (percentage/auto are ignored as they can't be a numeric pixel size). - #11: the `figure` conversion no longer hardcodes "center"; it reads the alignment back from the `align-*` class / `text-align` style the editor emits, and pulls dimensions, className and inline style from the inner img. - Add shared extractAlignment() and extractDimension() helpers used by both the img and figure conversions. Verified with a real-DOM (jsdom) export->serialize->parse->import round-trip across left/center/right/none alignments and sized/unsized images. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add `files: ["dist"]` so the published tarball contents are explicit and deterministic (only the build output ships). - Add `publishConfig.access: public` so the scoped package always publishes publicly. - Bump version to 0.0.39 to ship the image markdown/HTML round-trip fixes (#10, #11, #13). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
release.yml publishes @lexkit/editor to npm whenever its version changes on main: it builds, checks whether the version is already on npm, and if not publishes with provenance (id-token: write) and cuts a GitHub release. Requires an npm automation token in the `NPM_TOKEN` repo secret. ci.yml builds the workspace on PRs and pushes to main. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ound-trip Covers the three fixed issues so they can't silently regress: - #13: markdown export of top-level, nested, and inline images; inline import. - #10: width/height imported from img attributes and px inline styles. - #11: alignment preserved (left/center/right/none) across an HTML round-trip. Adds vitest + jsdom, a `test` script, and gates both CI and the release workflow on the suite so a broken build can never be published. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NodeJS.Timeout requires @types/node, which isn't a dependency of this browser library. It only resolved locally via hoisting and broke the DTS build on a clean CI install (TS2694: Namespace 'NodeJS' has no exported member 'Timeout'). ReturnType<typeof setTimeout> is environment-agnostic and the correct type for a browser timer handle. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
novincode
added a commit
that referenced
this pull request
Jun 15, 2026
fix(image): markdown export of nested images + HTML round-trip (alignment, dimensions)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13, #10, #11. Also adds the npm release pipeline with provenance and a regression test suite.
Bug fixes (all root-caused in
@lexkit/editor, with tests)#13 — images skipped in markdown export
Image markdown only worked for top-level images. Lexical applies
elementtransformers only to direct children of the root during export; an image nested inside a paragraph (where they land after HTML import or when placed inline with text) went throughexportChildren, which only runstext-matchtransformers and otherwise falls back to a decorator's emptygetTextContent()— so the image was silently dropped.IMAGE_TEXT_MATCH_TRANSFORMER(text-match) alongside the existing element transformer, sharing one export/create-node implementation. Top-level images use the element transformer; nested/inline ones use text-match. No duplication.text  text).#10 — width/height lost on HTML import
ImageTranslator.importDOMforimgnever read dimensions. It now readswidth/heightattributes andpxinline styles (percentage/auto are ignored, since they can't be a numeric pixel size).#11 — alignment reset to center on HTML round-trip
The
figureconversion hardcoded"center". It now reads alignment back from thealign-*class /text-alignstyle the editor emits, plus dimensions/className/style from the inner<img>.Also exported
ImageNode,$createImageNode,$isImageNode,ImageTranslator, and both image transformers from the package root for discoverability (issue #13's reporter couldn't find the transformer).Release pipeline
.github/workflows/release.yml: on push tomain, builds + tests, and ifpackages/editor/package.json's version isn't on npm yet, publishes with provenance (id-token: write+NPM_CONFIG_PROVENANCE) and cuts a GitHub release. Requires theNPM_TOKENrepo secret..github/workflows/ci.yml: builds + tests on every PR/push.files: ["dist"]+publishConfig.access: publicfor a clean, deterministic public package.0.0.39.Tests
15 vitest tests (jsdom) covering all three issues; both CI and release are gated on them.