@lapismd/mira 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/extensions/index.d.ts +7 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/preview/editable-markdown-preview/editable-markdown-surface.svelte +20 -9
- package/dist/preview/editable-markdown-preview/editable-markdown-surface.svelte.d.ts.map +1 -1
- package/dist/preview/editable-markdown-preview/editing-session.d.ts +13 -0
- package/dist/preview/editable-markdown-preview/editing-session.d.ts.map +1 -0
- package/dist/preview/editable-markdown-preview/editing-session.js +50 -0
- package/dist/preview/editable-markdown-preview/editor-surface.svelte +13 -4
- package/dist/preview/editable-markdown-preview/editor-surface.svelte.d.ts +1 -0
- package/dist/preview/editable-markdown-preview/editor-surface.svelte.d.ts.map +1 -1
- package/dist/preview/editable-markdown-preview/serialized-writer.d.ts +5 -1
- package/dist/preview/editable-markdown-preview/serialized-writer.d.ts.map +1 -1
- package/dist/preview/editable-markdown-preview/serialized-writer.js +29 -0
- package/dist/preview/editable-markdown-preview.svelte +8 -6
- package/dist/preview/editable-markdown-preview.svelte.d.ts.map +1 -1
- package/package.json +5 -2
- package/dist/core/code-mirror.test.d.ts +0 -2
- package/dist/core/code-mirror.test.d.ts.map +0 -1
- package/dist/core/code-mirror.test.js +0 -68
- package/dist/core/images.test.d.ts +0 -2
- package/dist/core/images.test.d.ts.map +0 -1
- package/dist/core/images.test.js +0 -109
- package/dist/core/index.test.d.ts +0 -2
- package/dist/core/index.test.d.ts.map +0 -1
- package/dist/core/index.test.js +0 -11
- package/dist/core/markdown-actions.test.d.ts +0 -2
- package/dist/core/markdown-actions.test.d.ts.map +0 -1
- package/dist/core/markdown-actions.test.js +0 -182
- package/dist/extensions/doodle-dividers.test.d.ts +0 -2
- package/dist/extensions/doodle-dividers.test.d.ts.map +0 -1
- package/dist/extensions/doodle-dividers.test.js +0 -296
- package/dist/extensions/index.test.d.ts +0 -2
- package/dist/extensions/index.test.d.ts.map +0 -1
- package/dist/extensions/index.test.js +0 -283
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -64
- package/dist/internal/appearance-context.test.d.ts +0 -2
- package/dist/internal/appearance-context.test.d.ts.map +0 -1
- package/dist/internal/appearance-context.test.js +0 -31
- package/dist/internal/codemirror/base/index.test.d.ts +0 -2
- package/dist/internal/codemirror/base/index.test.d.ts.map +0 -1
- package/dist/internal/codemirror/base/index.test.js +0 -303
- package/dist/internal/codemirror/base/search.test.d.ts +0 -2
- package/dist/internal/codemirror/base/search.test.d.ts.map +0 -1
- package/dist/internal/codemirror/base/search.test.js +0 -155
- package/dist/internal/codemirror/base/selection-toolbar.test.d.ts +0 -2
- package/dist/internal/codemirror/base/selection-toolbar.test.d.ts.map +0 -1
- package/dist/internal/codemirror/base/selection-toolbar.test.js +0 -149
- package/dist/internal/codemirror/markdown/authoring.test.d.ts +0 -2
- package/dist/internal/codemirror/markdown/authoring.test.d.ts.map +0 -1
- package/dist/internal/codemirror/markdown/authoring.test.js +0 -222
- package/dist/internal/codemirror/markdown/index.test.d.ts +0 -2
- package/dist/internal/codemirror/markdown/index.test.d.ts.map +0 -1
- package/dist/internal/codemirror/markdown/index.test.js +0 -158
- package/dist/internal/codemirror/markdown/showcase-fixture.test.d.ts +0 -2
- package/dist/internal/codemirror/markdown/showcase-fixture.test.d.ts.map +0 -1
- package/dist/internal/codemirror/markdown/showcase-fixture.test.js +0 -50
- package/dist/internal/codemirror/rich/block-controls.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/block-controls.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/block-controls.test.js +0 -401
- package/dist/internal/codemirror/rich/block-ranges.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/block-ranges.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/block-ranges.test.js +0 -310
- package/dist/internal/codemirror/rich/block-toolbar.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/block-toolbar.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/block-toolbar.test.js +0 -178
- package/dist/internal/codemirror/rich/decorations/fold-indicators.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/decorations/fold-indicators.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/decorations/fold-indicators.test.js +0 -8
- package/dist/internal/codemirror/rich/index.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/index.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/index.test.js +0 -607
- package/dist/internal/codemirror/rich/utils/code-block-lines.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/code-block-lines.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/code-block-lines.test.js +0 -82
- package/dist/internal/codemirror/rich/utils/fenced-code.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/fenced-code.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/fenced-code.test.js +0 -12
- package/dist/internal/codemirror/rich/utils/headings.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/headings.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/headings.test.js +0 -27
- package/dist/internal/codemirror/rich/utils/height-estimates.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/height-estimates.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/height-estimates.test.js +0 -10
- package/dist/internal/codemirror/rich/utils/images.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/images.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/images.test.js +0 -37
- package/dist/internal/codemirror/rich/utils/indent.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/indent.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/indent.test.js +0 -169
- package/dist/internal/codemirror/rich/utils/inline-math.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/inline-math.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/inline-math.test.js +0 -15
- package/dist/internal/codemirror/rich/utils/links.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/links.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/links.test.js +0 -28
- package/dist/internal/codemirror/rich/utils/list-callouts.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/list-callouts.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/list-callouts.test.js +0 -47
- package/dist/internal/codemirror/rich/utils/measured-indent.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/measured-indent.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/measured-indent.test.js +0 -102
- package/dist/internal/codemirror/rich/utils/ranges.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/ranges.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/ranges.test.js +0 -22
- package/dist/internal/codemirror/rich/utils/tasks.test.d.ts +0 -2
- package/dist/internal/codemirror/rich/utils/tasks.test.d.ts.map +0 -1
- package/dist/internal/codemirror/rich/utils/tasks.test.js +0 -57
- package/dist/internal/task-states.test.d.ts +0 -2
- package/dist/internal/task-states.test.d.ts.map +0 -1
- package/dist/internal/task-states.test.js +0 -36
- package/dist/mira-code-editor.test.d.ts +0 -2
- package/dist/mira-code-editor.test.d.ts.map +0 -1
- package/dist/mira-code-editor.test.js +0 -93
- package/dist/mode-position.test.d.ts +0 -2
- package/dist/mode-position.test.d.ts.map +0 -1
- package/dist/mode-position.test.js +0 -60
- package/dist/preview/code-language.test.d.ts +0 -2
- package/dist/preview/code-language.test.d.ts.map +0 -1
- package/dist/preview/code-language.test.js +0 -12
- package/dist/preview/components/icon.test.d.ts +0 -2
- package/dist/preview/components/icon.test.d.ts.map +0 -1
- package/dist/preview/components/icon.test.js +0 -20
- package/dist/preview/editable-markdown-preview/behavior.test.d.ts +0 -2
- package/dist/preview/editable-markdown-preview/behavior.test.d.ts.map +0 -1
- package/dist/preview/editable-markdown-preview/behavior.test.js +0 -36
- package/dist/preview/editable-markdown-preview/serialized-writer.test.d.ts +0 -2
- package/dist/preview/editable-markdown-preview/serialized-writer.test.d.ts.map +0 -1
- package/dist/preview/editable-markdown-preview/serialized-writer.test.js +0 -59
- package/dist/preview/embed-target.test.d.ts +0 -2
- package/dist/preview/embed-target.test.d.ts.map +0 -1
- package/dist/preview/embed-target.test.js +0 -78
- package/dist/preview/frontmatter/frontmatter.test.d.ts +0 -2
- package/dist/preview/frontmatter/frontmatter.test.d.ts.map +0 -1
- package/dist/preview/frontmatter/frontmatter.test.js +0 -190
- package/dist/preview/frontmatter/suggestions.test.d.ts +0 -2
- package/dist/preview/frontmatter/suggestions.test.d.ts.map +0 -1
- package/dist/preview/frontmatter/suggestions.test.js +0 -45
- package/dist/preview/outline.test.d.ts +0 -2
- package/dist/preview/outline.test.d.ts.map +0 -1
- package/dist/preview/outline.test.js +0 -98
- package/dist/preview/portable-surfaces.test.d.ts +0 -2
- package/dist/preview/portable-surfaces.test.d.ts.map +0 -1
- package/dist/preview/portable-surfaces.test.js +0 -513
- package/dist/preview/preview.test.d.ts +0 -2
- package/dist/preview/preview.test.d.ts.map +0 -1
- package/dist/preview/preview.test.js +0 -154
- package/dist/preview/remark/callouts.test.d.ts +0 -2
- package/dist/preview/remark/callouts.test.d.ts.map +0 -1
- package/dist/preview/remark/callouts.test.js +0 -23
- package/dist/preview/remark/custom-checklists.test.d.ts +0 -2
- package/dist/preview/remark/custom-checklists.test.d.ts.map +0 -1
- package/dist/preview/remark/custom-checklists.test.js +0 -51
- package/dist/preview/remark/links.test.d.ts +0 -2
- package/dist/preview/remark/links.test.d.ts.map +0 -1
- package/dist/preview/remark/links.test.js +0 -62
- package/dist/preview/remark/parity.test.d.ts +0 -2
- package/dist/preview/remark/parity.test.d.ts.map +0 -1
- package/dist/preview/remark/parity.test.js +0 -105
- package/dist/preview/styles/frontmatter-properties.test.d.ts +0 -2
- package/dist/preview/styles/frontmatter-properties.test.d.ts.map +0 -1
- package/dist/preview/styles/frontmatter-properties.test.js +0 -57
- package/dist/preview/styles/source-mode.test.d.ts +0 -2
- package/dist/preview/styles/source-mode.test.d.ts.map +0 -1
- package/dist/preview/styles/source-mode.test.js +0 -28
- package/dist/tables/extension.test.d.ts +0 -2
- package/dist/tables/extension.test.d.ts.map +0 -1
- package/dist/tables/extension.test.js +0 -100
- package/dist/tables/grid-editor-column.test.d.ts +0 -2
- package/dist/tables/grid-editor-column.test.d.ts.map +0 -1
- package/dist/tables/grid-editor-column.test.js +0 -27
- package/dist/tables/grid-table.test.d.ts +0 -2
- package/dist/tables/grid-table.test.d.ts.map +0 -1
- package/dist/tables/grid-table.test.js +0 -140
- package/dist/tables/index.test.d.ts +0 -2
- package/dist/tables/index.test.d.ts.map +0 -1
- package/dist/tables/index.test.js +0 -7
- package/dist/tables/inline-editor-extensions.test.d.ts +0 -2
- package/dist/tables/inline-editor-extensions.test.d.ts.map +0 -1
- package/dist/tables/inline-editor-extensions.test.js +0 -23
- package/dist/tables/pipe-table.test.d.ts +0 -2
- package/dist/tables/pipe-table.test.d.ts.map +0 -1
- package/dist/tables/pipe-table.test.js +0 -13
- package/dist/tables/table-node.test.d.ts +0 -2
- package/dist/tables/table-node.test.d.ts.map +0 -1
- package/dist/tables/table-node.test.js +0 -167
- package/dist/tables/widgets/source-button.test.d.ts +0 -2
- package/dist/tables/widgets/source-button.test.d.ts.map +0 -1
- package/dist/tables/widgets/source-button.test.js +0 -11
- package/dist/themes/theme-contract.test.d.ts +0 -2
- package/dist/themes/theme-contract.test.d.ts.map +0 -1
- package/dist/themes/theme-contract.test.js +0 -88
- package/dist/ui/index.test.d.ts +0 -2
- package/dist/ui/index.test.d.ts.map +0 -1
- package/dist/ui/index.test.js +0 -7
- package/dist/ui/styles.test.d.ts +0 -2
- package/dist/ui/styles.test.d.ts.map +0 -1
- package/dist/ui/styles.test.js +0 -26
- package/dist/ui/table-dnd/table-dnd-utils.test.d.ts +0 -2
- package/dist/ui/table-dnd/table-dnd-utils.test.d.ts.map +0 -1
- package/dist/ui/table-dnd/table-dnd-utils.test.js +0 -46
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { CompletionContext, } from "@codemirror/autocomplete";
|
|
2
|
-
import { EditorSelection, EditorState, } from "@codemirror/state";
|
|
3
|
-
import { EditorView } from "@codemirror/view";
|
|
4
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { convertHtmlToMarkdown, createMarkdownCompletionSources, createMarkdownInputHandlerExtensions, createMarkdownSmartPasteExtension, } from ".";
|
|
6
|
-
const files = [
|
|
7
|
-
{
|
|
8
|
-
extension: "md",
|
|
9
|
-
kind: "markdown",
|
|
10
|
-
name: "project.md",
|
|
11
|
-
path: "notes/project.md",
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
extension: "png",
|
|
15
|
-
kind: "image",
|
|
16
|
-
name: "diagram.png",
|
|
17
|
-
path: "assets/diagram.png",
|
|
18
|
-
},
|
|
19
|
-
];
|
|
20
|
-
const adapter = {
|
|
21
|
-
getHeadings(file) {
|
|
22
|
-
return file.path === "notes/project.md"
|
|
23
|
-
? [{ id: "next-steps", level: 2, text: "Next Steps" }]
|
|
24
|
-
: [];
|
|
25
|
-
},
|
|
26
|
-
listFiles: () => files,
|
|
27
|
-
resolveLink({ href }) {
|
|
28
|
-
const normalized = href.replace(/\.md$/i, "");
|
|
29
|
-
return (files.find((file) => file.path.replace(/\.md$/i, "") === normalized ||
|
|
30
|
-
file.name?.replace(/\.md$/i, "") === normalized ||
|
|
31
|
-
file.path.replace(/\.md$/i, "").endsWith(`/${normalized}`)) ?? null);
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
document.body.replaceChildren();
|
|
36
|
-
});
|
|
37
|
-
describe("Markdown completions", () => {
|
|
38
|
-
it("formats file and embed targets through the portable adapter", async () => {
|
|
39
|
-
const sources = createMarkdownCompletionSources({
|
|
40
|
-
fileAdapter: adapter,
|
|
41
|
-
sourcePath: "notes/today.md",
|
|
42
|
-
});
|
|
43
|
-
const file = await firstResult(sources, "[[pro");
|
|
44
|
-
expect(file.options.map((option) => option.label)).toContain("project.md");
|
|
45
|
-
expect(applyCompletion("[[pro", file, "project.md")).toBe("[[project]]");
|
|
46
|
-
const embed = await firstResult(sources, "![[dia");
|
|
47
|
-
expect(embed.options.map((option) => option.label)).toContain("diagram.png");
|
|
48
|
-
expect(applyCompletion("![[dia", embed, "diagram.png")).toBe("![[diagram.png]]");
|
|
49
|
-
});
|
|
50
|
-
it("completes headings while preserving existing display text", async () => {
|
|
51
|
-
const sources = createMarkdownCompletionSources({
|
|
52
|
-
fileAdapter: adapter,
|
|
53
|
-
sourcePath: "notes/today.md",
|
|
54
|
-
});
|
|
55
|
-
const doc = "[[project#Ne|Alias]]";
|
|
56
|
-
const position = doc.indexOf("|");
|
|
57
|
-
const result = await firstResult(sources, doc, position);
|
|
58
|
-
expect(result.options.map((option) => option.label)).toContain("Next Steps");
|
|
59
|
-
expect(applyCompletion(doc, result, "Next Steps", position)).toBe("[[project#Next Steps|Alias]]");
|
|
60
|
-
});
|
|
61
|
-
it("resolves a unique basename from listFiles when resolveLink cannot", async () => {
|
|
62
|
-
const sources = createMarkdownCompletionSources({
|
|
63
|
-
fileAdapter: {
|
|
64
|
-
...adapter,
|
|
65
|
-
resolveLink: () => null,
|
|
66
|
-
},
|
|
67
|
-
sourcePath: "notes/today.md",
|
|
68
|
-
});
|
|
69
|
-
const result = await firstResult(sources, "[[project#Ne");
|
|
70
|
-
expect(applyCompletion("[[project#Ne", result, "Next Steps")).toBe("[[project#Next Steps]]");
|
|
71
|
-
});
|
|
72
|
-
it("completes display text without losing the selected target", async () => {
|
|
73
|
-
const sources = createMarkdownCompletionSources({
|
|
74
|
-
fileAdapter: adapter,
|
|
75
|
-
sourcePath: "notes/today.md",
|
|
76
|
-
});
|
|
77
|
-
const result = await firstResult(sources, "[[project|Shown");
|
|
78
|
-
expect(applyCompletion("[[project|Shown", result, "Shown")).toBe("[[project|Shown]]");
|
|
79
|
-
});
|
|
80
|
-
it("lets consumers replace the link formatter", async () => {
|
|
81
|
-
const formatLink = vi.fn((target) => `${target.embed ? "embed" : "link"}:${target.targetPath}`);
|
|
82
|
-
const sources = createMarkdownCompletionSources({
|
|
83
|
-
config: { formatLink },
|
|
84
|
-
fileAdapter: adapter,
|
|
85
|
-
sourcePath: "notes/today.md",
|
|
86
|
-
});
|
|
87
|
-
const result = await firstResult(sources, "[[pro");
|
|
88
|
-
expect(applyCompletion("[[pro", result, "project.md")).toBe("link:notes/project.md");
|
|
89
|
-
expect(formatLink).toHaveBeenCalled();
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
describe("Markdown input handlers", () => {
|
|
93
|
-
it("scaffolds code fences and frontmatter by default", () => {
|
|
94
|
-
expect(runInputHandler("``", "`")).toEqual({
|
|
95
|
-
doc: "```\n```",
|
|
96
|
-
selection: 3,
|
|
97
|
-
});
|
|
98
|
-
expect(runInputHandler("--", "-")).toEqual({
|
|
99
|
-
doc: "---\n\n---",
|
|
100
|
-
selection: 4,
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
it("keeps ellipsis substitution opt-in", () => {
|
|
104
|
-
expect(runInputHandler("..", ".")).toEqual({
|
|
105
|
-
doc: "..",
|
|
106
|
-
selection: 2,
|
|
107
|
-
});
|
|
108
|
-
expect(runInputHandler("..", ".", { ellipsis: true })).toEqual({
|
|
109
|
-
doc: "…",
|
|
110
|
-
selection: 1,
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
describe("Markdown smart paste", () => {
|
|
115
|
-
it("converts rich HTML to Markdown", async () => {
|
|
116
|
-
const markdown = await convertHtmlToMarkdown("<h2>Plan</h2><ul><li>First</li><li>Second</li></ul>");
|
|
117
|
-
expect(markdown).toContain("## Plan");
|
|
118
|
-
expect(markdown).toContain("* First");
|
|
119
|
-
expect(markdown).toContain("* Second");
|
|
120
|
-
});
|
|
121
|
-
it("wraps the current selection when a URL is pasted", () => {
|
|
122
|
-
const view = createView("Read Mira", 5, 9, [
|
|
123
|
-
createMarkdownSmartPasteExtension(),
|
|
124
|
-
]);
|
|
125
|
-
const event = pasteEvent({
|
|
126
|
-
"text/plain": "https://mira.example/docs",
|
|
127
|
-
});
|
|
128
|
-
view.contentDOM.dispatchEvent(event);
|
|
129
|
-
expect(event.defaultPrevented).toBe(true);
|
|
130
|
-
expect(view.state.doc.toString()).toBe("Read [Mira](https://mira.example/docs)");
|
|
131
|
-
view.destroy();
|
|
132
|
-
});
|
|
133
|
-
it("supports an application-supplied HTML converter", async () => {
|
|
134
|
-
const view = createView("", 0, 0, [
|
|
135
|
-
createMarkdownSmartPasteExtension({
|
|
136
|
-
convertHtml: async () => "**converted**",
|
|
137
|
-
}),
|
|
138
|
-
]);
|
|
139
|
-
const event = pasteEvent({
|
|
140
|
-
"text/html": "<strong>converted</strong>",
|
|
141
|
-
"text/plain": "converted",
|
|
142
|
-
});
|
|
143
|
-
view.contentDOM.dispatchEvent(event);
|
|
144
|
-
await vi.waitFor(() => expect(view.state.doc.toString()).toBe("**converted**"));
|
|
145
|
-
expect(event.defaultPrevented).toBe(true);
|
|
146
|
-
view.destroy();
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
async function firstResult(sources, doc, position = doc.length) {
|
|
150
|
-
const state = EditorState.create({ doc });
|
|
151
|
-
const context = new CompletionContext(state, position, true);
|
|
152
|
-
for (const source of sources) {
|
|
153
|
-
const result = await source(context);
|
|
154
|
-
if (result) {
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
throw new Error(`No completion matched ${doc}`);
|
|
159
|
-
}
|
|
160
|
-
function applyCompletion(doc, result, label, position = doc.length) {
|
|
161
|
-
const option = result.options.find((item) => item.label === label);
|
|
162
|
-
if (!option || typeof option.apply !== "function") {
|
|
163
|
-
throw new Error(`Missing completion ${label}`);
|
|
164
|
-
}
|
|
165
|
-
const state = EditorState.create({
|
|
166
|
-
doc,
|
|
167
|
-
selection: EditorSelection.cursor(position),
|
|
168
|
-
});
|
|
169
|
-
const view = mockView(state);
|
|
170
|
-
option.apply(view, option, result.from, result.to ?? position);
|
|
171
|
-
return view.state.doc.toString();
|
|
172
|
-
}
|
|
173
|
-
function runInputHandler(doc, text, config = {}) {
|
|
174
|
-
const state = EditorState.create({
|
|
175
|
-
doc,
|
|
176
|
-
selection: EditorSelection.cursor(doc.length),
|
|
177
|
-
extensions: createMarkdownInputHandlerExtensions(config),
|
|
178
|
-
});
|
|
179
|
-
const view = mockView(state);
|
|
180
|
-
const handled = state.facet(EditorView.inputHandler).some((handler) => handler(view, doc.length, doc.length, text, () => view.state.update({
|
|
181
|
-
changes: { from: doc.length, insert: text, to: doc.length },
|
|
182
|
-
})));
|
|
183
|
-
return {
|
|
184
|
-
doc: view.state.doc.toString(),
|
|
185
|
-
selection: handled ? view.state.selection.main.anchor : doc.length,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
function mockView(initialState) {
|
|
189
|
-
let state = initialState;
|
|
190
|
-
return {
|
|
191
|
-
dispatch(spec) {
|
|
192
|
-
state = state.update(spec).state;
|
|
193
|
-
},
|
|
194
|
-
get state() {
|
|
195
|
-
return state;
|
|
196
|
-
},
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
function createView(doc, from, to, extensions) {
|
|
200
|
-
const parent = document.createElement("div");
|
|
201
|
-
document.body.append(parent);
|
|
202
|
-
return new EditorView({
|
|
203
|
-
parent,
|
|
204
|
-
state: EditorState.create({
|
|
205
|
-
doc,
|
|
206
|
-
extensions,
|
|
207
|
-
selection: EditorSelection.range(from, to),
|
|
208
|
-
}),
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
function pasteEvent(data) {
|
|
212
|
-
const event = new Event("paste", { bubbles: true, cancelable: true });
|
|
213
|
-
Object.defineProperty(event, "clipboardData", {
|
|
214
|
-
value: {
|
|
215
|
-
getData(type) {
|
|
216
|
-
return data[type] ?? "";
|
|
217
|
-
},
|
|
218
|
-
items: [],
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
return event;
|
|
222
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../src/internal/codemirror/markdown/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { syntaxTree } from "@codemirror/language";
|
|
3
|
-
import { EditorState } from "@codemirror/state";
|
|
4
|
-
import { EditorView } from "@codemirror/view";
|
|
5
|
-
import { createMarkdownCodeMirrorExtensions } from ".";
|
|
6
|
-
describe("createMarkdownCodeMirrorExtensions", () => {
|
|
7
|
-
it("returns markdown language and decoration extensions", () => {
|
|
8
|
-
expect(createMarkdownCodeMirrorExtensions()).toHaveLength(3);
|
|
9
|
-
});
|
|
10
|
-
it("parses Lapis-style grid tables", () => {
|
|
11
|
-
const state = EditorState.create({
|
|
12
|
-
doc: [
|
|
13
|
-
"+---------+----------+",
|
|
14
|
-
"| Feature | Behavior |",
|
|
15
|
-
"+=========+==========+",
|
|
16
|
-
"| Menus | Actions |",
|
|
17
|
-
"+---------+----------+",
|
|
18
|
-
].join("\n"),
|
|
19
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
20
|
-
});
|
|
21
|
-
expect(syntaxTree(state).toString()).toContain("GridTable");
|
|
22
|
-
});
|
|
23
|
-
it("starts a list after a lazy blockquote before parsing its indented quote", () => {
|
|
24
|
-
const state = EditorState.create({
|
|
25
|
-
doc: [
|
|
26
|
-
"- Unordered parent",
|
|
27
|
-
" > Quoted paragraph",
|
|
28
|
-
" > > Nested quote keeps a second quote guide.",
|
|
29
|
-
"3. Blockquote inside a list item:",
|
|
30
|
-
"",
|
|
31
|
-
" > Skip a line and indent the quote markers four spaces.",
|
|
32
|
-
" > The rendered blockquote stays attached to its first source line.",
|
|
33
|
-
].join("\n"),
|
|
34
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
35
|
-
});
|
|
36
|
-
const tree = syntaxTree(state).toString();
|
|
37
|
-
expect(tree).toContain("BulletList(ListItem(ListMark,Paragraph,Blockquote(QuoteMark,Paragraph,QuoteMark,Blockquote");
|
|
38
|
-
expect(tree).toContain("OrderedList(ListItem(ListMark,Paragraph,Blockquote(QuoteMark,Paragraph(QuoteMark))))");
|
|
39
|
-
expect(tree).not.toContain("CodeBlock");
|
|
40
|
-
});
|
|
41
|
-
it("marks quoted task delimiters for source-mode styling", async () => {
|
|
42
|
-
const parent = document.createElement("div");
|
|
43
|
-
document.body.append(parent);
|
|
44
|
-
const view = new EditorView({
|
|
45
|
-
doc: " > - [ ] Quoted checklist child",
|
|
46
|
-
extensions: createMarkdownCodeMirrorExtensions({ sourceMode: true }),
|
|
47
|
-
parent,
|
|
48
|
-
});
|
|
49
|
-
await new Promise((resolve) => requestAnimationFrame(() => resolve(null)));
|
|
50
|
-
const delimiter = parent.querySelector(".cm-formatting-task");
|
|
51
|
-
expect(delimiter?.textContent).toBe("[ ]");
|
|
52
|
-
view.destroy();
|
|
53
|
-
parent.remove();
|
|
54
|
-
});
|
|
55
|
-
it.each([
|
|
56
|
-
["justify", ["+>-----<+", "| A b C |", "+-------+"]],
|
|
57
|
-
["center", ["+:-----:+", "| ABC |", "+-------+"]],
|
|
58
|
-
["left", ["+:------+", "| ABC |", "+------+"]],
|
|
59
|
-
["right", ["+------:+", "| ABC |", "+------+"]],
|
|
60
|
-
[
|
|
61
|
-
"top",
|
|
62
|
-
[
|
|
63
|
-
"+---^---+",
|
|
64
|
-
"| Larum |",
|
|
65
|
-
"| Ipsum |",
|
|
66
|
-
"| |",
|
|
67
|
-
"| |",
|
|
68
|
-
"+-------+",
|
|
69
|
-
],
|
|
70
|
-
],
|
|
71
|
-
[
|
|
72
|
-
"middle",
|
|
73
|
-
[
|
|
74
|
-
"+---x---+",
|
|
75
|
-
"| |",
|
|
76
|
-
"| Larum |",
|
|
77
|
-
"| Ipsum |",
|
|
78
|
-
"| |",
|
|
79
|
-
"+-------+",
|
|
80
|
-
],
|
|
81
|
-
],
|
|
82
|
-
[
|
|
83
|
-
"bottom",
|
|
84
|
-
[
|
|
85
|
-
"+---v---+",
|
|
86
|
-
"| |",
|
|
87
|
-
"| |",
|
|
88
|
-
"| Larum |",
|
|
89
|
-
"| Ipsum |",
|
|
90
|
-
"+-------+",
|
|
91
|
-
],
|
|
92
|
-
],
|
|
93
|
-
])("parses Adobe %s alignment grid table separators", (_, markdown) => {
|
|
94
|
-
const state = EditorState.create({
|
|
95
|
-
doc: markdown.join("\n"),
|
|
96
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
97
|
-
});
|
|
98
|
-
expect(syntaxTree(state).toString()).toContain("GridTable");
|
|
99
|
-
});
|
|
100
|
-
it("parses Lapis wikilink, embed, pathlink, and tag nodes", () => {
|
|
101
|
-
const state = EditorState.create({
|
|
102
|
-
doc: [
|
|
103
|
-
"[[Project Plan#Section|Plan]]",
|
|
104
|
-
"![[Architecture Diagram#Overview|Diagram]]",
|
|
105
|
-
"[Project](notes/Project Plan.md)",
|
|
106
|
-
"#mira/editor",
|
|
107
|
-
].join("\n"),
|
|
108
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
109
|
-
});
|
|
110
|
-
const tree = syntaxTree(state).toString();
|
|
111
|
-
expect(tree).toContain("WikiLink");
|
|
112
|
-
expect(tree).toContain("WikiLinkPath");
|
|
113
|
-
expect(tree).toContain("WikiLinkAnchor");
|
|
114
|
-
expect(tree).toContain("WikiLinkText");
|
|
115
|
-
expect(tree).toContain("EmbedLink");
|
|
116
|
-
expect(tree).toContain("EmbedLinkPath");
|
|
117
|
-
expect(tree).toContain("EmbedLinkAnchor");
|
|
118
|
-
expect(tree).toContain("EmbedLinkText");
|
|
119
|
-
expect(tree).toContain("PathLink");
|
|
120
|
-
expect(tree).toContain("PathLinkDestination");
|
|
121
|
-
expect(tree).toContain("Tag");
|
|
122
|
-
expect(tree).toContain("TagName");
|
|
123
|
-
});
|
|
124
|
-
it("parses single-backslash bracket math delimiters", () => {
|
|
125
|
-
const state = EditorState.create({
|
|
126
|
-
doc: ["inline \\(x + 1\\)", "\\[", "x + 1", "\\]"].join("\n"),
|
|
127
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
128
|
-
});
|
|
129
|
-
const tree = syntaxTree(state).toString();
|
|
130
|
-
expect(tree).toContain("InlineMathBracket");
|
|
131
|
-
expect(tree).toContain("BlockMathBracket");
|
|
132
|
-
});
|
|
133
|
-
it("parses container, leaf, and inline directives structurally", () => {
|
|
134
|
-
const state = EditorState.create({
|
|
135
|
-
doc: [
|
|
136
|
-
':::cell[Load data]{lang="ts"}',
|
|
137
|
-
"```ts",
|
|
138
|
-
"const value = 1;",
|
|
139
|
-
"```",
|
|
140
|
-
":::",
|
|
141
|
-
"",
|
|
142
|
-
"::badge[Stable]{tone=success}",
|
|
143
|
-
"",
|
|
144
|
-
'Use :abbr[HTML]{title="HyperText Markup Language"}.',
|
|
145
|
-
].join("\n"),
|
|
146
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
147
|
-
});
|
|
148
|
-
const tree = syntaxTree(state).toString();
|
|
149
|
-
expect(tree).toContain("ContainerDirective");
|
|
150
|
-
expect(tree).toContain("LeafDirective");
|
|
151
|
-
expect(tree).toContain("InlineDirective");
|
|
152
|
-
expect(tree).toContain("DirectiveName");
|
|
153
|
-
expect(tree).toContain("DirectiveArgs");
|
|
154
|
-
expect(tree).toContain("DirectiveAttrName");
|
|
155
|
-
expect(tree).toContain("DirectiveAttrValue");
|
|
156
|
-
expect(tree).toContain("FencedCode");
|
|
157
|
-
});
|
|
158
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"showcase-fixture.test.d.ts","sourceRoot":"","sources":["../../../../src/internal/codemirror/markdown/showcase-fixture.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { ensureSyntaxTree } from "@codemirror/language";
|
|
4
|
-
import { EditorState } from "@codemirror/state";
|
|
5
|
-
import { describe, expect, it } from "vitest";
|
|
6
|
-
import { createMarkdownCodeMirrorExtensions } from ".";
|
|
7
|
-
const fixturePath = path.resolve(import.meta.dirname, "../../../../../../stories/markdown/layout/CodeMirror Layout Showcase.md");
|
|
8
|
-
describe("Mira CodeMirror Layout Showcase fixture", () => {
|
|
9
|
-
it("exercises the parser extensions used by every editor mode", () => {
|
|
10
|
-
const source = readFileSync(fixturePath, "utf8");
|
|
11
|
-
const state = EditorState.create({
|
|
12
|
-
doc: source,
|
|
13
|
-
extensions: createMarkdownCodeMirrorExtensions(),
|
|
14
|
-
});
|
|
15
|
-
const tree = ensureSyntaxTree(state, state.doc.length, 1_000);
|
|
16
|
-
expect(tree).not.toBeNull();
|
|
17
|
-
const cursor = tree.cursor();
|
|
18
|
-
const names = [];
|
|
19
|
-
function walk() {
|
|
20
|
-
names.push(cursor.name);
|
|
21
|
-
if (!cursor.firstChild()) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
do {
|
|
25
|
-
walk();
|
|
26
|
-
} while (cursor.nextSibling());
|
|
27
|
-
cursor.parent();
|
|
28
|
-
}
|
|
29
|
-
walk();
|
|
30
|
-
expect(names).toEqual(expect.arrayContaining([
|
|
31
|
-
"Document",
|
|
32
|
-
"ATXHeading1",
|
|
33
|
-
"ATXHeading2",
|
|
34
|
-
"Table",
|
|
35
|
-
"GridTable",
|
|
36
|
-
"Blockquote",
|
|
37
|
-
"BulletList",
|
|
38
|
-
"OrderedList",
|
|
39
|
-
"WikiLink",
|
|
40
|
-
"EmbedLink",
|
|
41
|
-
"PathLink",
|
|
42
|
-
"Tag",
|
|
43
|
-
"InlineDirective",
|
|
44
|
-
"LeafDirective",
|
|
45
|
-
"FencedCode",
|
|
46
|
-
"BlockMathDollar",
|
|
47
|
-
"InlineMathDollar",
|
|
48
|
-
]));
|
|
49
|
-
});
|
|
50
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"block-controls.test.d.ts","sourceRoot":"","sources":["../../../../src/internal/codemirror/rich/block-controls.test.ts"],"names":[],"mappings":""}
|