@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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.test.d.ts","sourceRoot":"","sources":["../../../../../src/internal/codemirror/rich/utils/tasks.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { EditorState } from "@codemirror/state";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { getTaskMarkerRange, selectionTouchesTaskMarker } from "./tasks";
|
|
4
|
-
describe("task utilities", () => {
|
|
5
|
-
it("resolves normal and custom task marker ranges", () => {
|
|
6
|
-
expect(getTaskMarkerRange("- [ ] Open task", 0)).toEqual({
|
|
7
|
-
markerStart: 0,
|
|
8
|
-
checkboxStart: 2,
|
|
9
|
-
checkboxEnd: 5,
|
|
10
|
-
markerEnd: 6,
|
|
11
|
-
taskValue: " ",
|
|
12
|
-
});
|
|
13
|
-
expect(getTaskMarkerRange(" * [/] Custom task", 10)).toEqual({
|
|
14
|
-
markerStart: 12,
|
|
15
|
-
checkboxStart: 14,
|
|
16
|
-
checkboxEnd: 17,
|
|
17
|
-
markerEnd: 18,
|
|
18
|
-
taskValue: "/",
|
|
19
|
-
});
|
|
20
|
-
expect(getTaskMarkerRange("- [?] Question task", 0)?.taskValue).toBe("?");
|
|
21
|
-
expect(getTaskMarkerRange("- [-] Cancelled task", 0)?.taskValue).toBe("-");
|
|
22
|
-
});
|
|
23
|
-
it("resolves task markers after authored blockquote prefixes", () => {
|
|
24
|
-
expect(getTaskMarkerRange(" > - [ ] Quoted checklist child", 20)).toEqual({
|
|
25
|
-
markerStart: 26,
|
|
26
|
-
checkboxStart: 28,
|
|
27
|
-
checkboxEnd: 31,
|
|
28
|
-
markerEnd: 32,
|
|
29
|
-
taskValue: " ",
|
|
30
|
-
});
|
|
31
|
-
expect(getTaskMarkerRange("> > 1. [x] Nested task", 0)).toEqual({
|
|
32
|
-
markerStart: 4,
|
|
33
|
-
checkboxStart: 7,
|
|
34
|
-
checkboxEnd: 10,
|
|
35
|
-
markerEnd: 11,
|
|
36
|
-
taskValue: "x",
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
it("treats the task marker prefix as active for source reveal", () => {
|
|
40
|
-
for (let anchor = 0; anchor <= 6; anchor += 1) {
|
|
41
|
-
const state = EditorState.create({
|
|
42
|
-
doc: "* [/] Custom task\nParagraph",
|
|
43
|
-
selection: { anchor },
|
|
44
|
-
});
|
|
45
|
-
const taskLine = state.doc.line(1);
|
|
46
|
-
const taskRange = getTaskMarkerRange(taskLine.text, taskLine.from);
|
|
47
|
-
expect(selectionTouchesTaskMarker(state, taskLine.from, taskRange.markerEnd)).toBe(true);
|
|
48
|
-
}
|
|
49
|
-
const state = EditorState.create({
|
|
50
|
-
doc: "* [/] Custom task\nParagraph",
|
|
51
|
-
selection: { anchor: 10 },
|
|
52
|
-
});
|
|
53
|
-
const taskLine = state.doc.line(1);
|
|
54
|
-
const taskRange = getTaskMarkerRange(taskLine.text, taskLine.from);
|
|
55
|
-
expect(selectionTouchesTaskMarker(state, taskLine.from, taskRange.markerEnd)).toBe(false);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-states.test.d.ts","sourceRoot":"","sources":["../../src/internal/task-states.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { miraTaskStates, normalizeMiraTaskMarker } from "./task-states";
|
|
3
|
-
describe("Mira task states", () => {
|
|
4
|
-
it("contains every shipped standard and custom checkbox marker once", () => {
|
|
5
|
-
const markers = miraTaskStates.map(({ marker }) => marker);
|
|
6
|
-
expect(markers).toEqual([
|
|
7
|
-
" ",
|
|
8
|
-
"x",
|
|
9
|
-
"/",
|
|
10
|
-
"?",
|
|
11
|
-
"-",
|
|
12
|
-
"!",
|
|
13
|
-
">",
|
|
14
|
-
"<",
|
|
15
|
-
"l",
|
|
16
|
-
"*",
|
|
17
|
-
"i",
|
|
18
|
-
"S",
|
|
19
|
-
"I",
|
|
20
|
-
"f",
|
|
21
|
-
"k",
|
|
22
|
-
"u",
|
|
23
|
-
"d",
|
|
24
|
-
"w",
|
|
25
|
-
"p",
|
|
26
|
-
"c",
|
|
27
|
-
"b",
|
|
28
|
-
'"',
|
|
29
|
-
]);
|
|
30
|
-
expect(new Set(markers).size).toBe(markers.length);
|
|
31
|
-
});
|
|
32
|
-
it("normalizes the alternate completed marker only", () => {
|
|
33
|
-
expect(normalizeMiraTaskMarker("X")).toBe("x");
|
|
34
|
-
expect(normalizeMiraTaskMarker("S")).toBe("S");
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mira-code-editor.test.d.ts","sourceRoot":"","sources":["../src/mira-code-editor.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { undo } from "@codemirror/commands";
|
|
2
|
-
import { Transaction } from "@codemirror/state";
|
|
3
|
-
import { EditorView } from "@codemirror/view";
|
|
4
|
-
import { readFileSync } from "node:fs";
|
|
5
|
-
import { resolve } from "node:path";
|
|
6
|
-
import { mount, tick, unmount } from "svelte";
|
|
7
|
-
import { describe, expect, it, vi } from "vitest";
|
|
8
|
-
import MiraCodeEditor from "./mira-code-editor.svelte";
|
|
9
|
-
import Mira from "./mira.svelte";
|
|
10
|
-
describe("MiraCodeEditor", () => {
|
|
11
|
-
it("keeps the gutter and search panel on the editor surface", () => {
|
|
12
|
-
const shellCss = readFileSync(resolve(process.cwd(), "src/mira-code-editor.css"), "utf8");
|
|
13
|
-
const searchPanel = readFileSync(resolve(process.cwd(), "src/internal/codemirror/base/search-panel.svelte"), "utf8");
|
|
14
|
-
expect(shellCss).toMatch(/background:\s*var\(\s*--mira-code-editor-gutter-background,\s*var\(--mira-code-editor-background/);
|
|
15
|
-
expect(shellCss).toMatch(/\[data-surface="framed"\]:focus-within\s*\{[\s\S]*?border-color:\s*transparent/);
|
|
16
|
-
expect(shellCss).not.toMatch(/^\s*--mira-code-editor-focus-ring:\s*var\(/m);
|
|
17
|
-
expect(searchPanel).toMatch(/background:\s*var\(\s*--mira-code-editor-background/);
|
|
18
|
-
expect(searchPanel).toContain("--mira-code-editor-search-input-background");
|
|
19
|
-
expect(searchPanel).toContain("--mira-code-editor-search-button-hover-background");
|
|
20
|
-
expect(searchPanel).toContain("--mira-code-editor-search-focus-ring");
|
|
21
|
-
expect(searchPanel).toMatch(/__search-field:focus-within,[\s\S]*?__button:focus-visible\s*\{[\s\S]*?border-color:\s*transparent/);
|
|
22
|
-
expect(searchPanel).toMatch(/--mira-code-editor-search-radius,[\s\S]*?999px/);
|
|
23
|
-
expect(searchPanel).toMatch(/font-size:\s*var\(--mira-code-editor-search-font-size,\s*0\.875rem\)/);
|
|
24
|
-
expect(searchPanel).toMatch(/\.cm-panels-top:has\(\.mira-search-panel-host\)[\s\S]*?background:\s*transparent;[\s\S]*?border-bottom:\s*0/);
|
|
25
|
-
});
|
|
26
|
-
it("owns a controlled accessible CodeMirror lifecycle", async () => {
|
|
27
|
-
const target = document.createElement("div");
|
|
28
|
-
document.body.append(target);
|
|
29
|
-
const onChange = vi.fn();
|
|
30
|
-
const component = mount(MiraCodeEditor, {
|
|
31
|
-
target,
|
|
32
|
-
props: {
|
|
33
|
-
value: "name: Mira",
|
|
34
|
-
ariaLabel: "YAML editor",
|
|
35
|
-
invalid: true,
|
|
36
|
-
minHeight: "12rem",
|
|
37
|
-
scrollerTabIndex: 0,
|
|
38
|
-
onChange,
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
await tick();
|
|
42
|
-
const view = component.getView();
|
|
43
|
-
expect(view).not.toBeNull();
|
|
44
|
-
expect(view?.contentDOM.getAttribute("aria-label")).toBe("YAML editor");
|
|
45
|
-
expect(view?.contentDOM.getAttribute("aria-invalid")).toBe("true");
|
|
46
|
-
expect(view?.scrollDOM.getAttribute("tabindex")).toBe("0");
|
|
47
|
-
expect(target.querySelector(".mira-code-editor")?.getAttribute("data-surface")).toBe("framed");
|
|
48
|
-
view?.dispatch({
|
|
49
|
-
changes: { from: view.state.doc.length, insert: "\nrole: editor" },
|
|
50
|
-
annotations: Transaction.userEvent.of("input"),
|
|
51
|
-
});
|
|
52
|
-
expect(onChange).toHaveBeenLastCalledWith("name: Mira\nrole: editor");
|
|
53
|
-
component.setValue("external: value");
|
|
54
|
-
expect(component.getValue()).toBe("external: value");
|
|
55
|
-
expect(onChange).toHaveBeenCalledTimes(1);
|
|
56
|
-
component.setSelection({
|
|
57
|
-
anchor: { line: 0, ch: 0 },
|
|
58
|
-
head: { line: 0, ch: 8 },
|
|
59
|
-
});
|
|
60
|
-
expect(component.getSelection()).toEqual({
|
|
61
|
-
anchor: { line: 0, ch: 0 },
|
|
62
|
-
head: { line: 0, ch: 8 },
|
|
63
|
-
});
|
|
64
|
-
await unmount(component);
|
|
65
|
-
expect(target.querySelector(".cm-editor")).toBeNull();
|
|
66
|
-
target.remove();
|
|
67
|
-
});
|
|
68
|
-
it("preserves edit history when the Markdown consumer reconfigures", async () => {
|
|
69
|
-
const target = document.createElement("div");
|
|
70
|
-
document.body.append(target);
|
|
71
|
-
const component = mount(Mira, {
|
|
72
|
-
target,
|
|
73
|
-
props: { value: "alpha", mode: "source" },
|
|
74
|
-
});
|
|
75
|
-
await tick();
|
|
76
|
-
const editorElement = target.querySelector(".cm-editor");
|
|
77
|
-
const view = editorElement ? EditorView.findFromDOM(editorElement) : null;
|
|
78
|
-
expect(view).not.toBeNull();
|
|
79
|
-
view?.dispatch({
|
|
80
|
-
changes: { from: 5, insert: " beta" },
|
|
81
|
-
annotations: Transaction.userEvent.of("input"),
|
|
82
|
-
});
|
|
83
|
-
expect(component.getMarkdown()).toBe("alpha beta");
|
|
84
|
-
component.setReadonly(true);
|
|
85
|
-
await tick();
|
|
86
|
-
component.setReadonly(false);
|
|
87
|
-
await tick();
|
|
88
|
-
expect(view && undo(view)).toBe(true);
|
|
89
|
-
expect(component.getMarkdown()).toBe("alpha");
|
|
90
|
-
await unmount(component);
|
|
91
|
-
target.remove();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mode-position.test.d.ts","sourceRoot":"","sources":["../src/mode-position.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { EditorState } from "@codemirror/state";
|
|
2
|
-
import { EditorView } from "@codemirror/view";
|
|
3
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { captureModeSwitchPosition, capturePreviewPosition, restorePreviewPosition, } from "./mode-position";
|
|
5
|
-
afterEach(() => {
|
|
6
|
-
document.body.replaceChildren();
|
|
7
|
-
});
|
|
8
|
-
describe("mode position continuity", () => {
|
|
9
|
-
it("captures the nearest visible preview source line and restores it", () => {
|
|
10
|
-
const scroller = document.createElement("div");
|
|
11
|
-
const first = appendAnchor(scroller, 5, -30);
|
|
12
|
-
const second = appendAnchor(scroller, 12, 20);
|
|
13
|
-
vi.spyOn(scroller, "getBoundingClientRect").mockReturnValue(rect(0, 100));
|
|
14
|
-
const scrollTo = vi.fn();
|
|
15
|
-
Object.defineProperty(scroller, "scrollTo", {
|
|
16
|
-
configurable: true,
|
|
17
|
-
value: scrollTo,
|
|
18
|
-
});
|
|
19
|
-
scroller.scrollTop = 50;
|
|
20
|
-
const position = capturePreviewPosition(scroller);
|
|
21
|
-
expect(position).toMatchObject({ line: 12, topDelta: 20 });
|
|
22
|
-
vi.mocked(first.getBoundingClientRect).mockReturnValue(rect(-20, 20));
|
|
23
|
-
vi.mocked(second.getBoundingClientRect).mockReturnValue(rect(40, 80));
|
|
24
|
-
restorePreviewPosition(scroller, position);
|
|
25
|
-
expect(scrollTo).toHaveBeenLastCalledWith({ top: 70 });
|
|
26
|
-
});
|
|
27
|
-
it("captures the surface that becomes hidden when entering preview or split", () => {
|
|
28
|
-
const host = document.createElement("div");
|
|
29
|
-
document.body.append(host);
|
|
30
|
-
const view = new EditorView({
|
|
31
|
-
parent: host,
|
|
32
|
-
state: EditorState.create({ doc: "one\ntwo\nthree" }),
|
|
33
|
-
});
|
|
34
|
-
const preview = document.createElement("div");
|
|
35
|
-
expect(captureModeSwitchPosition("source", "preview", view, preview)?.target).toBe("preview");
|
|
36
|
-
expect(captureModeSwitchPosition("preview", "split", view, preview)?.target).toBe("editor");
|
|
37
|
-
expect(captureModeSwitchPosition("live-preview", "source", view, preview)).toBeNull();
|
|
38
|
-
view.destroy();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
function appendAnchor(root, line, top) {
|
|
42
|
-
const anchor = document.createElement("p");
|
|
43
|
-
anchor.dataset["line"] = `${line}`;
|
|
44
|
-
vi.spyOn(anchor, "getBoundingClientRect").mockReturnValue(rect(top, top + 20));
|
|
45
|
-
root.append(anchor);
|
|
46
|
-
return anchor;
|
|
47
|
-
}
|
|
48
|
-
function rect(top, bottom) {
|
|
49
|
-
return {
|
|
50
|
-
bottom,
|
|
51
|
-
height: bottom - top,
|
|
52
|
-
left: 0,
|
|
53
|
-
right: 100,
|
|
54
|
-
top,
|
|
55
|
-
width: 100,
|
|
56
|
-
x: 0,
|
|
57
|
-
y: top,
|
|
58
|
-
toJSON: () => ({}),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"code-language.test.d.ts","sourceRoot":"","sources":["../../src/preview/code-language.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { codeLanguageLabel } from "./code-language";
|
|
3
|
-
describe("code language labels", () => {
|
|
4
|
-
it("uses readable labels for common fenced-code aliases", () => {
|
|
5
|
-
expect(codeLanguageLabel("hljs language-ts")).toBe("TypeScript");
|
|
6
|
-
expect(codeLanguageLabel("language-yml hljs")).toBe("YAML");
|
|
7
|
-
});
|
|
8
|
-
it("preserves unknown language ids and omits unlabelled blocks", () => {
|
|
9
|
-
expect(codeLanguageLabel("hljs language-gleam")).toBe("gleam");
|
|
10
|
-
expect(codeLanguageLabel("hljs")).toBe("");
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"icon.test.d.ts","sourceRoot":"","sources":["../../../src/preview/components/icon.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { mount, tick, unmount } from "svelte";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import Icon from "./icon.svelte";
|
|
4
|
-
describe("portable preview icon", () => {
|
|
5
|
-
it("renders canonical Lucide hash geometry", async () => {
|
|
6
|
-
const target = document.createElement("div");
|
|
7
|
-
document.body.append(target);
|
|
8
|
-
const component = mount(Icon, {
|
|
9
|
-
target,
|
|
10
|
-
props: { name: "lucide-hash" },
|
|
11
|
-
});
|
|
12
|
-
await tick();
|
|
13
|
-
expect(target.querySelector('path[d="M4 9h16"]')).not.toBeNull();
|
|
14
|
-
expect(target.querySelector('path[d="M4 15h16"]')).not.toBeNull();
|
|
15
|
-
expect(target.querySelector('path[d="M10 3 8 21"]')).not.toBeNull();
|
|
16
|
-
expect(target.querySelector('path[d="m16 3-2 18"]')).not.toBeNull();
|
|
17
|
-
await unmount(component);
|
|
18
|
-
target.remove();
|
|
19
|
-
});
|
|
20
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"behavior.test.d.ts","sourceRoot":"","sources":["../../../src/preview/editable-markdown-preview/behavior.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getEditableMarkdownPreviewOffset, isEditableMarkdownPreviewInteractiveTarget, shouldActivateEditableMarkdownPreview, shouldReturnEditableMarkdownPreviewOnBlur, } from "./behavior";
|
|
3
|
-
describe("editable Markdown preview behavior", () => {
|
|
4
|
-
it("accepts a plain primary click and reads the nearest source offset", () => {
|
|
5
|
-
const block = document.createElement("p");
|
|
6
|
-
block.dataset.offset = "24";
|
|
7
|
-
const text = document.createElement("span");
|
|
8
|
-
block.append(text);
|
|
9
|
-
const event = new MouseEvent("click", { button: 0, bubbles: true });
|
|
10
|
-
text.dispatchEvent(event);
|
|
11
|
-
expect(shouldActivateEditableMarkdownPreview(event)).toBe(true);
|
|
12
|
-
expect(getEditableMarkdownPreviewOffset(event)).toBe(24);
|
|
13
|
-
});
|
|
14
|
-
it("ignores interactive descendants, modifiers, and non-primary clicks", () => {
|
|
15
|
-
const button = document.createElement("button");
|
|
16
|
-
const child = document.createElement("span");
|
|
17
|
-
button.append(child);
|
|
18
|
-
expect(isEditableMarkdownPreviewInteractiveTarget(child)).toBe(true);
|
|
19
|
-
expect(shouldActivateEditableMarkdownPreview(new MouseEvent("click", { button: 0, ctrlKey: true }))).toBe(false);
|
|
20
|
-
const interactiveEvent = new MouseEvent("click", {
|
|
21
|
-
button: 0,
|
|
22
|
-
bubbles: true,
|
|
23
|
-
});
|
|
24
|
-
child.dispatchEvent(interactiveEvent);
|
|
25
|
-
expect(shouldActivateEditableMarkdownPreview(interactiveEvent)).toBe(false);
|
|
26
|
-
expect(shouldActivateEditableMarkdownPreview(new MouseEvent("click", { button: 1 }))).toBe(false);
|
|
27
|
-
});
|
|
28
|
-
it("returns to preview only when focus leaves the editor", () => {
|
|
29
|
-
const container = document.createElement("div");
|
|
30
|
-
const inside = document.createElement("button");
|
|
31
|
-
const outside = document.createElement("button");
|
|
32
|
-
container.append(inside);
|
|
33
|
-
expect(shouldReturnEditableMarkdownPreviewOnBlur(container, inside, inside)).toBe(false);
|
|
34
|
-
expect(shouldReturnEditableMarkdownPreviewOnBlur(container, outside, outside)).toBe(true);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serialized-writer.test.d.ts","sourceRoot":"","sources":["../../../src/preview/editable-markdown-preview/serialized-writer.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { SerializedMarkdownWriter } from "./serialized-writer";
|
|
3
|
-
describe("SerializedMarkdownWriter", () => {
|
|
4
|
-
it("debounces writes for 500ms", async () => {
|
|
5
|
-
vi.useFakeTimers();
|
|
6
|
-
const write = vi.fn();
|
|
7
|
-
const writer = new SerializedMarkdownWriter({ value: "old", write });
|
|
8
|
-
writer.update("one");
|
|
9
|
-
writer.update("two");
|
|
10
|
-
await vi.advanceTimersByTimeAsync(499);
|
|
11
|
-
expect(write).not.toHaveBeenCalled();
|
|
12
|
-
await vi.advanceTimersByTimeAsync(1);
|
|
13
|
-
expect(write).toHaveBeenCalledOnce();
|
|
14
|
-
expect(write).toHaveBeenCalledWith("two");
|
|
15
|
-
vi.useRealTimers();
|
|
16
|
-
});
|
|
17
|
-
it("serializes writes and flushes the latest value", async () => {
|
|
18
|
-
let releaseFirst;
|
|
19
|
-
const writes = [];
|
|
20
|
-
const write = vi.fn((value) => {
|
|
21
|
-
writes.push(value);
|
|
22
|
-
if (writes.length === 1) {
|
|
23
|
-
return new Promise((resolve) => {
|
|
24
|
-
releaseFirst = resolve;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
const writer = new SerializedMarkdownWriter({ value: "old", write });
|
|
29
|
-
writer.update("one");
|
|
30
|
-
const firstFlush = writer.flush();
|
|
31
|
-
await Promise.resolve();
|
|
32
|
-
writer.update("two");
|
|
33
|
-
const secondFlush = writer.flush();
|
|
34
|
-
expect(writes).toEqual(["one"]);
|
|
35
|
-
releaseFirst?.();
|
|
36
|
-
await expect(firstFlush).resolves.toBe(true);
|
|
37
|
-
await expect(secondFlush).resolves.toBe(true);
|
|
38
|
-
expect(writes).toEqual(["one", "two"]);
|
|
39
|
-
expect(writer.state.dirty).toBe(false);
|
|
40
|
-
});
|
|
41
|
-
it("preserves dirty data and rejects external replacement after failure", async () => {
|
|
42
|
-
const writer = new SerializedMarkdownWriter({
|
|
43
|
-
value: "old",
|
|
44
|
-
write: async () => {
|
|
45
|
-
throw new Error("disk full");
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
writer.update("unsaved");
|
|
49
|
-
await expect(writer.flush()).resolves.toBe(false);
|
|
50
|
-
expect(writer.state).toMatchObject({
|
|
51
|
-
dirty: true,
|
|
52
|
-
saving: false,
|
|
53
|
-
value: "unsaved",
|
|
54
|
-
});
|
|
55
|
-
expect(writer.state.error?.message).toBe("disk full");
|
|
56
|
-
expect(writer.replaceExternal("external")).toBe(false);
|
|
57
|
-
expect(writer.state.value).toBe("unsaved");
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"embed-target.test.d.ts","sourceRoot":"","sources":["../../src/preview/embed-target.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { parseMiraImageDetails, selectMarkdownEmbedFragment, } from "./embed-target";
|
|
3
|
-
describe("portable embed targets", () => {
|
|
4
|
-
const markdown = [
|
|
5
|
-
"# Project",
|
|
6
|
-
"",
|
|
7
|
-
"Introduction.",
|
|
8
|
-
"",
|
|
9
|
-
"## Next Steps",
|
|
10
|
-
"",
|
|
11
|
-
"Ship the adapter.",
|
|
12
|
-
"",
|
|
13
|
-
"### Detail",
|
|
14
|
-
"",
|
|
15
|
-
"Keep this nested section.",
|
|
16
|
-
"",
|
|
17
|
-
"## Decisions",
|
|
18
|
-
"",
|
|
19
|
-
"Use target watchers.",
|
|
20
|
-
"",
|
|
21
|
-
"A portable referenced paragraph. ^decision-1",
|
|
22
|
-
].join("\n");
|
|
23
|
-
it("selects heading sections through the next sibling heading", () => {
|
|
24
|
-
expect(selectMarkdownEmbedFragment(markdown, {
|
|
25
|
-
kind: "heading",
|
|
26
|
-
value: "Next Steps",
|
|
27
|
-
})).toEqual({
|
|
28
|
-
found: true,
|
|
29
|
-
markdown: [
|
|
30
|
-
"## Next Steps",
|
|
31
|
-
"",
|
|
32
|
-
"Ship the adapter.",
|
|
33
|
-
"",
|
|
34
|
-
"### Detail",
|
|
35
|
-
"",
|
|
36
|
-
"Keep this nested section.",
|
|
37
|
-
"",
|
|
38
|
-
].join("\n"),
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
it("accepts heading slugs and selects block references without the marker", () => {
|
|
42
|
-
expect(selectMarkdownEmbedFragment(markdown, {
|
|
43
|
-
kind: "heading",
|
|
44
|
-
value: "next-steps",
|
|
45
|
-
}).found).toBe(true);
|
|
46
|
-
expect(selectMarkdownEmbedFragment(markdown, {
|
|
47
|
-
kind: "block",
|
|
48
|
-
value: "decision-1",
|
|
49
|
-
})).toEqual({
|
|
50
|
-
found: true,
|
|
51
|
-
markdown: "A portable referenced paragraph.",
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
it("reports missing fragments without falling back to the whole note", () => {
|
|
55
|
-
expect(selectMarkdownEmbedFragment(markdown, {
|
|
56
|
-
kind: "heading",
|
|
57
|
-
value: "Missing",
|
|
58
|
-
})).toEqual({ found: false, markdown: "" });
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
describe("image details", () => {
|
|
62
|
-
it("parses Lapis-style width and width-by-height suffixes", () => {
|
|
63
|
-
expect(parseMiraImageDetails("Diagram|640x360")).toEqual({
|
|
64
|
-
alt: "Diagram",
|
|
65
|
-
width: 640,
|
|
66
|
-
height: 360,
|
|
67
|
-
});
|
|
68
|
-
expect(parseMiraImageDetails("320", "diagram.png")).toEqual({
|
|
69
|
-
alt: "diagram.png",
|
|
70
|
-
width: 320,
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
it("preserves ordinary alt text", () => {
|
|
74
|
-
expect(parseMiraImageDetails("Architecture diagram")).toEqual({
|
|
75
|
-
alt: "Architecture diagram",
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.test.d.ts","sourceRoot":"","sources":["../../../src/preview/frontmatter/frontmatter.test.ts"],"names":[],"mappings":""}
|