@k2b/ui 0.33.0 → 0.35.0
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/dist/base.css +14 -1
- package/dist/browser/actions/ContextMenu.js +13 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +16 -4
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/SelectionToolbar.js +129 -0
- package/dist/browser/actions/SelectionToolbar.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/charts.js +6 -0
- package/dist/browser/charts.js.map +1 -0
- package/dist/browser/chat/ChatComposer.js +525 -407
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +4 -0
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/composer-document.js +19 -0
- package/dist/browser/chat/composer-document.js.map +1 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/content/Chart.js +8 -0
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/FileGrid.js +231 -9
- package/dist/browser/content/FileGrid.js.map +1 -1
- package/dist/browser/content/FileTypeIcon.js +15 -0
- package/dist/browser/content/FileTypeIcon.js.map +1 -1
- package/dist/browser/content/FileView.js +11 -4
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/MatchText.js +61 -0
- package/dist/browser/content/MatchText.js.map +1 -0
- package/dist/browser/content/MessageRow.js +73 -53
- package/dist/browser/content/MessageRow.js.map +1 -1
- package/dist/browser/content/ReactionBar.js +3 -1
- package/dist/browser/content/ReactionBar.js.map +1 -1
- package/dist/browser/content/calendar-day-scroll.js +4 -3
- package/dist/browser/content/calendar-day-scroll.js.map +1 -1
- package/dist/browser/content/chart-bar.js +476 -0
- package/dist/browser/content/chart-bar.js.map +1 -0
- package/dist/browser/content/file-list-messages.js +52 -0
- package/dist/browser/content/file-list-messages.js.map +1 -0
- package/dist/browser/content/index.js +2 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/Tooltip.js +31 -14
- package/dist/browser/feedback/Tooltip.js.map +1 -1
- package/dist/browser/inputs/ChoiceList.js +178 -0
- package/dist/browser/inputs/ChoiceList.js.map +1 -0
- package/dist/browser/inputs/ChoiceSlider.js +314 -0
- package/dist/browser/inputs/ChoiceSlider.js.map +1 -0
- package/dist/browser/inputs/ChoiceTiles.js +135 -0
- package/dist/browser/inputs/ChoiceTiles.js.map +1 -0
- package/dist/browser/inputs/ColorChoices.js +120 -0
- package/dist/browser/inputs/ColorChoices.js.map +1 -0
- package/dist/browser/inputs/QrScanner.js +95 -13
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +15 -13
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/inputs/index.js +4 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/qr-messages.js +2 -0
- package/dist/browser/inputs/qr-messages.js.map +1 -1
- package/dist/browser/internal/radio-keys.js +13 -0
- package/dist/browser/internal/radio-keys.js.map +1 -0
- package/dist/browser/layout/AnchoredPopover.js +180 -0
- package/dist/browser/layout/AnchoredPopover.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +155 -20
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/DetailPanel.js +443 -333
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +21 -7
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/Settings.js +283 -175
- package/dist/browser/layout/Settings.js.map +1 -1
- package/dist/browser/layout/SidebarRailHint.js +79 -0
- package/dist/browser/layout/SidebarRailHint.js.map +1 -0
- package/dist/browser/layout/SidebarSwitcher.js +79 -66
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
- package/dist/browser/layout/TabBar.js +18 -4
- package/dist/browser/layout/TabBar.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +11 -4
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/detail-panel-messages.js +4 -2
- package/dist/browser/layout/detail-panel-messages.js.map +1 -1
- package/dist/browser/layout/index.js +2 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/settings-messages.js +26 -2
- package/dist/browser/layout/settings-messages.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +2 -14
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/DotStrip.js +70 -0
- package/dist/browser/surfaces/DotStrip.js.map +1 -0
- package/dist/browser/surfaces/ProgressRing.js +3 -0
- package/dist/browser/surfaces/ProgressRing.js.map +1 -1
- package/dist/browser/surfaces/ResourceCard.js +125 -68
- package/dist/browser/surfaces/ResourceCard.js.map +1 -1
- package/dist/browser/surfaces/index.js +2 -0
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/browser/surfaces/person-color.js +18 -0
- package/dist/browser/surfaces/person-color.js.map +1 -0
- package/dist/browser/surfaces/resource-messages.js +6 -2
- package/dist/browser/surfaces/resource-messages.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +1358 -0
- package/dist/browser/text-editor/TextEditor.js.map +1 -0
- package/dist/browser/text-editor/clipboard-html.js +152 -0
- package/dist/browser/text-editor/clipboard-html.js.map +1 -0
- package/dist/browser/text-editor/clipboard-loading.js +68 -0
- package/dist/browser/text-editor/clipboard-loading.js.map +1 -0
- package/dist/browser/text-editor/clipboard.js +51 -0
- package/dist/browser/text-editor/clipboard.js.map +1 -0
- package/dist/browser/text-editor/engine.js +125 -0
- package/dist/browser/text-editor/engine.js.map +1 -0
- package/dist/browser/text-editor/format.js +218 -0
- package/dist/browser/text-editor/format.js.map +1 -0
- package/dist/browser/text-editor/formatted.js +164 -0
- package/dist/browser/text-editor/formatted.js.map +1 -0
- package/dist/browser/text-editor/language.js +19 -0
- package/dist/browser/text-editor/language.js.map +1 -0
- package/dist/browser/text-editor/markdown-table.js +563 -0
- package/dist/browser/text-editor/markdown-table.js.map +1 -0
- package/dist/browser/text-editor/messages.js +233 -0
- package/dist/browser/text-editor/messages.js.map +1 -0
- package/dist/browser/text-editor/paste.js +115 -0
- package/dist/browser/text-editor/paste.js.map +1 -0
- package/dist/browser/text-editor/table.js +1760 -0
- package/dist/browser/text-editor/table.js.map +1 -0
- package/dist/browser/text-editor.js +5 -0
- package/dist/browser/text-editor.js.map +1 -0
- package/dist/browser/widgets/Widget.js +3 -2
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +9 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +15 -4
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/SelectionToolbar.js +104 -0
- package/dist/ssr/actions/SelectionToolbar.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/charts.js +6 -0
- package/dist/ssr/charts.js.map +1 -0
- package/dist/ssr/chat/ChatComposer.js +132 -53
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +4 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/composer-document.js +19 -0
- package/dist/ssr/chat/composer-document.js.map +1 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/content/Chart.js +8 -0
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/FileGrid.js +132 -5
- package/dist/ssr/content/FileGrid.js.map +1 -1
- package/dist/ssr/content/FileTypeIcon.js +15 -0
- package/dist/ssr/content/FileTypeIcon.js.map +1 -1
- package/dist/ssr/content/FileView.js +11 -4
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/MatchText.js +56 -0
- package/dist/ssr/content/MatchText.js.map +1 -0
- package/dist/ssr/content/MessageRow.js +16 -6
- package/dist/ssr/content/MessageRow.js.map +1 -1
- package/dist/ssr/content/ReactionBar.js +3 -1
- package/dist/ssr/content/ReactionBar.js.map +1 -1
- package/dist/ssr/content/calendar-day-scroll.js +4 -3
- package/dist/ssr/content/calendar-day-scroll.js.map +1 -1
- package/dist/ssr/content/chart-bar.js +476 -0
- package/dist/ssr/content/chart-bar.js.map +1 -0
- package/dist/ssr/content/file-list-messages.js +52 -0
- package/dist/ssr/content/file-list-messages.js.map +1 -0
- package/dist/ssr/content/index.js +2 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/Tooltip.js +31 -14
- package/dist/ssr/feedback/Tooltip.js.map +1 -1
- package/dist/ssr/inputs/ChoiceList.js +95 -0
- package/dist/ssr/inputs/ChoiceList.js.map +1 -0
- package/dist/ssr/inputs/ChoiceSlider.js +191 -0
- package/dist/ssr/inputs/ChoiceSlider.js.map +1 -0
- package/dist/ssr/inputs/ChoiceTiles.js +61 -0
- package/dist/ssr/inputs/ChoiceTiles.js.map +1 -0
- package/dist/ssr/inputs/ColorChoices.js +60 -0
- package/dist/ssr/inputs/ColorChoices.js.map +1 -0
- package/dist/ssr/inputs/QrScanner.js +89 -10
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js +13 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/inputs/index.js +4 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/qr-messages.js +2 -0
- package/dist/ssr/inputs/qr-messages.js.map +1 -1
- package/dist/ssr/internal/radio-keys.js +13 -0
- package/dist/ssr/internal/radio-keys.js.map +1 -0
- package/dist/ssr/layout/AnchoredPopover.js +142 -0
- package/dist/ssr/layout/AnchoredPopover.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +154 -20
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/DetailPanel.js +181 -108
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +20 -6
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/Settings.js +122 -45
- package/dist/ssr/layout/Settings.js.map +1 -1
- package/dist/ssr/layout/SidebarRailHint.js +79 -0
- package/dist/ssr/layout/SidebarRailHint.js.map +1 -0
- package/dist/ssr/layout/SidebarSwitcher.js +13 -3
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
- package/dist/ssr/layout/TabBar.js +11 -3
- package/dist/ssr/layout/TabBar.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +11 -4
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/detail-panel-messages.js +4 -2
- package/dist/ssr/layout/detail-panel-messages.js.map +1 -1
- package/dist/ssr/layout/index.js +2 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/settings-messages.js +26 -2
- package/dist/ssr/layout/settings-messages.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +2 -14
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/DotStrip.js +31 -0
- package/dist/ssr/surfaces/DotStrip.js.map +1 -0
- package/dist/ssr/surfaces/ProgressRing.js +3 -0
- package/dist/ssr/surfaces/ProgressRing.js.map +1 -1
- package/dist/ssr/surfaces/ResourceCard.js +40 -15
- package/dist/ssr/surfaces/ResourceCard.js.map +1 -1
- package/dist/ssr/surfaces/index.js +2 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/ssr/surfaces/person-color.js +18 -0
- package/dist/ssr/surfaces/person-color.js.map +1 -0
- package/dist/ssr/surfaces/resource-messages.js +6 -2
- package/dist/ssr/surfaces/resource-messages.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +1155 -0
- package/dist/ssr/text-editor/TextEditor.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-html.js +152 -0
- package/dist/ssr/text-editor/clipboard-html.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-loading.js +68 -0
- package/dist/ssr/text-editor/clipboard-loading.js.map +1 -0
- package/dist/ssr/text-editor/clipboard.js +51 -0
- package/dist/ssr/text-editor/clipboard.js.map +1 -0
- package/dist/ssr/text-editor/engine.js +125 -0
- package/dist/ssr/text-editor/engine.js.map +1 -0
- package/dist/ssr/text-editor/format.js +218 -0
- package/dist/ssr/text-editor/format.js.map +1 -0
- package/dist/ssr/text-editor/formatted.js +164 -0
- package/dist/ssr/text-editor/formatted.js.map +1 -0
- package/dist/ssr/text-editor/language.js +19 -0
- package/dist/ssr/text-editor/language.js.map +1 -0
- package/dist/ssr/text-editor/markdown-table.js +563 -0
- package/dist/ssr/text-editor/markdown-table.js.map +1 -0
- package/dist/ssr/text-editor/messages.js +233 -0
- package/dist/ssr/text-editor/messages.js.map +1 -0
- package/dist/ssr/text-editor/paste.js +115 -0
- package/dist/ssr/text-editor/paste.js.map +1 -0
- package/dist/ssr/text-editor/table.js +1760 -0
- package/dist/ssr/text-editor/table.js.map +1 -0
- package/dist/ssr/text-editor.js +5 -0
- package/dist/ssr/text-editor.js.map +1 -0
- package/dist/ssr/widgets/Widget.js +3 -2
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +5 -0
- package/dist/types/actions/Dropdown.d.ts +7 -0
- package/dist/types/actions/SelectionToolbar.d.ts +38 -0
- package/dist/types/actions/index.d.ts +2 -0
- package/dist/types/charts.d.ts +5 -0
- package/dist/types/chat/ChatComposer.d.ts +15 -0
- package/dist/types/chat/chat-messages.d.ts +2 -0
- package/dist/types/chat/composer-document.d.ts +5 -0
- package/dist/types/chat/index.d.ts +1 -1
- package/dist/types/content/Chart.d.ts +2 -1
- package/dist/types/content/FileGrid.d.ts +43 -3
- package/dist/types/content/FileTypeIcon.d.ts +10 -0
- package/dist/types/content/FileView.d.ts +5 -1
- package/dist/types/content/MatchText.d.ts +21 -0
- package/dist/types/content/MessageRow.d.ts +2 -0
- package/dist/types/content/calendar-day-scroll.d.ts +2 -1
- package/dist/types/content/chart-bar.d.ts +60 -0
- package/dist/types/content/file-list-messages.d.ts +24 -0
- package/dist/types/content/index.d.ts +3 -2
- package/dist/types/feedback/Tooltip.d.ts +8 -2
- package/dist/types/inputs/ChoiceList.d.ts +28 -0
- package/dist/types/inputs/ChoiceSlider.d.ts +36 -0
- package/dist/types/inputs/ChoiceTiles.d.ts +25 -0
- package/dist/types/inputs/ColorChoices.d.ts +19 -0
- package/dist/types/inputs/index.d.ts +8 -0
- package/dist/types/inputs/qr-messages.d.ts +1 -0
- package/dist/types/internal/radio-keys.d.ts +5 -0
- package/dist/types/layout/AnchoredPopover.d.ts +31 -0
- package/dist/types/layout/AppWorkspace.d.ts +10 -0
- package/dist/types/layout/DetailPanel.d.ts +17 -0
- package/dist/types/layout/MobileShell.d.ts +5 -2
- package/dist/types/layout/Settings.d.ts +22 -0
- package/dist/types/layout/SidebarRailHint.d.ts +26 -0
- package/dist/types/layout/TabBar.d.ts +5 -0
- package/dist/types/layout/detail-panel-messages.d.ts +1 -0
- package/dist/types/layout/index.d.ts +3 -2
- package/dist/types/layout/settings-messages.d.ts +12 -0
- package/dist/types/surfaces/DotStrip.d.ts +22 -0
- package/dist/types/surfaces/ProgressRing.d.ts +2 -1
- package/dist/types/surfaces/ResourceCard.d.ts +9 -0
- package/dist/types/surfaces/index.d.ts +4 -1
- package/dist/types/surfaces/person-color.d.ts +10 -0
- package/dist/types/surfaces/resource-messages.d.ts +2 -0
- package/dist/types/text-editor/TextEditor.d.ts +69 -0
- package/dist/types/text-editor/clipboard-html.d.ts +9 -0
- package/dist/types/text-editor/clipboard-loading.d.ts +8 -0
- package/dist/types/text-editor/clipboard.d.ts +20 -0
- package/dist/types/text-editor/engine.d.ts +34 -0
- package/dist/types/text-editor/format.d.ts +34 -0
- package/dist/types/text-editor/formatted.d.ts +1 -0
- package/dist/types/text-editor/language.d.ts +8 -0
- package/dist/types/text-editor/markdown-table.d.ts +105 -0
- package/dist/types/text-editor/messages.d.ts +113 -0
- package/dist/types/text-editor/paste.d.ts +6 -0
- package/dist/types/text-editor/table.d.ts +81 -0
- package/dist/types/text-editor.d.ts +4 -0
- package/dist/types/widgets/Widget.d.ts +3 -2
- package/package.json +28 -3
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { standardKeymap } from "@codemirror/commands";
|
|
2
|
+
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3
|
+
import { Compartment, EditorState, Prec, Text } from "@codemirror/state";
|
|
4
|
+
import { drawSelection, EditorView, keymap, placeholder, runScopeHandlers } from "@codemirror/view";
|
|
5
|
+
import { clipboardLoading } from "./clipboard-loading";
|
|
6
|
+
import { commands } from "./format";
|
|
7
|
+
import { formattedView } from "./formatted";
|
|
8
|
+
import { markdown } from "./language";
|
|
9
|
+
import { cleanPaste } from "./paste";
|
|
10
|
+
import { tableGrid, tableHost } from "./table";
|
|
11
|
+
const builtInPresentation = mode => [markdown(), syntaxHighlighting(defaultHighlightStyle, {
|
|
12
|
+
fallback: true
|
|
13
|
+
}), mode === "formatted" ? formattedView : EditorView.contentAttributes.of({
|
|
14
|
+
class: "k2b-ste-source"
|
|
15
|
+
}), keymap.of([{
|
|
16
|
+
key: "Mod-b",
|
|
17
|
+
run: commands.bold
|
|
18
|
+
}, {
|
|
19
|
+
key: "Mod-i",
|
|
20
|
+
run: commands.italic
|
|
21
|
+
}, {
|
|
22
|
+
key: "Mod-k",
|
|
23
|
+
run: commands.link
|
|
24
|
+
}, {
|
|
25
|
+
key: "Mod-Shift-x",
|
|
26
|
+
run: commands.strike
|
|
27
|
+
}])];
|
|
28
|
+
|
|
29
|
+
/** Shared engine; application extensions own transport, awareness and domain features. */
|
|
30
|
+
export function createTextEditor(options) {
|
|
31
|
+
const modeSlot = new Compartment();
|
|
32
|
+
const readOnlySlot = new Compartment();
|
|
33
|
+
const labelSlot = new Compartment();
|
|
34
|
+
const presentation = options.presentation ?? builtInPresentation;
|
|
35
|
+
const runHistory = (view, direction) => {
|
|
36
|
+
view.state.facet(tableHost)?.[direction]();
|
|
37
|
+
// Consume even an empty or read-only history, so another binding cannot handle it again.
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
const modeExtensions = mode => mode === "plain" ? [clipboardLoading(() => options.host), cleanPaste(options.onDroppedImages, true)] : [presentation(mode), mode === "formatted" ? tableGrid() : clipboardLoading(() => options.host), cleanPaste(options.onDroppedImages)];
|
|
41
|
+
const view = new EditorView({
|
|
42
|
+
parent: options.parent,
|
|
43
|
+
state: EditorState.create({
|
|
44
|
+
doc: Text.of((options.doc ?? "").split("\n")),
|
|
45
|
+
extensions: [drawSelection(), EditorView.lineWrapping, placeholder(options.placeholder ?? ""), labelSlot.of(EditorView.contentAttributes.of({
|
|
46
|
+
"aria-label": options.label
|
|
47
|
+
})), Prec.highest([keymap.of([{
|
|
48
|
+
key: "Mod-z",
|
|
49
|
+
run: view => runHistory(view, "undo"),
|
|
50
|
+
shift: view => runHistory(view, "redo"),
|
|
51
|
+
preventDefault: true
|
|
52
|
+
}, {
|
|
53
|
+
key: "Mod-y",
|
|
54
|
+
run: view => runHistory(view, "redo"),
|
|
55
|
+
preventDefault: true
|
|
56
|
+
}]), EditorView.domEventHandlers({
|
|
57
|
+
beforeinput(event, view) {
|
|
58
|
+
if (event.inputType === "historyUndo") return runHistory(view, "undo");
|
|
59
|
+
if (event.inputType === "historyRedo") return runHistory(view, "redo");
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
})]), keymap.of(standardKeymap), tableHost.of({
|
|
63
|
+
...options.host,
|
|
64
|
+
onDroppedImages: options.onDroppedImages,
|
|
65
|
+
undo: () => {
|
|
66
|
+
if (!view.state.readOnly) options.host.undo();
|
|
67
|
+
},
|
|
68
|
+
redo: () => {
|
|
69
|
+
if (!view.state.readOnly) options.host.redo();
|
|
70
|
+
}
|
|
71
|
+
}), EditorState.transactionFilter.of(tr => {
|
|
72
|
+
// Only growth is refused: an over-limit text stays editable so it can be shortened.
|
|
73
|
+
if (tr.docChanged && tr.isUserEvent("input") && tr.newDoc.length > options.host.maxLength && tr.newDoc.length > tr.startState.doc.length) {
|
|
74
|
+
const inserted = [];
|
|
75
|
+
tr.changes.iterChanges((_from, _to, _newFrom, _newTo, text) => {
|
|
76
|
+
if (text.length) inserted.push(text.toString());
|
|
77
|
+
});
|
|
78
|
+
queueMicrotask(() => {
|
|
79
|
+
if (inserted.length) options.host.onRecovery(inserted.join("\n"));
|
|
80
|
+
options.host.onError("textTooLarge");
|
|
81
|
+
});
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return tr;
|
|
85
|
+
}), EditorView.updateListener.of(update => {
|
|
86
|
+
if (update.docChanged) options.onChange?.(update.state.doc.toString());
|
|
87
|
+
}), modeSlot.of(modeExtensions(options.mode ?? "formatted")), readOnlySlot.of([EditorState.readOnly.of(options.readOnly ?? false), EditorView.editable.of(!options.readOnly)]), options.extensions ?? []]
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
// CM's Android DOM-input deferral can lose a physical Enter when the next
|
|
91
|
+
// EditContext update arrives before its animation frame. Run the public
|
|
92
|
+
// keymap synchronously only for that reliable, non-composing key event.
|
|
93
|
+
const enter = event => {
|
|
94
|
+
if (event.target !== view.contentDOM || event.key !== "Enter" || event.keyCode !== 13 || event.isComposing || view.composing || event.defaultPrevented || !/Android/.test(view.dom.ownerDocument.defaultView?.navigator.userAgent ?? "") || !("editContext" in view.contentDOM && view.contentDOM.editContext)) return;
|
|
95
|
+
if (runScopeHandlers(view, event, "editor")) {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
event.stopImmediatePropagation();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
view.contentDOM.addEventListener("keydown", enter, true);
|
|
101
|
+
return {
|
|
102
|
+
view,
|
|
103
|
+
/** Also re-reads `presentation`, so a host can refresh it, e.g. after a theme change. */
|
|
104
|
+
setMode: mode => view.dispatch({
|
|
105
|
+
effects: modeSlot.reconfigure(modeExtensions(mode))
|
|
106
|
+
}),
|
|
107
|
+
setLabel: label => view.dispatch({
|
|
108
|
+
effects: labelSlot.reconfigure(EditorView.contentAttributes.of({
|
|
109
|
+
"aria-label": label
|
|
110
|
+
}))
|
|
111
|
+
}),
|
|
112
|
+
// Hosts re-run this from reactive state that may change inside an editor update; an unchanged value must not dispatch.
|
|
113
|
+
setReadOnly: readOnly => {
|
|
114
|
+
if (view.state.readOnly === readOnly && view.state.facet(EditorView.editable) === !readOnly) return;
|
|
115
|
+
view.dispatch({
|
|
116
|
+
effects: readOnlySlot.reconfigure([EditorState.readOnly.of(readOnly), EditorView.editable.of(!readOnly)])
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
destroy: () => {
|
|
120
|
+
view.contentDOM.removeEventListener("keydown", enter, true);
|
|
121
|
+
view.destroy();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["text-editor/engine.ts"],"sourcesContent":["import { standardKeymap } from \"@codemirror/commands\";\nimport { defaultHighlightStyle, syntaxHighlighting } from \"@codemirror/language\";\nimport { Compartment, EditorState, type Extension, Prec, Text } from \"@codemirror/state\";\nimport { drawSelection, EditorView, keymap, placeholder, runScopeHandlers } from \"@codemirror/view\";\nimport { clipboardLoading } from \"./clipboard-loading\";\nimport { commands } from \"./format\";\nimport { formattedView } from \"./formatted\";\nimport { markdown } from \"./language\";\nimport { cleanPaste } from \"./paste\";\nimport { type TableHost, tableGrid, tableHost } from \"./table\";\n\nexport type TextEditorMode = \"formatted\" | \"source\" | \"plain\";\nexport type TextEditorOptions = {\n parent: HTMLElement;\n /** Initial Markdown. Subsequent collaborative changes arrive through extensions. */\n doc?: string;\n mode?: TextEditorMode;\n readOnly?: boolean;\n placeholder?: string;\n label: string;\n extensions?: Extension;\n /**\n * Replaces the built-in Markdown language, highlighting, formatted markers and\n * formatting keys of the formatted and source modes. The engine keeps the\n * table grid, clean paste, limits and history routing in every mode.\n */\n presentation?: (mode: Exclude<TextEditorMode, \"plain\">) => Extension;\n /** The host owns history; collaboration bindings supply theirs. */\n host: TableHost;\n onChange?: (text: string) => void;\n onDroppedImages?: (count: number, files: File[]) => void;\n};\n\nconst builtInPresentation = (mode: Exclude<TextEditorMode, \"plain\">): Extension => [\n markdown(),\n syntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n mode === \"formatted\" ? formattedView : EditorView.contentAttributes.of({ class: \"k2b-ste-source\" }),\n keymap.of([\n { key: \"Mod-b\", run: commands.bold },\n { key: \"Mod-i\", run: commands.italic },\n { key: \"Mod-k\", run: commands.link },\n { key: \"Mod-Shift-x\", run: commands.strike },\n ]),\n];\n\n/** Shared engine; application extensions own transport, awareness and domain features. */\nexport function createTextEditor(options: TextEditorOptions) {\n const modeSlot = new Compartment();\n const readOnlySlot = new Compartment();\n const labelSlot = new Compartment();\n const presentation = options.presentation ?? builtInPresentation;\n const runHistory = (view: EditorView, direction: \"undo\" | \"redo\") => {\n view.state.facet(tableHost)?.[direction]();\n // Consume even an empty or read-only history, so another binding cannot handle it again.\n return true;\n };\n const modeExtensions = (mode: TextEditorMode): Extension =>\n mode === \"plain\"\n ? [clipboardLoading(() => options.host), cleanPaste(options.onDroppedImages, true)]\n : [\n presentation(mode),\n mode === \"formatted\" ? tableGrid() : clipboardLoading(() => options.host),\n cleanPaste(options.onDroppedImages),\n ];\n const view = new EditorView({\n parent: options.parent,\n state: EditorState.create({\n doc: Text.of((options.doc ?? \"\").split(\"\\n\")),\n extensions: [\n drawSelection(),\n EditorView.lineWrapping,\n placeholder(options.placeholder ?? \"\"),\n labelSlot.of(EditorView.contentAttributes.of({ \"aria-label\": options.label })),\n Prec.highest([\n keymap.of([\n { key: \"Mod-z\", run: (view) => runHistory(view, \"undo\"), shift: (view) => runHistory(view, \"redo\"), preventDefault: true },\n { key: \"Mod-y\", run: (view) => runHistory(view, \"redo\"), preventDefault: true },\n ]),\n EditorView.domEventHandlers({\n beforeinput(event, view) {\n if (event.inputType === \"historyUndo\") return runHistory(view, \"undo\");\n if (event.inputType === \"historyRedo\") return runHistory(view, \"redo\");\n return false;\n },\n }),\n ]),\n keymap.of(standardKeymap),\n tableHost.of({\n ...options.host,\n onDroppedImages: options.onDroppedImages,\n undo: () => {\n if (!view.state.readOnly) options.host.undo();\n },\n redo: () => {\n if (!view.state.readOnly) options.host.redo();\n },\n }),\n EditorState.transactionFilter.of((tr) => {\n // Only growth is refused: an over-limit text stays editable so it can be shortened.\n if (\n tr.docChanged &&\n tr.isUserEvent(\"input\") &&\n tr.newDoc.length > options.host.maxLength &&\n tr.newDoc.length > tr.startState.doc.length\n ) {\n const inserted: string[] = [];\n tr.changes.iterChanges((_from, _to, _newFrom, _newTo, text) => {\n if (text.length) inserted.push(text.toString());\n });\n queueMicrotask(() => {\n if (inserted.length) options.host.onRecovery(inserted.join(\"\\n\"));\n options.host.onError(\"textTooLarge\");\n });\n return [];\n }\n return tr;\n }),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) options.onChange?.(update.state.doc.toString());\n }),\n modeSlot.of(modeExtensions(options.mode ?? \"formatted\")),\n readOnlySlot.of([EditorState.readOnly.of(options.readOnly ?? false), EditorView.editable.of(!options.readOnly)]),\n options.extensions ?? [],\n ],\n }),\n });\n // CM's Android DOM-input deferral can lose a physical Enter when the next\n // EditContext update arrives before its animation frame. Run the public\n // keymap synchronously only for that reliable, non-composing key event.\n const enter = (event: KeyboardEvent) => {\n if (\n event.target !== view.contentDOM ||\n event.key !== \"Enter\" ||\n event.keyCode !== 13 ||\n event.isComposing ||\n view.composing ||\n event.defaultPrevented ||\n !/Android/.test(view.dom.ownerDocument.defaultView?.navigator.userAgent ?? \"\") ||\n !(\"editContext\" in view.contentDOM && view.contentDOM.editContext)\n )\n return;\n if (runScopeHandlers(view, event, \"editor\")) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n };\n view.contentDOM.addEventListener(\"keydown\", enter, true);\n return {\n view,\n /** Also re-reads `presentation`, so a host can refresh it, e.g. after a theme change. */\n setMode: (mode: TextEditorMode) => view.dispatch({ effects: modeSlot.reconfigure(modeExtensions(mode)) }),\n setLabel: (label: string) =>\n view.dispatch({ effects: labelSlot.reconfigure(EditorView.contentAttributes.of({ \"aria-label\": label })) }),\n // Hosts re-run this from reactive state that may change inside an editor update; an unchanged value must not dispatch.\n setReadOnly: (readOnly: boolean) => {\n if (view.state.readOnly === readOnly && view.state.facet(EditorView.editable) === !readOnly) return;\n view.dispatch({ effects: readOnlySlot.reconfigure([EditorState.readOnly.of(readOnly), EditorView.editable.of(!readOnly)]) });\n },\n destroy: () => {\n view.contentDOM.removeEventListener(\"keydown\", enter, true);\n view.destroy();\n },\n };\n}\nexport type TextEditorController = ReturnType<typeof createTextEditor>;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/** Toolbar and keyboard commands. Each one is a plain Markdown edit of the selection. */
|
|
2
|
+
import { EditorSelection, Facet } from "@codemirror/state";
|
|
3
|
+
/** Insertion text follows the editor's inherited locale, including keyboard commands. */
|
|
4
|
+
export const formatLabels = Facet.define({
|
|
5
|
+
combine: values => values[0] ?? {
|
|
6
|
+
link: "Link",
|
|
7
|
+
column: column => `Column ${column}`
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/** Named Markdown marks or an app's single-line paired delimiter (for example Notebook's `==`). */
|
|
12
|
+
|
|
13
|
+
/** Pure transaction spec, also used when a missing table cell must be materialized atomically. */
|
|
14
|
+
export const inlineFormat = (state, name) => {
|
|
15
|
+
if (name === "link") {
|
|
16
|
+
const {
|
|
17
|
+
from,
|
|
18
|
+
to
|
|
19
|
+
} = state.selection.main;
|
|
20
|
+
const label = state.sliceDoc(from, to) || state.facet(formatLabels).link;
|
|
21
|
+
return {
|
|
22
|
+
changes: {
|
|
23
|
+
from,
|
|
24
|
+
to,
|
|
25
|
+
insert: `[${label}](https://)`
|
|
26
|
+
},
|
|
27
|
+
selection: {
|
|
28
|
+
anchor: from + label.length + 3,
|
|
29
|
+
head: from + label.length + 11
|
|
30
|
+
},
|
|
31
|
+
userEvent: "input.format"
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const marker = typeof name === "string" ? {
|
|
35
|
+
bold: "**",
|
|
36
|
+
italic: "*",
|
|
37
|
+
code: "`",
|
|
38
|
+
strike: "~~"
|
|
39
|
+
}[name] : name.marker;
|
|
40
|
+
// A host inline delimiter must not split a cell or introduce another row.
|
|
41
|
+
if (!marker || /[|\r\n]/.test(marker)) return {};
|
|
42
|
+
return {
|
|
43
|
+
...state.changeByRange(range => {
|
|
44
|
+
const text = state.sliceDoc(range.from, range.to);
|
|
45
|
+
const before = state.sliceDoc(Math.max(0, range.from - marker.length), range.from);
|
|
46
|
+
const after = state.sliceDoc(range.to, Math.min(state.doc.length, range.to + marker.length));
|
|
47
|
+
const italicBoundary = name !== "italic" || (/\*+$/.exec(state.sliceDoc(state.doc.lineAt(range.from).from, range.from))?.[0].length ?? 0) % 2 === 1 && (/^\*+/.exec(state.sliceDoc(range.to, state.doc.lineAt(range.to).to))?.[0].length ?? 0) % 2 === 1;
|
|
48
|
+
if (before === marker && after === marker && italicBoundary) return {
|
|
49
|
+
changes: [{
|
|
50
|
+
from: range.from - marker.length,
|
|
51
|
+
to: range.from
|
|
52
|
+
}, {
|
|
53
|
+
from: range.to,
|
|
54
|
+
to: range.to + marker.length
|
|
55
|
+
}],
|
|
56
|
+
range: EditorSelection.range(range.from - marker.length, range.to - marker.length)
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
changes: {
|
|
60
|
+
from: range.from,
|
|
61
|
+
to: range.to,
|
|
62
|
+
insert: `${marker}${text}${marker}`
|
|
63
|
+
},
|
|
64
|
+
range: EditorSelection.range(range.from + marker.length, range.to + marker.length)
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
67
|
+
userEvent: "input.format"
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const inlineCommand = name => view => {
|
|
71
|
+
if (view.state.readOnly) return false;
|
|
72
|
+
view.dispatch(inlineFormat(view.state, name));
|
|
73
|
+
view.focus();
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
76
|
+
const linePrefix = (pattern, prefix) => view => {
|
|
77
|
+
if (view.state.readOnly) return false;
|
|
78
|
+
const {
|
|
79
|
+
state
|
|
80
|
+
} = view;
|
|
81
|
+
const lines = new Set();
|
|
82
|
+
for (const r of state.selection.ranges) for (let n = state.doc.lineAt(r.from).number; n <= state.doc.lineAt(r.to).number; n++) lines.add(n);
|
|
83
|
+
const all = [...lines].every(n => pattern.test(state.doc.line(n).text));
|
|
84
|
+
const changes = [...lines].map(n => {
|
|
85
|
+
const line = state.doc.line(n);
|
|
86
|
+
const m = pattern.exec(line.text);
|
|
87
|
+
return all && m ? {
|
|
88
|
+
from: line.from,
|
|
89
|
+
to: line.from + m[0].length
|
|
90
|
+
} : {
|
|
91
|
+
from: line.from,
|
|
92
|
+
insert: prefix(state, n)
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
view.dispatch({
|
|
96
|
+
changes,
|
|
97
|
+
userEvent: "input.format"
|
|
98
|
+
});
|
|
99
|
+
view.focus();
|
|
100
|
+
return true;
|
|
101
|
+
};
|
|
102
|
+
const heading = level => view => {
|
|
103
|
+
if (view.state.readOnly) return false;
|
|
104
|
+
const {
|
|
105
|
+
state
|
|
106
|
+
} = view;
|
|
107
|
+
const numbers = new Set();
|
|
108
|
+
for (const range of state.selection.ranges) for (let n = state.doc.lineAt(range.from).number; n <= state.doc.lineAt(range.to).number; n++) numbers.add(n);
|
|
109
|
+
const prefix = `${"#".repeat(level)} `;
|
|
110
|
+
const lines = [...numbers].sort((a, b) => a - b).map(number => state.doc.line(number));
|
|
111
|
+
const remove = lines.every(line => line.text.startsWith(prefix));
|
|
112
|
+
view.dispatch({
|
|
113
|
+
changes: lines.map(line => ({
|
|
114
|
+
from: line.from,
|
|
115
|
+
to: line.from + (/^#{1,6} /.exec(line.text)?.[0].length ?? 0),
|
|
116
|
+
insert: remove ? "" : prefix
|
|
117
|
+
})),
|
|
118
|
+
userEvent: "input.format"
|
|
119
|
+
});
|
|
120
|
+
view.focus();
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
export const commands = {
|
|
124
|
+
bold: inlineCommand("bold"),
|
|
125
|
+
italic: inlineCommand("italic"),
|
|
126
|
+
code: inlineCommand("code"),
|
|
127
|
+
strike: inlineCommand("strike"),
|
|
128
|
+
heading: heading(2),
|
|
129
|
+
heading1: heading(1),
|
|
130
|
+
heading2: heading(2),
|
|
131
|
+
heading3: heading(3),
|
|
132
|
+
codeBlock: view => {
|
|
133
|
+
if (view.state.readOnly) return false;
|
|
134
|
+
const {
|
|
135
|
+
state
|
|
136
|
+
} = view;
|
|
137
|
+
const from = state.doc.lineAt(state.selection.main.from).from;
|
|
138
|
+
const to = state.doc.lineAt(state.selection.main.to).to;
|
|
139
|
+
const text = state.sliceDoc(from, to);
|
|
140
|
+
let fenceLength = 3;
|
|
141
|
+
for (const match of text.matchAll(/`+/g)) fenceLength = Math.max(fenceLength, match[0].length + 1);
|
|
142
|
+
const fence = "`".repeat(fenceLength);
|
|
143
|
+
const lead = from > 0 && state.doc.lineAt(from - 1).length ? "\n" : "";
|
|
144
|
+
const tail = to < state.doc.length && state.doc.lineAt(to + 1).length ? "\n" : "";
|
|
145
|
+
const start = from + lead.length + fence.length + 1;
|
|
146
|
+
view.dispatch({
|
|
147
|
+
changes: {
|
|
148
|
+
from,
|
|
149
|
+
to,
|
|
150
|
+
insert: `${lead}${fence}\n${text}\n${fence}${tail}`
|
|
151
|
+
},
|
|
152
|
+
selection: {
|
|
153
|
+
anchor: start,
|
|
154
|
+
head: start + text.length
|
|
155
|
+
},
|
|
156
|
+
userEvent: "input.format"
|
|
157
|
+
});
|
|
158
|
+
view.focus();
|
|
159
|
+
return true;
|
|
160
|
+
},
|
|
161
|
+
bulletList: linePrefix(/^\s*[-*] /, () => "- "),
|
|
162
|
+
orderedList: linePrefix(/^\s*\d+\. /, () => "1. "),
|
|
163
|
+
quote: linePrefix(/^> ?/, () => "> "),
|
|
164
|
+
link: inlineCommand("link"),
|
|
165
|
+
table: view => {
|
|
166
|
+
if (view.state.readOnly) return false;
|
|
167
|
+
const {
|
|
168
|
+
from
|
|
169
|
+
} = view.state.selection.main;
|
|
170
|
+
const line = view.state.doc.lineAt(from);
|
|
171
|
+
const lead = line.length ? "\n\n" : "";
|
|
172
|
+
const labels = view.state.facet(formatLabels);
|
|
173
|
+
const first = labels.column(1);
|
|
174
|
+
const insert = `${lead}| ${first} | ${labels.column(2)} |\n| --- | --- |\n| | |\n`;
|
|
175
|
+
const anchor = line.to + lead.length + 2;
|
|
176
|
+
view.dispatch({
|
|
177
|
+
changes: {
|
|
178
|
+
from: line.to,
|
|
179
|
+
insert
|
|
180
|
+
},
|
|
181
|
+
selection: {
|
|
182
|
+
anchor,
|
|
183
|
+
head: anchor + first.length
|
|
184
|
+
},
|
|
185
|
+
userEvent: "input.format"
|
|
186
|
+
});
|
|
187
|
+
view.focus();
|
|
188
|
+
queueMicrotask(() => {
|
|
189
|
+
if (!view.dom.isConnected) return;
|
|
190
|
+
const table = [...view.contentDOM.querySelectorAll(".k2b-ste-table")].find(element => view.posAtDOM(element) === line.to + lead.length);
|
|
191
|
+
const cell = table?.querySelector('.k2b-ste-cell[data-r="0"][data-c="0"]');
|
|
192
|
+
if (!cell) return;
|
|
193
|
+
cell.focus();
|
|
194
|
+
const selection = cell.ownerDocument.getSelection();
|
|
195
|
+
const range = cell.ownerDocument.createRange();
|
|
196
|
+
range.selectNodeContents(cell);
|
|
197
|
+
selection?.removeAllRanges();
|
|
198
|
+
selection?.addRange(range);
|
|
199
|
+
});
|
|
200
|
+
return true;
|
|
201
|
+
},
|
|
202
|
+
rule: view => {
|
|
203
|
+
if (view.state.readOnly) return false;
|
|
204
|
+
const line = view.state.doc.lineAt(view.state.selection.main.from);
|
|
205
|
+
const previousHasText = line.number > 1 && view.state.doc.line(line.number - 1).text.trim().length > 0;
|
|
206
|
+
const lead = line.length ? "\n\n" : previousHasText ? "\n" : "";
|
|
207
|
+
view.dispatch({
|
|
208
|
+
changes: {
|
|
209
|
+
from: line.to,
|
|
210
|
+
insert: `${lead}---\n`
|
|
211
|
+
},
|
|
212
|
+
userEvent: "input.format"
|
|
213
|
+
});
|
|
214
|
+
view.focus();
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["text-editor/format.ts"],"sourcesContent":["/** Toolbar and keyboard commands. Each one is a plain Markdown edit of the selection. */\nimport { EditorSelection, type EditorState, Facet, type TransactionSpec } from \"@codemirror/state\";\nimport type { EditorView } from \"@codemirror/view\";\n\n/** Insertion text follows the editor's inherited locale, including keyboard commands. */\nexport const formatLabels = Facet.define<\n { link: string; column: (column: number) => string },\n { link: string; column: (column: number) => string }\n>({\n combine: (values) => values[0] ?? { link: \"Link\", column: (column) => `Column ${column}` },\n});\n\n/** Named Markdown marks or an app's single-line paired delimiter (for example Notebook's `==`). */\nexport type InlineFormat = \"bold\" | \"italic\" | \"code\" | \"strike\" | \"link\" | { marker: string };\n/** Pure transaction spec, also used when a missing table cell must be materialized atomically. */\nexport const inlineFormat = (state: EditorState, name: InlineFormat): TransactionSpec => {\n if (name === \"link\") {\n const { from, to } = state.selection.main;\n const label = state.sliceDoc(from, to) || state.facet(formatLabels).link;\n return {\n changes: { from, to, insert: `[${label}](https://)` },\n selection: { anchor: from + label.length + 3, head: from + label.length + 11 },\n userEvent: \"input.format\",\n };\n }\n const marker = typeof name === \"string\" ? { bold: \"**\", italic: \"*\", code: \"`\", strike: \"~~\" }[name] : name.marker;\n // A host inline delimiter must not split a cell or introduce another row.\n if (!marker || /[|\\r\\n]/.test(marker)) return {};\n return {\n ...state.changeByRange((range) => {\n const text = state.sliceDoc(range.from, range.to);\n const before = state.sliceDoc(Math.max(0, range.from - marker.length), range.from);\n const after = state.sliceDoc(range.to, Math.min(state.doc.length, range.to + marker.length));\n const italicBoundary =\n name !== \"italic\" ||\n ((/\\*+$/.exec(state.sliceDoc(state.doc.lineAt(range.from).from, range.from))?.[0].length ?? 0) % 2 === 1 &&\n (/^\\*+/.exec(state.sliceDoc(range.to, state.doc.lineAt(range.to).to))?.[0].length ?? 0) % 2 === 1);\n if (before === marker && after === marker && italicBoundary)\n return {\n changes: [\n { from: range.from - marker.length, to: range.from },\n { from: range.to, to: range.to + marker.length },\n ],\n range: EditorSelection.range(range.from - marker.length, range.to - marker.length),\n };\n return {\n changes: { from: range.from, to: range.to, insert: `${marker}${text}${marker}` },\n range: EditorSelection.range(range.from + marker.length, range.to + marker.length),\n };\n }),\n userEvent: \"input.format\",\n };\n};\nconst inlineCommand = (name: InlineFormat) => (view: EditorView) => {\n if (view.state.readOnly) return false;\n view.dispatch(inlineFormat(view.state, name));\n view.focus();\n return true;\n};\n\nconst linePrefix = (pattern: RegExp, prefix: (state: EditorState, n: number) => string) => (view: EditorView) => {\n if (view.state.readOnly) return false;\n const { state } = view;\n const lines = new Set<number>();\n for (const r of state.selection.ranges)\n for (let n = state.doc.lineAt(r.from).number; n <= state.doc.lineAt(r.to).number; n++) lines.add(n);\n const all = [...lines].every((n) => pattern.test(state.doc.line(n).text));\n const changes = [...lines].map((n) => {\n const line = state.doc.line(n);\n const m = pattern.exec(line.text);\n return all && m ? { from: line.from, to: line.from + m[0].length } : { from: line.from, insert: prefix(state, n) };\n });\n view.dispatch({ changes, userEvent: \"input.format\" });\n view.focus();\n return true;\n};\n\nconst heading = (level: number) => (view: EditorView) => {\n if (view.state.readOnly) return false;\n const { state } = view;\n const numbers = new Set<number>();\n for (const range of state.selection.ranges)\n for (let n = state.doc.lineAt(range.from).number; n <= state.doc.lineAt(range.to).number; n++) numbers.add(n);\n const prefix = `${\"#\".repeat(level)} `;\n const lines = [...numbers].sort((a, b) => a - b).map((number) => state.doc.line(number));\n const remove = lines.every((line) => line.text.startsWith(prefix));\n view.dispatch({\n changes: lines.map((line) => ({\n from: line.from,\n to: line.from + (/^#{1,6} /.exec(line.text)?.[0].length ?? 0),\n insert: remove ? \"\" : prefix,\n })),\n userEvent: \"input.format\",\n });\n view.focus();\n return true;\n};\n\nexport const commands = {\n bold: inlineCommand(\"bold\"),\n italic: inlineCommand(\"italic\"),\n code: inlineCommand(\"code\"),\n strike: inlineCommand(\"strike\"),\n heading: heading(2),\n heading1: heading(1),\n heading2: heading(2),\n heading3: heading(3),\n codeBlock: (view: EditorView) => {\n if (view.state.readOnly) return false;\n const { state } = view;\n const from = state.doc.lineAt(state.selection.main.from).from;\n const to = state.doc.lineAt(state.selection.main.to).to;\n const text = state.sliceDoc(from, to);\n let fenceLength = 3;\n for (const match of text.matchAll(/`+/g)) fenceLength = Math.max(fenceLength, match[0].length + 1);\n const fence = \"`\".repeat(fenceLength);\n const lead = from > 0 && state.doc.lineAt(from - 1).length ? \"\\n\" : \"\";\n const tail = to < state.doc.length && state.doc.lineAt(to + 1).length ? \"\\n\" : \"\";\n const start = from + lead.length + fence.length + 1;\n view.dispatch({\n changes: { from, to, insert: `${lead}${fence}\\n${text}\\n${fence}${tail}` },\n selection: { anchor: start, head: start + text.length },\n userEvent: \"input.format\",\n });\n view.focus();\n return true;\n },\n bulletList: linePrefix(/^\\s*[-*] /, () => \"- \"),\n orderedList: linePrefix(/^\\s*\\d+\\. /, () => \"1. \"),\n quote: linePrefix(/^> ?/, () => \"> \"),\n link: inlineCommand(\"link\"),\n table: (view: EditorView) => {\n if (view.state.readOnly) return false;\n const { from } = view.state.selection.main;\n const line = view.state.doc.lineAt(from);\n const lead = line.length ? \"\\n\\n\" : \"\";\n const labels = view.state.facet(formatLabels);\n const first = labels.column(1);\n const insert = `${lead}| ${first} | ${labels.column(2)} |\\n| --- | --- |\\n| | |\\n`;\n const anchor = line.to + lead.length + 2;\n view.dispatch({ changes: { from: line.to, insert }, selection: { anchor, head: anchor + first.length }, userEvent: \"input.format\" });\n view.focus();\n queueMicrotask(() => {\n if (!view.dom.isConnected) return;\n const table = [...view.contentDOM.querySelectorAll<HTMLElement>(\".k2b-ste-table\")].find(\n (element) => view.posAtDOM(element) === line.to + lead.length,\n );\n const cell = table?.querySelector<HTMLElement>('.k2b-ste-cell[data-r=\"0\"][data-c=\"0\"]');\n if (!cell) return;\n cell.focus();\n const selection = cell.ownerDocument.getSelection();\n const range = cell.ownerDocument.createRange();\n range.selectNodeContents(cell);\n selection?.removeAllRanges();\n selection?.addRange(range);\n });\n return true;\n },\n rule: (view: EditorView) => {\n if (view.state.readOnly) return false;\n const line = view.state.doc.lineAt(view.state.selection.main.from);\n const previousHasText = line.number > 1 && view.state.doc.line(line.number - 1).text.trim().length > 0;\n const lead = line.length ? \"\\n\\n\" : previousHasText ? \"\\n\" : \"\";\n view.dispatch({ changes: { from: line.to, insert: `${lead}---\\n` }, userEvent: \"input.format\" });\n view.focus();\n return true;\n },\n};\n"],"mappings":"AAAA;AACA,SAAS,eAAe,EAAoB,KAAK,QAA8B,mBAAmB;AAGlG;AACA,OAAO,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAGtC;EACA,OAAO,EAAG,MAAM,IAAK,MAAM,CAAC,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,MAAM;IAAE,MAAM,EAAG,MAAM,IAAK,UAAU,MAAM;EAAG;AAC3F,CAAC,CAAC;;AAEF;;AAEA;AACA,OAAO,MAAM,YAAY,GAAG,CAAC,KAAkB,EAAE,IAAkB,KAAsB;EACvF,IAAI,IAAI,KAAK,MAAM,EAAE;IACnB,MAAM;MAAE,IAAI;MAAE;IAAG,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI;IACxE,OAAO;MACL,OAAO,EAAE;QAAE,IAAI;QAAE,EAAE;QAAE,MAAM,EAAE,IAAI,KAAK;MAAc,CAAC;MACrD,SAAS,EAAE;QAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG;MAAG,CAAC;MAC9E,SAAS,EAAE;IACb,CAAC;EACH;EACA,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,GAAG;IAAE,IAAI,EAAE,IAAI;IAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,GAAG;IAAE,MAAM,EAAE;EAAK,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM;EAClH;EACA,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;EAChD,OAAO;IACL,GAAG,KAAK,CAAC,aAAa,CAAE,KAAK,IAAK;MAChC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;MACjD,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;MAClF,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;MAC5F,MAAM,cAAc,GAClB,IAAI,KAAK,QAAQ,IAChB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IACtG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAE;MACtG,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,IAAI,cAAc,EACzD,OAAO;QACL,OAAO,EAAE,CACP;UAAE,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM;UAAE,EAAE,EAAE,KAAK,CAAC;QAAK,CAAC,EACpD;UAAE,IAAI,EAAE,KAAK,CAAC,EAAE;UAAE,EAAE,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC;QAAO,CAAC,CACjD;QACD,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM;MACnF,CAAC;MACH,OAAO;QACL,OAAO,EAAE;UAAE,IAAI,EAAE,KAAK,CAAC,IAAI;UAAE,EAAE,EAAE,KAAK,CAAC,EAAE;UAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM;QAAG,CAAC;QAChF,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM;MACnF,CAAC;IACH,CAAC,CAAC;IACF,SAAS,EAAE;EACb,CAAC;AACH,CAAC;AACD,MAAM,aAAa,GAAI,IAAkB,IAAM,IAAgB,IAAK;EAClE,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;EACrC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;EAC7C,IAAI,CAAC,KAAK,CAAC,CAAC;EACZ,OAAO,IAAI;AACb,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,MAAiD,KAAM,IAAgB,IAAK;EAC/G,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;EACrC,MAAM;IAAE;EAAM,CAAC,GAAG,IAAI;EACtB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC;EAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EACpC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;EACrG,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAE,CAAC,IAAK,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EACzE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAE,CAAC,IAAK;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACjC,OAAO,GAAG,IAAI,CAAC,GAAG;MAAE,IAAI,EAAE,IAAI,CAAC,IAAI;MAAE,EAAE,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAAO,CAAC,GAAG;MAAE,IAAI,EAAE,IAAI,CAAC,IAAI;MAAE,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;IAAE,CAAC;EACpH,CAAC,CAAC;EACF,IAAI,CAAC,QAAQ,CAAC;IAAE,OAAO;IAAE,SAAS,EAAE;EAAe,CAAC,CAAC;EACrD,IAAI,CAAC,KAAK,CAAC,CAAC;EACZ,OAAO,IAAI;AACb,CAAC;AAED,MAAM,OAAO,GAAI,KAAa,IAAM,IAAgB,IAAK;EACvD,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;EACrC,MAAM;IAAE;EAAM,CAAC,GAAG,IAAI;EACtB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,CAAC;EACjC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,EACxC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;EAC/G,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG;EACtC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAE,MAAM,IAAK,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;EACxF,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAE,IAAI,IAAK,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;EAClE,IAAI,CAAC,QAAQ,CAAC;IACZ,OAAO,EAAE,KAAK,CAAC,GAAG,CAAE,IAAI,KAAM;MAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;MACf,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;MAC7D,MAAM,EAAE,MAAM,GAAG,EAAE,GAAG;IACxB,CAAC,CAAC,CAAC;IACH,SAAS,EAAE;EACb,CAAC,CAAC;EACF,IAAI,CAAC,KAAK,CAAC,CAAC;EACZ,OAAO,IAAI;AACb,CAAC;AAED,OAAO,MAAM,QAAQ,GAAG;EACtB,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC;EAC3B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC;EAC/B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC;EAC3B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC;EAC/B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;EACnB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;EACpB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;EACpB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;EACpB,SAAS,EAAG,IAAgB,IAAK;IAC/B,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;IACrC,MAAM;MAAE;IAAM,CAAC,GAAG,IAAI;IACtB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI;IAC7D,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;IACrC,IAAI,WAAW,GAAG,CAAC;IACnB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAClG,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE;IACtE,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE;IACjF,MAAM,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC;MACZ,OAAO,EAAE;QAAE,IAAI;QAAE,EAAE;QAAE,MAAM,EAAE,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,GAAG,IAAI;MAAG,CAAC;MAC1E,SAAS,EAAE;QAAE,MAAM,EAAE,KAAK;QAAE,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;MAAO,CAAC;MACvD,SAAS,EAAE;IACb,CAAC,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,CAAC;IACZ,OAAO,IAAI;EACb,CAAC;EACD,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC;EAC/C,WAAW,EAAE,UAAU,CAAC,YAAY,EAAE,MAAM,KAAK,CAAC;EAClD,KAAK,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;EACrC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC;EAC3B,KAAK,EAAG,IAAgB,IAAK;IAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;IACrC,MAAM;MAAE;IAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,IAAI,KAAK,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,gCAAgC;IACtF,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC;IACxC,IAAI,CAAC,QAAQ,CAAC;MAAE,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC,EAAE;QAAE;MAAO,CAAC;MAAE,SAAS,EAAE;QAAE,MAAM;QAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;MAAO,CAAC;MAAE,SAAS,EAAE;IAAe,CAAC,CAAC;IACpI,IAAI,CAAC,KAAK,CAAC,CAAC;IACZ,cAAc,CAAC,MAAM;MACnB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE;MAC3B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAc,gBAAgB,CAAC,CAAC,CAAC,IAAI,CACpF,OAAO,IAAK,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,MACzD,CAAC;MACD,MAAM,IAAI,GAAG,KAAK,EAAE,aAAa,CAAc,uCAAuC,CAAC;MACvF,IAAI,CAAC,IAAI,EAAE;MACX,IAAI,CAAC,KAAK,CAAC,CAAC;MACZ,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;MACnD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;MAC9C,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC;MAC9B,SAAS,EAAE,eAAe,CAAC,CAAC;MAC5B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC5B,CAAC,CAAC;IACF,OAAO,IAAI;EACb,CAAC;EACD,IAAI,EAAG,IAAgB,IAAK;IAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,KAAK;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IAClE,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;IACtG,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,eAAe,GAAG,IAAI,GAAG,EAAE;IAC/D,IAAI,CAAC,QAAQ,CAAC;MAAE,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,GAAG,IAAI;MAAQ,CAAC;MAAE,SAAS,EAAE;IAAe,CAAC,CAAC;IAChG,IAAI,CAAC,KAAK,CAAC,CAAC;IACZ,OAAO,IAAI;EACb;AACF,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatted view: Markdown markers hide outside the element you are editing.
|
|
3
|
+
* The document never changes; only decorations do. Headings, bold, italic,
|
|
4
|
+
* strikethrough, inline code, links, quotes, lists, code blocks and `---`.
|
|
5
|
+
*/
|
|
6
|
+
import { syntaxTree } from "@codemirror/language";
|
|
7
|
+
import { Decoration, EditorView, ViewPlugin, WidgetType } from "@codemirror/view";
|
|
8
|
+
class BulletWidget extends WidgetType {
|
|
9
|
+
toDOM() {
|
|
10
|
+
const el = document.createElement("span");
|
|
11
|
+
el.className = "k2b-ste-bullet";
|
|
12
|
+
el.textContent = "•";
|
|
13
|
+
return el;
|
|
14
|
+
}
|
|
15
|
+
eq() {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
class RuleWidget extends WidgetType {
|
|
20
|
+
toDOM() {
|
|
21
|
+
const el = document.createElement("span");
|
|
22
|
+
el.className = "k2b-ste-hr";
|
|
23
|
+
return el;
|
|
24
|
+
}
|
|
25
|
+
eq() {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const hide = Decoration.replace({});
|
|
30
|
+
const lineClass = cls => Decoration.line({
|
|
31
|
+
class: cls
|
|
32
|
+
});
|
|
33
|
+
const mark = cls => Decoration.mark({
|
|
34
|
+
class: cls
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Without focus nothing is "being edited": the whole text shows formatted.
|
|
38
|
+
|
|
39
|
+
const touches = (state, from, to, focused) => focused && state.selection.ranges.some(r => r.from <= to && r.to >= from);
|
|
40
|
+
const onLine = (state, from, to, focused) => {
|
|
41
|
+
if (!focused) return false;
|
|
42
|
+
const a = state.doc.lineAt(from).number;
|
|
43
|
+
const b = state.doc.lineAt(to).number;
|
|
44
|
+
return state.selection.ranges.some(r => state.doc.lineAt(r.from).number <= b && state.doc.lineAt(r.to).number >= a);
|
|
45
|
+
};
|
|
46
|
+
const build = view => {
|
|
47
|
+
const {
|
|
48
|
+
state
|
|
49
|
+
} = view;
|
|
50
|
+
const focused = view.hasFocus;
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const {
|
|
53
|
+
from,
|
|
54
|
+
to
|
|
55
|
+
} of view.visibleRanges) {
|
|
56
|
+
syntaxTree(state).iterate({
|
|
57
|
+
from,
|
|
58
|
+
to,
|
|
59
|
+
enter: node => {
|
|
60
|
+
const name = node.name;
|
|
61
|
+
if (name === "Table") return false; // owned by the table grid
|
|
62
|
+
if (name === "FencedCode" || name === "CodeBlock") {
|
|
63
|
+
for (let pos = node.from; pos <= node.to;) {
|
|
64
|
+
const line = state.doc.lineAt(pos);
|
|
65
|
+
out.push(lineClass("k2b-ste-codeblock").range(line.from));
|
|
66
|
+
pos = line.to + 1;
|
|
67
|
+
}
|
|
68
|
+
if (name === "FencedCode" && !touches(state, node.from, node.to, focused)) {
|
|
69
|
+
for (const marker of node.node.getChildren("CodeMark")) out.push(hide.range(marker.from, marker.to));
|
|
70
|
+
const info = node.node.getChild("CodeInfo");
|
|
71
|
+
if (info) out.push(hide.range(info.from, info.to));
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const heading = /^ATXHeading(\d)$/.exec(name);
|
|
76
|
+
if (heading) {
|
|
77
|
+
const line = state.doc.lineAt(node.from);
|
|
78
|
+
out.push(lineClass(`k2b-ste-h k2b-ste-h${heading[1]}`).range(line.from));
|
|
79
|
+
if (!onLine(state, node.from, node.to, focused)) {
|
|
80
|
+
const markNode = node.node.getChild("HeaderMark");
|
|
81
|
+
if (markNode) {
|
|
82
|
+
const end = state.doc.sliceString(markNode.to, markNode.to + 1) === " " ? markNode.to + 1 : markNode.to;
|
|
83
|
+
out.push(hide.range(markNode.from, end));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (name === "Blockquote") {
|
|
89
|
+
for (let pos = node.from; pos <= node.to;) {
|
|
90
|
+
const line = state.doc.lineAt(pos);
|
|
91
|
+
out.push(lineClass("k2b-ste-quote").range(line.from));
|
|
92
|
+
pos = line.to + 1;
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (name === "QuoteMark") {
|
|
97
|
+
if (!onLine(state, node.from, node.to, focused)) {
|
|
98
|
+
const end = state.doc.sliceString(node.to, node.to + 1) === " " ? node.to + 1 : node.to;
|
|
99
|
+
out.push(hide.range(node.from, end));
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (name === "HorizontalRule") {
|
|
104
|
+
if (!onLine(state, node.from, node.to, focused)) out.push(Decoration.replace({
|
|
105
|
+
widget: new RuleWidget()
|
|
106
|
+
}).range(node.from, node.to));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (name === "ListMark") {
|
|
110
|
+
const bullet = /^[-*+]$/.test(state.sliceDoc(node.from, node.to));
|
|
111
|
+
if (bullet && !onLine(state, node.from, node.to, focused)) out.push(Decoration.replace({
|
|
112
|
+
widget: new BulletWidget()
|
|
113
|
+
}).range(node.from, node.to));else out.push(mark("k2b-ste-listmark").range(node.from, node.to));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const inline = {
|
|
117
|
+
StrongEmphasis: ["k2b-ste-strong", "EmphasisMark"],
|
|
118
|
+
Emphasis: ["k2b-ste-em", "EmphasisMark"],
|
|
119
|
+
Strikethrough: ["k2b-ste-strike", "StrikethroughMark"],
|
|
120
|
+
InlineCode: ["k2b-ste-code", "CodeMark"]
|
|
121
|
+
};
|
|
122
|
+
const spec = inline[name];
|
|
123
|
+
if (spec) {
|
|
124
|
+
if (node.to > node.from) out.push(mark(spec[0]).range(node.from, node.to));
|
|
125
|
+
if (!touches(state, node.from, node.to, focused)) {
|
|
126
|
+
const cursor = node.node.cursor();
|
|
127
|
+
if (cursor.firstChild()) do {
|
|
128
|
+
if (cursor.name === spec[1] && cursor.to > cursor.from) out.push(hide.range(cursor.from, cursor.to));
|
|
129
|
+
} while (cursor.nextSibling());
|
|
130
|
+
}
|
|
131
|
+
return name === "InlineCode" ? false : undefined;
|
|
132
|
+
}
|
|
133
|
+
if (name === "Link") {
|
|
134
|
+
const marks = node.node.getChildren("LinkMark");
|
|
135
|
+
const url = node.node.getChild("URL");
|
|
136
|
+
if (marks.length >= 2) {
|
|
137
|
+
out.push(mark("k2b-ste-link").range(marks[0].to, marks[1].from));
|
|
138
|
+
if (!touches(state, node.from, node.to, focused)) {
|
|
139
|
+
out.push(hide.range(marks[0].from, marks[0].to));
|
|
140
|
+
out.push(hide.range(marks[1].from, node.to));
|
|
141
|
+
} else if (url) out.push(mark("k2b-ste-url").range(url.from, url.to));
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return Decoration.set(out, true);
|
|
150
|
+
};
|
|
151
|
+
export const formattedView = [ViewPlugin.fromClass(class {
|
|
152
|
+
decorations;
|
|
153
|
+
constructor(view) {
|
|
154
|
+
this.decorations = build(view);
|
|
155
|
+
}
|
|
156
|
+
update(update) {
|
|
157
|
+
if (update.docChanged || update.selectionSet || update.focusChanged || update.viewportChanged || syntaxTree(update.startState) !== syntaxTree(update.state)) this.decorations = build(update.view);
|
|
158
|
+
}
|
|
159
|
+
}, {
|
|
160
|
+
decorations: v => v.decorations
|
|
161
|
+
}), EditorView.contentAttributes.of({
|
|
162
|
+
class: "k2b-ste-formatted"
|
|
163
|
+
})];
|
|
164
|
+
//# sourceMappingURL=formatted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["text-editor/formatted.ts"],"sourcesContent":["/**\n * Formatted view: Markdown markers hide outside the element you are editing.\n * The document never changes; only decorations do. Headings, bold, italic,\n * strikethrough, inline code, links, quotes, lists, code blocks and `---`.\n */\nimport { syntaxTree } from \"@codemirror/language\";\nimport type { EditorState, Range } from \"@codemirror/state\";\nimport { Decoration, type DecorationSet, EditorView, ViewPlugin, type ViewUpdate, WidgetType } from \"@codemirror/view\";\n\nclass BulletWidget extends WidgetType {\n override toDOM() {\n const el = document.createElement(\"span\");\n el.className = \"k2b-ste-bullet\";\n el.textContent = \"•\";\n return el;\n }\n override eq() {\n return true;\n }\n}\n\nclass RuleWidget extends WidgetType {\n override toDOM() {\n const el = document.createElement(\"span\");\n el.className = \"k2b-ste-hr\";\n return el;\n }\n override eq() {\n return true;\n }\n}\n\nconst hide = Decoration.replace({});\nconst lineClass = (cls: string) => Decoration.line({ class: cls });\nconst mark = (cls: string) => Decoration.mark({ class: cls });\n\n// Without focus nothing is \"being edited\": the whole text shows formatted.\n\nconst touches = (state: EditorState, from: number, to: number, focused: boolean) =>\n focused && state.selection.ranges.some((r) => r.from <= to && r.to >= from);\nconst onLine = (state: EditorState, from: number, to: number, focused: boolean) => {\n if (!focused) return false;\n const a = state.doc.lineAt(from).number;\n const b = state.doc.lineAt(to).number;\n return state.selection.ranges.some((r) => state.doc.lineAt(r.from).number <= b && state.doc.lineAt(r.to).number >= a);\n};\n\nconst build = (view: EditorView): DecorationSet => {\n const { state } = view;\n const focused = view.hasFocus;\n const out: Range<Decoration>[] = [];\n for (const { from, to } of view.visibleRanges) {\n syntaxTree(state).iterate({\n from,\n to,\n enter: (node) => {\n const name = node.name;\n if (name === \"Table\") return false; // owned by the table grid\n if (name === \"FencedCode\" || name === \"CodeBlock\") {\n for (let pos = node.from; pos <= node.to; ) {\n const line = state.doc.lineAt(pos);\n out.push(lineClass(\"k2b-ste-codeblock\").range(line.from));\n pos = line.to + 1;\n }\n if (name === \"FencedCode\" && !touches(state, node.from, node.to, focused)) {\n for (const marker of node.node.getChildren(\"CodeMark\")) out.push(hide.range(marker.from, marker.to));\n const info = node.node.getChild(\"CodeInfo\");\n if (info) out.push(hide.range(info.from, info.to));\n }\n return false;\n }\n const heading = /^ATXHeading(\\d)$/.exec(name);\n if (heading) {\n const line = state.doc.lineAt(node.from);\n out.push(lineClass(`k2b-ste-h k2b-ste-h${heading[1]}`).range(line.from));\n if (!onLine(state, node.from, node.to, focused)) {\n const markNode = node.node.getChild(\"HeaderMark\");\n if (markNode) {\n const end = state.doc.sliceString(markNode.to, markNode.to + 1) === \" \" ? markNode.to + 1 : markNode.to;\n out.push(hide.range(markNode.from, end));\n }\n }\n return;\n }\n if (name === \"Blockquote\") {\n for (let pos = node.from; pos <= node.to; ) {\n const line = state.doc.lineAt(pos);\n out.push(lineClass(\"k2b-ste-quote\").range(line.from));\n pos = line.to + 1;\n }\n return;\n }\n if (name === \"QuoteMark\") {\n if (!onLine(state, node.from, node.to, focused)) {\n const end = state.doc.sliceString(node.to, node.to + 1) === \" \" ? node.to + 1 : node.to;\n out.push(hide.range(node.from, end));\n }\n return;\n }\n if (name === \"HorizontalRule\") {\n if (!onLine(state, node.from, node.to, focused))\n out.push(Decoration.replace({ widget: new RuleWidget() }).range(node.from, node.to));\n return;\n }\n if (name === \"ListMark\") {\n const bullet = /^[-*+]$/.test(state.sliceDoc(node.from, node.to));\n if (bullet && !onLine(state, node.from, node.to, focused))\n out.push(Decoration.replace({ widget: new BulletWidget() }).range(node.from, node.to));\n else out.push(mark(\"k2b-ste-listmark\").range(node.from, node.to));\n return;\n }\n const inline: Record<string, [string, string]> = {\n StrongEmphasis: [\"k2b-ste-strong\", \"EmphasisMark\"],\n Emphasis: [\"k2b-ste-em\", \"EmphasisMark\"],\n Strikethrough: [\"k2b-ste-strike\", \"StrikethroughMark\"],\n InlineCode: [\"k2b-ste-code\", \"CodeMark\"],\n };\n const spec = inline[name];\n if (spec) {\n if (node.to > node.from) out.push(mark(spec[0]).range(node.from, node.to));\n if (!touches(state, node.from, node.to, focused)) {\n const cursor = node.node.cursor();\n if (cursor.firstChild())\n do {\n if (cursor.name === spec[1] && cursor.to > cursor.from) out.push(hide.range(cursor.from, cursor.to));\n } while (cursor.nextSibling());\n }\n return name === \"InlineCode\" ? false : undefined;\n }\n if (name === \"Link\") {\n const marks = node.node.getChildren(\"LinkMark\");\n const url = node.node.getChild(\"URL\");\n if (marks.length >= 2) {\n out.push(mark(\"k2b-ste-link\").range(marks[0]!.to, marks[1]!.from));\n if (!touches(state, node.from, node.to, focused)) {\n out.push(hide.range(marks[0]!.from, marks[0]!.to));\n out.push(hide.range(marks[1]!.from, node.to));\n } else if (url) out.push(mark(\"k2b-ste-url\").range(url.from, url.to));\n }\n return false;\n }\n return;\n },\n });\n }\n return Decoration.set(out, true);\n};\n\nexport const formattedView = [\n ViewPlugin.fromClass(\n class {\n decorations: DecorationSet;\n constructor(view: EditorView) {\n this.decorations = build(view);\n }\n update(update: ViewUpdate) {\n if (\n update.docChanged ||\n update.selectionSet ||\n update.focusChanged ||\n update.viewportChanged ||\n syntaxTree(update.startState) !== syntaxTree(update.state)\n )\n this.decorations = build(update.view);\n }\n },\n { decorations: (v) => v.decorations },\n ),\n EditorView.contentAttributes.of({ class: \"k2b-ste-formatted\" }),\n];\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown language without `@codemirror/lang-markdown`: that package pulls in
|
|
3
|
+
* `@codemirror/lang-html` (and with it CSS and JavaScript) for HTML blocks.
|
|
4
|
+
* The shared editor needs only the GFM tree, so it wraps `@lezer/markdown`.
|
|
5
|
+
*/
|
|
6
|
+
import { defineLanguageFacet, Language, LanguageSupport } from "@codemirror/language";
|
|
7
|
+
import { GFM, parser } from "@lezer/markdown";
|
|
8
|
+
const facet = defineLanguageFacet({
|
|
9
|
+
commentTokens: {
|
|
10
|
+
block: {
|
|
11
|
+
open: "<!--",
|
|
12
|
+
close: "-->"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const gfmParser = parser.configure([GFM]);
|
|
17
|
+
export const markdownLanguage = new Language(facet, gfmParser, [], "markdown");
|
|
18
|
+
export const markdown = () => new LanguageSupport(markdownLanguage);
|
|
19
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["text-editor/language.ts"],"sourcesContent":["/**\n * Markdown language without `@codemirror/lang-markdown`: that package pulls in\n * `@codemirror/lang-html` (and with it CSS and JavaScript) for HTML blocks.\n * The shared editor needs only the GFM tree, so it wraps `@lezer/markdown`.\n */\nimport { defineLanguageFacet, Language, LanguageSupport } from \"@codemirror/language\";\nimport { GFM, parser } from \"@lezer/markdown\";\n\nconst facet = defineLanguageFacet({ commentTokens: { block: { open: \"<!--\", close: \"-->\" } } });\nconst gfmParser = parser.configure([GFM]);\n\nexport const markdownLanguage = new Language(facet, gfmParser, [], \"markdown\");\nexport const markdown = () => new LanguageSupport(markdownLanguage);\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,SAAS,mBAAmB,EAAE,QAAQ,EAAE,eAAe,QAAQ,sBAAsB;AACrF,SAAS,GAAG,EAAE,MAAM,QAAQ,iBAAiB;AAE7C,MAAM,KAAK,GAAG,mBAAmB,CAAC;EAAE,aAAa,EAAE;IAAE,KAAK,EAAE;MAAE,IAAI,EAAE,MAAM;MAAE,KAAK,EAAE;IAAM;EAAE;AAAE,CAAC,CAAC;AAC/F,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;AAEzC,OAAO,MAAM,gBAAgB,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC;AAC9E,OAAO,MAAM,QAAQ,GAAG,MAAM,IAAI,eAAe,CAAC,gBAAgB,CAAC","ignoreList":[]}
|