Skip to content

Commit 6f4239f

Browse files
fix: add context,nestingLevel to toExternalHTML (#2373)
* fix: add contaxt,nestingLevel to toExternalHTML * Added docs --------- Co-authored-by: Matthew Lipski <matthewlipski@gmail.com>
1 parent 90f1d90 commit 6f4239f

File tree

5 files changed

+30
-6
lines changed

5 files changed

+30
-6
lines changed

docs/content/docs/features/custom-schemas/custom-blocks.mdx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ type ReactCustomBlockImplementation = {
121121
block: Block;
122122
editor: BlockNoteEditor;
123123
contentRef?: (node: HTMLElement | null) => void;
124+
contest: { nestingLevel: number };
124125
}>;
125126
parse?: (element: HTMLElement) => PartialBlock["props"] | undefined;
126127
runsBefore?: string[];
@@ -143,7 +144,9 @@ type ReactCustomBlockImplementation = {
143144

144145
- `contentRef:` A React `ref` you can use to mark which element in your block is editable, this is only available if your block config contains `content: "inline"`.
145146

146-
`toExternalHTML?:` This component is used whenever the block is being exported to HTML for use outside BlockNote, for example when copying it to the clipboard. If it's not defined, BlockNote will just use `render` for the HTML conversion. Takes the same props as `render`.
147+
`toExternalHTML?:` This component is used whenever the block is being exported to HTML for use outside BlockNote, for example when copying it to the clipboard. If it's not defined, BlockNote will just use `render` for the HTML conversion. Takes the same props as `render` and an additional `context` prop, which is. an object with the following attributes:
148+
149+
- `nestingLevel`: How deep the block being exported in nested inside other blocks. 0 means it's at the top level of the document.
147150

148151
<Callout type="info">
149152
_Note that your component passed to `toExternalHTML` is rendered and

packages/core/src/api/exporters/html/util/serializeBlocksExternalHTML.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ function serializeBlock<
207207
{},
208208
{ ...block, props } as any,
209209
editor as any,
210+
{
211+
nestingLevel,
212+
},
210213
) ||
211214
blockImplementation.render.call(
212215
{},

packages/core/src/schema/blocks/createSpec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ export function addNodeAndExtensionsToSpec<
242242
},
243243
// TODO: this should not have wrapInBlockStructure and generally be a lot simpler
244244
// post-processing in externalHTMLExporter should not be necessary
245-
toExternalHTML: (block, editor) => {
245+
toExternalHTML: (block, editor, context) => {
246246
const blockContentDOMAttributes =
247247
node.options.domAttributes?.blockContent || {};
248248

@@ -251,6 +251,7 @@ export function addNodeAndExtensionsToSpec<
251251
{ blockContentDOMAttributes },
252252
block as any,
253253
editor as any,
254+
context,
254255
) ??
255256
blockImplementation.render.call(
256257
{ blockContentDOMAttributes, renderType: "dom", props: undefined },
@@ -393,11 +394,12 @@ export function createBlockSpec<
393394
...blockImplementation,
394395
// TODO: this should not have wrapInBlockStructure and generally be a lot simpler
395396
// post-processing in externalHTMLExporter should not be necessary
396-
toExternalHTML(block, editor) {
397+
toExternalHTML(block, editor, context) {
397398
const output = blockImplementation.toExternalHTML?.call(
398399
{ blockContentDOMAttributes: this.blockContentDOMAttributes },
399400
block as any,
400401
editor as any,
402+
context,
401403
);
402404

403405
if (output === undefined) {

packages/core/src/schema/blocks/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ export type LooseBlockSpec<
139139
toExternalHTML?: (
140140
block: any,
141141
editor: BlockNoteEditor<any>,
142+
context: {
143+
nestingLevel: number;
144+
},
142145
) =>
143146
| {
144147
dom: HTMLElement | DocumentFragment;
@@ -193,6 +196,9 @@ export type BlockSpecs = {
193196
toExternalHTML?: (
194197
block: any,
195198
editor: BlockNoteEditor<any>,
199+
context: {
200+
nestingLevel: number;
201+
},
196202
) =>
197203
| {
198204
dom: HTMLElement | DocumentFragment;
@@ -463,6 +469,9 @@ export type BlockImplementation<
463469
editor: BlockNoteEditor<
464470
Record<TName, BlockConfig<TName, TProps, TContent>>
465471
>,
472+
context: {
473+
nestingLevel: number;
474+
},
466475
) =>
467476
| {
468477
dom: HTMLElement | DocumentFragment;

packages/react/src/schema/ReactBlockSpec.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import {
33
BlockImplementation,
44
BlockNoDefaults,
55
BlockNoteEditor,
6-
Extension,
76
BlockSpec,
87
camelToDataKebab,
98
CustomBlockImplementation,
9+
Extension,
1010
getBlockFromPos,
1111
mergeCSSClasses,
1212
Props,
@@ -51,7 +51,13 @@ export type ReactCustomBlockImplementation<
5151
"render" | "toExternalHTML"
5252
> & {
5353
render: FC<ReactCustomBlockRenderProps<TName, TProps, TContent>>;
54-
toExternalHTML?: FC<ReactCustomBlockRenderProps<TName, TProps, TContent>>;
54+
toExternalHTML?: FC<
55+
ReactCustomBlockRenderProps<TName, TProps, TContent> & {
56+
context: {
57+
nestingLevel: number;
58+
};
59+
}
60+
>;
5561
};
5662

5763
export type ReactCustomBlockSpec<
@@ -224,7 +230,7 @@ export function createReactBlockSpec<
224230
config: blockConfig,
225231
implementation: {
226232
...blockImplementation,
227-
toExternalHTML(block, editor) {
233+
toExternalHTML(block, editor, context) {
228234
const BlockContent =
229235
blockImplementation.toExternalHTML || blockImplementation.render;
230236
const output = renderToDOMSpec((refCB) => {
@@ -247,6 +253,7 @@ export function createReactBlockSpec<
247253
);
248254
}
249255
}}
256+
context={context}
250257
/>
251258
</BlockContentWrapper>
252259
);

0 commit comments

Comments
 (0)