From 4c4b0efa8ecfc45053dee992f7ceb8566c520ede Mon Sep 17 00:00:00 2001 From: Emma Hamilton Date: Fri, 10 Jan 2025 14:48:12 +1000 Subject: [PATCH] Fix language being discarded when copy and pasting code block in new editor (#1391) --- .changeset/silent-singers-reflect.md | 5 +++ .../src/form/fields/markdoc/editor/schema.tsx | 24 ++++++++---- .../pasting/pasting-within-editor.test.tsx | 39 +++++++++++++++++++ .../fields/markdoc/editor/tests/utils.tsx | 10 +++++ 4 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 .changeset/silent-singers-reflect.md diff --git a/.changeset/silent-singers-reflect.md b/.changeset/silent-singers-reflect.md new file mode 100644 index 000000000..3d4c80d9a --- /dev/null +++ b/.changeset/silent-singers-reflect.md @@ -0,0 +1,5 @@ +--- +'@keystatic/core': patch +--- + +Fix language being discarded when copy and pasting code block in new editor diff --git a/packages/keystatic/src/form/fields/markdoc/editor/schema.tsx b/packages/keystatic/src/form/fields/markdoc/editor/schema.tsx index 96e976144..4f708a8cc 100644 --- a/packages/keystatic/src/form/fields/markdoc/editor/schema.tsx +++ b/packages/keystatic/src/form/fields/markdoc/editor/schema.tsx @@ -70,11 +70,6 @@ const dividerDOM: DOMOutputSpec = [ }), }, ]; -const codeDOM: DOMOutputSpec = [ - 'pre', - { spellcheck: 'false' }, - ['code', {}, 0], -]; const hardBreakDOM: DOMOutputSpec = ['br']; const olDOM: DOMOutputSpec = ['ol', {}, 0]; @@ -191,9 +186,22 @@ const nodeSpecs = { }, marks: '', code: true, - parseDOM: [{ tag: 'pre', preserveWhitespace: 'full' }], - toDOM() { - return codeDOM; + parseDOM: [ + { + tag: 'pre', + preserveWhitespace: 'full', + getAttrs(node) { + if (typeof node === 'string') return {}; + return { language: node.getAttribute('data-language') ?? '' }; + }, + }, + ], + toDOM(node) { + return [ + 'pre', + { spellcheck: 'false', 'data-language': node.attrs.language }, + ['code', {}, 0], + ]; }, }, list_item: { diff --git a/packages/keystatic/src/form/fields/markdoc/editor/tests/pasting/pasting-within-editor.test.tsx b/packages/keystatic/src/form/fields/markdoc/editor/tests/pasting/pasting-within-editor.test.tsx index 583460c17..516074cb1 100644 --- a/packages/keystatic/src/form/fields/markdoc/editor/tests/pasting/pasting-within-editor.test.tsx +++ b/packages/keystatic/src/form/fields/markdoc/editor/tests/pasting/pasting-within-editor.test.tsx @@ -122,3 +122,42 @@ test('blockquote pasting', async () => { `); }); + +test('codeblock pasting with language', async () => { + let dataTransfer; + const codeBlock = ( + + console.log(1); + + ); + { + const { user } = renderEditor( + + + + + {codeBlock} + + + + + ); + + dataTransfer = await user.copy(); + } + const { state, user } = renderEditor( + + + + ); + await user.paste(dataTransfer); + expect(state()).toEqual( + + + {codeBlock} + + + + + ); +}); diff --git a/packages/keystatic/src/form/fields/markdoc/editor/tests/utils.tsx b/packages/keystatic/src/form/fields/markdoc/editor/tests/utils.tsx index e5064f510..891863212 100644 --- a/packages/keystatic/src/form/fields/markdoc/editor/tests/utils.tsx +++ b/packages/keystatic/src/form/fields/markdoc/editor/tests/utils.tsx @@ -516,6 +516,7 @@ export function renderEditor(editorState: EditorStateDescription): { rendered: ReturnType; user: ReturnType<(typeof userEvent)['setup']>; state: () => EditorStateDescription; + contentElement: HTMLElement; } { const viewRef = createRef<{ view: EditorView | null }>(); const user = userEvent.setup(); @@ -537,10 +538,19 @@ export function renderEditor(editorState: EditorStateDescription): { viewRef.current!.view!.focus(); + const contentElement = rendered.baseElement.querySelector( + '[contenteditable="true"]' + )!; + + if (!(contentElement instanceof HTMLElement)) { + throw new Error('content element not found/not HTMLElement'); + } + return { state: () => editorState, user, rendered, + contentElement, }; }