snapshot of https://github.com/ueberdosis/tiptap.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
This commit is contained in:
212
packages/markdown/tests/integration/server-side-parsing.test.ts
Normal file
212
packages/markdown/tests/integration/server-side-parsing.test.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* @vitest-environment node
|
||||
*/
|
||||
|
||||
import { Code } from '@tiptap/extension-code'
|
||||
import { Document } from '@tiptap/extension-document'
|
||||
import { Heading } from '@tiptap/extension-heading'
|
||||
import { Paragraph } from '@tiptap/extension-paragraph'
|
||||
import { Strike } from '@tiptap/extension-strike'
|
||||
import { Text } from '@tiptap/extension-text'
|
||||
import { MarkdownManager } from '@tiptap/markdown'
|
||||
import { beforeEach, describe, expect, it } from 'vite-plus/test'
|
||||
|
||||
describe('MarkdownManager Server-side Parsing', () => {
|
||||
let manager: MarkdownManager
|
||||
const basicExtensions = [Document, Paragraph, Text, Strike, Code, Heading]
|
||||
|
||||
beforeEach(() => {
|
||||
manager = new MarkdownManager({ extensions: basicExtensions })
|
||||
})
|
||||
|
||||
it('parses inline code with HTML-like tags and strike marks without error', () => {
|
||||
const md = '`<h1>`~`<h6>`'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
|
||||
const paragraph = doc.content![0]
|
||||
expect(paragraph.type).toBe('paragraph')
|
||||
expect(paragraph.content).toBeDefined()
|
||||
|
||||
// Find text nodes with code marks (inline code)
|
||||
const codeTextNodes = paragraph.content!.filter(
|
||||
(n: any) => n.type === 'text' && n.marks?.some((m: any) => m.type === 'code'),
|
||||
)
|
||||
expect(codeTextNodes.length).toBeGreaterThan(0)
|
||||
|
||||
// At least one code segment should contain an HTML-like tag
|
||||
const hasHtmlTag = codeTextNodes.some(
|
||||
(n: any) => n.text && (n.text.includes('<h1>') || n.text.includes('<h6>')),
|
||||
)
|
||||
expect(hasHtmlTag).toBe(true)
|
||||
|
||||
// All text content combined should include both HTML tags and the tilde
|
||||
const allTextNodes = paragraph.content!.filter((n: any) => n.type === 'text')
|
||||
const allText = allTextNodes.map((n: any) => n.text).join('')
|
||||
expect(allText).toContain('h1')
|
||||
expect(allText).toContain('h6')
|
||||
expect(allText).toMatch(/~/)
|
||||
})
|
||||
|
||||
it('parses inline code with HTML-like tags and double strike marks without error', () => {
|
||||
const md = '`<h1>`~~`<h6>`'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
|
||||
const paragraph = doc.content![0]
|
||||
expect(paragraph.type).toBe('paragraph')
|
||||
|
||||
// Find text nodes with code marks
|
||||
const codeTextNodes = paragraph.content!.filter(
|
||||
(n: any) => n.type === 'text' && n.marks?.some((m: any) => m.type === 'code'),
|
||||
)
|
||||
expect(codeTextNodes.length).toBeGreaterThan(0)
|
||||
|
||||
// At least one code segment should contain an HTML-like tag
|
||||
const hasHtmlTag = codeTextNodes.some(
|
||||
(n: any) => n.text && (n.text.includes('<h1>') || n.text.includes('<h6>')),
|
||||
)
|
||||
expect(hasHtmlTag).toBe(true)
|
||||
|
||||
// All text should contain both HTML tags
|
||||
const allTextNodes = paragraph.content!.filter((n: any) => n.type === 'text')
|
||||
const allText = allTextNodes.map((n: any) => n.text).join('')
|
||||
expect(allText).toContain('h1')
|
||||
expect(allText).toContain('h6')
|
||||
})
|
||||
|
||||
it('parses strike marks in normal text', () => {
|
||||
const md = 'a~b'
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(Array.isArray(doc.content)).toBe(true)
|
||||
})
|
||||
|
||||
it('parses HTML heading tags with strike marks', () => {
|
||||
const md = '<h1>~~test~~</h1>'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
|
||||
const paragraph = doc.content![0]
|
||||
expect(paragraph.type).toBe('paragraph')
|
||||
expect(paragraph.content).toBeDefined()
|
||||
|
||||
// In Node.js environment, HTML tags should be treated as literal text
|
||||
const allText = paragraph
|
||||
.content!.map((n: any) =>
|
||||
n.text ? n.text : n.content?.map((c: any) => c.text).join('') || '',
|
||||
)
|
||||
.join('')
|
||||
|
||||
// Should contain the HTML tags as literal text
|
||||
expect(allText).toContain('<h1>')
|
||||
expect(allText).toContain('</h1>')
|
||||
|
||||
// Should contain 'test' text
|
||||
expect(allText).toContain('test')
|
||||
})
|
||||
|
||||
it('parses multiple inline code segments with HTML-like content and strike', () => {
|
||||
const md = 'text `<h1>` more ~~text~~ and `<h2>`'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
|
||||
const paragraph = doc.content![0]
|
||||
expect(paragraph.type).toBe('paragraph')
|
||||
|
||||
// Find text nodes with code marks (inline code)
|
||||
const codeTextNodes = paragraph.content!.filter(
|
||||
(n: any) => n.type === 'text' && n.marks?.some((m: any) => m.type === 'code'),
|
||||
)
|
||||
expect(codeTextNodes.length).toBeGreaterThanOrEqual(2)
|
||||
|
||||
// Code text should contain literal HTML-like tags
|
||||
expect(codeTextNodes[0].text).toBe('<h1>')
|
||||
expect(codeTextNodes[1].text).toBe('<h2>')
|
||||
|
||||
// Find text nodes with strike marks
|
||||
const textNodes = paragraph.content!.filter((n: any) => n.type === 'text')
|
||||
const strikeTextNode = textNodes.find(
|
||||
(n: any) =>
|
||||
n.text && n.text.includes('text') && n.marks?.some((m: any) => m.type === 'strike'),
|
||||
)
|
||||
expect(strikeTextNode).toBeDefined()
|
||||
})
|
||||
|
||||
it('preserves unknown angle-bracket placeholders as literal text in server environment', () => {
|
||||
const md = '<enter existing CID here if available>\n\nother text after'
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(Array.isArray(doc.content)).toBe(true)
|
||||
expect(doc.content).toHaveLength(2)
|
||||
|
||||
// angle-bracket placeholder preserved as literal text
|
||||
const firstPara = doc.content![0]
|
||||
expect(firstPara.type).toBe('paragraph')
|
||||
expect(firstPara.content).toHaveLength(1)
|
||||
expect(firstPara.content![0].type).toBe('text')
|
||||
expect(firstPara.content![0].text).toBe('<enter existing CID here if available>')
|
||||
|
||||
// trailing text after the blank line
|
||||
const secondPara = doc.content![1]
|
||||
expect(secondPara.type).toBe('paragraph')
|
||||
expect(secondPara.content).toHaveLength(1)
|
||||
expect(secondPara.content![0].type).toBe('text')
|
||||
expect(secondPara.content![0].text).toBe('other text after')
|
||||
})
|
||||
|
||||
it('parses HTML tags as plain text in server environment', () => {
|
||||
const md = '<p>Hello</p>'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
expect(Array.isArray(doc.content)).toBe(true)
|
||||
|
||||
// The document should have a paragraph
|
||||
const paragraph = doc.content![0]
|
||||
expect(paragraph.type).toBe('paragraph')
|
||||
expect(paragraph.content).toBeDefined()
|
||||
|
||||
// The HTML should be preserved as literal text (not parsed)
|
||||
const textContent = paragraph.content!.map((n: any) => n.text).join('')
|
||||
expect(textContent).toContain('<p>Hello</p>')
|
||||
})
|
||||
|
||||
it('still parses markdown syntax correctly alongside HTML', () => {
|
||||
const md = '<div>test</div> ~~world~~'
|
||||
|
||||
const doc = manager.parse(md)
|
||||
|
||||
expect(doc.type).toBe('doc')
|
||||
expect(doc.content).toBeDefined()
|
||||
|
||||
// Find all text nodes
|
||||
const textNodes = doc.content!.flatMap((node: any) =>
|
||||
node.content ? node.content.filter((n: any) => n.type === 'text') : [],
|
||||
)
|
||||
|
||||
// Should have HTML as literal text
|
||||
const hasHtmlText = textNodes.some((n: any) => n.text && n.text.includes('<div>test</div>'))
|
||||
expect(hasHtmlText).toBe(true)
|
||||
|
||||
// Should have 'world' text (with or without strike mark depending on parsing)
|
||||
const hasWorldText = textNodes.some((n: any) => n.text && n.text.includes('world'))
|
||||
expect(hasWorldText).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user