[Bug] @tiptap/markdown: code blocks containing backticks serialize with an unsafe fence and break on round trip
Affected Packages
markdown, extension-code-block
Tiptap Version
3.30.5
Browser Used
Not browser-specific
What happened?
Code blocks are always serialized with exactly three backticks, even when their content contains a triple-backtick fence.
A valid Markdown code block enclosed in four backticks parses correctly. After serialization, the outer fence is shortened to three backticks, allowing a fence inside the content to close the block prematurely on the next parse.
import { flattenExtensions } from '@tiptap/core'
import { MarkdownManager } from '@tiptap/markdown'
import StarterKit from '@tiptap/starter-kit'
const manager = new MarkdownManager({
extensions: flattenExtensions([StarterKit]),
})
const markdown = [
'````markdown',
'```js',
'console.log("Hello");',
'```',
'````',
].join('\n')
const document = manager.parse(markdown)
const serialized = manager.serialize(document)
const reparsed = manager.parse(serialized)
console.log(document.content?.length) // 1
console.log(serialized)
console.log(reparsed.content?.length) // 2The serialized Markdown is:
```markdown
```js
console.log("Hello");
```
```The inner closing fence now closes the outer block. The final fence opens a second, empty code block. The original code content therefore loses its closing triple backticks.
Expected Behavior
Serialization should choose a fence that cannot be closed by the code block’s contents. In this example, preserving the four-backtick outer fence would produce valid Markdown:
````markdown
```js
console.log("Hello");
```
````Parsing the serialized output should preserve the original single code block and its complete text content.
Reproducible Example URL (Optional)
No response
Additional Context (Optional)
Related to #8298, which describes the equivalent delimiter problem for inline code. This report concerns fenced code blocks in extension-code-block.
Source: ueberdosis/tiptap