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,
};
}