Repository navigation
Conversation
… as code on import ## Description Two things made whitespace inside inline code drop out of the code on import: 1. `$normalizeMarkdownTextNode()` replaced every tab in every imported text node with a `TabNode`, and only the text around the tab kept the node's format. A tab inside a code span therefore left the code, the span was split around it, and a span holding only a tab stopped being code at all. `` `a⇥b` `` was exported back as `` `a`⇥`b` ``. 2. `isEmptyParagraph()` treated a paragraph whose only text node holds up to three whitespace characters as empty, without looking at the code format. A paragraph of only `` ` ` `` or `` `⇥` `` was removed on import, and export used the same check to separate blocks. This change keeps the tabs of an inline-code node as text, and does not count a paragraph of inline code as empty. Tabs outside code, and tabs in code blocks, are unchanged, and a paragraph that really is empty is still dropped. A tab is kept as text in the code node rather than as a `TabNode` with the code format: separate code nodes on each side of a tab would be exported as adjacent code spans, which a reader merges into one span holding backticks. The fix follows the one suggested in the issue. Closes meta#9409 ## Test plan ### Before `pnpm exec vitest --project unit --no-watch packages/lexical-markdown/src/__tests__/unit/CodeSpanWhitespaceImport.test.ts` ``` × keeps a tab inside a code span as part of the code × round trips a code span that holds a tab × keeps a paragraph whose only content is whitespace code AssertionError: expected [ [ { code: true, …(2) }, …(2) ] ] to deeply equal [ Array(1) ] AssertionError: expected '`a`\t`b`' to be '`a\tb`' // Object.is equality AssertionError: expected [ [ { code: false, …(2) } ], …(1) ] to deeply equal [ [ { code: false, …(2) } ], …(2) ] Tests 3 failed | 2 passed (5) ``` ### After `pnpm exec vitest --project unit --no-watch packages/lexical-markdown packages/lexical-mdast packages/lexical-playground/__tests__/unit` ``` Test Files 45 passed (45) Tests 1180 passed (1180) ``` `tsc`, `tsc -p tsconfig.test.json`, ESLint and Prettier pass on the changed files. Only unit tests (Node) were run. How the editor handles typing into a code-formatted text node that holds a tab was not checked in a browser.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
lexical
@lexical/a11y
@lexical/clipboard
@lexical/code
@lexical/code-core
@lexical/code-prism
@lexical/code-shiki
@lexical/compiler
@lexical/devtools-core
@lexical/dragon
@lexical/eslint-plugin
@lexical/extension
@lexical/fast-check
@lexical/file
@lexical/hashtag
@lexical/headless
@lexical/history
@lexical/html
@lexical/internal
@lexical/link
@lexical/list
@lexical/mark
@lexical/markdown
@lexical/mdast
@lexical/offset
@lexical/overflow
@lexical/plain-text
@lexical/react
@lexical/rich-text
@lexical/selection
@lexical/table
@lexical/tailwind
@lexical/text
@lexical/utils
@lexical/yjs
commit: |
There was a problem hiding this comment.
Thanks for the fix! This looks good to me. Keeping the tabs of a code-formatted text node as text, and no longer treating whitespace-only inline code as an empty paragraph, matches CommonMark's code-span rule (§6.1: code-span content is literal, and only spaces are stripped from its ends). The new tests fail on main and pass with the change. Everything below is optional and non-blocking.
Optional suggestions
-
Changeset. AGENTS.md (Changesets) and CONTRIBUTING.md (Changesets) ask for a changeset when a published package's behavior changes, and a fix that changes output gets a
Verify:paragraph. For example,.changeset/markdown-code-span-whitespace.md:--- '@lexical/markdown': patch --- [fix] Keep tabs and whitespace-only inline code as code when importing Markdown Verify: importing a code span that contains a tab gives one inline-code text node and exports back unchanged, and a paragraph holding only `` ` ` `` is kept instead of dropped.
A maintainer can also add it for you.
-
Two more test cases.
isEmptyParagraph(packages/lexical-markdown/src/utils.ts:76) also decides how loose lists are joined during import (packages/lexical-markdown/src/MarkdownTransformers.ts:630) and which block separators the exporter writes (packages/lexical-markdown/src/MarkdownExport.ts:83-84). Both new behaviors are correct.- a\n\n` `\n\n- bnow imports as list, paragraph, list, where it used to become one list with the code paragraph dropped. A whitespace-code paragraph between two paragraphs now exports with blank lines around it. Adding both cases toCodeSpanWhitespaceImport.test.tswould keep them from regressing. -
Possible follow-up, not for this PR. Pressing Tab inside inline code inserts a
TabNodewith the code format, and@lexical/mdastimports`a<tab>b`the same way.@lexical/markdownstill exports that shape as adjacent spans, which read back as one span with backticks inside, just as it did before this change. Keeping the tab as text is the right call for the current exporter. TeachingexportTextFormatto write adjacent code-formatted nodes as one span could be its own issue.
| (node.getChildrenSize() === 1 && | ||
| $isTextNode(firstChild) && | ||
| // Inline code is content even when it holds only whitespace. | ||
| !firstChild.hasFormat('code') && |
There was a problem hiding this comment.
Optional: this check also decides list joining during import (MarkdownTransformers.ts:630) and block separators on export (MarkdownExport.ts:83-84). Both new behaviors are correct: - a\n\n` `\n\n- b now imports as list, paragraph, list, and a whitespace-code paragraph exports with blank lines around it. Neither is tested yet, and two extra cases in CodeSpanWhitespaceImport.test.ts would cover them.
Description
Two things made whitespace inside inline code drop out of the code on import:
$normalizeMarkdownTextNode()replaced every tab in every imported text node with aTabNode, and only the text around the tab kept the node's format. A tab inside a code span therefore left the code, the span was split around it, and a span holding only a tab stopped being code at all.`a⇥b`was exported back as`a`⇥`b`.isEmptyParagraph()treated a paragraph whose only text node holds up to three whitespace characters as empty, without looking at the code format. A paragraph of only` `or`⇥`was removed on import, and export used the same check to separate blocks.This change keeps the tabs of an inline-code node as text, and does not count a paragraph of inline code as empty. Tabs outside code, and tabs in code blocks, are unchanged, and a paragraph that really is empty is still dropped.
A tab is kept as text in the code node rather than as a
TabNodewith the code format: separate code nodes on each side of a tab would be exported as adjacent code spans, which a reader merges into one span holding backticks. The fix follows the one suggested in the issue.AI disclosure: this change, its tests and this description were prepared with the help of an AI coding assistant.
Closes #9409
Test plan
Before
pnpm exec vitest --project unit --no-watch packages/lexical-markdown/src/__tests__/unit/CodeSpanWhitespaceImport.test.tsAfter
pnpm exec vitest --project unit --no-watch packages/lexical-markdown packages/lexical-mdast packages/lexical-playground/__tests__/unittsc,tsc -p tsconfig.test.json, ESLint and Prettier pass on the changed files. Only unit tests (Node) were run. How the editor handles typing into a code-formatted text node that holds a tab was not checked in a browser.