import { EditorSelection, EditorState } from "@codemirror/state"; import type { EditorView } from "@codemirror/view"; import { expect, test } from "vitest"; import { applyPlainleafEditorAction, type PlainleafEditorAction, } from "./plainleaf_markdown_toolbar.ts"; function edit( text: string, action: PlainleafEditorAction, from = 0, to = text.length, ) { let state = EditorState.create({ doc: text, selection: EditorSelection.range(from, to), }); const view = { get state() { return state; }, dispatch(spec: Parameters[0]) { state = state.update(spec).state; }, focus() {}, } as unknown as EditorView; expect(applyPlainleafEditorAction(view, action)).toBe(true); return { text: state.doc.toString(), from: state.selection.main.from, to: state.selection.main.to, }; } test("turns selected lines into headings and toggles the active heading", () => { expect(edit("标题", "heading-1").text).toBe("# 标题"); expect(edit("# 标题", "heading-1").text).toBe("标题"); expect(edit("# 标题", "heading-2").text).toBe("## 标题"); }); test("creates Markdown lists and task items for multiple lines", () => { expect(edit("第一项\n第二项", "bullet-list").text).toBe("- 第一项\n- 第二项"); expect(edit("第一项\n第二项", "numbered-list").text).toBe( "1. 第一项\n2. 第二项", ); expect(edit("第一项\n第二项", "task-list").text).toBe( "- [ ] 第一项\n- [ ] 第二项", ); }); test("wraps selected text and selects the editable URL", () => { expect(edit("重点", "bold")).toMatchObject({ text: "**重点**", from: 2, to: 4, }); const link = edit("官网", "link"); expect(link.text).toBe("[官网](https://)"); expect(link.text.slice(link.from, link.to)).toBe("https://"); }); test("uses fenced code for multi-line selections", () => { expect(edit("a\nb", "code").text).toBe("```\na\nb\n```"); });