Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to disable nest or unnest feature? #876

Open
jueinin opened this issue Jun 27, 2024 · 5 comments
Open

how to disable nest or unnest feature? #876

jueinin opened this issue Jun 27, 2024 · 5 comments
Labels
enhancement New feature or request

Comments

@jueinin
Copy link

jueinin commented Jun 27, 2024

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>
@jueinin
Copy link
Author

jueinin commented Jun 27, 2024

and I'am wondering why this #408 PR hasn't been merged?

@matthewlipski
Copy link
Collaborator

matthewlipski commented Jun 27, 2024

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.

@matthewlipski
Copy link
Collaborator

Also, nesting is a pretty core feature of BlockNote, so adding this hasn't been a high priority issue

@jueinin
Copy link
Author

jueinin commented Jun 28, 2024

@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

@vincealwynsibay
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants