import { EditorSelection, EditorState } from '@codemirror/state'; import createTestEditor from '../testing/createTestEditor'; import findNodesWithName from '../testing/findNodesWithName'; import { highlightMarkerTagName, highlightTagName, insertMarkerTagName, insertTagName } from './markdownHighlightExtension'; const createEditorState = async (initialText: string, expectedTags: string[]): Promise => { return (await createTestEditor(initialText, EditorSelection.cursor(0), expectedTags)).state; }; describe('markdownHighlightExtension', () => { jest.retryTimes(2); it.each([ { // Should support single-word highlights text: '==highlight==', expectedHighlightRanges: [{ from: 0, to: '==highlight=='.length }], expectedMarkerRanges: [ { from: 0, to: 2 }, { from: '==highlight'.length, to: '==highlight=='.length }, ], }, { // Should support multi-word highlights text: '==highlight test==', expectedHighlightRanges: [{ from: 0, to: '==highlight test=='.length }], expectedMarkerRanges: [ { from: 0, to: 2 }, { from: '==highlight test'.length, to: '==highlight test=='.length }, ], }, { // Should support within-word highlights text: 'test==ing==', expectedHighlightRanges: [{ from: 'test'.length, to: 'test==ing=='.length }], }, { // Should not highlight if just one = text: 'test==ing=', expectedHighlightRanges: [], }, { // Should not highlight within code text: '`==highlight test==`', expectedHighlightRanges: [], expectedMarkerRanges: [], }, { // Should highlight across line breaks text: '==highlight\ntest== test', expectedHighlightRanges: [{ from: 0, to: '==highlight\ntest=='.length }], }, { // Should not highlight across paragraph breaks text: '==highlight\n\ntest== test', expectedHighlightRanges: [], expectedMarkerRanges: [], }, ])('should parse inline highlights (case %#: %j)', async ({ text, expectedHighlightRanges, expectedMarkerRanges }) => { const expectedNodes: string[] = []; if (expectedHighlightRanges.length) { expectedNodes.push(highlightTagName); } if (expectedMarkerRanges?.length) { expectedNodes.push(highlightMarkerTagName); } const editor = await createEditorState(text, expectedNodes); const highlightNodes = findNodesWithName(editor, highlightTagName); expect(highlightNodes).toMatchObject(expectedHighlightRanges); if (expectedMarkerRanges) { const markerNodes = findNodesWithName(editor, highlightMarkerTagName); expect(markerNodes).toMatchObject(expectedMarkerRanges); } }); it.each([ { // Should support single-word insert text: '++insert++', expectedInsertRanges: [{ from: 0, to: '++insert++'.length }], expectedMarkerRanges: [ { from: 0, to: 2 }, { from: '++insert'.length, to: '++insert++'.length }, ], }, { // Should not parse if only one + text: 'test++ing+', expectedInsertRanges: [], }, ])('should parse inline insert (case %#: %j)', async ({ text, expectedInsertRanges, expectedMarkerRanges }) => { const expectedNodes: string[] = []; if (expectedInsertRanges.length) { expectedNodes.push(insertTagName); } if (expectedMarkerRanges?.length) { expectedNodes.push(insertMarkerTagName); } const editor = await createEditorState(text, expectedNodes); const insertNodes = findNodesWithName(editor, insertTagName); expect(insertNodes).toMatchObject(expectedInsertRanges); if (expectedMarkerRanges) { const markerNodes = findNodesWithName(editor, insertMarkerTagName); expect(markerNodes).toMatchObject(expectedMarkerRanges); } }); });