Skip to content

Commit 50b1328

Browse files
authored
feat(markdown): replace unified.js with custom markdown parser/serializer (#2624)
We've decided to move away from shipping the unified.js ecosystem for parsing and serializing to markdown and instead use our own custom parser/serializer. This should significantly reduce bundle-size, if you need to handle more complex edge cases with markdown, we would recommend preprocessing it beforehand and inserting the result into the editor as HTML (which we have better parsing support for).
1 parent 8ceea90 commit 50b1328

300 files changed

Lines changed: 13374 additions & 715 deletions

File tree

Some content is hidden

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

docs/content/docs/features/import/markdown.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ imageTitle: Markdown Import
1515

1616
BlockNote can import Markdown content into Block objects. Note that this is considered "lossy", as not all Markdown structures can be entirely represented as BlockNote blocks.
1717

18+
<Callout type={"warning"}>
19+
**BlockNote ships a minimal Markdown parser.** It covers the common subset used by most users (CommonMark + GFM basics: headings, paragraphs, lists, task lists, tables, code, blockquotes, links, images, emphasis, strikethrough, hard breaks).
20+
21+
There are many Markdown specifications (CommonMark, GFM, MDX, Pandoc, and various dialect-specific extensions) and supporting all of them inside a rich text editor is not a goal of BlockNote. **If you need to handle Markdown beyond this minimal subset, parse it to HTML yourself with a parser of your choice (e.g. [`marked`](https://github.com/markedjs/marked), [`markdown-it`](https://github.com/markdown-it/markdown-it), or [`remark`](https://github.com/remarkjs/remark)) and pass the resulting HTML to [`tryParseHTMLToBlocks`](/docs/features/import) instead.** BlockNote's HTML interoperability is much broader, since HTML is the format the editor uses internally for arbitrary pastes.
22+
</Callout>
23+
1824
## Markdown to Blocks
1925

2026
Use `tryParseMarkdownToBlocks` to try parsing a Markdown string into `Block` objects:

docs/content/docs/foundations/supported-formats.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,20 @@ export default function App() {
165165

166166
BlockNote also supports converting to and from Markdown. However, converting to and from Markdown is a **lossy** conversion.
167167

168+
<Callout type="warning">
169+
BlockNote ships a **minimal** Markdown parser/serializer that targets the
170+
common CommonMark + GFM subset (headings, paragraphs, lists, task lists,
171+
tables, code, blockquotes, links, images, emphasis, strikethrough, hard
172+
breaks). Supporting every Markdown dialect (CommonMark, GFM, MDX, Pandoc,
173+
and various extensions) is not a goal for the editor. If your use case
174+
requires Markdown features beyond this subset, **parse the Markdown to
175+
HTML yourself** (with a library like [`marked`](https://github.com/markedjs/marked),
176+
[`markdown-it`](https://github.com/markdown-it/markdown-it), or
177+
[`remark`](https://github.com/remarkjs/remark)) and feed the resulting
178+
HTML to `editor.tryParseHTMLToBlocks` — HTML is the format BlockNote uses
179+
for arbitrary pastes and has much broader interoperability.
180+
</Callout>
181+
168182
### Saving as Markdown
169183

170184
To convert the document to a Markdown string, you can use `editor.blocksToMarkdownLossy()`:

packages/core/package.json

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,18 @@
107107
"@tiptap/pm": "^3.13.0",
108108
"emoji-mart": "^5.6.0",
109109
"fast-deep-equal": "^3.1.3",
110-
"hast-util-from-dom": "^5.0.1",
111110
"lib0": "^0.2.99",
112111
"prosemirror-highlight": "^0.15.1",
113112
"prosemirror-model": "^1.25.4",
114113
"prosemirror-state": "^1.4.4",
115114
"prosemirror-tables": "^1.8.3",
116115
"prosemirror-transform": "^1.11.0",
117116
"prosemirror-view": "^1.41.4",
118-
"rehype-format": "^5.0.1",
119-
"rehype-parse": "^9.0.1",
120-
"rehype-remark": "^10.0.1",
121-
"rehype-stringify": "^10.0.1",
122-
"remark-gfm": "^4.0.1",
123-
"remark-parse": "^11.0.0",
124-
"remark-rehype": "^11.1.2",
125-
"remark-stringify": "^11.0.0",
126-
"unified": "^11.0.5",
127-
"unist-util-visit": "^5.0.0",
128117
"y-prosemirror": "^1.3.7",
129118
"y-protocols": "^1.0.6",
130119
"yjs": "^13.6.27"
131120
},
132121
"devDependencies": {
133-
"@types/hast": "^3.0.4",
134122
"eslint": "^8.57.1",
135123
"jsdom": "^29.0.2",
136124
"rimraf": "^5.0.10",

0 commit comments

Comments
 (0)