Skip to content

Commit ed8c681

Browse files
committed
Major changes
1 parent 719fd7a commit ed8c681

41 files changed

Lines changed: 849 additions & 1261 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/06-custom-schema/09-math-block/.bnexample.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
"playground": true,
33
"docs": true,
44
"author": "matthewlipski",
5-
"tags": ["Intermediate", "Blocks", "Custom Schemas"],
5+
"tags": [
6+
"Intermediate",
7+
"Blocks",
8+
"Custom Schemas",
9+
"Suggestion Menus",
10+
"Slash Menu"
11+
],
612
"dependencies": {
713
"@blocknote/code-block": "latest",
8-
"@blocknote/math-block": "latest"
14+
"@blocknote/math-block": "latest",
15+
"react-icons": "^5.5.0"
916
}
1017
}

examples/06-custom-schema/09-math-block/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"react": "^19.2.3",
2222
"react-dom": "^19.2.3",
2323
"@blocknote/code-block": "latest",
24-
"@blocknote/math-block": "latest"
24+
"@blocknote/math-block": "latest",
25+
"react-icons": "^5.5.0"
2526
},
2627
"devDependencies": {
2728
"@types/react": "^19.2.3",
Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
11
import "@blocknote/core/fonts/inter.css";
22
import { BlockNoteSchema } from "@blocknote/core";
3+
import {
4+
filterSuggestionItems,
5+
insertOrUpdateBlockForSlashMenu,
6+
} from "@blocknote/core/extensions";
37
import { createHighlighter } from "@blocknote/code-block";
48
import { createMathBlockSpec } from "@blocknote/math-block";
59
import { BlockNoteView } from "@blocknote/mantine";
610
import "@blocknote/mantine/style.css";
7-
import { useCreateBlockNote } from "@blocknote/react";
11+
import {
12+
getDefaultReactSlashMenuItems,
13+
SuggestionMenuController,
14+
useCreateBlockNote,
15+
} from "@blocknote/react";
16+
import { TbMathFunction } from "react-icons/tb";
17+
18+
// Our schema with block specs, which contain the configs and implementations for blocks
19+
// that we want our editor to use.
20+
const schema = BlockNoteSchema.create().extend({
21+
blockSpecs: {
22+
// Creates an instance of the Math block and adds it to the schema.
23+
math: createMathBlockSpec(),
24+
},
25+
});
26+
27+
// Slash menu item to insert a Math block.
28+
const insertMath = (editor: typeof schema.BlockNoteEditor) => ({
29+
title: "Math",
30+
subtext: "Insert a LaTeX math formula",
31+
onItemClick: () =>
32+
insertOrUpdateBlockForSlashMenu(editor, {
33+
type: "math",
34+
}),
35+
aliases: ["math", "latex", "formula", "equation"],
36+
group: "Basic blocks",
37+
icon: <TbMathFunction />,
38+
});
839

940
export default function App() {
10-
// The math block isn't a default block, so we register it in a custom schema.
1141
const editor = useCreateBlockNote({
12-
// The Shiki highlighter (from @blocknote/code-block) syntax-highlights the
13-
// math block's editable LaTeX source popup. `highlightBlock` enables it for
14-
// the math block and highlights it as LaTeX.
42+
// Configures the syntax highlighting extension to always use LaTeX syntax highlighting in the
43+
// Math block.
1544
syntaxHighlighting: {
1645
createHighlighter,
1746
highlightBlock: (block) =>
1847
block.type === "math" ? "latex" : block.props.language,
1948
},
20-
schema: BlockNoteSchema.create().extend({
21-
blockSpecs: {
22-
math: createMathBlockSpec(),
23-
},
24-
}),
49+
schema,
2550
initialContent: [
2651
{
2752
type: "paragraph",
@@ -37,10 +62,31 @@ export default function App() {
3762
},
3863
{
3964
type: "paragraph",
65+
content: "Press the '/' key to open the Slash Menu and add another",
4066
},
4167
],
4268
});
4369

4470
// Renders the editor instance using a React component.
45-
return <BlockNoteView editor={editor} />;
71+
return (
72+
<BlockNoteView editor={editor} slashMenu={false}>
73+
{/* Replaces the default Slash Menu. */}
74+
<SuggestionMenuController
75+
triggerCharacter={"/"}
76+
getItems={async (query) => {
77+
// Gets all default slash menu items.
78+
const defaultItems = getDefaultReactSlashMenuItems(editor);
79+
// Finds index of last item in "Basic blocks" group.
80+
const lastBasicBlockIndex = defaultItems.findLastIndex(
81+
(item) => item.group === "Basic blocks",
82+
);
83+
// Inserts the Math item as the last item in the "Basic blocks" group.
84+
defaultItems.splice(lastBasicBlockIndex + 1, 0, insertMath(editor));
85+
86+
// Returns filtered items based on the query.
87+
return filterSuggestionItems(defaultItems, query);
88+
}}
89+
/>
90+
</BlockNoteView>
91+
);
4692
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="vite-plus/client" />

packages/core/src/blocks/Code/CodeBlockOptions.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ViewMutationRecord } from "prosemirror-view";
1+
// import type { ViewMutationRecord } from "prosemirror-view";
22
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
33
import type { BlockFromConfig } from "../../schema/index.js";
44

@@ -15,12 +15,8 @@ export type CodeBlockPreview = (
1515
block: BlockFromConfig<any, any, any>,
1616
editor: BlockNoteEditor<any>,
1717
) => {
18-
dom: HTMLElement;
19-
// TODO: This is for showing any syntax errors found while rendering the preview, not sure if it
20-
// should be here.
18+
dom: HTMLElement | DocumentFragment;
2119
error?: string | null;
22-
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
23-
destroy?: () => void;
2420
};
2521

2622
export type CodeBlockOptions = {

packages/core/src/blocks/Code/block.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import {
33
parsePreCode,
44
parsePreCodeContent,
55
} from "./helpers/parse/parsePreCode.js";
6-
import { createCodeBlockWrapper } from "./helpers/render/createCodeBlockWrapper.js";
76
import { createPreCode } from "./helpers/toExternalHTML/createPreCode.js";
87
import { createCodeKeyboardShortcutsExtension } from "./helpers/extensions/createCodeKeyboardShortcutsExtension.js";
98
import { CodeBlockOptions } from "./CodeBlockOptions.js";
9+
import { createSourceBlockWithPreview } from "./helpers/render/createSourceBlockWithPreview.js";
1010

1111
export type CodeBlockConfig = ReturnType<typeof createCodeBlockConfig>;
1212

@@ -33,7 +33,17 @@ export const createCodeBlockSpec = createBlockSpec(
3333
},
3434
parse: (el) => parsePreCode(el),
3535
parseContent: (opts) => parsePreCodeContent(opts, "codeBlock"),
36-
render: (block, editor) => createCodeBlockWrapper(options)(block, editor),
36+
render: (block, editor) =>
37+
createSourceBlockWithPreview(
38+
block,
39+
editor,
40+
options.supportedLanguages && {
41+
selectedLanguage: block.props.language,
42+
supportedLanguages: options.supportedLanguages,
43+
createPreview:
44+
options.supportedLanguages[block.props.language].createPreview,
45+
},
46+
),
3747
toExternalHTML: (block) => createPreCode(block),
3848
}),
3949
(options) => {

0 commit comments

Comments
 (0)