BlockNote
BlockNote copied to clipboard
how to disable nest or unnest feature?
Due to some special reasons, I need to disable the nest feature.
I customized the toolbar to remove the nest unNest button. However, I still can't get rid of the Tab and Shift Tab shortcuts. I found that the shortcut code is written in the blockContainer, and I intended to disable it through the extend method, with the code as follows:
import {BlockContainer} from "@blocknote/core/src/pm-nodes";
const newBlockContainer = BlockContainer.extend({
addKeyboardShortcuts() {
const obj = this.parent?.() || {};
delete obj.Tab
delete obj['Shift-Tab']
return obj
}
})
export default function App() {
const editor = useCreateBlockNote({
_tiptapOptions: {
extensions: [
newBlockContainer.configure({
editor, // the editor has not been initialized
domAttributes: {},
})
]
},
disableExtensions: ['blockContainer'],
});
return <BlockNoteView editor={editor} />;
}
However, the issue lies in the fact that the configure method requires the editor object, which, at this point, has not been fully initialized, leading to an error. In this scenario, perhaps the tiptapOptions could be a function instead?
_tiptapOptions: (editor) => Partial<EditorOptions>
and I'am wondering why this https://github.com/TypeCellOS/BlockNote/pull/408 PR hasn't been merged?
and I'am wondering why this #408 PR hasn't been merged?
This PR doesn't completely removed block nesting - it's a bandaid fix that disables functions to nest/unnest blocks, but nested blocks are allowed in the schema. This means that you can still create them by e.g. copy pasting a nested list from somewhere else, passing them in initialContent, etc. Implementing this feature is a bigger undertaking than it seems, because most block-related types have to be overhauled to "properly" remove nesting.
Also, nesting is a pretty core feature of BlockNote, so adding this hasn't been a high priority issue
@matthewlipski because I need to transform the editor exported JSON data to another data structure, for some history reason. and the data structure do not support nesting. so that I want to disable the nesting feature.
i know this method is not perfect, but it's enough for us. and how about if someone want to extend some buildin extensions?
so I hope this PR can be merged
From what I found, there are three ways to indent on the editor: the indent from the toolbar, using the tab key, and to paste text with indentation.
To remove the indent and unindent from the toolbar, customize the toolbar itself by removing the NestBlockButton and UnnestBlockButton.
<BlockNoteView
editor={editor}
formattingToolbar={false}
>
<FormattingToolbarController
formattingToolbar={() => (
<FormattingToolbar>
<BlockTypeSelect key={"blockTypeSelect"} />
<FileCaptionButton key={"fileCaptionButton"} />
<FileReplaceButton key={"replaceFileButton"} />
<BasicTextStyleButton
basicTextStyle={"bold"}
key={"boldStyleButton"}
/>
<BasicTextStyleButton
basicTextStyle={"italic"}
key={"italicStyleButton"}
/>
<BasicTextStyleButton
basicTextStyle={"underline"}
key={"underlineStyleButton"}
/>
<BasicTextStyleButton
basicTextStyle={"strike"}
key={"strikeStyleButton"}
/>
<BasicTextStyleButton
key={"codeStyleButton"}
basicTextStyle={"code"}
/>
<TextAlignButton
textAlignment={"left"}
key={"textAlignLeftButton"}
/>
<TextAlignButton
textAlignment={"center"}
key={"textAlignCenterButton"}
/>
<TextAlignButton
textAlignment={"right"}
key={"textAlignRightButton"}
/>
<ColorStyleButton key={"colorStyleButton"} />
<CreateLinkButton key={"createLinkButton"} />
</FormattingToolbar>
)}
/>
</BlockNoteView>
To disable the tab key and to format the pasted text, I used the _tipTapOptions.editorProps option on the useCreateBlockNote().
const editor = useCreateBlockNote({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...(blocks.length > 0 && { initialContent: [...(blocks as any)] }),
schema,
uploadFile,
_tiptapOptions: {
editorProps: {
handleDOMEvents: {
drop: () => true,
},
handleKeyDown: (_, event) => {
// Disable tab key
if (event.key === "Tab") {
event.preventDefault();
return true;
}
return false;
},
transformPastedText: (text) => {
// Remove all types of whitespace from the start of lines
return text
.split("\n")
.map((line) => line.replace(/^[\s\t]+/, ""))
.join("\n");
},
transformPastedHTML: (html) => {
// Remove any margin, padding, or text-indent CSS properties
return html.replace(/style="[^"]*"/g, (match) => {
return match
.replace(/margin-left:[^;"]+;?/g, "")
.replace(/padding-left:[^;"]+;?/g, "")
.replace(/text-indent:[^;"]+;?/g, "");
});
},
},
},
});
For my own use case, removing the styles from the indents works great because my problem was that the user can indent on the editor but there will be no indents on the resulting HTML.
Why do people need to disable nesting for blocknote?
This would likely be better implemented with the onBeforeChange API: https://www.blocknotejs.org/docs/reference/editor/events#onbeforechange