feat: add tests for YAML front matter tokenizer and enhance parsing logic

This commit is contained in:
suyao 2025-12-22 13:26:01 +08:00
parent a8ded04eef
commit daf5b7c5a1
No known key found for this signature in database
2 changed files with 91 additions and 2 deletions

View File

@ -0,0 +1,84 @@
import type { JSONContent } from '@tiptap/core'
import { MarkdownManager } from '@tiptap/markdown'
import { describe, expect, it } from 'vitest'
import { YamlFrontMatter } from '../yaml-front-matter'
const parseFrontMatters = (markdown: string) => {
const manager = new MarkdownManager({
extensions: [YamlFrontMatter]
})
const doc = manager.parse(markdown) as JSONContent
const frontMatterNodes = (doc.content || []).filter((node) => node.type === 'yamlFrontMatter')
return frontMatterNodes.map((node) => (node.attrs as { content?: string } | undefined)?.content?.trim())
}
describe('YamlFrontMatter markdown tokenizer', () => {
it('only parses the first front matter block at the very start of the document', () => {
const markdown = `---
title: First
---
Body text
---
title: Second
---
More content`
const contents = parseFrontMatters(markdown)
expect(contents).toHaveLength(1)
expect(contents[0]).toBe('title: First')
})
it('ignores a front matter block when it is not at the beginning of the document', () => {
const markdown = `Intro paragraph
---
title: Should not parse
---`
const contents = parseFrontMatters(markdown)
expect(contents).toHaveLength(0)
})
it('ignores consecutive front matter blocks after the first one', () => {
const markdown = `---
first: yes
---
---
second: no
---`
const contents = parseFrontMatters(markdown)
expect(contents).toHaveLength(1)
expect(contents[0]).toBe('first: yes')
})
it('does not treat body content containing --- as additional front matter', () => {
const markdown = `---
title: Only header
---
Paragraph text.
---
More text.`
const contents = parseFrontMatters(markdown)
expect(contents).toHaveLength(1)
expect(contents[0]).toBe('title: Only header')
})
it('treats later front matter markers as regular markdown when content already exists', () => {
const markdown = `Intro paragraph
---
title: Should not parse
---`
const contents = parseFrontMatters(markdown)
expect(contents).toHaveLength(0)
})
})

View File

@ -1,4 +1,4 @@
import { mergeAttributes, Node } from '@tiptap/core'
import { type MarkdownToken,mergeAttributes, Node } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import YamlFrontMatterNodeView from '../components/YamlFrontMatterNodeView'
@ -27,7 +27,12 @@ export const YamlFrontMatter = Node.create({
return result
},
// Parse YAML front matter
tokenize(src: string) {
tokenize(src: string, tokens: MarkdownToken[] = []) {
const hasExistingContent = tokens.some((token) => token.type && token.type !== 'space')
if (hasExistingContent) {
return undefined
}
// Match: ---\n...yaml content...\n---
const match = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(src)