mirror of
https://github.com/suitenumerique/docs.git
synced 2026-09-05 17:27:48 +02:00
🐛(frontend) codeblock throws errors when unsupported language
Implementation of code block throws a errors when a `language` prop is not supported by BlockNote, which crashes the whole editor. In our case, the language is supported but flagged as an alias (e.g. `js` instead of `javascript`), but Blocknote does not resolve aliases and throws an error. This file wraps the code block spec to normalize the `language` prop before BlockNote renders it, so a single legacy code block does not crash the whole editor.
This commit is contained in:
@@ -28,7 +28,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor, nisl ege
|
||||
|
||||
**Code block:**
|
||||
|
||||
```javascript
|
||||
```js
|
||||
const hello_world = () => {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
|
||||
@@ -164,6 +164,8 @@ test.describe('Doc Tree', () => {
|
||||
await clickOnAddRootSubPage(page);
|
||||
await updateDocTitle(page, 'second move');
|
||||
|
||||
await page.waitForTimeout(500); // Wait for the tree to be stable
|
||||
|
||||
const firstSubPageItem = docTree.getByText('first move').first();
|
||||
const secondSubPageItem = docTree.getByText('second move').first();
|
||||
|
||||
|
||||
+3
-3
@@ -1,7 +1,6 @@
|
||||
import { codeBlockOptions, syntaxHighlighter } from '@blocknote/code-block';
|
||||
import { syntaxHighlighter } from '@blocknote/code-block';
|
||||
import {
|
||||
BlockNoteSchema,
|
||||
createCodeBlockSpec,
|
||||
defaultBlockSpecs,
|
||||
defaultInlineContentSpecs,
|
||||
withPageBreak,
|
||||
@@ -72,6 +71,7 @@ const AIMenu = BlockNoteAI?.AIMenu;
|
||||
const AIMenuController = BlockNoteAI?.AIMenuController;
|
||||
const useAI = BlockNoteAI?.useAI;
|
||||
const localesBNAI = BlockNoteAI?.localesAI || {};
|
||||
import { createSafeCodeBlockSpec } from './custom-blocks/CodeBlock';
|
||||
import { InterlinkingLinkInlineContent } from './custom-inline-content';
|
||||
import XLMultiColumn from './xl-multi-column';
|
||||
|
||||
@@ -83,7 +83,7 @@ const baseBlockNoteSchema = withPageBreak(
|
||||
blockSpecs: {
|
||||
...defaultBlockSpecs,
|
||||
callout: CalloutBlock(),
|
||||
codeBlock: createCodeBlockSpec(codeBlockOptions),
|
||||
codeBlock: createSafeCodeBlockSpec(),
|
||||
diagram: createReactDiagramBlockSpec(),
|
||||
mathBlock: createReactMathBlockSpec(),
|
||||
pdf: PdfBlock(),
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Implementation of code block throws a errors when a `language` prop
|
||||
* is not supported by BlockNote, which crashes the whole editor.
|
||||
* In our case, the language is supported but flagged as an alias (e.g. `js` instead of `javascript`),
|
||||
* but Blocknote does not resolve aliases and throws an error.
|
||||
*
|
||||
* This file wraps the code block spec to normalize the `language` prop before BlockNote renders it,
|
||||
* so a single legacy code block does not crash the whole editor.
|
||||
*
|
||||
* See:
|
||||
* https://github.com/TypeCellOS/BlockNote/issues/3005
|
||||
* https://github.com/TypeCellOS/BlockNote/blob/main/packages/core/src/blocks/Code/CodeBlockOptions.ts
|
||||
* https://github.com/TypeCellOS/BlockNote/blob/63c2389e34be417bd4c03d7e047d304f5bfd6555/packages/core/src/blocks/Code/helpers/render/createCodeBlock.ts#L16-L18
|
||||
*
|
||||
* @TODO Remove this wrapper once BlockNote fixes the issue and supports aliases in the code block spec.
|
||||
*/
|
||||
|
||||
import { codeBlockOptions } from '@blocknote/code-block';
|
||||
import { createCodeBlockSpec } from '@blocknote/core';
|
||||
|
||||
const CODE_BLOCK_FALLBACK_LANGUAGE = 'text';
|
||||
|
||||
/**
|
||||
* Find the language id supported by BlockNote for a given language or alias.
|
||||
*/
|
||||
const codeBlockLanguageById = new Map<string, string>(
|
||||
Object.entries(codeBlockOptions.supportedLanguages).flatMap(
|
||||
([id, language]) =>
|
||||
[id, ...(language.aliases ?? [])].map(
|
||||
(key) => [key.toLowerCase(), id] as const,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
export const resolveCodeBlockLanguage = (language: unknown): string => {
|
||||
if (typeof language !== 'string') {
|
||||
return CODE_BLOCK_FALLBACK_LANGUAGE;
|
||||
}
|
||||
|
||||
return (
|
||||
codeBlockLanguageById.get(language.trim().toLowerCase()) ??
|
||||
CODE_BLOCK_FALLBACK_LANGUAGE
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds the code block spec, wrapping its `render` so an unsupported
|
||||
* `language` prop is normalized before BlockNote renders the language picker.
|
||||
* This prevents a single legacy code block from crashing the whole editor.
|
||||
*/
|
||||
export const createSafeCodeBlockSpec = (): ReturnType<
|
||||
typeof createCodeBlockSpec
|
||||
> => {
|
||||
const spec = createCodeBlockSpec(codeBlockOptions);
|
||||
const baseRender = spec.implementation.render;
|
||||
|
||||
return {
|
||||
...spec,
|
||||
implementation: {
|
||||
...spec.implementation,
|
||||
render(
|
||||
this: ThisParameterType<typeof baseRender>,
|
||||
...args: Parameters<typeof baseRender>
|
||||
): ReturnType<typeof baseRender> {
|
||||
const [block, editor] = args;
|
||||
const language = resolveCodeBlockLanguage(block.props.language);
|
||||
|
||||
if (language === block.props.language) {
|
||||
return baseRender.apply(this, args);
|
||||
}
|
||||
|
||||
return baseRender.call(
|
||||
this,
|
||||
{ ...block, props: { ...block.props, language } },
|
||||
editor,
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user