文档
Markdown 与 HTML

Markdown 与 HTML

可以导出或导入块到 Markdown 和 HTML。

⚠️

导入/导出 Markdown/HTML 的功能被视为「有损」;导出块到这些格式时,部分信息可能会丢失。

要序列化块为无损格式(例如,存储编辑器内容到后端),只需使用 JSON.stringify(editor.document) 导出内置块格式。

Markdown

BlockNote 可以导入 / 导出块到 Markdown。请注意这也是「有损」的,因为并非所有结构都能完全用 Markdown 表示。

将块转换为 Markdown

blocksToMarkdownLossyBlock 对象转换为 Markdown 字符串:

async blocksToMarkdownLossy(blocks?: Block[]): Promise<string>;
 
// 用法
const markdownFromBlocks = await editor.blocksToMarkdownLossy(blocks);

blocks: 要转换的块。如果未提供,则使用整个文档(所有顶级块)。

返回: 以 Markdown 字符串序列化的块。

输出经过简化,因为 Markdown 不支持 BlockNote 的所有功能(例如:非列表项块的子项会被取消嵌套,且某些样式会被移除)。

演示

import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
import { useEffect, useState } from "react";
 
import "./styles.css";
 
export default function App() {
  // Stores the editor's contents as Markdown.
  const [markdown, setMarkdown] = useState<string>("");
 
  // Creates a new editor instance with some initial content.
  const editor = useCreateBlockNote({
    initialContent: [
      {
        type: "paragraph",
        content: [
          "Hello, ",
          {
            type: "text",
            text: "world!",
            styles: {
              bold: true,
            },
          },
        ],
      },
    ],
  });
 
  const onChange = async () => {
    // Converts the editor's contents from Block objects to Markdown and store to state.
    const markdown = await editor.blocksToMarkdownLossy(editor.document);
    setMarkdown(markdown);
  };
 
  useEffect(() => {
    // on mount, trigger initial conversion of the initial content to md
    onChange();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
 
  // Renders the editor instance, and its contents as Markdown below.
  return (
    <div className={"wrapper"}>
      <div>Input (BlockNote Editor):</div>
      <div className={"item"}>
        <BlockNoteView editor={editor} onChange={onChange} />
      </div>
      <div>Output (Markdown):</div>
      <div className={"item bordered"}>
        <pre>
          <code>{markdown}</code>
        </pre>
      </div>
    </div>
  );
}
 

解析 Markdown 为块

使用 tryParseMarkdownToBlocks 尝试将 Markdown 字符串解析为 Block 对象:

async tryParseMarkdownToBlocks(markdown: string): Promise<Blocks[]>;
 
// 用法
const blocksFromMarkdown = await editor.tryParseMarkdownToBlocks(markdown);

返回: 从 Markdown 字符串解析得到的块。

尝试基于 Markdown 语法创建 BlockInlineContent 对象,但并非所有符号都被识别。如果 BlockNote 不认识某个符号,则将其作为文本解析。

演示

import "@blocknote/core/fonts/inter.css";
import { useCreateBlockNote } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { ChangeEvent, useCallback, useEffect } from "react";
 
const initialMarkdown = "Hello, **world!**";
 
export default function App() {
  // Creates a new editor instance.
  const editor = useCreateBlockNote();
 
  const markdownInputChanged = useCallback(
    async (e: ChangeEvent<HTMLTextAreaElement>) => {
      // Whenever the current Markdown content changes, converts it to an array of
      // Block objects and replaces the editor's content with them.
      const blocks = await editor.tryParseMarkdownToBlocks(e.target.value);
      editor.replaceBlocks(editor.document, blocks);
    },
    [editor],
  );
 
  // For initialization; on mount, convert the initial Markdown to blocks and replace the default editor's content
  useEffect(() => {
    async function loadInitialHTML() {
      const blocks = await editor.tryParseMarkdownToBlocks(initialMarkdown);
      editor.replaceBlocks(editor.document, blocks);
    }
    loadInitialHTML();
  }, [editor]);
 
  // Renders a text area for you to write/paste Markdown in, and the editor instance
  // below, which displays the current Markdown as blocks.
  return (
    <div className={"wrapper"}>
      <div>Input (Markdown):</div>
      <div className={"item bordered"}>
        <code>
          <textarea
            defaultValue={initialMarkdown}
            onChange={markdownInputChanged}
          />
        </code>
      </div>
      <div>Output (BlockNote Editor):</div>
      <div className={"item"}>
        <BlockNoteView editor={editor} editable={false} />
      </div>
    </div>
  );
}
 

导出 HTML(用于静态渲染)

使用 blocksToFullHTML 导出整个文档,包括所有结构、样式和格式。 导出的 HTML 与 BlockNote 用于渲染编辑器的 HTML 相同,包含所有嵌套块的结构。

例如,可以用此方法静态渲染用编辑器创建的文档。 渲染输出 HTML 时,确保引入相同的样式表(参见示例)。

async blocksToFullHTML(blocks?: Block[]): Promise<string>;
 
// 用法
const HTMLFromBlocks = await editor.blocksToFullHTML(blocks);

blocks: 要转换的块。如果未提供,则使用整个文档(所有顶级块)。

返回: 导出的 HTML 字符串。

HTML(用于互操作)

编辑器提供函数将块与 HTML 相互转换,实现与其他应用的互操作。

此方式将块转换为 HTML 会丢失部分信息,例如节点嵌套,以导出更简洁的 HTML 结构。

将块转换为 HTML

使用 blocksToHTMLLossy 导出 Block 对象为 HTML 字符串:

async blocksToHTMLLossy(blocks?: Block[]): Promise<string>;
 
// 用法
const HTMLFromBlocks = await editor.blocksToHTMLLossy(blocks);

blocks: 要转换的块。如果未提供,则使用整个文档(所有顶级块)。

返回: 导出的 HTML 字符串。

为了更符合法 HTML 标准,非列表项块的子项在输出 HTML 中会取消嵌套。

演示

import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
import { useEffect, useState } from "react";
 
import "./styles.css";
 
export default function App() {
  // Stores the editor's contents as HTML.
  const [html, setHTML] = useState<string>("");
 
  // Creates a new editor instance with some initial content.
  const editor = useCreateBlockNote({
    initialContent: [
      {
        type: "paragraph",
        content: [
          "Hello, ",
          {
            type: "text",
            text: "world!",
            styles: {
              bold: true,
            },
          },
        ],
      },
    ],
  });
 
  const onChange = async () => {
    // Converts the editor's contents from Block objects to HTML and store to state.
    const html = await editor.blocksToHTMLLossy(editor.document);
    setHTML(html);
  };
 
  useEffect(() => {
    // on mount, trigger initial conversion of the initial content to html
    onChange();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
 
  // Renders the editor instance, and its contents as HTML below.
  return (
    <div className="wrapper">
      <div>Input (BlockNote Editor):</div>
      <div className="item">
        <BlockNoteView editor={editor} onChange={onChange} />
      </div>
      <div>Output (HTML):</div>
      <div className="item bordered">
        <pre>
          <code>{html}</code>
        </pre>
      </div>
    </div>
  );
}
 

解析 HTML 为块

使用 tryParseHTMLToBlocks 将 HTML 字符串解析为 Block 对象:

async tryParseHTMLToBlocks(html: string): Promise<Blocks[]>;
 
// 用法
const blocksFromHTML = await editor.tryParseHTMLToBlocks(html);

返回: 从 HTML 字符串解析得到的块。

尝试从任何 HTML 块级元素创建 Block 对象,从任何 HTML 行内元素创建 InlineContent 对象,但并非所有 HTML 标签都被识别。如果 BlockNote 不认识元素标签,则作为段落或纯文本解析。

演示

import "@blocknote/core/fonts/inter.css";
import { useCreateBlockNote } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { ChangeEvent, useCallback, useEffect } from "react";
 
import "./styles.css";
 
const initialHTML = "<p>Hello, <strong>world!</strong></p>";
 
export default function App() {
  // Creates a new editor instance.
  const editor = useCreateBlockNote();
 
  const htmlInputChanged = useCallback(
    async (e: ChangeEvent<HTMLTextAreaElement>) => {
      // Whenever the current HTML content changes, converts it to an array of
      // Block objects and replaces the editor's content with them.
      const blocks = await editor.tryParseHTMLToBlocks(e.target.value);
      editor.replaceBlocks(editor.document, blocks);
    },
    [editor],
  );
 
  // For initialization; on mount, convert the initial HTML to blocks and replace the default editor's content
  useEffect(() => {
    async function loadInitialHTML() {
      const blocks = await editor.tryParseHTMLToBlocks(initialHTML);
      editor.replaceBlocks(editor.document, blocks);
    }
    loadInitialHTML();
  }, [editor]);
 
  // Renders a text area for you to write/paste HTML in, and the editor instance
  // below, which displays the current HTML as blocks.
  return (
    <div className={"wrapper"}>
      <div>Input (HTML):</div>
      <div className={"item bordered"}>
        <code>
          <textarea defaultValue={initialHTML} onChange={htmlInputChanged} />
        </code>
      </div>
      <div>Output (BlockNote Editor):</div>
      <div className={"item"}>
        <BlockNoteView editor={editor} editable={false} />
      </div>
    </div>
  );
}