Adds line numbers, current line highlight, and syntax highlighting (YAML frontmatter keys/values, --- delimiters, markdown headings). Extracted useCodeMirror hook and frontmatterHighlight extension. Preserves wikilink autocomplete, Cmd+S save, and Escape dismiss. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { EditorState } from '@codemirror/state'
|
|
import { EditorView } from '@codemirror/view'
|
|
import { frontmatterHighlightPlugin, frontmatterHighlightTheme } from './frontmatterHighlight'
|
|
|
|
function createView(doc: string) {
|
|
const parent = document.createElement('div')
|
|
document.body.appendChild(parent)
|
|
const state = EditorState.create({
|
|
doc,
|
|
extensions: [frontmatterHighlightPlugin, frontmatterHighlightTheme(false)],
|
|
})
|
|
const view = new EditorView({ state, parent })
|
|
return { view, parent }
|
|
}
|
|
|
|
describe('frontmatterHighlightPlugin', () => {
|
|
it('applies delimiter class to --- lines', () => {
|
|
const { view, parent } = createView('---\ntitle: Hello\n---\n\n# Heading')
|
|
const delimiters = parent.querySelectorAll('.cm-frontmatter-delimiter')
|
|
expect(delimiters.length).toBeGreaterThanOrEqual(2)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
|
|
it('applies key class to YAML keys', () => {
|
|
const { view, parent } = createView('---\ntitle: Hello\ntags: one\n---\n')
|
|
const keys = parent.querySelectorAll('.cm-frontmatter-key')
|
|
expect(keys.length).toBeGreaterThanOrEqual(2)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
|
|
it('applies value class to YAML values', () => {
|
|
const { view, parent } = createView('---\ntitle: Hello\n---\n')
|
|
const values = parent.querySelectorAll('.cm-frontmatter-value')
|
|
expect(values.length).toBeGreaterThanOrEqual(1)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
|
|
it('applies heading class to markdown headings', () => {
|
|
const { view, parent } = createView('# Heading One\n\nSome text\n\n## Heading Two')
|
|
const headings = parent.querySelectorAll('.cm-md-heading')
|
|
expect(headings.length).toBeGreaterThanOrEqual(2)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
|
|
it('does not apply heading class to plain text', () => {
|
|
const { view, parent } = createView('Just some plain text\nAnother line')
|
|
const headings = parent.querySelectorAll('.cm-md-heading')
|
|
expect(headings.length).toBe(0)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
|
|
it('handles content without frontmatter', () => {
|
|
const { view, parent } = createView('# Just a heading\n\nNo frontmatter here.')
|
|
const delimiters = parent.querySelectorAll('.cm-frontmatter-delimiter')
|
|
expect(delimiters.length).toBe(0)
|
|
const keys = parent.querySelectorAll('.cm-frontmatter-key')
|
|
expect(keys.length).toBe(0)
|
|
view.destroy()
|
|
parent.remove()
|
|
})
|
|
})
|
|
|
|
describe('frontmatterHighlightTheme', () => {
|
|
it('returns an EditorView extension for light mode', () => {
|
|
const theme = frontmatterHighlightTheme(false)
|
|
expect(theme).toBeDefined()
|
|
})
|
|
|
|
it('returns an EditorView extension for dark mode', () => {
|
|
const theme = frontmatterHighlightTheme(true)
|
|
expect(theme).toBeDefined()
|
|
})
|
|
})
|