mirror of
https://github.com/laurent22/joplin.git
synced 2026-03-13 08:09:59 +08:00
117 lines
5.2 KiB
TypeScript
117 lines
5.2 KiB
TypeScript
import { EditorSelection, EditorState } from '@codemirror/state';
|
|
import { frontMatterTagName, frontMatterContentTagName, frontMatterMarkerTagName } from './markdownFrontMatterExtension';
|
|
|
|
import createTestEditor from '../testing/createTestEditor';
|
|
import findNodesWithName from '../testing/findNodesWithName';
|
|
|
|
// Creates an EditorState with FrontMatter and markdown extensions
|
|
const createEditorState = async (initialText: string, expectedTags: string[]): Promise<EditorState> => {
|
|
return (await createTestEditor(initialText, EditorSelection.cursor(0), expectedTags)).state;
|
|
};
|
|
|
|
describe('MarkdownFrontMatterExtension', () => {
|
|
|
|
jest.retryTimes(2);
|
|
|
|
it('should parse a basic FrontMatter block at the start of the document', async () => {
|
|
const documentText = '---\ntitle: Test\n---\n\n# Heading';
|
|
const editor = await createEditorState(documentText, [frontMatterTagName, 'ATXHeading1']);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
expect(frontMatterNodes.length).toBe(1);
|
|
expect(frontMatterNodes[0].from).toBe(0);
|
|
expect(frontMatterNodes[0].to).toBe('---\ntitle: Test\n---'.length);
|
|
});
|
|
|
|
it('should parse FrontMatter with multiple properties', async () => {
|
|
const frontMatter = '---\ntitle: Test\ndate: 2024-01-01\ntags: [one, two]\n---';
|
|
const documentText = `${frontMatter}\n\nContent here.`;
|
|
const editor = await createEditorState(documentText, [frontMatterTagName]);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
expect(frontMatterNodes.length).toBe(1);
|
|
expect(frontMatterNodes[0].from).toBe(0);
|
|
expect(frontMatterNodes[0].to).toBe(frontMatter.length);
|
|
});
|
|
|
|
it('should not parse FrontMatter if not at document start', async () => {
|
|
const documentText = 'Some text\n\n---\ntitle: Test\n---';
|
|
const editor = await createEditorState(documentText, ['Paragraph']);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
// Should not be recognized as FrontMatter since it's not at the start
|
|
expect(frontMatterNodes.length).toBe(0);
|
|
});
|
|
|
|
it('should not parse FrontMatter without closing delimiter', async () => {
|
|
// Test document with --- at start but no closing delimiter
|
|
// This should be parsed as a horizontal rule followed by content
|
|
const documentText = '# Heading\n\n---\ntitle: Test';
|
|
const editor = await createEditorState(documentText, ['ATXHeading1', 'HorizontalRule']);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
// FrontMatter only works at the very start of the document, so this should not be recognized
|
|
expect(frontMatterNodes.length).toBe(0);
|
|
});
|
|
|
|
it('should treat the entire document as frontmatter when closing delimiter is missing (issue #14542)', async () => {
|
|
const documentText = '---\nsome: frontmatter\n--\n\n# Hey';
|
|
const editor = await createEditorState(documentText, [frontMatterTagName]);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
// Frontmatter block must be recognised and span the entire document
|
|
expect(frontMatterNodes.length).toBe(1);
|
|
expect(frontMatterNodes[0].from).toBe(0);
|
|
expect(frontMatterNodes[0].to).toBe(documentText.length);
|
|
});
|
|
|
|
it('should handle empty FrontMatter block', async () => {
|
|
const documentText = '---\n---\n\n# Heading';
|
|
const editor = await createEditorState(documentText, [frontMatterTagName, 'ATXHeading1']);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
|
|
expect(frontMatterNodes.length).toBe(1);
|
|
expect(frontMatterNodes[0].from).toBe(0);
|
|
expect(frontMatterNodes[0].to).toBe('---\n---'.length);
|
|
});
|
|
|
|
it('should have FrontMatterContent as child node', async () => {
|
|
const documentText = '---\nkey: value\n---';
|
|
const editor = await createEditorState(documentText, [frontMatterTagName]);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
const contentNodes = findNodesWithName(editor, frontMatterContentTagName);
|
|
|
|
expect(frontMatterNodes.length).toBe(1);
|
|
// Content node may be replaced by YAML parser, but if not, it should exist
|
|
// The presence depends on whether YAML language was loaded
|
|
expect(contentNodes.length).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
it('should not confuse horizontal rules with FrontMatter', async () => {
|
|
const documentText = '# Title\n\n---\n\nSome text';
|
|
const editor = await createEditorState(documentText, ['ATXHeading1', 'HorizontalRule']);
|
|
const frontMatterNodes = findNodesWithName(editor, frontMatterTagName);
|
|
const hrNodes = findNodesWithName(editor, 'HorizontalRule');
|
|
|
|
expect(frontMatterNodes.length).toBe(0);
|
|
expect(hrNodes.length).toBe(1);
|
|
});
|
|
|
|
it('should create FrontMatterMarker nodes for the delimiters', async () => {
|
|
const documentText = '---\ntitle: Test\n---\n\n# Heading';
|
|
const editor = await createEditorState(documentText, [frontMatterTagName, frontMatterMarkerTagName]);
|
|
const markerNodes = findNodesWithName(editor, frontMatterMarkerTagName);
|
|
|
|
// Should have two markers: opening and closing ---
|
|
expect(markerNodes.length).toBe(2);
|
|
|
|
// Opening marker
|
|
expect(markerNodes[0].from).toBe(0);
|
|
expect(markerNodes[0].to).toBe(3); // '---'.length
|
|
|
|
// Closing marker
|
|
expect(markerNodes[1].from).toBe('---\ntitle: Test\n'.length);
|
|
expect(markerNodes[1].to).toBe('---\ntitle: Test\n---'.length);
|
|
});
|
|
});
|