Skip to content

Commit 85f1067

Browse files
authored
Fix pasting inline code blocks (#2607)
1 parent 1d9750d commit 85f1067

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

packages/lexical-code/src/index.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,20 @@ export class CodeNode extends ElementNode {
265265

266266
static importDOM(): DOMConversionMap | null {
267267
return {
268-
code: (node: Node) => ({
269-
conversion: convertPreElement,
270-
priority: 0,
271-
}),
268+
// Typically <pre> is used for code blocks, and <code> for inline code styles
269+
// but if it's a multi line <code> we'll create a block. Pass through to
270+
// inline format handled by TextNode otherwise
271+
code: (node: Node) => {
272+
const isMultiLine =
273+
node.textContent != null && /\r?\n/.test(node.textContent);
274+
275+
return isMultiLine
276+
? {
277+
conversion: convertPreElement,
278+
priority: 1,
279+
}
280+
: null;
281+
},
272282
div: (node: Node) => ({
273283
conversion: convertDivElement,
274284
priority: 1,

packages/lexical-playground/__tests__/e2e/CodeBlock.spec.mjs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,40 @@ test.describe('CodeBlock', () => {
10041004
name: 'GitHub / Gist',
10051005
pastedHTML: `<meta charset='utf-8'><table class="highlight tab-size js-file-line-container js-code-nav-container js-tagsearch-file" data-tab-size="8" data-paste-markdown-skip="" data-tagsearch-lang="JavaScript" data-tagsearch-path="example.js" style="box-sizing: border-box; border-spacing: 0px; border-collapse: collapse; tab-size: 8; color: rgb(36, 41, 47); font-family: -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><td id="file-example-js-LC1" class="blob-code blob-code-inner js-file-line" style="box-sizing: border-box; padding: 0px 10px; position: relative; line-height: 20px; vertical-align: top; overflow: visible; font-family: ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;, monospace; font-size: 12px; color: var(--color-fg-default); overflow-wrap: normal; white-space: pre;"><span class="pl-k" style="box-sizing: border-box; color: var(--color-prettylights-syntax-keyword);">function</span> <span class="pl-en" style="box-sizing: border-box; color: var(--color-prettylights-syntax-entity);">run</span><span class="pl-kos" style="box-sizing: border-box;">(</span><span class="pl-kos" style="box-sizing: border-box;">)</span> <span class="pl-kos" style="box-sizing: border-box;">{</span></td></tr><tr style="box-sizing: border-box; background-color: transparent;"><td id="file-example-js-L2" class="blob-num js-line-number js-code-nav-line-number" data-line-number="2" style="box-sizing: border-box; padding: 0px 10px; width: 50px; min-width: 50px; font-family: ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;, monospace; font-size: 12px; line-height: 20px; color: var(--color-fg-subtle); text-align: right; white-space: nowrap; vertical-align: top; cursor: pointer; user-select: none;"></td><td id="file-example-js-LC2" class="blob-code blob-code-inner js-file-line" style="box-sizing: border-box; padding: 0px 10px; position: relative; line-height: 20px; vertical-align: top; overflow: visible; font-family: ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;, monospace; font-size: 12px; color: var(--color-fg-default); overflow-wrap: normal; white-space: pre;"> <span class="pl-k" style="box-sizing: border-box; color: var(--color-prettylights-syntax-keyword);">return</span> <span class="pl-kos" style="box-sizing: border-box;">[</span><span class="pl-c1" style="box-sizing: border-box; color: var(--color-prettylights-syntax-constant);">null</span><span class="pl-kos" style="box-sizing: border-box;">,</span> <span class="pl-c1" style="box-sizing: border-box; color: var(--color-prettylights-syntax-constant);">undefined</span><span class="pl-kos" style="box-sizing: border-box;">,</span> <span class="pl-c1" style="box-sizing: border-box; color: var(--color-prettylights-syntax-constant);">2</span><span class="pl-kos" style="box-sizing: border-box;">,</span> <span class="pl-s" style="box-sizing: border-box; color: var(--color-prettylights-syntax-string);">""</span><span class="pl-kos" style="box-sizing: border-box;">]</span><span class="pl-kos" style="box-sizing: border-box;">;</span></td></tr><tr style="box-sizing: border-box;"><td id="file-example-js-L3" class="blob-num js-line-number js-code-nav-line-number" data-line-number="3" style="box-sizing: border-box; padding: 0px 10px; width: 50px; min-width: 50px; font-family: ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;, monospace; font-size: 12px; line-height: 20px; color: var(--color-fg-subtle); text-align: right; white-space: nowrap; vertical-align: top; cursor: pointer; user-select: none;"></td><td id="file-example-js-LC3" class="blob-code blob-code-inner js-file-line" style="box-sizing: border-box; padding: 0px 10px; position: relative; line-height: 20px; vertical-align: top; overflow: visible; font-family: ui-monospace, SFMono-Regular, &quot;SF Mono&quot;, Menlo, Consolas, &quot;Liberation Mono&quot;, monospace; font-size: 12px; color: var(--color-fg-default); overflow-wrap: normal; white-space: pre;"><span class="pl-kos" style="box-sizing: border-box;">}</span></td></tr></tbody></table>`,
10061006
},
1007+
{
1008+
expectedHTML: html`
1009+
<p class="PlaygroundEditorTheme__paragraph">
1010+
<code data-lexical-text="true">
1011+
<span class="PlaygroundEditorTheme__textCode">12</span>
1012+
</code>
1013+
</p>
1014+
`,
1015+
name: 'Single line <code>',
1016+
pastedHTML: `<meta charset='utf-8'><code>12</code>`,
1017+
},
1018+
{
1019+
expectedHTML: html`
1020+
<code
1021+
class="PlaygroundEditorTheme__code"
1022+
spellcheck="false"
1023+
data-gutter="12"
1024+
data-highlight-language="javascript">
1025+
<span
1026+
class="PlaygroundEditorTheme__tokenProperty"
1027+
data-lexical-text="true">
1028+
1
1029+
</span>
1030+
<br />
1031+
<span
1032+
class="PlaygroundEditorTheme__tokenProperty"
1033+
data-lexical-text="true">
1034+
2
1035+
</span>
1036+
</code>
1037+
`,
1038+
name: 'Multiline <code>',
1039+
pastedHTML: `<meta charset='utf-8'><code>1\n2</code>`,
1040+
},
10071041
];
10081042

10091043
CODE_PASTING_TESTS.forEach((testCase, i) => {

packages/lexical/src/nodes/LexicalTextNode.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,10 @@ export class TextNode extends LexicalNode {
451451
conversion: convertBringAttentionToElement,
452452
priority: 0,
453453
}),
454+
code: (node: Node) => ({
455+
conversion: convertTextFormatElement,
456+
priority: 0,
457+
}),
454458
em: (node: Node) => ({
455459
conversion: convertTextFormatElement,
456460
priority: 0,
@@ -915,6 +919,7 @@ function convertTextDOMNode(domNode: Node): DOMConversionOutput {
915919
return {node: $createTextNode(textContent)};
916920
}
917921
const nodeNameToTextFormat: Record<string, TextFormatType> = {
922+
code: 'code',
918923
em: 'italic',
919924
i: 'italic',
920925
strong: 'bold',

0 commit comments

Comments
 (0)