@dxos/react-ui-editor 0.4.8-next.fff1521 → 0.4.9-main.1057b49
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/lib/browser/index.mjs +1687 -1694
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +1 -6
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +3 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +3 -0
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts +7 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +5 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts +9 -0
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +1 -1
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +4 -2
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.stories.d.ts +3 -0
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +3 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/TextEditor/TextEditor.stories.tsx +14 -2
- package/src/components/Toolbar/Toolbar.stories.tsx +0 -1
- package/src/components/Toolbar/Toolbar.tsx +46 -59
- package/src/extensions/automerge/automerge.ts +4 -4
- package/src/extensions/command/state.ts +2 -2
- package/src/extensions/dnd.ts +31 -9
- package/src/extensions/factories.ts +41 -15
- package/src/extensions/index.ts +0 -1
- package/src/extensions/markdown/action.ts +112 -0
- package/src/extensions/markdown/bundle.ts +8 -11
- package/src/extensions/markdown/formatting.ts +11 -11
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/modes.ts +8 -1
- package/src/hooks/useActionHandler.ts +4 -89
- package/src/hooks/useDocAccessor.ts +8 -2
- package/src/index.ts +0 -1
- package/src/themes/default.ts +24 -8
- package/src/translations.ts +3 -0
- package/dist/types/src/extensions/cursor-line-margin.d.ts +0 -7
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +0 -1
- package/src/extensions/cursor-line-margin.ts +0 -94
|
@@ -17,24 +17,26 @@ var translations_default = [
|
|
|
17
17
|
"comment label": "Create comment",
|
|
18
18
|
"image label": "Insert image",
|
|
19
19
|
"heading label": "Heading level",
|
|
20
|
-
"table label": "Create table"
|
|
20
|
+
"table label": "Create table",
|
|
21
|
+
"heading level label_zero": "Paragraph",
|
|
22
|
+
"heading level label_one": "Heading level {{count}}",
|
|
23
|
+
"heading level label_other": "Heading level {{count}}"
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
];
|
|
25
28
|
|
|
26
29
|
// packages/ui/react-ui-editor/src/index.ts
|
|
27
|
-
import { keymap as
|
|
30
|
+
import { keymap as keymap11 } from "@codemirror/view";
|
|
28
31
|
import { tags as tags2 } from "@lezer/highlight";
|
|
29
32
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
30
|
-
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
31
33
|
|
|
32
34
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
33
35
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
34
|
-
import { EditorView as
|
|
36
|
+
import { EditorView as EditorView16 } from "@codemirror/view";
|
|
35
37
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
36
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
37
|
-
import { log as
|
|
38
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
39
|
+
import { log as log7 } from "@dxos/log";
|
|
38
40
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
39
41
|
|
|
40
42
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
|
@@ -122,8 +124,8 @@ var annotations = (options = {}) => {
|
|
|
122
124
|
annotationsState
|
|
123
125
|
], (state2) => {
|
|
124
126
|
const annotations2 = state2.field(annotationsState);
|
|
125
|
-
const decorations = annotations2.map((
|
|
126
|
-
const range = Cursor.getRangeFromCursor(state2,
|
|
127
|
+
const decorations = annotations2.map((annotation) => {
|
|
128
|
+
const range = Cursor.getRangeFromCursor(state2, annotation.cursor);
|
|
127
129
|
return range && annotationMark.range(range.from, range.to);
|
|
128
130
|
}).filter(isNotFalsy);
|
|
129
131
|
return Decoration.set(decorations);
|
|
@@ -475,13 +477,13 @@ var automerge = (accessor) => {
|
|
|
475
477
|
ViewPlugin.fromClass(class {
|
|
476
478
|
constructor(_view) {
|
|
477
479
|
this._view = _view;
|
|
478
|
-
|
|
480
|
+
this._handleChange = () => {
|
|
481
|
+
syncer.reconcile(this._view, false);
|
|
482
|
+
};
|
|
483
|
+
accessor.handle.addListener("change", this._handleChange);
|
|
479
484
|
}
|
|
480
485
|
destroy() {
|
|
481
|
-
accessor.handle.removeListener("change", this._handleChange
|
|
482
|
-
}
|
|
483
|
-
_handleChange() {
|
|
484
|
-
syncer.reconcile(this._view, false);
|
|
486
|
+
accessor.handle.removeListener("change", this._handleChange);
|
|
485
487
|
}
|
|
486
488
|
}),
|
|
487
489
|
// Reconcile local updates.
|
|
@@ -1196,7 +1198,7 @@ var commandState = StateField3.define({
|
|
|
1196
1198
|
}
|
|
1197
1199
|
});
|
|
1198
1200
|
}
|
|
1199
|
-
|
|
1201
|
+
requestAnimationFrame(() => view2.focus());
|
|
1200
1202
|
});
|
|
1201
1203
|
}
|
|
1202
1204
|
};
|
|
@@ -1851,76 +1853,14 @@ var useComments = (view, id, comments2) => {
|
|
|
1851
1853
|
]);
|
|
1852
1854
|
};
|
|
1853
1855
|
|
|
1854
|
-
// packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
|
|
1855
|
-
import { Transaction } from "@codemirror/state";
|
|
1856
|
-
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1857
|
-
import { log as log5 } from "@dxos/log";
|
|
1858
|
-
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
|
|
1859
|
-
var annotation = "cursorLineMargin";
|
|
1860
|
-
var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
|
|
1861
|
-
var cursorLineMargin = (options = {
|
|
1862
|
-
lines: 3
|
|
1863
|
-
}) => {
|
|
1864
|
-
const { lines } = options;
|
|
1865
|
-
if (!lines || lines <= 0) {
|
|
1866
|
-
return [];
|
|
1867
|
-
}
|
|
1868
|
-
return EditorView8.updateListener.of(({ transactions, state: state2, selectionSet, startState, view }) => {
|
|
1869
|
-
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1870
|
-
return;
|
|
1871
|
-
}
|
|
1872
|
-
const s = state2;
|
|
1873
|
-
const { main } = s.selection;
|
|
1874
|
-
const rect = view.dom.getBoundingClientRect();
|
|
1875
|
-
const viewportTop = rect.top - view.documentTop;
|
|
1876
|
-
const viewportBottom = rect.bottom - view.documentTop;
|
|
1877
|
-
const mainLine = lineAtPos(s, main.head);
|
|
1878
|
-
const _visTopLine = lineAtPos(s, view.lineBlockAtHeight(viewportTop).from);
|
|
1879
|
-
const botLineBlk = view.lineBlockAtHeight(viewportBottom);
|
|
1880
|
-
const visBotLineDoc = lineAtPos(s, Math.min(botLineBlk.to, s.doc.length));
|
|
1881
|
-
const visBotLine = botLineBlk.bottom >= viewportBottom ? visBotLineDoc : visBotLineDoc + Math.floor((viewportBottom - botLineBlk.bottom) / view.defaultLineHeight);
|
|
1882
|
-
const needsScrollTop = false;
|
|
1883
|
-
const needsScrollBot = mainLine >= visBotLine - lines;
|
|
1884
|
-
if (needsScrollTop && needsScrollBot) {
|
|
1885
|
-
log5.warn("is cursorScrollMargin too large for the editor size?", void 0, {
|
|
1886
|
-
F: __dxlog_file6,
|
|
1887
|
-
L: 65,
|
|
1888
|
-
S: void 0,
|
|
1889
|
-
C: (f, a) => f(...a)
|
|
1890
|
-
});
|
|
1891
|
-
return;
|
|
1892
|
-
}
|
|
1893
|
-
if (!needsScrollTop && !needsScrollBot) {
|
|
1894
|
-
return;
|
|
1895
|
-
}
|
|
1896
|
-
if (selectionSet) {
|
|
1897
|
-
const { head } = startState.selection.main;
|
|
1898
|
-
const oldMainLine = lineAtPos(startState, head);
|
|
1899
|
-
if (needsScrollTop && oldMainLine < mainLine) {
|
|
1900
|
-
return;
|
|
1901
|
-
}
|
|
1902
|
-
if (needsScrollBot && oldMainLine > mainLine) {
|
|
1903
|
-
return;
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
view.dispatch({
|
|
1907
|
-
annotations: Transaction.userEvent.of(annotation),
|
|
1908
|
-
effects: EditorView8.scrollIntoView(s.selection.main.head, {
|
|
1909
|
-
y: needsScrollTop ? "start" : "end",
|
|
1910
|
-
yMargin: view.defaultLineHeight * lines
|
|
1911
|
-
})
|
|
1912
|
-
});
|
|
1913
|
-
});
|
|
1914
|
-
};
|
|
1915
|
-
|
|
1916
1856
|
// packages/ui/react-ui-editor/src/extensions/doc.ts
|
|
1917
1857
|
import { Facet as Facet5 } from "@codemirror/state";
|
|
1918
1858
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1919
|
-
var
|
|
1859
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
|
|
1920
1860
|
var documentId2 = Facet5.define({
|
|
1921
1861
|
combine: (providers) => {
|
|
1922
1862
|
invariant3(providers.length <= 1, void 0, {
|
|
1923
|
-
F:
|
|
1863
|
+
F: __dxlog_file6,
|
|
1924
1864
|
L: 11,
|
|
1925
1865
|
S: void 0,
|
|
1926
1866
|
A: [
|
|
@@ -1933,33 +1873,51 @@ var documentId2 = Facet5.define({
|
|
|
1933
1873
|
});
|
|
1934
1874
|
|
|
1935
1875
|
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
|
1936
|
-
import { EditorView as
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1876
|
+
import { dropCursor, EditorView as EditorView8 } from "@codemirror/view";
|
|
1877
|
+
var styles4 = EditorView8.baseTheme({
|
|
1878
|
+
".cm-dropCursor": {
|
|
1879
|
+
borderLeft: `2px solid ${getToken("extend.colors.primary.500")}`,
|
|
1880
|
+
color: getToken("extend.colors.primary.500"),
|
|
1881
|
+
padding: "0 4px"
|
|
1882
|
+
},
|
|
1883
|
+
".cm-dropCursor:after": {
|
|
1884
|
+
content: '"\u2190"'
|
|
1885
|
+
}
|
|
1886
|
+
});
|
|
1887
|
+
var dropFile = (options = {}) => {
|
|
1888
|
+
return [
|
|
1889
|
+
styles4,
|
|
1890
|
+
dropCursor(),
|
|
1891
|
+
EditorView8.domEventHandlers({
|
|
1892
|
+
drop: (event, view) => {
|
|
1893
|
+
event.preventDefault();
|
|
1894
|
+
const files = event.dataTransfer?.files;
|
|
1895
|
+
const pos = view.posAtCoords(event);
|
|
1896
|
+
if (files?.length && pos !== null) {
|
|
1897
|
+
view.dispatch({
|
|
1898
|
+
selection: {
|
|
1899
|
+
anchor: pos
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
options.onDrop?.(view, {
|
|
1903
|
+
files
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
})
|
|
1908
|
+
];
|
|
1952
1909
|
};
|
|
1953
1910
|
|
|
1954
1911
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
1955
|
-
import { closeBrackets } from "@codemirror/autocomplete";
|
|
1956
|
-
import { history } from "@codemirror/commands";
|
|
1912
|
+
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1913
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1957
1914
|
import { bracketMatching } from "@codemirror/language";
|
|
1915
|
+
import { searchKeymap } from "@codemirror/search";
|
|
1958
1916
|
import { EditorState } from "@codemirror/state";
|
|
1959
|
-
import { EditorView as
|
|
1917
|
+
import { EditorView as EditorView9, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap5, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
|
1960
1918
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1961
1919
|
import { generateName } from "@dxos/display-name";
|
|
1962
|
-
import { log as
|
|
1920
|
+
import { log as log5 } from "@dxos/log";
|
|
1963
1921
|
import { hueTokens } from "@dxos/react-ui-theme";
|
|
1964
1922
|
import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1965
1923
|
|
|
@@ -2164,50 +2122,75 @@ var defaultTheme = {
|
|
|
2164
2122
|
* </div>
|
|
2165
2123
|
* </div
|
|
2166
2124
|
*/
|
|
2167
|
-
".cm-panels": {
|
|
2168
|
-
border: `1px solid ${get3(tokens, "extend.colors.neutral.200")}`
|
|
2169
|
-
},
|
|
2125
|
+
".cm-panels": {},
|
|
2170
2126
|
".cm-panel": {
|
|
2171
|
-
background: get3(tokens, "extend.colors.neutral.50"),
|
|
2172
2127
|
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2173
2128
|
},
|
|
2129
|
+
".cm-panel input[type=checkbox]": {
|
|
2130
|
+
marginRight: "0.4rem !important"
|
|
2131
|
+
},
|
|
2132
|
+
"&light .cm-panel": {
|
|
2133
|
+
background: get3(tokens, "extend.colors.neutral.50")
|
|
2134
|
+
},
|
|
2135
|
+
"&dark .cm-panel": {
|
|
2136
|
+
background: get3(tokens, "extend.colors.neutral.850")
|
|
2137
|
+
},
|
|
2174
2138
|
".cm-button": {
|
|
2175
2139
|
margin: "4px",
|
|
2176
2140
|
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2177
|
-
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2178
2141
|
backgroundImage: "none",
|
|
2179
2142
|
border: "none",
|
|
2143
|
+
"&:active": {
|
|
2144
|
+
backgroundImage: "none"
|
|
2145
|
+
}
|
|
2146
|
+
},
|
|
2147
|
+
"&light .cm-button": {
|
|
2148
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2180
2149
|
"&:hover": {
|
|
2181
2150
|
background: get3(tokens, "extend.colors.neutral.200")
|
|
2182
2151
|
},
|
|
2183
2152
|
"&:active": {
|
|
2184
|
-
background: get3(tokens, "extend.colors.neutral.300")
|
|
2185
|
-
backgroundImage: "none"
|
|
2153
|
+
background: get3(tokens, "extend.colors.neutral.300")
|
|
2186
2154
|
}
|
|
2187
2155
|
},
|
|
2188
|
-
".cm-
|
|
2189
|
-
|
|
2156
|
+
"&dark .cm-button": {
|
|
2157
|
+
background: get3(tokens, "extend.colors.neutral.800"),
|
|
2158
|
+
"&:hover": {
|
|
2159
|
+
background: get3(tokens, "extend.colors.neutral.700")
|
|
2160
|
+
},
|
|
2161
|
+
"&:active": {
|
|
2162
|
+
background: get3(tokens, "extend.colors.neutral.600")
|
|
2163
|
+
}
|
|
2190
2164
|
}
|
|
2191
2165
|
};
|
|
2192
2166
|
|
|
2193
2167
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2194
|
-
var
|
|
2195
|
-
var
|
|
2168
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
|
2169
|
+
var defaultBasicOptions = {
|
|
2170
|
+
allowMultipleSelections: true,
|
|
2196
2171
|
bracketMatching: true,
|
|
2197
2172
|
closeBrackets: true,
|
|
2198
2173
|
drawSelection: true,
|
|
2199
2174
|
editable: true,
|
|
2200
2175
|
history: true,
|
|
2201
|
-
|
|
2176
|
+
keymap: "standard",
|
|
2177
|
+
lineWrapping: true,
|
|
2178
|
+
search: true
|
|
2179
|
+
};
|
|
2180
|
+
var keymaps = {
|
|
2181
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2182
|
+
standard: standardKeymap,
|
|
2183
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
2184
|
+
default: defaultKeymap
|
|
2202
2185
|
};
|
|
2203
2186
|
var createBasicExtensions = (_props) => {
|
|
2204
|
-
const props = defaultsDeep2({}, _props,
|
|
2187
|
+
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
|
2205
2188
|
return [
|
|
2206
|
-
//
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
F:
|
|
2210
|
-
L:
|
|
2189
|
+
// NOTE: Doesn't catch errors in keymap functions.
|
|
2190
|
+
EditorView9.exceptionSink.of((err) => {
|
|
2191
|
+
log5.catch(err, void 0, {
|
|
2192
|
+
F: __dxlog_file7,
|
|
2193
|
+
L: 91,
|
|
2211
2194
|
S: void 0,
|
|
2212
2195
|
C: (f, a) => f(...a)
|
|
2213
2196
|
});
|
|
@@ -2215,37 +2198,50 @@ var createBasicExtensions = (_props) => {
|
|
|
2215
2198
|
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2216
2199
|
props.bracketMatching && bracketMatching(),
|
|
2217
2200
|
props.closeBrackets && closeBrackets(),
|
|
2218
|
-
props.
|
|
2219
|
-
props.dropCursor && dropCursor(),
|
|
2201
|
+
props.dropCursor && dropCursor2(),
|
|
2220
2202
|
props.drawSelection && drawSelection(),
|
|
2221
2203
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2222
2204
|
props.history && history(),
|
|
2223
2205
|
props.lineNumbers && lineNumbers(),
|
|
2224
|
-
props.lineWrapping &&
|
|
2206
|
+
props.lineWrapping && EditorView9.lineWrapping,
|
|
2225
2207
|
props.placeholder && placeholder(props.placeholder),
|
|
2226
2208
|
props.readonly && [
|
|
2227
2209
|
EditorState.readOnly.of(true),
|
|
2228
|
-
|
|
2210
|
+
EditorView9.editable.of(false)
|
|
2229
2211
|
],
|
|
2230
2212
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2231
|
-
props.tabSize && EditorState.tabSize.of(props.tabSize)
|
|
2213
|
+
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
2214
|
+
// https://codemirror.net/docs/ref/#view.KeyBinding
|
|
2215
|
+
keymap5.of([
|
|
2216
|
+
...(props.keymap && keymaps[props.keymap]) ?? [],
|
|
2217
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2218
|
+
...props.indentWithTab ? [
|
|
2219
|
+
indentWithTab
|
|
2220
|
+
] : [],
|
|
2221
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2222
|
+
...props.closeBrackets ? closeBracketsKeymap : [],
|
|
2223
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2224
|
+
...props.history ? historyKeymap : [],
|
|
2225
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2226
|
+
...props.search ? searchKeymap : []
|
|
2227
|
+
].filter(isNotFalsy2))
|
|
2232
2228
|
].filter(isNotFalsy2);
|
|
2233
2229
|
};
|
|
2234
|
-
var
|
|
2230
|
+
var defaultThemeSlots = {
|
|
2235
2231
|
editor: {
|
|
2236
2232
|
className: "w-full bs-full"
|
|
2237
2233
|
}
|
|
2238
2234
|
};
|
|
2239
2235
|
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2240
|
-
const slots = defaultsDeep2({}, _slots,
|
|
2236
|
+
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
|
2241
2237
|
return [
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
theme &&
|
|
2245
|
-
slots.editor?.className &&
|
|
2238
|
+
EditorView9.baseTheme(defaultTheme),
|
|
2239
|
+
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
2240
|
+
theme && EditorView9.theme(theme),
|
|
2241
|
+
slots.editor?.className && EditorView9.editorAttributes.of({
|
|
2246
2242
|
class: slots.editor.className
|
|
2247
2243
|
}),
|
|
2248
|
-
slots.content?.className &&
|
|
2244
|
+
slots.content?.className && EditorView9.contentAttributes.of({
|
|
2249
2245
|
class: slots.content.className
|
|
2250
2246
|
})
|
|
2251
2247
|
].filter(isNotFalsy2);
|
|
@@ -2273,1618 +2269,1667 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
|
2273
2269
|
};
|
|
2274
2270
|
|
|
2275
2271
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
2276
|
-
import { EditorView as
|
|
2272
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
2277
2273
|
var listener = ({ onFocus, onChange }) => {
|
|
2278
2274
|
const extensions = [];
|
|
2279
|
-
onFocus && extensions.push(
|
|
2275
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
2280
2276
|
onFocus(focusing);
|
|
2281
2277
|
return null;
|
|
2282
2278
|
}));
|
|
2283
|
-
onChange && extensions.push(
|
|
2279
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
2284
2280
|
onChange(update2.state.doc.toString());
|
|
2285
2281
|
}));
|
|
2286
2282
|
return extensions;
|
|
2287
2283
|
};
|
|
2288
2284
|
|
|
2289
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
2290
|
-
import {
|
|
2291
|
-
import {
|
|
2292
|
-
import {
|
|
2293
|
-
import {
|
|
2294
|
-
import {
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2285
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
2286
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
2287
|
+
import { syntaxTree } from "@codemirror/language";
|
|
2288
|
+
import { EditorSelection } from "@codemirror/state";
|
|
2289
|
+
import { EditorView as EditorView11, keymap as keymap6 } from "@codemirror/view";
|
|
2290
|
+
import { useMemo, useState } from "react";
|
|
2291
|
+
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
|
2292
|
+
var Inline;
|
|
2293
|
+
(function(Inline2) {
|
|
2294
|
+
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
2295
|
+
Inline2[Inline2["Emphasis"] = 1] = "Emphasis";
|
|
2296
|
+
Inline2[Inline2["Strikethrough"] = 2] = "Strikethrough";
|
|
2297
|
+
Inline2[Inline2["Code"] = 3] = "Code";
|
|
2298
|
+
})(Inline || (Inline = {}));
|
|
2299
|
+
var List;
|
|
2300
|
+
(function(List2) {
|
|
2301
|
+
List2[List2["Ordered"] = 0] = "Ordered";
|
|
2302
|
+
List2[List2["Bullet"] = 1] = "Bullet";
|
|
2303
|
+
List2[List2["Task"] = 2] = "Task";
|
|
2304
|
+
})(List || (List = {}));
|
|
2305
|
+
var setHeading = (level) => ({ state: state2, dispatch }) => {
|
|
2306
|
+
const { selection: { ranges }, doc } = state2;
|
|
2307
|
+
const changes = [];
|
|
2308
|
+
let prevBlock = -1;
|
|
2309
|
+
for (const range of ranges) {
|
|
2310
|
+
let sawBlock = false;
|
|
2311
|
+
syntaxTree(state2).iterate({
|
|
2312
|
+
from: range.from,
|
|
2313
|
+
to: range.to,
|
|
2314
|
+
enter: (node) => {
|
|
2315
|
+
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
sawBlock = true;
|
|
2319
|
+
prevBlock = node.from;
|
|
2320
|
+
const blockType = Textblocks[node.name];
|
|
2321
|
+
const isHeading = /heading(\d)/.exec(blockType);
|
|
2322
|
+
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2323
|
+
if (curLevel < 0 || curLevel === level) {
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
if (curLevel === 0) {
|
|
2327
|
+
changes.push({
|
|
2328
|
+
from: node.from,
|
|
2329
|
+
insert: "#".repeat(level) + " "
|
|
2330
|
+
});
|
|
2331
|
+
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
2332
|
+
const nextLine = doc.lineAt(node.to);
|
|
2333
|
+
if (level) {
|
|
2334
|
+
changes.push({
|
|
2335
|
+
from: node.from,
|
|
2336
|
+
insert: "#".repeat(level) + " "
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
changes.push({
|
|
2340
|
+
from: nextLine.from - 1,
|
|
2341
|
+
to: nextLine.to
|
|
2342
|
+
});
|
|
2343
|
+
} else {
|
|
2344
|
+
if (level === 0) {
|
|
2345
|
+
changes.push({
|
|
2346
|
+
from: node.from,
|
|
2347
|
+
to: Math.min(node.to, node.from + curLevel + 1)
|
|
2348
|
+
});
|
|
2349
|
+
} else if (level < curLevel) {
|
|
2350
|
+
changes.push({
|
|
2351
|
+
from: node.from,
|
|
2352
|
+
to: node.from + (curLevel - level)
|
|
2353
|
+
});
|
|
2354
|
+
} else {
|
|
2355
|
+
changes.push({
|
|
2356
|
+
from: node.from,
|
|
2357
|
+
insert: "#".repeat(level - curLevel)
|
|
2358
|
+
});
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
});
|
|
2363
|
+
let line;
|
|
2364
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2365
|
+
changes.push({
|
|
2366
|
+
from: line.from,
|
|
2367
|
+
to: line.to,
|
|
2368
|
+
insert: "#".repeat(level) + " "
|
|
2369
|
+
});
|
|
2324
2370
|
}
|
|
2325
2371
|
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
Table,
|
|
2329
|
-
{
|
|
2330
|
-
props: [
|
|
2331
|
-
styleTags(markdownTags)
|
|
2332
|
-
]
|
|
2372
|
+
if (!changes.length) {
|
|
2373
|
+
return false;
|
|
2333
2374
|
}
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
tags.string,
|
|
2370
|
-
tags.inserted,
|
|
2371
|
-
tags.invalid
|
|
2372
|
-
],
|
|
2373
|
-
color: "inherit !important"
|
|
2374
|
-
},
|
|
2375
|
-
// Markdown marks.
|
|
2376
|
-
{
|
|
2377
|
-
tag: [
|
|
2378
|
-
tags.meta,
|
|
2379
|
-
tags.processingInstruction,
|
|
2380
|
-
markdownTags.LinkLabel,
|
|
2381
|
-
markdownTags.LinkReference,
|
|
2382
|
-
markdownTags.ListMark
|
|
2383
|
-
],
|
|
2384
|
-
class: mark
|
|
2385
|
-
},
|
|
2386
|
-
// Markdown marks.
|
|
2387
|
-
{
|
|
2388
|
-
tag: [
|
|
2389
|
-
markdownTags.CodeMark,
|
|
2390
|
-
markdownTags.HeaderMark,
|
|
2391
|
-
markdownTags.QuoteMark,
|
|
2392
|
-
markdownTags.EmphasisMark
|
|
2393
|
-
],
|
|
2394
|
-
class: mark
|
|
2395
|
-
},
|
|
2396
|
-
// E.g., code block language (after ```).
|
|
2397
|
-
{
|
|
2398
|
-
tag: [
|
|
2399
|
-
tags.function(tags.variableName),
|
|
2400
|
-
tags.labelName
|
|
2401
|
-
],
|
|
2402
|
-
class: codeMark
|
|
2403
|
-
},
|
|
2404
|
-
{
|
|
2405
|
-
tag: [
|
|
2406
|
-
tags.monospace
|
|
2407
|
-
],
|
|
2408
|
-
class: "font-mono"
|
|
2409
|
-
},
|
|
2410
|
-
// Headings.
|
|
2411
|
-
{
|
|
2412
|
-
tag: tags.heading1,
|
|
2413
|
-
class: heading(1)
|
|
2414
|
-
},
|
|
2415
|
-
{
|
|
2416
|
-
tag: tags.heading2,
|
|
2417
|
-
class: heading(2)
|
|
2418
|
-
},
|
|
2419
|
-
{
|
|
2420
|
-
tag: tags.heading3,
|
|
2421
|
-
class: heading(3)
|
|
2422
|
-
},
|
|
2423
|
-
{
|
|
2424
|
-
tag: tags.heading4,
|
|
2425
|
-
class: heading(4)
|
|
2426
|
-
},
|
|
2427
|
-
{
|
|
2428
|
-
tag: tags.heading5,
|
|
2429
|
-
class: heading(5)
|
|
2430
|
-
},
|
|
2431
|
-
{
|
|
2432
|
-
tag: tags.heading6,
|
|
2433
|
-
class: heading(6)
|
|
2434
|
-
},
|
|
2435
|
-
// Emphasis.
|
|
2436
|
-
{
|
|
2437
|
-
tag: tags.emphasis,
|
|
2438
|
-
class: italic
|
|
2439
|
-
},
|
|
2440
|
-
{
|
|
2441
|
-
tag: tags.strong,
|
|
2442
|
-
class: bold
|
|
2443
|
-
},
|
|
2444
|
-
{
|
|
2445
|
-
tag: tags.strikethrough,
|
|
2446
|
-
class: strikethrough
|
|
2447
|
-
},
|
|
2448
|
-
// Naked URLs.
|
|
2449
|
-
{
|
|
2450
|
-
tag: [
|
|
2451
|
-
markdownTags.URL
|
|
2452
|
-
],
|
|
2453
|
-
class: inlineUrl
|
|
2454
|
-
},
|
|
2455
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
2456
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
2457
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
2458
|
-
// the code, but all other CSS properties will be inherited.
|
|
2459
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
2460
|
-
{
|
|
2461
|
-
tag: [
|
|
2462
|
-
markdownTags.CodeText,
|
|
2463
|
-
markdownTags.InlineCode
|
|
2464
|
-
],
|
|
2465
|
-
class: code
|
|
2466
|
-
},
|
|
2467
|
-
{
|
|
2468
|
-
tag: [
|
|
2469
|
-
markdownTags.QuoteMark
|
|
2470
|
-
],
|
|
2471
|
-
class: blockquote
|
|
2472
|
-
},
|
|
2473
|
-
{
|
|
2474
|
-
tag: [
|
|
2475
|
-
markdownTags.TableCell
|
|
2476
|
-
],
|
|
2477
|
-
class: "font-mono"
|
|
2375
|
+
const changeSet = state2.changes(changes);
|
|
2376
|
+
dispatch(state2.update({
|
|
2377
|
+
changes: changeSet,
|
|
2378
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2379
|
+
userEvent: "format.setHeading",
|
|
2380
|
+
scrollIntoView: true
|
|
2381
|
+
}));
|
|
2382
|
+
return true;
|
|
2383
|
+
};
|
|
2384
|
+
var setStyle = (type, enable) => ({ state: state2, dispatch }) => {
|
|
2385
|
+
const marker = inlineMarkerText(type);
|
|
2386
|
+
const changes = state2.changeByRange((range) => {
|
|
2387
|
+
if (!enable && range.empty) {
|
|
2388
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2389
|
+
const found = after.indexOf(marker);
|
|
2390
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2391
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2392
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2393
|
+
...before.slice(before.length - found)
|
|
2394
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
2395
|
+
return {
|
|
2396
|
+
changes: [
|
|
2397
|
+
{
|
|
2398
|
+
from: range.head - marker.length - found,
|
|
2399
|
+
to: range.head - found
|
|
2400
|
+
},
|
|
2401
|
+
{
|
|
2402
|
+
from: range.head + found,
|
|
2403
|
+
to: range.head + found + marker.length
|
|
2404
|
+
}
|
|
2405
|
+
],
|
|
2406
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2478
2410
|
}
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2411
|
+
const changes2 = [];
|
|
2412
|
+
const changesAtEnd = [];
|
|
2413
|
+
let blockStart = -1;
|
|
2414
|
+
let blockEnd = -1;
|
|
2415
|
+
let startCovered = false;
|
|
2416
|
+
let endCovered = false;
|
|
2417
|
+
let { from, to } = range;
|
|
2418
|
+
syntaxTree(state2).iterate({
|
|
2419
|
+
from,
|
|
2420
|
+
to,
|
|
2421
|
+
enter: (node) => {
|
|
2422
|
+
const { name } = node;
|
|
2423
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2424
|
+
blockStart = blockContentStart(node);
|
|
2425
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2426
|
+
startCovered = endCovered = false;
|
|
2427
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
2428
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
2429
|
+
to = node.to;
|
|
2430
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2431
|
+
from = node.from;
|
|
2432
|
+
}
|
|
2433
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
2434
|
+
if (node.from < from && node.to > from) {
|
|
2435
|
+
if (to === from) {
|
|
2436
|
+
to = node.to;
|
|
2437
|
+
}
|
|
2438
|
+
from = node.to;
|
|
2439
|
+
}
|
|
2440
|
+
if (node.from < to && node.to > to) {
|
|
2441
|
+
to = node.from;
|
|
2442
|
+
}
|
|
2443
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2444
|
+
const markType = InlineMarker[name];
|
|
2445
|
+
const size = inlineMarkerText(markType).length;
|
|
2446
|
+
const openEnd = node.from + size;
|
|
2447
|
+
const closeStart = node.to - size;
|
|
2448
|
+
if (markType === type) {
|
|
2449
|
+
if (openEnd <= from && closeStart >= from) {
|
|
2450
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2451
|
+
from: node.from,
|
|
2452
|
+
to: openEnd
|
|
2453
|
+
} : true;
|
|
2454
|
+
}
|
|
2455
|
+
if (openEnd <= to && closeStart >= to) {
|
|
2456
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2457
|
+
from: closeStart,
|
|
2458
|
+
to: node.to
|
|
2459
|
+
} : true;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
if (markType === type || type === 3 && enable) {
|
|
2463
|
+
if (node.from >= from && openEnd <= to) {
|
|
2464
|
+
changes2.push({
|
|
2465
|
+
from: node.from,
|
|
2466
|
+
to: openEnd
|
|
2467
|
+
});
|
|
2468
|
+
if (markType !== type && closeStart >= to) {
|
|
2469
|
+
changesAtEnd.push({
|
|
2470
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2471
|
+
insert: inlineMarkerText(markType)
|
|
2472
|
+
});
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
if (closeStart >= from && node.to <= to) {
|
|
2476
|
+
changes2.push({
|
|
2477
|
+
from: closeStart,
|
|
2478
|
+
to: node.to
|
|
2479
|
+
});
|
|
2480
|
+
if (markType !== type && openEnd <= from) {
|
|
2481
|
+
changes2.push({
|
|
2482
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2483
|
+
insert: inlineMarkerText(markType)
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
},
|
|
2490
|
+
leave: (node) => {
|
|
2491
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2492
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2493
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2494
|
+
if (enable) {
|
|
2495
|
+
if (!startCovered) {
|
|
2496
|
+
changes2.push({
|
|
2497
|
+
from: rangeStart,
|
|
2498
|
+
insert: marker
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
if (!endCovered) {
|
|
2502
|
+
changes2.push({
|
|
2503
|
+
from: rangeEnd,
|
|
2504
|
+
insert: marker
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
} else {
|
|
2508
|
+
if (typeof startCovered === "object") {
|
|
2509
|
+
changes2.push(startCovered);
|
|
2510
|
+
} else if (startCovered) {
|
|
2511
|
+
changes2.push({
|
|
2512
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
2513
|
+
insert: marker
|
|
2514
|
+
});
|
|
2515
|
+
}
|
|
2516
|
+
if (typeof endCovered === "object") {
|
|
2517
|
+
changes2.push(endCovered);
|
|
2518
|
+
} else if (endCovered) {
|
|
2519
|
+
changes2.push({
|
|
2520
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
2521
|
+
insert: marker
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
});
|
|
2528
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2529
|
+
return {
|
|
2530
|
+
changes: {
|
|
2531
|
+
from: range.head,
|
|
2532
|
+
insert: marker + marker
|
|
2533
|
+
},
|
|
2534
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2535
|
+
};
|
|
2483
2536
|
}
|
|
2537
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
2538
|
+
return {
|
|
2539
|
+
changes: changeSet,
|
|
2540
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2541
|
+
};
|
|
2484
2542
|
});
|
|
2543
|
+
dispatch(state2.update(changes, {
|
|
2544
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2545
|
+
scrollIntoView: true
|
|
2546
|
+
}));
|
|
2547
|
+
return true;
|
|
2485
2548
|
};
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
var
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
// https://github.com/codemirror/lang-markdown
|
|
2492
|
-
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
2493
|
-
markdown({
|
|
2494
|
-
// GRM by default (vs strict CommonMark):
|
|
2495
|
-
// Table, TaskList, Strikethrough, and Autolink.
|
|
2496
|
-
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
2497
|
-
// https://github.github.com/gfm
|
|
2498
|
-
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
2499
|
-
base: markdownLanguage3,
|
|
2500
|
-
// Languages for syntax highlighting fenced code blocks.
|
|
2501
|
-
codeLanguages: languages,
|
|
2502
|
-
// Parser extensions.
|
|
2503
|
-
extensions: [
|
|
2504
|
-
// GFM provided by default.
|
|
2505
|
-
markdownTagsExtensions
|
|
2506
|
-
]
|
|
2507
|
-
}),
|
|
2508
|
-
// https://github.com/codemirror/theme-one-dark
|
|
2509
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
2510
|
-
// Custom styles.
|
|
2511
|
-
syntaxHighlighting(markdownHighlightStyle()),
|
|
2512
|
-
keymap5.of([
|
|
2513
|
-
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2514
|
-
indentWithTab,
|
|
2515
|
-
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2516
|
-
...closeBracketsKeymap,
|
|
2517
|
-
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2518
|
-
...historyKeymap,
|
|
2519
|
-
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2520
|
-
...searchKeymap,
|
|
2521
|
-
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2522
|
-
...standardKeymap
|
|
2523
|
-
])
|
|
2524
|
-
];
|
|
2549
|
+
var addStyle = (style) => setStyle(style, true);
|
|
2550
|
+
var removeStyle = (style) => setStyle(style, false);
|
|
2551
|
+
var toggleStyle = (style) => (arg) => {
|
|
2552
|
+
const form = getFormatting(arg.state);
|
|
2553
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2525
2554
|
};
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
el.className = "cm-hr";
|
|
2536
|
-
return el;
|
|
2555
|
+
var toggleStrong = toggleStyle(0);
|
|
2556
|
+
var toggleEmphasis = toggleStyle(1);
|
|
2557
|
+
var toggleStrikethrough = toggleStyle(2);
|
|
2558
|
+
var toggleInlineCode = toggleStyle(3);
|
|
2559
|
+
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
2560
|
+
var blockContentStart = (node) => {
|
|
2561
|
+
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
2562
|
+
if (atx) {
|
|
2563
|
+
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
2537
2564
|
}
|
|
2565
|
+
return node.from;
|
|
2566
|
+
};
|
|
2567
|
+
var blockContentEnd = (node, doc) => {
|
|
2568
|
+
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
2569
|
+
const lastLine = doc.lineAt(node.to);
|
|
2570
|
+
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
2571
|
+
return lastLine.from - 1;
|
|
2572
|
+
}
|
|
2573
|
+
return node.to;
|
|
2574
|
+
};
|
|
2575
|
+
var skipSpaces = (pos, doc, dir, limit) => {
|
|
2576
|
+
const line = doc.lineAt(pos);
|
|
2577
|
+
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
2578
|
+
pos += dir;
|
|
2579
|
+
}
|
|
2580
|
+
return pos;
|
|
2581
|
+
};
|
|
2582
|
+
var skipMarkers = (pos, tree, dir, limit) => {
|
|
2583
|
+
for (; ; ) {
|
|
2584
|
+
const next = tree.resolve(pos, dir);
|
|
2585
|
+
if (!IgnoreInline.has(next.name)) {
|
|
2586
|
+
return pos;
|
|
2587
|
+
}
|
|
2588
|
+
const moveTo = dir < 0 ? next.from : next.to;
|
|
2589
|
+
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
2590
|
+
return pos;
|
|
2591
|
+
}
|
|
2592
|
+
pos = moveTo;
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
var snippets = {
|
|
2596
|
+
codeblock: snippet([
|
|
2597
|
+
//
|
|
2598
|
+
"```#{}",
|
|
2599
|
+
"",
|
|
2600
|
+
"```"
|
|
2601
|
+
].join("\n")),
|
|
2602
|
+
table: snippet([
|
|
2603
|
+
//
|
|
2604
|
+
"| #{col1} | #{col2} |",
|
|
2605
|
+
"| ---- | ---- |",
|
|
2606
|
+
"| #{val1} | #{val2} |",
|
|
2607
|
+
"| #{val3} | #{val4} |",
|
|
2608
|
+
""
|
|
2609
|
+
].join("\n"))
|
|
2538
2610
|
};
|
|
2539
|
-
var
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
}
|
|
2545
|
-
eq(other) {
|
|
2546
|
-
return this.url === other.url;
|
|
2547
|
-
}
|
|
2548
|
-
toDOM(view) {
|
|
2549
|
-
const el = document.createElement("span");
|
|
2550
|
-
this.render(el, this.url);
|
|
2551
|
-
return el;
|
|
2552
|
-
}
|
|
2611
|
+
var insertTable = (view) => {
|
|
2612
|
+
const { selection: { main }, doc } = view.state;
|
|
2613
|
+
const { number } = doc.lineAt(main.anchor);
|
|
2614
|
+
const { from } = doc.line(number);
|
|
2615
|
+
snippets.table(view, null, from, from);
|
|
2553
2616
|
};
|
|
2554
|
-
var
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2617
|
+
var removeLinkInner = (from, to, changes, state2) => {
|
|
2618
|
+
syntaxTree(state2).iterate({
|
|
2619
|
+
from,
|
|
2620
|
+
to,
|
|
2621
|
+
enter: (node) => {
|
|
2622
|
+
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
2623
|
+
node.node.cursor().iterate((node2) => {
|
|
2624
|
+
const { name } = node2;
|
|
2625
|
+
if (name === "LinkMark" || name === "LinkLabel") {
|
|
2626
|
+
changes.push({
|
|
2627
|
+
from: node2.from,
|
|
2628
|
+
to: node2.to
|
|
2629
|
+
});
|
|
2630
|
+
} else if (name === "LinkTitle" || name === "URL") {
|
|
2631
|
+
changes.push({
|
|
2632
|
+
from: skipSpaces(node2.from, state2.doc, -1),
|
|
2633
|
+
to: skipSpaces(node2.to, state2.doc, 1)
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
});
|
|
2637
|
+
return false;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
});
|
|
2641
|
+
};
|
|
2642
|
+
var removeLink = ({ state: state2, dispatch }) => {
|
|
2643
|
+
const changes = [];
|
|
2644
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2645
|
+
removeLinkInner(from, to, changes, state2);
|
|
2558
2646
|
}
|
|
2559
|
-
|
|
2560
|
-
return
|
|
2647
|
+
if (!changes) {
|
|
2648
|
+
return false;
|
|
2561
2649
|
}
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2650
|
+
dispatch(state2.update({
|
|
2651
|
+
changes,
|
|
2652
|
+
userEvent: "format.link.remove",
|
|
2653
|
+
scrollIntoView: true
|
|
2654
|
+
}));
|
|
2655
|
+
return true;
|
|
2656
|
+
};
|
|
2657
|
+
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
2658
|
+
const changes = state2.changeByRange((range) => {
|
|
2659
|
+
let { from, to } = range;
|
|
2660
|
+
const cutStyles = [];
|
|
2661
|
+
let okay = null;
|
|
2662
|
+
syntaxTree(state2).iterate({
|
|
2663
|
+
from,
|
|
2664
|
+
to,
|
|
2665
|
+
enter: (node) => {
|
|
2666
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2667
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
2668
|
+
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2669
|
+
const sNode = node.node;
|
|
2670
|
+
if (node.from < from && node.to <= to) {
|
|
2671
|
+
if (sNode.firstChild.to === from) {
|
|
2672
|
+
from = node.from;
|
|
2673
|
+
} else {
|
|
2674
|
+
cutStyles.push(sNode);
|
|
2579
2675
|
}
|
|
2580
|
-
})
|
|
2581
|
-
|
|
2676
|
+
} else if (node.from >= from && node.to > to) {
|
|
2677
|
+
if (sNode.lastChild.from === to) {
|
|
2678
|
+
to = node.to;
|
|
2679
|
+
} else {
|
|
2680
|
+
cutStyles.push(sNode);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2582
2683
|
}
|
|
2684
|
+
}
|
|
2685
|
+
});
|
|
2686
|
+
if (okay === null) {
|
|
2687
|
+
const line = state2.doc.lineAt(from);
|
|
2688
|
+
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
2689
|
+
}
|
|
2690
|
+
if (!okay) {
|
|
2691
|
+
return {
|
|
2692
|
+
range
|
|
2583
2693
|
};
|
|
2584
2694
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2695
|
+
const changes2 = [];
|
|
2696
|
+
const changesAfter = [];
|
|
2697
|
+
removeLinkInner(from, to, changesAfter, state2);
|
|
2698
|
+
let cursorOffset = 1;
|
|
2699
|
+
for (const style of cutStyles) {
|
|
2700
|
+
const type = InlineMarker[style.name];
|
|
2701
|
+
const mark2 = inlineMarkerText(type);
|
|
2702
|
+
if (style.from < from) {
|
|
2703
|
+
changes2.push({
|
|
2704
|
+
from: skipSpaces(from, state2.doc, -1),
|
|
2705
|
+
insert: mark2
|
|
2706
|
+
});
|
|
2707
|
+
changesAfter.push({
|
|
2708
|
+
from: skipSpaces(from, state2.doc, 1, to),
|
|
2709
|
+
insert: mark2
|
|
2710
|
+
});
|
|
2711
|
+
} else {
|
|
2712
|
+
changes2.push({
|
|
2713
|
+
from: skipSpaces(to, state2.doc, -1, from),
|
|
2714
|
+
insert: mark2
|
|
2715
|
+
});
|
|
2716
|
+
const after = skipSpaces(to, state2.doc, 1);
|
|
2717
|
+
if (after === to) {
|
|
2718
|
+
cursorOffset += mark2.length;
|
|
2719
|
+
}
|
|
2720
|
+
changesAfter.push({
|
|
2721
|
+
from: after,
|
|
2722
|
+
insert: mark2
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
changes2.push({
|
|
2727
|
+
from,
|
|
2728
|
+
insert: image2 ? "`
|
|
2732
|
+
});
|
|
2733
|
+
const changeSet = state2.changes(changes2.concat(changesAfter));
|
|
2734
|
+
return {
|
|
2735
|
+
changes: changeSet,
|
|
2736
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset - (url ? url.length + 2 : 0))
|
|
2737
|
+
};
|
|
2738
|
+
});
|
|
2739
|
+
if (changes.changes.empty) {
|
|
2588
2740
|
return false;
|
|
2589
2741
|
}
|
|
2742
|
+
dispatch(state2.update(changes, {
|
|
2743
|
+
userEvent: "format.link.add",
|
|
2744
|
+
scrollIntoView: true
|
|
2745
|
+
}));
|
|
2746
|
+
return true;
|
|
2590
2747
|
};
|
|
2591
|
-
var
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
})
|
|
2598
|
-
var fencedCodeLineLast = Decoration5.line({
|
|
2599
|
-
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
2600
|
-
});
|
|
2601
|
-
var horizontalRule = Decoration5.replace({
|
|
2602
|
-
widget: new HorizontalRuleWidget()
|
|
2603
|
-
});
|
|
2604
|
-
var checkedTask = Decoration5.replace({
|
|
2605
|
-
widget: new CheckboxWidget(true)
|
|
2606
|
-
});
|
|
2607
|
-
var uncheckedTask = Decoration5.replace({
|
|
2608
|
-
widget: new CheckboxWidget(false)
|
|
2609
|
-
});
|
|
2610
|
-
var editingRange = (state2, range, focus) => {
|
|
2611
|
-
const { readOnly, selection: { main: { head } } } = state2;
|
|
2612
|
-
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
2613
|
-
};
|
|
2614
|
-
var MarksByParent = /* @__PURE__ */ new Set([
|
|
2615
|
-
"CodeMark",
|
|
2616
|
-
"EmphasisMark",
|
|
2617
|
-
"StrikethroughMark",
|
|
2618
|
-
"SubscriptMark",
|
|
2619
|
-
"SuperscriptMark"
|
|
2620
|
-
]);
|
|
2621
|
-
var buildDecorations = (view, options, focus) => {
|
|
2622
|
-
const deco = new RangeSetBuilder2();
|
|
2623
|
-
const atomicDeco = new RangeSetBuilder2();
|
|
2624
|
-
const { state: state2 } = view;
|
|
2625
|
-
for (const { from, to } of view.visibleRanges) {
|
|
2748
|
+
var addList = (type) => ({ state: state2, dispatch }) => {
|
|
2749
|
+
let lastBlock = -1;
|
|
2750
|
+
let counter = 1;
|
|
2751
|
+
let first = true;
|
|
2752
|
+
let parentColumn = null;
|
|
2753
|
+
const blocks = [];
|
|
2754
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2626
2755
|
syntaxTree(state2).iterate({
|
|
2627
2756
|
from,
|
|
2628
2757
|
to,
|
|
2629
2758
|
enter: (node) => {
|
|
2630
|
-
if (node.name === "
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}
|
|
2636
|
-
if (block.from > node.to) {
|
|
2637
|
-
break;
|
|
2638
|
-
}
|
|
2639
|
-
const first = block.from <= node.from;
|
|
2640
|
-
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
2641
|
-
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
2642
|
-
if (!editing && (first || last)) {
|
|
2643
|
-
atomicDeco.add(block.from, block.to, hide);
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
return false;
|
|
2647
|
-
} else if (node.name === "Link") {
|
|
2648
|
-
const marks = node.node.getChildren("LinkMark");
|
|
2649
|
-
const urlNode = node.node.getChild("URL");
|
|
2650
|
-
const editing = editingRange(state2, node, focus);
|
|
2651
|
-
if (urlNode && marks.length >= 2) {
|
|
2652
|
-
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
2653
|
-
if (!editing) {
|
|
2654
|
-
atomicDeco.add(node.from, marks[0].to, hide);
|
|
2759
|
+
if (Object.hasOwn(Textblocks, node.name) && node.name !== "TableCell" || node.name === "Table") {
|
|
2760
|
+
if (first) {
|
|
2761
|
+
let before = node.node.prevSibling;
|
|
2762
|
+
while (before && /Mark$/.test(before.name)) {
|
|
2763
|
+
before = before.prevSibling;
|
|
2655
2764
|
}
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2765
|
+
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
2766
|
+
const item = before.lastChild;
|
|
2767
|
+
const itemLine = state2.doc.lineAt(item.from);
|
|
2768
|
+
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2769
|
+
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2770
|
+
if (type === 0) {
|
|
2771
|
+
const mark2 = /^\s*(\d+)[.)]/.exec(itemText);
|
|
2772
|
+
if (mark2) {
|
|
2773
|
+
parentColumn += mark2[1].length;
|
|
2774
|
+
counter = +mark2[1] + 1;
|
|
2775
|
+
}
|
|
2663
2776
|
}
|
|
2664
|
-
}));
|
|
2665
|
-
if (!editing) {
|
|
2666
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
2667
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
|
2668
|
-
}) : hide);
|
|
2669
2777
|
}
|
|
2778
|
+
first = false;
|
|
2670
2779
|
}
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
2674
|
-
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
2675
|
-
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2676
|
-
}
|
|
2677
|
-
} else if (node.name === "HorizontalRule") {
|
|
2678
|
-
if (!editingRange(state2, node, focus)) {
|
|
2679
|
-
deco.add(node.from, node.to, horizontalRule);
|
|
2680
|
-
}
|
|
2681
|
-
} else if (node.name === "TaskMarker") {
|
|
2682
|
-
if (!editingRange(state2, node, focus)) {
|
|
2683
|
-
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2684
|
-
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
2685
|
-
class: "cm-task"
|
|
2686
|
-
}));
|
|
2687
|
-
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
2688
|
-
}
|
|
2689
|
-
} else if (MarksByParent.has(node.name)) {
|
|
2690
|
-
if (!editingRange(state2, node.node.parent, focus)) {
|
|
2691
|
-
atomicDeco.add(node.from, node.to, hide);
|
|
2780
|
+
if (node.from === lastBlock) {
|
|
2781
|
+
return;
|
|
2692
2782
|
}
|
|
2783
|
+
lastBlock = node.from;
|
|
2784
|
+
blocks.push({
|
|
2785
|
+
node: node.node,
|
|
2786
|
+
counter,
|
|
2787
|
+
parentColumn
|
|
2788
|
+
});
|
|
2789
|
+
counter++;
|
|
2790
|
+
return false;
|
|
2791
|
+
}
|
|
2792
|
+
},
|
|
2793
|
+
leave: (node) => {
|
|
2794
|
+
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
2795
|
+
counter = 1;
|
|
2796
|
+
parentColumn = null;
|
|
2693
2797
|
}
|
|
2694
2798
|
}
|
|
2695
2799
|
});
|
|
2696
2800
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2801
|
+
if (!blocks.length) {
|
|
2802
|
+
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
2803
|
+
if (from === to) {
|
|
2804
|
+
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
2805
|
+
dispatch(state2.update({
|
|
2806
|
+
changes: [
|
|
2807
|
+
{
|
|
2808
|
+
from,
|
|
2809
|
+
insert
|
|
2810
|
+
}
|
|
2811
|
+
],
|
|
2812
|
+
selection: {
|
|
2813
|
+
anchor: from + insert.length
|
|
2814
|
+
},
|
|
2815
|
+
userEvent: "format.list.add",
|
|
2816
|
+
scrollIntoView: true
|
|
2817
|
+
}));
|
|
2818
|
+
return true;
|
|
2819
|
+
}
|
|
2820
|
+
return false;
|
|
2821
|
+
}
|
|
2822
|
+
const changes = [];
|
|
2823
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
2824
|
+
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2825
|
+
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2826
|
+
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2827
|
+
if (type === 0) {
|
|
2828
|
+
padding += String(counter2).length;
|
|
2829
|
+
}
|
|
2830
|
+
let line = state2.doc.lineAt(nodeFrom);
|
|
2831
|
+
const column = nodeFrom - line.from;
|
|
2832
|
+
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
2833
|
+
padding = Math.max(padding, parentColumn2 - column);
|
|
2834
|
+
}
|
|
2835
|
+
let mark2;
|
|
2836
|
+
if (type === 0) {
|
|
2837
|
+
let max = counter2;
|
|
2838
|
+
for (let j = i + 1; j < blocks.length; j++) {
|
|
2839
|
+
if (blocks[j].counter !== max + 1) {
|
|
2840
|
+
break;
|
|
2731
2841
|
}
|
|
2842
|
+
max++;
|
|
2732
2843
|
}
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
})
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
"& .cm-codeblock-line": {
|
|
2751
|
-
paddingInline: "1rem !important"
|
|
2752
|
-
},
|
|
2753
|
-
"& .cm-codeblock-end": {
|
|
2754
|
-
display: "inline-block",
|
|
2755
|
-
width: "100%",
|
|
2756
|
-
position: "relative",
|
|
2757
|
-
"&::after": {
|
|
2758
|
-
position: "absolute",
|
|
2759
|
-
inset: 0,
|
|
2760
|
-
content: '""'
|
|
2844
|
+
const num = String(counter2);
|
|
2845
|
+
padding = Math.max(String(max).length, padding);
|
|
2846
|
+
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
2847
|
+
} else {
|
|
2848
|
+
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
2849
|
+
}
|
|
2850
|
+
changes.push({
|
|
2851
|
+
from: nodeFrom,
|
|
2852
|
+
insert: mark2
|
|
2853
|
+
});
|
|
2854
|
+
while (line.to < node.to) {
|
|
2855
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2856
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2857
|
+
changes.push({
|
|
2858
|
+
from: line.from + Math.min(open, column),
|
|
2859
|
+
insert: " ".repeat(mark2.length)
|
|
2860
|
+
});
|
|
2761
2861
|
}
|
|
2762
|
-
},
|
|
2763
|
-
"& .cm-codeblock-first": {
|
|
2764
|
-
borderTopLeftRadius: ".5rem",
|
|
2765
|
-
borderTopRightRadius: ".5rem"
|
|
2766
|
-
},
|
|
2767
|
-
"& .cm-codeblock-last": {
|
|
2768
|
-
borderBottomLeftRadius: ".5rem",
|
|
2769
|
-
borderBottomRightRadius: ".5rem"
|
|
2770
|
-
},
|
|
2771
|
-
"&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
|
|
2772
|
-
background: getToken("extend.semanticColors.input.light"),
|
|
2773
|
-
mixBlendMode: "darken"
|
|
2774
|
-
},
|
|
2775
|
-
"&dark .cm-codeblock-line, &dark .cm-activeLine.cm-codeblock-line": {
|
|
2776
|
-
background: getToken("extend.semanticColors.input.dark"),
|
|
2777
|
-
mixBlendMode: "lighten"
|
|
2778
|
-
},
|
|
2779
|
-
"& .cm-hr": {
|
|
2780
|
-
display: "inline-block",
|
|
2781
|
-
width: "100%",
|
|
2782
|
-
height: "0",
|
|
2783
|
-
verticalAlign: "middle",
|
|
2784
|
-
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2785
|
-
},
|
|
2786
|
-
"& .cm-task": {
|
|
2787
|
-
color: getToken("extend.colors.blue.500")
|
|
2788
|
-
},
|
|
2789
|
-
"& .cm-task-checkbox": {
|
|
2790
|
-
marginLeft: "4px",
|
|
2791
|
-
marginRight: "4px"
|
|
2792
2862
|
}
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
(
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
})
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
List2[List2["Task"] = 2] = "Task";
|
|
2815
|
-
})(List || (List = {}));
|
|
2816
|
-
var setHeading = (level) => ({ state: state2, dispatch }) => {
|
|
2817
|
-
const { selection: { ranges }, doc } = state2;
|
|
2863
|
+
if (type === 0) {
|
|
2864
|
+
const last = blocks[blocks.length - 1];
|
|
2865
|
+
let next = last.node.nextSibling;
|
|
2866
|
+
while (next && /Mark$/.test(next.name)) {
|
|
2867
|
+
next = next.nextSibling;
|
|
2868
|
+
}
|
|
2869
|
+
if (next?.name === "OrderedList") {
|
|
2870
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
const changeSet = state2.changes(changes);
|
|
2874
|
+
dispatch(state2.update({
|
|
2875
|
+
changes: changeSet,
|
|
2876
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2877
|
+
userEvent: "format.list.add",
|
|
2878
|
+
scrollIntoView: true
|
|
2879
|
+
}));
|
|
2880
|
+
return true;
|
|
2881
|
+
};
|
|
2882
|
+
var removeList = (type) => ({ state: state2, dispatch }) => {
|
|
2883
|
+
let lastBlock = -1;
|
|
2818
2884
|
const changes = [];
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
from
|
|
2824
|
-
to
|
|
2825
|
-
enter: (node) => {
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
const blockType = Textblocks[node.name];
|
|
2832
|
-
const isHeading = /heading(\d)/.exec(blockType);
|
|
2833
|
-
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2834
|
-
if (curLevel < 0 || curLevel === level) {
|
|
2835
|
-
return;
|
|
2885
|
+
const stack = [];
|
|
2886
|
+
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
2887
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2888
|
+
syntaxTree(state2).iterate({
|
|
2889
|
+
from,
|
|
2890
|
+
to,
|
|
2891
|
+
enter: (node) => {
|
|
2892
|
+
const { name } = node;
|
|
2893
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2894
|
+
stack.push(name);
|
|
2895
|
+
} else if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2896
|
+
stack[stack.length - 1] = "TaskList";
|
|
2836
2897
|
}
|
|
2837
|
-
|
|
2898
|
+
},
|
|
2899
|
+
leave: (node) => {
|
|
2900
|
+
const { name } = node;
|
|
2901
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2902
|
+
stack.pop();
|
|
2903
|
+
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2904
|
+
lastBlock = node.from;
|
|
2905
|
+
let line = state2.doc.lineAt(node.from);
|
|
2906
|
+
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2907
|
+
if (!mark2) {
|
|
2908
|
+
return false;
|
|
2909
|
+
}
|
|
2910
|
+
const column = node.from - line.from;
|
|
2838
2911
|
changes.push({
|
|
2839
2912
|
from: node.from,
|
|
2840
|
-
|
|
2913
|
+
to: node.from + mark2[0].length
|
|
2841
2914
|
});
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2915
|
+
while (line.to < node.to) {
|
|
2916
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2917
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2918
|
+
if (open > column) {
|
|
2919
|
+
changes.push({
|
|
2920
|
+
from: line.from + column,
|
|
2921
|
+
to: line.from + Math.min(column + mark2[0].length, open)
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2849
2924
|
}
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
to: nextLine.to
|
|
2853
|
-
});
|
|
2854
|
-
} else {
|
|
2855
|
-
if (level === 0) {
|
|
2856
|
-
changes.push({
|
|
2857
|
-
from: node.from,
|
|
2858
|
-
to: Math.min(node.to, node.from + curLevel + 1)
|
|
2859
|
-
});
|
|
2860
|
-
} else if (level < curLevel) {
|
|
2861
|
-
changes.push({
|
|
2862
|
-
from: node.from,
|
|
2863
|
-
to: node.from + (curLevel - level)
|
|
2864
|
-
});
|
|
2865
|
-
} else {
|
|
2866
|
-
changes.push({
|
|
2867
|
-
from: node.from,
|
|
2868
|
-
insert: "#".repeat(level - curLevel)
|
|
2869
|
-
});
|
|
2925
|
+
if (node.to >= to) {
|
|
2926
|
+
renumberListItems(node.node.nextSibling, 1, changes, state2.doc);
|
|
2870
2927
|
}
|
|
2928
|
+
return false;
|
|
2871
2929
|
}
|
|
2872
2930
|
}
|
|
2873
2931
|
});
|
|
2874
|
-
let line;
|
|
2875
|
-
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2876
|
-
changes.push({
|
|
2877
|
-
from: line.from,
|
|
2878
|
-
to: line.to,
|
|
2879
|
-
insert: "#".repeat(level) + " "
|
|
2880
|
-
});
|
|
2881
|
-
}
|
|
2882
2932
|
}
|
|
2883
2933
|
if (!changes.length) {
|
|
2884
2934
|
return false;
|
|
2885
2935
|
}
|
|
2886
|
-
const changeSet = state2.changes(changes);
|
|
2887
2936
|
dispatch(state2.update({
|
|
2888
|
-
changes
|
|
2889
|
-
|
|
2890
|
-
userEvent: "format.setHeading",
|
|
2937
|
+
changes,
|
|
2938
|
+
userEvent: "format.list.remove",
|
|
2891
2939
|
scrollIntoView: true
|
|
2892
2940
|
}));
|
|
2893
2941
|
return true;
|
|
2894
2942
|
};
|
|
2895
|
-
var
|
|
2896
|
-
const
|
|
2897
|
-
const
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
return {
|
|
2907
|
-
changes: [
|
|
2908
|
-
{
|
|
2909
|
-
from: range.head - marker.length - found,
|
|
2910
|
-
to: range.head - found
|
|
2911
|
-
},
|
|
2912
|
-
{
|
|
2913
|
-
from: range.head + found,
|
|
2914
|
-
to: range.head + found + marker.length
|
|
2915
|
-
}
|
|
2916
|
-
],
|
|
2917
|
-
range: EditorSelection.cursor(range.from - marker.length)
|
|
2918
|
-
};
|
|
2919
|
-
}
|
|
2943
|
+
var toggleList = (type) => (target) => {
|
|
2944
|
+
const formatting = getFormatting(target.state);
|
|
2945
|
+
const active = formatting.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
2946
|
+
return (active ? removeList(type) : addList(type))(target);
|
|
2947
|
+
};
|
|
2948
|
+
var renumberListItems = (item, counter, changes, doc) => {
|
|
2949
|
+
for (; item; item = item.nextSibling) {
|
|
2950
|
+
if (item.name === "ListItem") {
|
|
2951
|
+
const number = /(\s*)(\d+)[.)]/.exec(doc.sliceString(item.from, item.from + 10));
|
|
2952
|
+
if (!number || +number[2] === counter) {
|
|
2953
|
+
break;
|
|
2920
2954
|
}
|
|
2955
|
+
const size = number[1].length + number[2].length;
|
|
2956
|
+
const newNum = String(counter);
|
|
2957
|
+
changes.push({
|
|
2958
|
+
from: item.from + Math.max(0, size - newNum.length),
|
|
2959
|
+
to: item.from + size,
|
|
2960
|
+
insert: newNum
|
|
2961
|
+
});
|
|
2962
|
+
counter++;
|
|
2921
2963
|
}
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2964
|
+
}
|
|
2965
|
+
};
|
|
2966
|
+
var setBlockquote = (enable) => ({ state: state2, dispatch }) => {
|
|
2967
|
+
const lines = [];
|
|
2968
|
+
let lastBlock = -1;
|
|
2969
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2970
|
+
const sawBlock = false;
|
|
2971
|
+
syntaxTree(state2).iterate({
|
|
2930
2972
|
from,
|
|
2931
2973
|
to,
|
|
2932
2974
|
enter: (node) => {
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
blockEnd = blockContentEnd(node, state2.doc);
|
|
2937
|
-
startCovered = endCovered = false;
|
|
2938
|
-
} else if (name === "Link" || name === "Image" && enable) {
|
|
2939
|
-
if (from < node.from && to > node.from && to <= node.to) {
|
|
2940
|
-
to = node.to;
|
|
2941
|
-
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2942
|
-
from = node.from;
|
|
2943
|
-
}
|
|
2944
|
-
} else if (IgnoreInline.has(name) && enable) {
|
|
2945
|
-
if (node.from < from && node.to > from) {
|
|
2946
|
-
if (to === from) {
|
|
2947
|
-
to = node.to;
|
|
2948
|
-
}
|
|
2949
|
-
from = node.to;
|
|
2950
|
-
}
|
|
2951
|
-
if (node.from < to && node.to > to) {
|
|
2952
|
-
to = node.from;
|
|
2953
|
-
}
|
|
2954
|
-
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2955
|
-
const markType = InlineMarker[name];
|
|
2956
|
-
const size = inlineMarkerText(markType).length;
|
|
2957
|
-
const openEnd = node.from + size;
|
|
2958
|
-
const closeStart = node.to - size;
|
|
2959
|
-
if (markType === type) {
|
|
2960
|
-
if (openEnd <= from && closeStart >= from) {
|
|
2961
|
-
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2962
|
-
from: node.from,
|
|
2963
|
-
to: openEnd
|
|
2964
|
-
} : true;
|
|
2965
|
-
}
|
|
2966
|
-
if (openEnd <= to && closeStart >= to) {
|
|
2967
|
-
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2968
|
-
from: closeStart,
|
|
2969
|
-
to: node.to
|
|
2970
|
-
} : true;
|
|
2971
|
-
}
|
|
2975
|
+
if (Object.hasOwn(Textblocks, node.name) || node.name === "Table") {
|
|
2976
|
+
if (node.from === lastBlock) {
|
|
2977
|
+
return false;
|
|
2972
2978
|
}
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
changesAtEnd.push({
|
|
2981
|
-
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2982
|
-
insert: inlineMarkerText(markType)
|
|
2983
|
-
});
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
if (closeStart >= from && node.to <= to) {
|
|
2987
|
-
changes2.push({
|
|
2988
|
-
from: closeStart,
|
|
2989
|
-
to: node.to
|
|
2990
|
-
});
|
|
2991
|
-
if (markType !== type && openEnd <= from) {
|
|
2992
|
-
changes2.push({
|
|
2993
|
-
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2994
|
-
insert: inlineMarkerText(markType)
|
|
2995
|
-
});
|
|
2979
|
+
lastBlock = node.from;
|
|
2980
|
+
let line2 = state2.doc.lineAt(node.from);
|
|
2981
|
+
if (line2.number > 1) {
|
|
2982
|
+
const prevLine = state2.doc.line(line2.number - 1);
|
|
2983
|
+
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2984
|
+
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2985
|
+
lines.push(prevLine);
|
|
2996
2986
|
}
|
|
2997
2987
|
}
|
|
2998
2988
|
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
const rangeStart = Math.max(from, blockStart);
|
|
3004
|
-
const rangeEnd = Math.min(to, blockEnd);
|
|
3005
|
-
if (enable) {
|
|
3006
|
-
if (!startCovered) {
|
|
3007
|
-
changes2.push({
|
|
3008
|
-
from: rangeStart,
|
|
3009
|
-
insert: marker
|
|
3010
|
-
});
|
|
3011
|
-
}
|
|
3012
|
-
if (!endCovered) {
|
|
3013
|
-
changes2.push({
|
|
3014
|
-
from: rangeEnd,
|
|
3015
|
-
insert: marker
|
|
3016
|
-
});
|
|
3017
|
-
}
|
|
3018
|
-
} else {
|
|
3019
|
-
if (typeof startCovered === "object") {
|
|
3020
|
-
changes2.push(startCovered);
|
|
3021
|
-
} else if (startCovered) {
|
|
3022
|
-
changes2.push({
|
|
3023
|
-
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
3024
|
-
insert: marker
|
|
3025
|
-
});
|
|
2989
|
+
for (; ; ) {
|
|
2990
|
+
lines.push(line2);
|
|
2991
|
+
if (line2.to >= node.to) {
|
|
2992
|
+
break;
|
|
3026
2993
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
});
|
|
2994
|
+
line2 = state2.doc.line(line2.number + 1);
|
|
2995
|
+
}
|
|
2996
|
+
if (!enable && line2.number < state2.doc.lines) {
|
|
2997
|
+
const nextLine = state2.doc.line(line2.number + 1);
|
|
2998
|
+
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2999
|
+
lines.push(nextLine);
|
|
3034
3000
|
}
|
|
3035
3001
|
}
|
|
3002
|
+
return false;
|
|
3036
3003
|
}
|
|
3037
3004
|
}
|
|
3038
3005
|
});
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
from: range.head,
|
|
3043
|
-
insert: marker + marker
|
|
3044
|
-
},
|
|
3045
|
-
range: EditorSelection.cursor(range.head + marker.length)
|
|
3046
|
-
};
|
|
3047
|
-
}
|
|
3048
|
-
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
3049
|
-
return {
|
|
3050
|
-
changes: changeSet,
|
|
3051
|
-
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
3052
|
-
};
|
|
3053
|
-
});
|
|
3054
|
-
dispatch(state2.update(changes, {
|
|
3055
|
-
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
3056
|
-
scrollIntoView: true
|
|
3057
|
-
}));
|
|
3058
|
-
return true;
|
|
3059
|
-
};
|
|
3060
|
-
var addStyle = (style) => setStyle(style, true);
|
|
3061
|
-
var removeStyle = (style) => setStyle(style, false);
|
|
3062
|
-
var toggleStyle = (style) => (arg) => {
|
|
3063
|
-
const form = getFormatting(arg.state);
|
|
3064
|
-
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
3065
|
-
};
|
|
3066
|
-
var toggleStrong = toggleStyle(0);
|
|
3067
|
-
var toggleEmphasis = toggleStyle(1);
|
|
3068
|
-
var toggleStrikethrough = toggleStyle(2);
|
|
3069
|
-
var toggleInlineCode = toggleStyle(3);
|
|
3070
|
-
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
3071
|
-
var blockContentStart = (node) => {
|
|
3072
|
-
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
3073
|
-
if (atx) {
|
|
3074
|
-
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
3075
|
-
}
|
|
3076
|
-
return node.from;
|
|
3077
|
-
};
|
|
3078
|
-
var blockContentEnd = (node, doc) => {
|
|
3079
|
-
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
3080
|
-
const lastLine = doc.lineAt(node.to);
|
|
3081
|
-
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
3082
|
-
return lastLine.from - 1;
|
|
3083
|
-
}
|
|
3084
|
-
return node.to;
|
|
3085
|
-
};
|
|
3086
|
-
var skipSpaces = (pos, doc, dir, limit) => {
|
|
3087
|
-
const line = doc.lineAt(pos);
|
|
3088
|
-
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
3089
|
-
pos += dir;
|
|
3090
|
-
}
|
|
3091
|
-
return pos;
|
|
3092
|
-
};
|
|
3093
|
-
var skipMarkers = (pos, tree, dir, limit) => {
|
|
3094
|
-
for (; ; ) {
|
|
3095
|
-
const next = tree.resolve(pos, dir);
|
|
3096
|
-
if (!IgnoreInline.has(next.name)) {
|
|
3097
|
-
return pos;
|
|
3098
|
-
}
|
|
3099
|
-
const moveTo = dir < 0 ? next.from : next.to;
|
|
3100
|
-
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
3101
|
-
return pos;
|
|
3006
|
+
let line;
|
|
3007
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state2.doc.lineAt(from)).text)) {
|
|
3008
|
+
lines.push(line);
|
|
3102
3009
|
}
|
|
3103
|
-
pos = moveTo;
|
|
3104
3010
|
}
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
"| #{val3} | #{val4} |",
|
|
3119
|
-
""
|
|
3120
|
-
].join("\n"))
|
|
3121
|
-
};
|
|
3122
|
-
var insertTable = (view) => {
|
|
3123
|
-
const { selection: { main }, doc } = view.state;
|
|
3124
|
-
const { number } = doc.lineAt(main.anchor);
|
|
3125
|
-
const { from } = doc.line(number);
|
|
3126
|
-
snippets.table(view, null, from, from);
|
|
3127
|
-
};
|
|
3128
|
-
var removeLinkInner = (from, to, changes, state2) => {
|
|
3129
|
-
syntaxTree2(state2).iterate({
|
|
3130
|
-
from,
|
|
3131
|
-
to,
|
|
3132
|
-
enter: (node) => {
|
|
3133
|
-
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
3134
|
-
node.node.cursor().iterate((node2) => {
|
|
3135
|
-
const { name } = node2;
|
|
3136
|
-
if (name === "LinkMark" || name === "LinkLabel") {
|
|
3137
|
-
changes.push({
|
|
3138
|
-
from: node2.from,
|
|
3139
|
-
to: node2.to
|
|
3140
|
-
});
|
|
3141
|
-
} else if (name === "LinkTitle" || name === "URL") {
|
|
3142
|
-
changes.push({
|
|
3143
|
-
from: skipSpaces(node2.from, state2.doc, -1),
|
|
3144
|
-
to: skipSpaces(node2.to, state2.doc, 1)
|
|
3145
|
-
});
|
|
3146
|
-
}
|
|
3011
|
+
const changes = [];
|
|
3012
|
+
for (const line of lines) {
|
|
3013
|
+
if (enable) {
|
|
3014
|
+
changes.push({
|
|
3015
|
+
from: line.from,
|
|
3016
|
+
insert: /\S/.test(line.text) ? "> " : ">"
|
|
3017
|
+
});
|
|
3018
|
+
} else {
|
|
3019
|
+
const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
|
|
3020
|
+
if (quote) {
|
|
3021
|
+
changes.push({
|
|
3022
|
+
from: line.from + quote[1].length,
|
|
3023
|
+
to: line.from + quote[0].length
|
|
3147
3024
|
});
|
|
3148
|
-
return false;
|
|
3149
3025
|
}
|
|
3150
3026
|
}
|
|
3151
|
-
});
|
|
3152
|
-
};
|
|
3153
|
-
var removeLink = ({ state: state2, dispatch }) => {
|
|
3154
|
-
const changes = [];
|
|
3155
|
-
for (const { from, to } of state2.selection.ranges) {
|
|
3156
|
-
removeLinkInner(from, to, changes, state2);
|
|
3157
3027
|
}
|
|
3158
|
-
if (!changes) {
|
|
3028
|
+
if (!changes.length) {
|
|
3159
3029
|
return false;
|
|
3160
3030
|
}
|
|
3031
|
+
const changeSet = state2.changes(changes);
|
|
3161
3032
|
dispatch(state2.update({
|
|
3162
|
-
changes,
|
|
3163
|
-
|
|
3033
|
+
changes: changeSet,
|
|
3034
|
+
selection: state2.selection.map(changeSet, 1),
|
|
3035
|
+
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
3164
3036
|
scrollIntoView: true
|
|
3165
3037
|
}));
|
|
3166
3038
|
return true;
|
|
3167
3039
|
};
|
|
3168
|
-
var
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3040
|
+
var addBlockquote = setBlockquote(true);
|
|
3041
|
+
var removeBlockquote = setBlockquote(false);
|
|
3042
|
+
var toggleBlockquote = (target) => {
|
|
3043
|
+
return (getFormatting(target.state).blockQuote ? removeBlockquote : addBlockquote)(target);
|
|
3044
|
+
};
|
|
3045
|
+
var addCodeblock = (target) => {
|
|
3046
|
+
const { state: state2, dispatch } = target;
|
|
3047
|
+
const { selection } = state2;
|
|
3048
|
+
if (selection.ranges.length === 1 && selection.main.empty) {
|
|
3049
|
+
const { head } = selection.main;
|
|
3050
|
+
const line = state2.doc.lineAt(head);
|
|
3051
|
+
if (!/\S/.test(line.text) && head === line.from) {
|
|
3052
|
+
snippets.codeblock(target, null, line.from, line.to);
|
|
3053
|
+
return true;
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
const ranges = [];
|
|
3057
|
+
for (const { from, to } of selection.ranges) {
|
|
3058
|
+
let blockFrom = from;
|
|
3059
|
+
let blockTo = to;
|
|
3060
|
+
syntaxTree(state2).iterate({
|
|
3174
3061
|
from,
|
|
3175
3062
|
to,
|
|
3176
3063
|
enter: (node) => {
|
|
3177
3064
|
if (Object.hasOwn(Textblocks, node.name)) {
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
} else {
|
|
3185
|
-
cutStyles.push(sNode);
|
|
3186
|
-
}
|
|
3187
|
-
} else if (node.from >= from && node.to > to) {
|
|
3188
|
-
if (sNode.lastChild.from === to) {
|
|
3189
|
-
to = node.to;
|
|
3190
|
-
} else {
|
|
3191
|
-
cutStyles.push(sNode);
|
|
3192
|
-
}
|
|
3065
|
+
if (from >= node.from && to <= node.to) {
|
|
3066
|
+
blockFrom = node.from;
|
|
3067
|
+
blockTo = node.to;
|
|
3068
|
+
} else {
|
|
3069
|
+
blockFrom = Math.min(blockFrom, state2.doc.lineAt(node.from).from);
|
|
3070
|
+
blockTo = Math.max(blockTo, state2.doc.lineAt(node.to).to);
|
|
3193
3071
|
}
|
|
3194
3072
|
}
|
|
3195
3073
|
}
|
|
3196
3074
|
});
|
|
3197
|
-
if (
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
};
|
|
3205
|
-
}
|
|
3206
|
-
const changes2 = [];
|
|
3207
|
-
const changesAfter = [];
|
|
3208
|
-
removeLinkInner(from, to, changesAfter, state2);
|
|
3209
|
-
let cursorOffset = 1;
|
|
3210
|
-
for (const style of cutStyles) {
|
|
3211
|
-
const type = InlineMarker[style.name];
|
|
3212
|
-
const mark2 = inlineMarkerText(type);
|
|
3213
|
-
if (style.from < from) {
|
|
3214
|
-
changes2.push({
|
|
3215
|
-
from: skipSpaces(from, state2.doc, -1),
|
|
3216
|
-
insert: mark2
|
|
3217
|
-
});
|
|
3218
|
-
changesAfter.push({
|
|
3219
|
-
from: skipSpaces(from, state2.doc, 1, to),
|
|
3220
|
-
insert: mark2
|
|
3221
|
-
});
|
|
3222
|
-
} else {
|
|
3223
|
-
changes2.push({
|
|
3224
|
-
from: skipSpaces(to, state2.doc, -1, from),
|
|
3225
|
-
insert: mark2
|
|
3226
|
-
});
|
|
3227
|
-
const after = skipSpaces(to, state2.doc, 1);
|
|
3228
|
-
if (after === to) {
|
|
3229
|
-
cursorOffset += mark2.length;
|
|
3230
|
-
}
|
|
3231
|
-
changesAfter.push({
|
|
3232
|
-
from: after,
|
|
3233
|
-
insert: mark2
|
|
3234
|
-
});
|
|
3235
|
-
}
|
|
3075
|
+
if (ranges.length && ranges[ranges.length - 1].to >= blockFrom - 1) {
|
|
3076
|
+
ranges[ranges.length - 1].to = blockTo;
|
|
3077
|
+
} else {
|
|
3078
|
+
ranges.push({
|
|
3079
|
+
from: blockFrom,
|
|
3080
|
+
to: blockTo
|
|
3081
|
+
});
|
|
3236
3082
|
}
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3083
|
+
}
|
|
3084
|
+
if (!ranges.length) {
|
|
3085
|
+
return false;
|
|
3086
|
+
}
|
|
3087
|
+
const changes = ranges.map(({ from, to }) => {
|
|
3088
|
+
const column = from - state2.doc.lineAt(from).from;
|
|
3089
|
+
return [
|
|
3090
|
+
{
|
|
3091
|
+
from,
|
|
3092
|
+
insert: "```\n" + " ".repeat(column)
|
|
3093
|
+
},
|
|
3094
|
+
{
|
|
3095
|
+
from: to,
|
|
3096
|
+
insert: "\n" + " ".repeat(column) + "```"
|
|
3097
|
+
}
|
|
3098
|
+
];
|
|
3249
3099
|
});
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
dispatch(state2.update(changes, {
|
|
3254
|
-
userEvent: "format.link.add",
|
|
3100
|
+
dispatch(state2.update({
|
|
3101
|
+
changes,
|
|
3102
|
+
userEvent: "format.codeblock.add",
|
|
3255
3103
|
scrollIntoView: true
|
|
3256
3104
|
}));
|
|
3257
3105
|
return true;
|
|
3258
3106
|
};
|
|
3259
|
-
var
|
|
3107
|
+
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3108
|
+
const changes = [];
|
|
3260
3109
|
let lastBlock = -1;
|
|
3261
|
-
let counter = 1;
|
|
3262
|
-
let first = true;
|
|
3263
|
-
let parentColumn = null;
|
|
3264
|
-
const blocks = [];
|
|
3265
3110
|
for (const { from, to } of state2.selection.ranges) {
|
|
3266
|
-
|
|
3111
|
+
syntaxTree(state2).iterate({
|
|
3267
3112
|
from,
|
|
3268
3113
|
to,
|
|
3269
3114
|
enter: (node) => {
|
|
3270
|
-
if (
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3115
|
+
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
3116
|
+
lastBlock = node.from;
|
|
3117
|
+
const firstLine = state2.doc.lineAt(node.from);
|
|
3118
|
+
if (node.name === "FencedCode") {
|
|
3119
|
+
changes.push({
|
|
3120
|
+
from: node.from,
|
|
3121
|
+
to: firstLine.to + 1 + node.from - firstLine.from
|
|
3122
|
+
});
|
|
3123
|
+
const lastLine = state2.doc.lineAt(node.to);
|
|
3124
|
+
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
3125
|
+
changes.push({
|
|
3126
|
+
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
3127
|
+
to: lastLine.to
|
|
3128
|
+
});
|
|
3275
3129
|
}
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
counter = +mark2[1] + 1;
|
|
3286
|
-
}
|
|
3130
|
+
} else {
|
|
3131
|
+
const column = node.from - firstLine.from;
|
|
3132
|
+
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3133
|
+
changes.push({
|
|
3134
|
+
from: line.from + column - 4,
|
|
3135
|
+
to: line.from + column
|
|
3136
|
+
});
|
|
3137
|
+
if (line.to >= node.to) {
|
|
3138
|
+
break;
|
|
3287
3139
|
}
|
|
3288
3140
|
}
|
|
3289
|
-
first = false;
|
|
3290
3141
|
}
|
|
3291
|
-
if (node.from === lastBlock) {
|
|
3292
|
-
return;
|
|
3293
|
-
}
|
|
3294
|
-
lastBlock = node.from;
|
|
3295
|
-
blocks.push({
|
|
3296
|
-
node: node.node,
|
|
3297
|
-
counter,
|
|
3298
|
-
parentColumn
|
|
3299
|
-
});
|
|
3300
|
-
counter++;
|
|
3301
|
-
return false;
|
|
3302
|
-
}
|
|
3303
|
-
},
|
|
3304
|
-
leave: (node) => {
|
|
3305
|
-
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
3306
|
-
counter = 1;
|
|
3307
|
-
parentColumn = null;
|
|
3308
3142
|
}
|
|
3309
3143
|
}
|
|
3310
3144
|
});
|
|
3311
3145
|
}
|
|
3312
|
-
if (!
|
|
3313
|
-
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
3314
|
-
if (from === to) {
|
|
3315
|
-
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
3316
|
-
dispatch(state2.update({
|
|
3317
|
-
changes: [
|
|
3318
|
-
{
|
|
3319
|
-
from,
|
|
3320
|
-
insert
|
|
3321
|
-
}
|
|
3322
|
-
],
|
|
3323
|
-
selection: {
|
|
3324
|
-
anchor: from + insert.length
|
|
3325
|
-
},
|
|
3326
|
-
userEvent: "format.list.add",
|
|
3327
|
-
scrollIntoView: true
|
|
3328
|
-
}));
|
|
3329
|
-
return true;
|
|
3330
|
-
}
|
|
3146
|
+
if (!changes.length) {
|
|
3331
3147
|
return false;
|
|
3332
3148
|
}
|
|
3333
|
-
const changes = [];
|
|
3334
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
3335
|
-
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
3336
|
-
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
3337
|
-
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
3338
|
-
if (type === 0) {
|
|
3339
|
-
padding += String(counter2).length;
|
|
3340
|
-
}
|
|
3341
|
-
let line = state2.doc.lineAt(nodeFrom);
|
|
3342
|
-
const column = nodeFrom - line.from;
|
|
3343
|
-
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
3344
|
-
padding = Math.max(padding, parentColumn2 - column);
|
|
3345
|
-
}
|
|
3346
|
-
let mark2;
|
|
3347
|
-
if (type === 0) {
|
|
3348
|
-
let max = counter2;
|
|
3349
|
-
for (let j = i + 1; j < blocks.length; j++) {
|
|
3350
|
-
if (blocks[j].counter !== max + 1) {
|
|
3351
|
-
break;
|
|
3352
|
-
}
|
|
3353
|
-
max++;
|
|
3354
|
-
}
|
|
3355
|
-
const num = String(counter2);
|
|
3356
|
-
padding = Math.max(String(max).length, padding);
|
|
3357
|
-
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
3358
|
-
} else {
|
|
3359
|
-
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
3360
|
-
}
|
|
3361
|
-
changes.push({
|
|
3362
|
-
from: nodeFrom,
|
|
3363
|
-
insert: mark2
|
|
3364
|
-
});
|
|
3365
|
-
while (line.to < node.to) {
|
|
3366
|
-
line = state2.doc.lineAt(line.to + 1);
|
|
3367
|
-
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
3368
|
-
changes.push({
|
|
3369
|
-
from: line.from + Math.min(open, column),
|
|
3370
|
-
insert: " ".repeat(mark2.length)
|
|
3371
|
-
});
|
|
3372
|
-
}
|
|
3373
|
-
}
|
|
3374
|
-
if (type === 0) {
|
|
3375
|
-
const last = blocks[blocks.length - 1];
|
|
3376
|
-
let next = last.node.nextSibling;
|
|
3377
|
-
while (next && /Mark$/.test(next.name)) {
|
|
3378
|
-
next = next.nextSibling;
|
|
3379
|
-
}
|
|
3380
|
-
if (next?.name === "OrderedList") {
|
|
3381
|
-
renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
|
|
3382
|
-
}
|
|
3383
|
-
}
|
|
3384
|
-
const changeSet = state2.changes(changes);
|
|
3385
3149
|
dispatch(state2.update({
|
|
3386
|
-
changes
|
|
3387
|
-
|
|
3388
|
-
userEvent: "format.list.add",
|
|
3150
|
+
changes,
|
|
3151
|
+
userEvent: "format.codeblock.remove",
|
|
3389
3152
|
scrollIntoView: true
|
|
3390
3153
|
}));
|
|
3391
3154
|
return true;
|
|
3392
3155
|
};
|
|
3393
|
-
var
|
|
3394
|
-
|
|
3395
|
-
|
|
3156
|
+
var toggleCodeblock = (target) => {
|
|
3157
|
+
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3158
|
+
};
|
|
3159
|
+
var formattingKeymap = (options = {}) => {
|
|
3160
|
+
return [
|
|
3161
|
+
keymap6.of([
|
|
3162
|
+
{
|
|
3163
|
+
key: "meta-b",
|
|
3164
|
+
run: toggleStrong
|
|
3165
|
+
}
|
|
3166
|
+
])
|
|
3167
|
+
];
|
|
3168
|
+
};
|
|
3169
|
+
var InlineMarker = {
|
|
3170
|
+
Emphasis: 1,
|
|
3171
|
+
StrongEmphasis: 0,
|
|
3172
|
+
InlineCode: 3,
|
|
3173
|
+
Strikethrough: 2
|
|
3174
|
+
};
|
|
3175
|
+
var IgnoreInline = /* @__PURE__ */ new Set([
|
|
3176
|
+
"Autolink",
|
|
3177
|
+
"CodeMark",
|
|
3178
|
+
"CodeText",
|
|
3179
|
+
"Comment",
|
|
3180
|
+
"EmphasisMark",
|
|
3181
|
+
"Hardbreak",
|
|
3182
|
+
"HeaderMark",
|
|
3183
|
+
"HTMLTag",
|
|
3184
|
+
"LinkMark",
|
|
3185
|
+
"ListMark",
|
|
3186
|
+
"ProcessingInstruction",
|
|
3187
|
+
"QuoteMark",
|
|
3188
|
+
"StrikethroughMark",
|
|
3189
|
+
"SubscriptMark",
|
|
3190
|
+
"SuperscriptMark",
|
|
3191
|
+
"TaskMarker"
|
|
3192
|
+
]);
|
|
3193
|
+
var Textblocks = {
|
|
3194
|
+
ATXHeading1: "heading1",
|
|
3195
|
+
ATXHeading2: "heading2",
|
|
3196
|
+
ATXHeading3: "heading3",
|
|
3197
|
+
ATXHeading4: "heading4",
|
|
3198
|
+
ATXHeading5: "heading5",
|
|
3199
|
+
ATXHeading6: "heading6",
|
|
3200
|
+
CodeBlock: "codeblock",
|
|
3201
|
+
FencedCode: "codeblock",
|
|
3202
|
+
Paragraph: "paragraph",
|
|
3203
|
+
SetextHeading1: "heading1",
|
|
3204
|
+
SetextHeading2: "heading2",
|
|
3205
|
+
TableCell: "tablecell",
|
|
3206
|
+
Task: "paragraph"
|
|
3207
|
+
};
|
|
3208
|
+
var getFormatting = (state2) => {
|
|
3209
|
+
let blockType = null;
|
|
3210
|
+
const inline = [
|
|
3211
|
+
null,
|
|
3212
|
+
null,
|
|
3213
|
+
null,
|
|
3214
|
+
null
|
|
3215
|
+
];
|
|
3216
|
+
let link = false;
|
|
3217
|
+
let blockQuote = null;
|
|
3218
|
+
let listStyle = null;
|
|
3396
3219
|
const stack = [];
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3220
|
+
let currentBlock = null;
|
|
3221
|
+
const advanceInline = (upto) => {
|
|
3222
|
+
if (!currentBlock) {
|
|
3223
|
+
return;
|
|
3224
|
+
}
|
|
3225
|
+
upto = Math.min(upto, currentBlock.end);
|
|
3226
|
+
if (upto <= currentBlock.pos) {
|
|
3227
|
+
return;
|
|
3228
|
+
}
|
|
3229
|
+
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
3230
|
+
if (inline[i] === false) {
|
|
3231
|
+
continue;
|
|
3232
|
+
} else if (currentBlock.active[i]) {
|
|
3233
|
+
inline[i] = true;
|
|
3234
|
+
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3235
|
+
inline[i] = false;
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
currentBlock.pos = upto;
|
|
3239
|
+
};
|
|
3240
|
+
const skipInline = (upto) => {
|
|
3241
|
+
if (currentBlock && upto > currentBlock.pos) {
|
|
3242
|
+
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3243
|
+
}
|
|
3244
|
+
};
|
|
3245
|
+
const { selection } = state2;
|
|
3246
|
+
for (const range of selection.ranges) {
|
|
3247
|
+
if (range.empty && inline.some((v) => v === null)) {
|
|
3248
|
+
const contextSize = Math.min(range.head, 6);
|
|
3249
|
+
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3250
|
+
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3251
|
+
for (let i = 0; i < contextSize; i++) {
|
|
3252
|
+
const ch = contextAfter[i];
|
|
3253
|
+
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
3254
|
+
contextAfter = contextAfter.slice(0, i);
|
|
3255
|
+
break;
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
for (let i = 0; i < inline.length; i++) {
|
|
3259
|
+
const mark2 = inlineMarkerText(i);
|
|
3260
|
+
const found = contextAfter.indexOf(mark2);
|
|
3261
|
+
if (found > -1) {
|
|
3262
|
+
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
3263
|
+
if (inline[i] === null) {
|
|
3264
|
+
inline[i] = true;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
syntaxTree(state2).iterate({
|
|
3270
|
+
from: range.from,
|
|
3271
|
+
to: range.to,
|
|
3402
3272
|
enter: (node) => {
|
|
3273
|
+
advanceInline(node.from);
|
|
3403
3274
|
const { name } = node;
|
|
3404
3275
|
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3405
3276
|
stack.push(name);
|
|
3406
|
-
} else if (name === "
|
|
3407
|
-
|
|
3277
|
+
} else if (name === "Link") {
|
|
3278
|
+
link = true;
|
|
3279
|
+
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
3280
|
+
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
3281
|
+
stack[stack.length - 1] = "TaskList";
|
|
3282
|
+
}
|
|
3283
|
+
const blockCode = Textblocks[name];
|
|
3284
|
+
if (blockType === null) {
|
|
3285
|
+
blockType = blockCode;
|
|
3286
|
+
} else if (blockType !== blockCode) {
|
|
3287
|
+
blockType = false;
|
|
3288
|
+
}
|
|
3289
|
+
if (blockCode !== "codeblock" && inline.some((i) => i !== false)) {
|
|
3290
|
+
currentBlock = {
|
|
3291
|
+
pos: Math.max(range.from, node.from),
|
|
3292
|
+
end: Math.min(range.to, node.to),
|
|
3293
|
+
active: [
|
|
3294
|
+
false,
|
|
3295
|
+
false,
|
|
3296
|
+
false,
|
|
3297
|
+
false
|
|
3298
|
+
]
|
|
3299
|
+
};
|
|
3300
|
+
}
|
|
3301
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3302
|
+
const index = InlineMarker[name];
|
|
3303
|
+
if (range.empty && inline[index] === null) {
|
|
3304
|
+
inline[index] = true;
|
|
3305
|
+
}
|
|
3306
|
+
currentBlock.active[index] = true;
|
|
3307
|
+
} else if (IgnoreInline.has(name)) {
|
|
3308
|
+
skipInline(node.to);
|
|
3408
3309
|
}
|
|
3409
3310
|
},
|
|
3410
3311
|
leave: (node) => {
|
|
3312
|
+
advanceInline(node.to);
|
|
3411
3313
|
const { name } = node;
|
|
3412
3314
|
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3413
3315
|
stack.pop();
|
|
3414
|
-
} else if (
|
|
3415
|
-
|
|
3416
|
-
let
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
changes.push({
|
|
3423
|
-
from: node.from,
|
|
3424
|
-
to: node.from + mark2[0].length
|
|
3425
|
-
});
|
|
3426
|
-
while (line.to < node.to) {
|
|
3427
|
-
line = state2.doc.lineAt(line.to + 1);
|
|
3428
|
-
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
3429
|
-
if (open > column) {
|
|
3430
|
-
changes.push({
|
|
3431
|
-
from: line.from + column,
|
|
3432
|
-
to: line.from + Math.min(column + mark2[0].length, open)
|
|
3433
|
-
});
|
|
3316
|
+
} else if (Object.hasOwn(Textblocks, name)) {
|
|
3317
|
+
let hasList = false;
|
|
3318
|
+
let hasQuote = false;
|
|
3319
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3320
|
+
if (stack[i] === "Blockquote") {
|
|
3321
|
+
hasQuote = true;
|
|
3322
|
+
} else if (!hasList) {
|
|
3323
|
+
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
3434
3324
|
}
|
|
3435
3325
|
}
|
|
3436
|
-
if (
|
|
3437
|
-
|
|
3326
|
+
if (blockQuote === null) {
|
|
3327
|
+
blockQuote = hasQuote;
|
|
3328
|
+
} else if (!hasQuote && blockQuote) {
|
|
3329
|
+
blockQuote = false;
|
|
3438
3330
|
}
|
|
3439
|
-
|
|
3331
|
+
if (listStyle === null) {
|
|
3332
|
+
listStyle = hasList;
|
|
3333
|
+
} else if (listStyle !== hasList) {
|
|
3334
|
+
listStyle = false;
|
|
3335
|
+
}
|
|
3336
|
+
currentBlock = null;
|
|
3337
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3338
|
+
currentBlock.active[InlineMarker[name]] = false;
|
|
3440
3339
|
}
|
|
3441
3340
|
}
|
|
3442
3341
|
});
|
|
3443
3342
|
}
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
return (active ? removeList(type) : addList(type))(target);
|
|
3343
|
+
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3344
|
+
const blankLine = from === to;
|
|
3345
|
+
return {
|
|
3346
|
+
blankLine,
|
|
3347
|
+
blockType: blockType || null,
|
|
3348
|
+
blockQuote: blockQuote ?? false,
|
|
3349
|
+
code: inline[3] ?? false,
|
|
3350
|
+
emphasis: inline[1] ?? false,
|
|
3351
|
+
strong: inline[0] ?? false,
|
|
3352
|
+
strikethrough: inline[2] ?? false,
|
|
3353
|
+
link,
|
|
3354
|
+
listStyle: listStyle || null
|
|
3355
|
+
};
|
|
3458
3356
|
};
|
|
3459
|
-
var
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
from: item.from + Math.max(0, size - newNum.length),
|
|
3470
|
-
to: item.from + size,
|
|
3471
|
-
insert: newNum
|
|
3357
|
+
var useFormattingState = () => {
|
|
3358
|
+
const [state2, setState] = useState();
|
|
3359
|
+
const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
|
|
3360
|
+
if (update2.docChanged || update2.selectionSet) {
|
|
3361
|
+
setState((prevState) => {
|
|
3362
|
+
const newState = getFormatting(update2.state);
|
|
3363
|
+
if (!prevState || !formattingEquals(prevState, newState)) {
|
|
3364
|
+
return newState;
|
|
3365
|
+
}
|
|
3366
|
+
return prevState;
|
|
3472
3367
|
});
|
|
3473
|
-
counter++;
|
|
3474
3368
|
}
|
|
3475
|
-
}
|
|
3369
|
+
}), [
|
|
3370
|
+
setState
|
|
3371
|
+
]);
|
|
3372
|
+
return [
|
|
3373
|
+
state2,
|
|
3374
|
+
observer
|
|
3375
|
+
];
|
|
3476
3376
|
};
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
lines.push(line);
|
|
3520
|
-
}
|
|
3377
|
+
|
|
3378
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/action.ts
|
|
3379
|
+
var processAction = (view, action) => {
|
|
3380
|
+
let inlineType, listType;
|
|
3381
|
+
switch (action.type) {
|
|
3382
|
+
case "heading":
|
|
3383
|
+
setHeading(parseInt(action.data))(view);
|
|
3384
|
+
break;
|
|
3385
|
+
case "strong":
|
|
3386
|
+
case "emphasis":
|
|
3387
|
+
case "strikethrough":
|
|
3388
|
+
case "code":
|
|
3389
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
3390
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3391
|
+
break;
|
|
3392
|
+
case "list-ordered":
|
|
3393
|
+
case "list-bullet":
|
|
3394
|
+
case "list-task":
|
|
3395
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3396
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3397
|
+
break;
|
|
3398
|
+
case "blockquote":
|
|
3399
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3400
|
+
break;
|
|
3401
|
+
case "codeblock":
|
|
3402
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3403
|
+
break;
|
|
3404
|
+
case "table":
|
|
3405
|
+
insertTable(view);
|
|
3406
|
+
break;
|
|
3407
|
+
case "link":
|
|
3408
|
+
(action.data === false ? removeLink : addLink())(view);
|
|
3409
|
+
break;
|
|
3410
|
+
case "image":
|
|
3411
|
+
addLink({
|
|
3412
|
+
url: action.data,
|
|
3413
|
+
image: true
|
|
3414
|
+
})(view);
|
|
3415
|
+
break;
|
|
3416
|
+
case "comment":
|
|
3417
|
+
createComment(view);
|
|
3418
|
+
break;
|
|
3521
3419
|
}
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3420
|
+
requestAnimationFrame(() => {
|
|
3421
|
+
if (!view.hasFocus) {
|
|
3422
|
+
view.focus();
|
|
3423
|
+
}
|
|
3424
|
+
});
|
|
3425
|
+
};
|
|
3426
|
+
|
|
3427
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3428
|
+
import { completionKeymap as completionKeymap2 } from "@codemirror/autocomplete";
|
|
3429
|
+
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
3430
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
3431
|
+
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3432
|
+
import { languages } from "@codemirror/language-data";
|
|
3433
|
+
import { lintKeymap } from "@codemirror/lint";
|
|
3434
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
3435
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
3436
|
+
|
|
3437
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
3438
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
3439
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
3440
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
3441
|
+
import { Table } from "@lezer/markdown";
|
|
3442
|
+
var markdownTags = {
|
|
3443
|
+
Blockquote: Tag.define(),
|
|
3444
|
+
CodeMark: Tag.define(),
|
|
3445
|
+
CodeText: Tag.define(),
|
|
3446
|
+
EmphasisMark: Tag.define(),
|
|
3447
|
+
HeaderMark: Tag.define(),
|
|
3448
|
+
InlineCode: Tag.define(),
|
|
3449
|
+
LinkLabel: Tag.define(),
|
|
3450
|
+
LinkReference: Tag.define(),
|
|
3451
|
+
ListMark: Tag.define(),
|
|
3452
|
+
QuoteMark: Tag.define(),
|
|
3453
|
+
URL: Tag.define(),
|
|
3454
|
+
// Custom.
|
|
3455
|
+
TableCell: Tag.define()
|
|
3456
|
+
};
|
|
3457
|
+
Table.defineNodes?.forEach((node) => {
|
|
3458
|
+
switch (node?.name) {
|
|
3459
|
+
case "TableCell": {
|
|
3460
|
+
node.style = markdownTags.TableCell;
|
|
3461
|
+
break;
|
|
3537
3462
|
}
|
|
3538
3463
|
}
|
|
3539
|
-
|
|
3540
|
-
|
|
3464
|
+
});
|
|
3465
|
+
var markdownTagsExtensions = [
|
|
3466
|
+
Table,
|
|
3467
|
+
{
|
|
3468
|
+
props: [
|
|
3469
|
+
styleTags(markdownTags)
|
|
3470
|
+
]
|
|
3541
3471
|
}
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3472
|
+
];
|
|
3473
|
+
var markdownHighlightStyle = (readonly) => {
|
|
3474
|
+
return HighlightStyle.define([
|
|
3475
|
+
{
|
|
3476
|
+
tag: [
|
|
3477
|
+
tags.keyword,
|
|
3478
|
+
tags.name,
|
|
3479
|
+
tags.deleted,
|
|
3480
|
+
tags.character,
|
|
3481
|
+
tags.propertyName,
|
|
3482
|
+
tags.macroName,
|
|
3483
|
+
tags.color,
|
|
3484
|
+
tags.constant(tags.name),
|
|
3485
|
+
tags.standard(tags.name),
|
|
3486
|
+
tags.definition(tags.name),
|
|
3487
|
+
tags.separator,
|
|
3488
|
+
tags.typeName,
|
|
3489
|
+
tags.className,
|
|
3490
|
+
tags.number,
|
|
3491
|
+
tags.changed,
|
|
3492
|
+
tags.annotation,
|
|
3493
|
+
tags.modifier,
|
|
3494
|
+
tags.self,
|
|
3495
|
+
tags.namespace,
|
|
3496
|
+
tags.operator,
|
|
3497
|
+
tags.operatorKeyword,
|
|
3498
|
+
tags.escape,
|
|
3499
|
+
tags.regexp,
|
|
3500
|
+
tags.special(tags.string),
|
|
3501
|
+
tags.meta,
|
|
3502
|
+
tags.comment,
|
|
3503
|
+
tags.atom,
|
|
3504
|
+
tags.bool,
|
|
3505
|
+
tags.special(tags.variableName),
|
|
3506
|
+
tags.processingInstruction,
|
|
3507
|
+
tags.string,
|
|
3508
|
+
tags.inserted,
|
|
3509
|
+
tags.invalid
|
|
3510
|
+
],
|
|
3511
|
+
color: "inherit !important"
|
|
3512
|
+
},
|
|
3513
|
+
// Markdown marks.
|
|
3514
|
+
{
|
|
3515
|
+
tag: [
|
|
3516
|
+
tags.meta,
|
|
3517
|
+
tags.processingInstruction,
|
|
3518
|
+
markdownTags.LinkLabel,
|
|
3519
|
+
markdownTags.LinkReference,
|
|
3520
|
+
markdownTags.ListMark
|
|
3521
|
+
],
|
|
3522
|
+
class: mark
|
|
3523
|
+
},
|
|
3524
|
+
// Markdown marks.
|
|
3525
|
+
{
|
|
3526
|
+
tag: [
|
|
3527
|
+
markdownTags.CodeMark,
|
|
3528
|
+
markdownTags.HeaderMark,
|
|
3529
|
+
markdownTags.QuoteMark,
|
|
3530
|
+
markdownTags.EmphasisMark
|
|
3531
|
+
],
|
|
3532
|
+
class: mark
|
|
3533
|
+
},
|
|
3534
|
+
// E.g., code block language (after ```).
|
|
3535
|
+
{
|
|
3536
|
+
tag: [
|
|
3537
|
+
tags.function(tags.variableName),
|
|
3538
|
+
tags.labelName
|
|
3539
|
+
],
|
|
3540
|
+
class: codeMark
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
tag: [
|
|
3544
|
+
tags.monospace
|
|
3545
|
+
],
|
|
3546
|
+
class: "font-mono"
|
|
3547
|
+
},
|
|
3548
|
+
// Headings.
|
|
3549
|
+
{
|
|
3550
|
+
tag: tags.heading1,
|
|
3551
|
+
class: heading(1)
|
|
3552
|
+
},
|
|
3553
|
+
{
|
|
3554
|
+
tag: tags.heading2,
|
|
3555
|
+
class: heading(2)
|
|
3556
|
+
},
|
|
3557
|
+
{
|
|
3558
|
+
tag: tags.heading3,
|
|
3559
|
+
class: heading(3)
|
|
3560
|
+
},
|
|
3561
|
+
{
|
|
3562
|
+
tag: tags.heading4,
|
|
3563
|
+
class: heading(4)
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
tag: tags.heading5,
|
|
3567
|
+
class: heading(5)
|
|
3568
|
+
},
|
|
3569
|
+
{
|
|
3570
|
+
tag: tags.heading6,
|
|
3571
|
+
class: heading(6)
|
|
3572
|
+
},
|
|
3573
|
+
// Emphasis.
|
|
3574
|
+
{
|
|
3575
|
+
tag: tags.emphasis,
|
|
3576
|
+
class: italic
|
|
3577
|
+
},
|
|
3578
|
+
{
|
|
3579
|
+
tag: tags.strong,
|
|
3580
|
+
class: bold
|
|
3581
|
+
},
|
|
3582
|
+
{
|
|
3583
|
+
tag: tags.strikethrough,
|
|
3584
|
+
class: strikethrough
|
|
3585
|
+
},
|
|
3586
|
+
// Naked URLs.
|
|
3587
|
+
{
|
|
3588
|
+
tag: [
|
|
3589
|
+
markdownTags.URL
|
|
3590
|
+
],
|
|
3591
|
+
class: inlineUrl
|
|
3592
|
+
},
|
|
3593
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
3594
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
3595
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
3596
|
+
// the code, but all other CSS properties will be inherited.
|
|
3597
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
3598
|
+
{
|
|
3599
|
+
tag: [
|
|
3600
|
+
markdownTags.CodeText,
|
|
3601
|
+
markdownTags.InlineCode
|
|
3602
|
+
],
|
|
3603
|
+
class: code
|
|
3604
|
+
},
|
|
3605
|
+
{
|
|
3606
|
+
tag: [
|
|
3607
|
+
markdownTags.QuoteMark
|
|
3608
|
+
],
|
|
3609
|
+
class: blockquote
|
|
3610
|
+
},
|
|
3611
|
+
{
|
|
3612
|
+
tag: [
|
|
3613
|
+
markdownTags.TableCell
|
|
3614
|
+
],
|
|
3615
|
+
class: "font-mono"
|
|
3616
|
+
}
|
|
3617
|
+
], {
|
|
3618
|
+
scope: markdownLanguage2,
|
|
3619
|
+
all: {
|
|
3620
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3550
3623
|
};
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
var
|
|
3554
|
-
return
|
|
3624
|
+
|
|
3625
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3626
|
+
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
3627
|
+
return [
|
|
3628
|
+
// Main extension.
|
|
3629
|
+
// https://github.com/codemirror/lang-markdown
|
|
3630
|
+
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
3631
|
+
markdown({
|
|
3632
|
+
// GRM by default (vs strict CommonMark):
|
|
3633
|
+
// Table, TaskList, Strikethrough, and Autolink.
|
|
3634
|
+
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
3635
|
+
// https://github.github.com/gfm
|
|
3636
|
+
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
3637
|
+
base: markdownLanguage3,
|
|
3638
|
+
// Languages for syntax highlighting fenced code blocks.
|
|
3639
|
+
codeLanguages: languages,
|
|
3640
|
+
// Parser extensions.
|
|
3641
|
+
extensions: [
|
|
3642
|
+
// GFM provided by default.
|
|
3643
|
+
markdownTagsExtensions
|
|
3644
|
+
]
|
|
3645
|
+
}),
|
|
3646
|
+
// https://github.com/codemirror/theme-one-dark
|
|
3647
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
3648
|
+
// Custom styles.
|
|
3649
|
+
syntaxHighlighting(markdownHighlightStyle()),
|
|
3650
|
+
keymap7.of([
|
|
3651
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
3652
|
+
indentWithTab2,
|
|
3653
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
3654
|
+
...defaultKeymap2,
|
|
3655
|
+
...completionKeymap2,
|
|
3656
|
+
...lintKeymap
|
|
3657
|
+
])
|
|
3658
|
+
];
|
|
3555
3659
|
};
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3660
|
+
|
|
3661
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
3662
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3663
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
3664
|
+
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
3665
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
3666
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
3667
|
+
toDOM() {
|
|
3668
|
+
const el = document.createElement("span");
|
|
3669
|
+
el.className = "cm-hr";
|
|
3670
|
+
return el;
|
|
3566
3671
|
}
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
to,
|
|
3574
|
-
enter: (node) => {
|
|
3575
|
-
if (Object.hasOwn(Textblocks, node.name)) {
|
|
3576
|
-
if (from >= node.from && to <= node.to) {
|
|
3577
|
-
blockFrom = node.from;
|
|
3578
|
-
blockTo = node.to;
|
|
3579
|
-
} else {
|
|
3580
|
-
blockFrom = Math.min(blockFrom, state2.doc.lineAt(node.from).from);
|
|
3581
|
-
blockTo = Math.max(blockTo, state2.doc.lineAt(node.to).to);
|
|
3582
|
-
}
|
|
3583
|
-
}
|
|
3584
|
-
}
|
|
3585
|
-
});
|
|
3586
|
-
if (ranges.length && ranges[ranges.length - 1].to >= blockFrom - 1) {
|
|
3587
|
-
ranges[ranges.length - 1].to = blockTo;
|
|
3588
|
-
} else {
|
|
3589
|
-
ranges.push({
|
|
3590
|
-
from: blockFrom,
|
|
3591
|
-
to: blockTo
|
|
3592
|
-
});
|
|
3593
|
-
}
|
|
3672
|
+
};
|
|
3673
|
+
var LinkButton = class extends WidgetType3 {
|
|
3674
|
+
constructor(url, render) {
|
|
3675
|
+
super();
|
|
3676
|
+
this.url = url;
|
|
3677
|
+
this.render = render;
|
|
3594
3678
|
}
|
|
3595
|
-
|
|
3596
|
-
return
|
|
3679
|
+
eq(other) {
|
|
3680
|
+
return this.url === other.url;
|
|
3681
|
+
}
|
|
3682
|
+
toDOM(view) {
|
|
3683
|
+
const el = document.createElement("span");
|
|
3684
|
+
this.render(el, this.url);
|
|
3685
|
+
return el;
|
|
3597
3686
|
}
|
|
3598
|
-
const changes = ranges.map(({ from, to }) => {
|
|
3599
|
-
const column = from - state2.doc.lineAt(from).from;
|
|
3600
|
-
return [
|
|
3601
|
-
{
|
|
3602
|
-
from,
|
|
3603
|
-
insert: "```\n" + " ".repeat(column)
|
|
3604
|
-
},
|
|
3605
|
-
{
|
|
3606
|
-
from: to,
|
|
3607
|
-
insert: "\n" + " ".repeat(column) + "```"
|
|
3608
|
-
}
|
|
3609
|
-
];
|
|
3610
|
-
});
|
|
3611
|
-
dispatch(state2.update({
|
|
3612
|
-
changes,
|
|
3613
|
-
userEvent: "format.codeblock.add",
|
|
3614
|
-
scrollIntoView: true
|
|
3615
|
-
}));
|
|
3616
|
-
return true;
|
|
3617
3687
|
};
|
|
3618
|
-
var
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3644
|
-
changes.push({
|
|
3645
|
-
from: line.from + column - 4,
|
|
3646
|
-
to: line.from + column
|
|
3647
|
-
});
|
|
3648
|
-
if (line.to >= node.to) {
|
|
3649
|
-
break;
|
|
3650
|
-
}
|
|
3688
|
+
var CheckboxWidget = class extends WidgetType3 {
|
|
3689
|
+
constructor(_checked) {
|
|
3690
|
+
super();
|
|
3691
|
+
this._checked = _checked;
|
|
3692
|
+
}
|
|
3693
|
+
eq(other) {
|
|
3694
|
+
return this._checked === other._checked;
|
|
3695
|
+
}
|
|
3696
|
+
toDOM(view) {
|
|
3697
|
+
const input = document.createElement("input");
|
|
3698
|
+
input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
|
|
3699
|
+
input.type = "checkbox";
|
|
3700
|
+
input.checked = this._checked;
|
|
3701
|
+
if (view.state.readOnly) {
|
|
3702
|
+
input.setAttribute("disabled", "true");
|
|
3703
|
+
} else {
|
|
3704
|
+
input.onmousedown = (event) => {
|
|
3705
|
+
const pos = view.posAtDOM(input);
|
|
3706
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
3707
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
3708
|
+
view.dispatch({
|
|
3709
|
+
changes: {
|
|
3710
|
+
from: pos + 1,
|
|
3711
|
+
to: pos + 2,
|
|
3712
|
+
insert: this._checked ? " " : "x"
|
|
3651
3713
|
}
|
|
3652
|
-
}
|
|
3714
|
+
});
|
|
3715
|
+
event.preventDefault();
|
|
3653
3716
|
}
|
|
3654
|
-
}
|
|
3655
|
-
}
|
|
3717
|
+
};
|
|
3718
|
+
}
|
|
3719
|
+
return input;
|
|
3656
3720
|
}
|
|
3657
|
-
|
|
3721
|
+
ignoreEvent() {
|
|
3658
3722
|
return false;
|
|
3659
3723
|
}
|
|
3660
|
-
dispatch(state2.update({
|
|
3661
|
-
changes,
|
|
3662
|
-
userEvent: "format.codeblock.remove",
|
|
3663
|
-
scrollIntoView: true
|
|
3664
|
-
}));
|
|
3665
|
-
return true;
|
|
3666
|
-
};
|
|
3667
|
-
var toggleCodeblock = (target) => {
|
|
3668
|
-
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3669
|
-
};
|
|
3670
|
-
var formattingKeymap = (options = {}) => {
|
|
3671
|
-
return [
|
|
3672
|
-
keymap6.of([
|
|
3673
|
-
{
|
|
3674
|
-
key: "meta-b",
|
|
3675
|
-
run: toggleStrong
|
|
3676
|
-
}
|
|
3677
|
-
])
|
|
3678
|
-
];
|
|
3679
3724
|
};
|
|
3680
|
-
var
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3725
|
+
var hide = Decoration5.replace({});
|
|
3726
|
+
var fencedCodeLine = Decoration5.line({
|
|
3727
|
+
class: mx2("cm-code cm-codeblock-line")
|
|
3728
|
+
});
|
|
3729
|
+
var fencedCodeLineFirst = Decoration5.line({
|
|
3730
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
|
3731
|
+
});
|
|
3732
|
+
var fencedCodeLineLast = Decoration5.line({
|
|
3733
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
3734
|
+
});
|
|
3735
|
+
var horizontalRule = Decoration5.replace({
|
|
3736
|
+
widget: new HorizontalRuleWidget()
|
|
3737
|
+
});
|
|
3738
|
+
var checkedTask = Decoration5.replace({
|
|
3739
|
+
widget: new CheckboxWidget(true)
|
|
3740
|
+
});
|
|
3741
|
+
var uncheckedTask = Decoration5.replace({
|
|
3742
|
+
widget: new CheckboxWidget(false)
|
|
3743
|
+
});
|
|
3744
|
+
var editingRange = (state2, range, focus) => {
|
|
3745
|
+
const { readOnly, selection: { main: { head } } } = state2;
|
|
3746
|
+
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
3685
3747
|
};
|
|
3686
|
-
var
|
|
3687
|
-
"Autolink",
|
|
3748
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
3688
3749
|
"CodeMark",
|
|
3689
|
-
"CodeText",
|
|
3690
|
-
"Comment",
|
|
3691
3750
|
"EmphasisMark",
|
|
3692
|
-
"Hardbreak",
|
|
3693
|
-
"HeaderMark",
|
|
3694
|
-
"HTMLTag",
|
|
3695
|
-
"LinkMark",
|
|
3696
|
-
"ListMark",
|
|
3697
|
-
"ProcessingInstruction",
|
|
3698
|
-
"QuoteMark",
|
|
3699
3751
|
"StrikethroughMark",
|
|
3700
3752
|
"SubscriptMark",
|
|
3701
|
-
"SuperscriptMark"
|
|
3702
|
-
"TaskMarker"
|
|
3753
|
+
"SuperscriptMark"
|
|
3703
3754
|
]);
|
|
3704
|
-
var
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
let blockQuote = null;
|
|
3729
|
-
let listStyle = null;
|
|
3730
|
-
const stack = [];
|
|
3731
|
-
let currentBlock = null;
|
|
3732
|
-
const advanceInline = (upto) => {
|
|
3733
|
-
if (!currentBlock) {
|
|
3734
|
-
return;
|
|
3735
|
-
}
|
|
3736
|
-
upto = Math.min(upto, currentBlock.end);
|
|
3737
|
-
if (upto <= currentBlock.pos) {
|
|
3738
|
-
return;
|
|
3739
|
-
}
|
|
3740
|
-
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
3741
|
-
if (inline[i] === false) {
|
|
3742
|
-
continue;
|
|
3743
|
-
} else if (currentBlock.active[i]) {
|
|
3744
|
-
inline[i] = true;
|
|
3745
|
-
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3746
|
-
inline[i] = false;
|
|
3747
|
-
}
|
|
3748
|
-
}
|
|
3749
|
-
currentBlock.pos = upto;
|
|
3750
|
-
};
|
|
3751
|
-
const skipInline = (upto) => {
|
|
3752
|
-
if (currentBlock && upto > currentBlock.pos) {
|
|
3753
|
-
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3754
|
-
}
|
|
3755
|
-
};
|
|
3756
|
-
const { selection } = state2;
|
|
3757
|
-
for (const range of selection.ranges) {
|
|
3758
|
-
if (range.empty && inline.some((v) => v === null)) {
|
|
3759
|
-
const contextSize = Math.min(range.head, 6);
|
|
3760
|
-
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3761
|
-
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3762
|
-
for (let i = 0; i < contextSize; i++) {
|
|
3763
|
-
const ch = contextAfter[i];
|
|
3764
|
-
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
3765
|
-
contextAfter = contextAfter.slice(0, i);
|
|
3766
|
-
break;
|
|
3767
|
-
}
|
|
3768
|
-
}
|
|
3769
|
-
for (let i = 0; i < inline.length; i++) {
|
|
3770
|
-
const mark2 = inlineMarkerText(i);
|
|
3771
|
-
const found = contextAfter.indexOf(mark2);
|
|
3772
|
-
if (found > -1) {
|
|
3773
|
-
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
3774
|
-
if (inline[i] === null) {
|
|
3775
|
-
inline[i] = true;
|
|
3776
|
-
}
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
syntaxTree2(state2).iterate({
|
|
3781
|
-
from: range.from,
|
|
3782
|
-
to: range.to,
|
|
3783
|
-
enter: (node) => {
|
|
3784
|
-
advanceInline(node.from);
|
|
3785
|
-
const { name } = node;
|
|
3786
|
-
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3787
|
-
stack.push(name);
|
|
3788
|
-
} else if (name === "Link") {
|
|
3789
|
-
link = true;
|
|
3790
|
-
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
3791
|
-
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
3792
|
-
stack[stack.length - 1] = "TaskList";
|
|
3793
|
-
}
|
|
3794
|
-
const blockCode = Textblocks[name];
|
|
3795
|
-
if (blockType === null) {
|
|
3796
|
-
blockType = blockCode;
|
|
3797
|
-
} else if (blockType !== blockCode) {
|
|
3798
|
-
blockType = false;
|
|
3755
|
+
var buildDecorations = (view, options, focus) => {
|
|
3756
|
+
const deco = new RangeSetBuilder2();
|
|
3757
|
+
const atomicDeco = new RangeSetBuilder2();
|
|
3758
|
+
const { state: state2 } = view;
|
|
3759
|
+
for (const { from, to } of view.visibleRanges) {
|
|
3760
|
+
syntaxTree2(state2).iterate({
|
|
3761
|
+
from,
|
|
3762
|
+
to,
|
|
3763
|
+
enter: (node) => {
|
|
3764
|
+
if (node.name === "FencedCode") {
|
|
3765
|
+
const editing = editingRange(state2, node, focus);
|
|
3766
|
+
for (const block of view.viewportLineBlocks) {
|
|
3767
|
+
if (block.to < node.from) {
|
|
3768
|
+
continue;
|
|
3769
|
+
}
|
|
3770
|
+
if (block.from > node.to) {
|
|
3771
|
+
break;
|
|
3772
|
+
}
|
|
3773
|
+
const first = block.from <= node.from;
|
|
3774
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
3775
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
3776
|
+
if (!editing && (first || last)) {
|
|
3777
|
+
atomicDeco.add(block.from, block.to, hide);
|
|
3778
|
+
}
|
|
3799
3779
|
}
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3780
|
+
return false;
|
|
3781
|
+
} else if (node.name === "Link") {
|
|
3782
|
+
const marks = node.node.getChildren("LinkMark");
|
|
3783
|
+
const urlNode = node.node.getChild("URL");
|
|
3784
|
+
const editing = editingRange(state2, node, focus);
|
|
3785
|
+
if (urlNode && marks.length >= 2) {
|
|
3786
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3787
|
+
if (!editing) {
|
|
3788
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
|
3789
|
+
}
|
|
3790
|
+
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
3791
|
+
tagName: "a",
|
|
3792
|
+
attributes: {
|
|
3793
|
+
class: "cm-link",
|
|
3794
|
+
href: url,
|
|
3795
|
+
rel: "noreferrer",
|
|
3796
|
+
target: "_blank"
|
|
3797
|
+
}
|
|
3798
|
+
}));
|
|
3799
|
+
if (!editing) {
|
|
3800
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
3801
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
3802
|
+
}) : hide);
|
|
3803
|
+
}
|
|
3811
3804
|
}
|
|
3812
|
-
} else if (
|
|
3813
|
-
const
|
|
3814
|
-
if (
|
|
3815
|
-
|
|
3805
|
+
} else if (node.name === "HeaderMark") {
|
|
3806
|
+
const parent = node.node.parent;
|
|
3807
|
+
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
3808
|
+
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
3809
|
+
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
3816
3810
|
}
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
}
|
|
3821
|
-
},
|
|
3822
|
-
leave: (node) => {
|
|
3823
|
-
advanceInline(node.to);
|
|
3824
|
-
const { name } = node;
|
|
3825
|
-
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3826
|
-
stack.pop();
|
|
3827
|
-
} else if (Object.hasOwn(Textblocks, name)) {
|
|
3828
|
-
let hasList = false;
|
|
3829
|
-
let hasQuote = false;
|
|
3830
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3831
|
-
if (stack[i] === "Blockquote") {
|
|
3832
|
-
hasQuote = true;
|
|
3833
|
-
} else if (!hasList) {
|
|
3834
|
-
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
3835
|
-
}
|
|
3811
|
+
} else if (node.name === "HorizontalRule") {
|
|
3812
|
+
if (!editingRange(state2, node, focus)) {
|
|
3813
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
3836
3814
|
}
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3815
|
+
} else if (node.name === "TaskMarker") {
|
|
3816
|
+
if (!editingRange(state2, node, focus)) {
|
|
3817
|
+
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3818
|
+
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
3819
|
+
class: "cm-task"
|
|
3820
|
+
}));
|
|
3821
|
+
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
3841
3822
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
listStyle = false;
|
|
3823
|
+
} else if (MarksByParent.has(node.name)) {
|
|
3824
|
+
if (!editingRange(state2, node.node.parent, focus)) {
|
|
3825
|
+
atomicDeco.add(node.from, node.to, hide);
|
|
3846
3826
|
}
|
|
3847
|
-
currentBlock = null;
|
|
3848
|
-
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3849
|
-
currentBlock.active[InlineMarker[name]] = false;
|
|
3850
3827
|
}
|
|
3851
3828
|
}
|
|
3852
3829
|
});
|
|
3853
3830
|
}
|
|
3854
|
-
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3855
|
-
const blankLine = from === to;
|
|
3856
3831
|
return {
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
blockQuote: blockQuote ?? false,
|
|
3860
|
-
code: inline[3] ?? false,
|
|
3861
|
-
emphasis: inline[1] ?? false,
|
|
3862
|
-
strong: inline[0] ?? false,
|
|
3863
|
-
strikethrough: inline[2] ?? false,
|
|
3864
|
-
link,
|
|
3865
|
-
listStyle: listStyle || null
|
|
3832
|
+
deco: deco.finish(),
|
|
3833
|
+
atomicDeco: atomicDeco.finish()
|
|
3866
3834
|
};
|
|
3867
3835
|
};
|
|
3868
|
-
var
|
|
3869
|
-
|
|
3870
|
-
const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
|
|
3871
|
-
if (update2.docChanged || update2.selectionSet) {
|
|
3872
|
-
const newState = getFormatting(update2.state);
|
|
3873
|
-
if (!stateRef.current || !formattingEquals(stateRef.current, newState)) {
|
|
3874
|
-
setState(newState);
|
|
3875
|
-
}
|
|
3876
|
-
}
|
|
3877
|
-
}), []);
|
|
3836
|
+
var forceUpdate = StateEffect4.define();
|
|
3837
|
+
var decorateMarkdown = (options = {}) => {
|
|
3878
3838
|
return [
|
|
3879
|
-
|
|
3880
|
-
|
|
3839
|
+
ViewPlugin4.fromClass(class {
|
|
3840
|
+
constructor(view) {
|
|
3841
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
|
|
3842
|
+
}
|
|
3843
|
+
update(update2) {
|
|
3844
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
3845
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
3846
|
+
this.clearUpdate();
|
|
3847
|
+
} else if (update2.selectionSet) {
|
|
3848
|
+
this.scheduleUpdate(update2.view);
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
3852
|
+
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
3853
|
+
scheduleUpdate(view) {
|
|
3854
|
+
this.clearUpdate();
|
|
3855
|
+
this.pendingUpdate = setTimeout(() => {
|
|
3856
|
+
view.dispatch({
|
|
3857
|
+
effects: forceUpdate.of(null)
|
|
3858
|
+
});
|
|
3859
|
+
}, options.selectionChangeDelay);
|
|
3860
|
+
}
|
|
3861
|
+
clearUpdate() {
|
|
3862
|
+
if (this.pendingUpdate) {
|
|
3863
|
+
clearTimeout(this.pendingUpdate);
|
|
3864
|
+
this.pendingUpdate = void 0;
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
destroy() {
|
|
3868
|
+
this.clearUpdate();
|
|
3869
|
+
}
|
|
3870
|
+
}, {
|
|
3871
|
+
provide: (plugin) => [
|
|
3872
|
+
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3873
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3874
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
3875
|
+
]
|
|
3876
|
+
}),
|
|
3877
|
+
formattingStyles
|
|
3881
3878
|
];
|
|
3882
3879
|
};
|
|
3880
|
+
var formattingStyles = EditorView12.baseTheme({
|
|
3881
|
+
"& .cm-code": {
|
|
3882
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
3883
|
+
},
|
|
3884
|
+
"& .cm-codeblock-line": {
|
|
3885
|
+
paddingInline: "1rem !important"
|
|
3886
|
+
},
|
|
3887
|
+
"& .cm-codeblock-end": {
|
|
3888
|
+
display: "inline-block",
|
|
3889
|
+
width: "100%",
|
|
3890
|
+
position: "relative",
|
|
3891
|
+
"&::after": {
|
|
3892
|
+
position: "absolute",
|
|
3893
|
+
inset: 0,
|
|
3894
|
+
content: '""'
|
|
3895
|
+
}
|
|
3896
|
+
},
|
|
3897
|
+
"& .cm-codeblock-first": {
|
|
3898
|
+
borderTopLeftRadius: ".5rem",
|
|
3899
|
+
borderTopRightRadius: ".5rem"
|
|
3900
|
+
},
|
|
3901
|
+
"& .cm-codeblock-last": {
|
|
3902
|
+
borderBottomLeftRadius: ".5rem",
|
|
3903
|
+
borderBottomRightRadius: ".5rem"
|
|
3904
|
+
},
|
|
3905
|
+
"&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
|
|
3906
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
3907
|
+
mixBlendMode: "darken"
|
|
3908
|
+
},
|
|
3909
|
+
"&dark .cm-codeblock-line, &dark .cm-activeLine.cm-codeblock-line": {
|
|
3910
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
3911
|
+
mixBlendMode: "lighten"
|
|
3912
|
+
},
|
|
3913
|
+
"& .cm-hr": {
|
|
3914
|
+
display: "inline-block",
|
|
3915
|
+
width: "100%",
|
|
3916
|
+
height: "0",
|
|
3917
|
+
verticalAlign: "middle",
|
|
3918
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
3919
|
+
},
|
|
3920
|
+
"& .cm-task": {
|
|
3921
|
+
color: getToken("extend.colors.blue.500")
|
|
3922
|
+
},
|
|
3923
|
+
"& .cm-task-checkbox": {
|
|
3924
|
+
marginLeft: "4px",
|
|
3925
|
+
marginRight: "4px"
|
|
3926
|
+
}
|
|
3927
|
+
});
|
|
3883
3928
|
|
|
3884
3929
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3885
3930
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3886
3931
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
3887
|
-
import { Decoration as Decoration6, EditorView as
|
|
3932
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3888
3933
|
var image = (options = {}) => {
|
|
3889
3934
|
return StateField5.define({
|
|
3890
3935
|
create: (state2) => {
|
|
@@ -3911,7 +3956,7 @@ var image = (options = {}) => {
|
|
|
3911
3956
|
add: buildDecorations2(from, to, tr.state)
|
|
3912
3957
|
});
|
|
3913
3958
|
},
|
|
3914
|
-
provide: (field) =>
|
|
3959
|
+
provide: (field) => EditorView13.decorations.from(field)
|
|
3915
3960
|
});
|
|
3916
3961
|
};
|
|
3917
3962
|
var preloaded = /* @__PURE__ */ new Set();
|
|
@@ -4001,12 +4046,12 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
|
4001
4046
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
4002
4047
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4003
4048
|
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
4004
|
-
import { Decoration as Decoration7, EditorView as
|
|
4049
|
+
import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4005
4050
|
var table = (options = {}) => {
|
|
4006
4051
|
return StateField6.define({
|
|
4007
4052
|
create: (state2) => update(state2, options),
|
|
4008
4053
|
update: (_, tr) => update(tr.state, options),
|
|
4009
|
-
provide: (field) =>
|
|
4054
|
+
provide: (field) => EditorView14.decorations.from(field)
|
|
4010
4055
|
});
|
|
4011
4056
|
};
|
|
4012
4057
|
var update = (state2, options) => {
|
|
@@ -4100,8 +4145,8 @@ var TableWidget = class extends WidgetType5 {
|
|
|
4100
4145
|
|
|
4101
4146
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
4102
4147
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
4103
|
-
import { log as
|
|
4104
|
-
var
|
|
4148
|
+
import { log as log6 } from "@dxos/log";
|
|
4149
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
|
4105
4150
|
var mention = ({ onSearch }) => {
|
|
4106
4151
|
return autocompletion2({
|
|
4107
4152
|
// TODO(burdon): Not working.
|
|
@@ -4113,10 +4158,10 @@ var mention = ({ onSearch }) => {
|
|
|
4113
4158
|
icons: false,
|
|
4114
4159
|
override: [
|
|
4115
4160
|
(context) => {
|
|
4116
|
-
|
|
4161
|
+
log6.info("completion context", {
|
|
4117
4162
|
context
|
|
4118
4163
|
}, {
|
|
4119
|
-
F:
|
|
4164
|
+
F: __dxlog_file8,
|
|
4120
4165
|
L: 26,
|
|
4121
4166
|
S: void 0,
|
|
4122
4167
|
C: (f, a) => f(...a)
|
|
@@ -4138,21 +4183,30 @@ var mention = ({ onSearch }) => {
|
|
|
4138
4183
|
|
|
4139
4184
|
// packages/ui/react-ui-editor/src/extensions/modes.ts
|
|
4140
4185
|
import { Facet as Facet6 } from "@codemirror/state";
|
|
4141
|
-
import { keymap as
|
|
4186
|
+
import { keymap as keymap8 } from "@codemirror/view";
|
|
4142
4187
|
import { vim } from "@replit/codemirror-vim";
|
|
4188
|
+
import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
|
|
4143
4189
|
var focusEvent = "focus.container";
|
|
4144
4190
|
var editorMode = Facet6.define({
|
|
4145
4191
|
combine: (modes) => modes[0] ?? {}
|
|
4146
4192
|
});
|
|
4147
4193
|
var EditorModes = {
|
|
4148
4194
|
default: [],
|
|
4195
|
+
vscode: [
|
|
4196
|
+
// https://github.com/replit/codemirror-vscode-keymap
|
|
4197
|
+
editorMode.of({
|
|
4198
|
+
type: "vscode"
|
|
4199
|
+
}),
|
|
4200
|
+
keymap8.of(vscodeKeymap)
|
|
4201
|
+
],
|
|
4149
4202
|
vim: [
|
|
4203
|
+
// https://github.com/replit/codemirror-vim
|
|
4150
4204
|
vim(),
|
|
4151
4205
|
editorMode.of({
|
|
4152
4206
|
type: "vim",
|
|
4153
4207
|
noTabster: true
|
|
4154
4208
|
}),
|
|
4155
|
-
|
|
4209
|
+
keymap8.of([
|
|
4156
4210
|
{
|
|
4157
4211
|
key: "Alt-Escape",
|
|
4158
4212
|
run: (view) => {
|
|
@@ -4167,18 +4221,18 @@ var EditorModes = {
|
|
|
4167
4221
|
};
|
|
4168
4222
|
|
|
4169
4223
|
// packages/ui/react-ui-editor/src/extensions/state.ts
|
|
4170
|
-
import { Transaction
|
|
4171
|
-
import { EditorView as
|
|
4224
|
+
import { Transaction } from "@codemirror/state";
|
|
4225
|
+
import { EditorView as EditorView15, keymap as keymap9 } from "@codemirror/view";
|
|
4172
4226
|
import { debounce as debounce2 } from "@dxos/async";
|
|
4173
4227
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4174
4228
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4175
|
-
var
|
|
4229
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4176
4230
|
var scrollAnnotation = "dxos.org/cm/scrolling";
|
|
4177
4231
|
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4178
4232
|
var localStorageStateStoreAdapter = {
|
|
4179
4233
|
setState: (id, state2) => {
|
|
4180
4234
|
invariant4(id, void 0, {
|
|
4181
|
-
F:
|
|
4235
|
+
F: __dxlog_file9,
|
|
4182
4236
|
L: 35,
|
|
4183
4237
|
S: void 0,
|
|
4184
4238
|
A: [
|
|
@@ -4190,7 +4244,7 @@ var localStorageStateStoreAdapter = {
|
|
|
4190
4244
|
},
|
|
4191
4245
|
getState: (id) => {
|
|
4192
4246
|
invariant4(id, void 0, {
|
|
4193
|
-
F:
|
|
4247
|
+
F: __dxlog_file9,
|
|
4194
4248
|
L: 39,
|
|
4195
4249
|
S: void 0,
|
|
4196
4250
|
A: [
|
|
@@ -4206,7 +4260,7 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4206
4260
|
const setStateDebounced = debounce2(setState, 1e3);
|
|
4207
4261
|
return [
|
|
4208
4262
|
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4209
|
-
|
|
4263
|
+
EditorView15.updateListener.of(({ view, changes, transactions }) => {
|
|
4210
4264
|
const id = view.state.facet(documentId2);
|
|
4211
4265
|
if (!id || transactions.some((tr) => tr.isUserEvent(scrollAnnotation))) {
|
|
4212
4266
|
return;
|
|
@@ -4232,18 +4286,18 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4232
4286
|
}
|
|
4233
4287
|
}
|
|
4234
4288
|
}),
|
|
4235
|
-
getState &&
|
|
4289
|
+
getState && keymap9.of([
|
|
4236
4290
|
{
|
|
4237
4291
|
key: "ctrl-r",
|
|
4238
4292
|
run: (view) => {
|
|
4239
4293
|
const state2 = getState(view.state.facet(documentId2));
|
|
4240
4294
|
if (state2) {
|
|
4241
4295
|
view.dispatch({
|
|
4242
|
-
effects:
|
|
4296
|
+
effects: EditorView15.scrollIntoView(state2.scrollTo.from, {
|
|
4243
4297
|
yMargin: 0
|
|
4244
4298
|
}),
|
|
4245
4299
|
selection: state2.selection,
|
|
4246
|
-
annotations:
|
|
4300
|
+
annotations: Transaction.userEvent.of(scrollAnnotation)
|
|
4247
4301
|
});
|
|
4248
4302
|
}
|
|
4249
4303
|
return true;
|
|
@@ -4254,7 +4308,7 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4254
4308
|
};
|
|
4255
4309
|
|
|
4256
4310
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
4257
|
-
import { keymap as
|
|
4311
|
+
import { keymap as keymap10 } from "@codemirror/view";
|
|
4258
4312
|
var defaultItems = [
|
|
4259
4313
|
"hello world!",
|
|
4260
4314
|
"this is a test.",
|
|
@@ -4264,7 +4318,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4264
4318
|
let t;
|
|
4265
4319
|
let idx = 0;
|
|
4266
4320
|
return [
|
|
4267
|
-
|
|
4321
|
+
keymap10.of([
|
|
4268
4322
|
{
|
|
4269
4323
|
// Reset.
|
|
4270
4324
|
key: "alt-meta-'",
|
|
@@ -4311,17 +4365,17 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4311
4365
|
};
|
|
4312
4366
|
|
|
4313
4367
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4314
|
-
var
|
|
4368
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4315
4369
|
var instanceCount = 0;
|
|
4316
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo =
|
|
4370
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView16.scrollIntoView(0, {
|
|
4317
4371
|
yMargin: 0
|
|
4318
4372
|
}), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
|
|
4319
|
-
const [instanceId] =
|
|
4373
|
+
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
4320
4374
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
4321
4375
|
tabBehavior: "limited"
|
|
4322
4376
|
});
|
|
4323
4377
|
const rootRef = useRef(null);
|
|
4324
|
-
const [view, setView] =
|
|
4378
|
+
const [view, setView] = useState2(null);
|
|
4325
4379
|
useImperativeHandle(forwardedRef, () => view, [
|
|
4326
4380
|
view
|
|
4327
4381
|
]);
|
|
@@ -4334,11 +4388,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4334
4388
|
autoFocus
|
|
4335
4389
|
]);
|
|
4336
4390
|
useEffect2(() => {
|
|
4337
|
-
|
|
4391
|
+
log7("create", {
|
|
4338
4392
|
id,
|
|
4339
4393
|
instanceId
|
|
4340
4394
|
}, {
|
|
4341
|
-
F:
|
|
4395
|
+
F: __dxlog_file10,
|
|
4342
4396
|
L: 88,
|
|
4343
4397
|
S: void 0,
|
|
4344
4398
|
C: (f, a) => f(...a)
|
|
@@ -4349,16 +4403,16 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4349
4403
|
extensions: [
|
|
4350
4404
|
id && documentId2.of(id),
|
|
4351
4405
|
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
F:
|
|
4406
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4407
|
+
log7.catch(err, void 0, {
|
|
4408
|
+
F: __dxlog_file10,
|
|
4355
4409
|
L: 101,
|
|
4356
4410
|
S: void 0,
|
|
4357
4411
|
C: (f, a) => f(...a)
|
|
4358
4412
|
});
|
|
4359
4413
|
}),
|
|
4360
4414
|
// Focus.
|
|
4361
|
-
|
|
4415
|
+
EditorView16.updateListener.of((update2) => {
|
|
4362
4416
|
update2.transactions.forEach((transaction) => {
|
|
4363
4417
|
if (transaction.isUserEvent(focusEvent)) {
|
|
4364
4418
|
rootRef.current?.focus();
|
|
@@ -4368,7 +4422,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4368
4422
|
extensions
|
|
4369
4423
|
].filter(isNotFalsy4)
|
|
4370
4424
|
});
|
|
4371
|
-
const view2 = new
|
|
4425
|
+
const view2 = new EditorView16({
|
|
4372
4426
|
state: state2,
|
|
4373
4427
|
parent: rootRef.current,
|
|
4374
4428
|
scrollTo,
|
|
@@ -4394,11 +4448,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4394
4448
|
}
|
|
4395
4449
|
setView(view2);
|
|
4396
4450
|
return () => {
|
|
4397
|
-
|
|
4451
|
+
log7("destroy", {
|
|
4398
4452
|
id,
|
|
4399
4453
|
instanceId
|
|
4400
4454
|
}, {
|
|
4401
|
-
F:
|
|
4455
|
+
F: __dxlog_file10,
|
|
4402
4456
|
L: 150,
|
|
4403
4457
|
S: void 0,
|
|
4404
4458
|
C: (f, a) => f(...a)
|
|
@@ -4433,11 +4487,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4433
4487
|
});
|
|
4434
4488
|
|
|
4435
4489
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4436
|
-
import { ChatText, Code, CodeBlock, Image, Link, ListBullets, ListChecks, ListNumbers, Paragraph, Quotes, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
|
|
4490
|
+
import { ChatText, Code, CodeBlock, Image, Link, ListBullets, ListChecks, ListNumbers, Paragraph, Quotes, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, CaretDown, Check } from "@phosphor-icons/react";
|
|
4437
4491
|
import { createContext } from "@radix-ui/react-context";
|
|
4438
|
-
import React2, { useEffect as useEffect3, useRef as useRef2, useState as
|
|
4492
|
+
import React2, { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
4439
4493
|
import { useDropzone } from "react-dropzone";
|
|
4440
|
-
import { DensityProvider, ElevationProvider,
|
|
4494
|
+
import { DensityProvider, ElevationProvider, Toolbar as NaturalToolbar, Tooltip, useTranslation, DropdownMenu, Button } from "@dxos/react-ui";
|
|
4441
4495
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4442
4496
|
var tooltipProps = {
|
|
4443
4497
|
side: "top",
|
|
@@ -4508,8 +4562,8 @@ var MarkdownHeading = () => {
|
|
|
4508
4562
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4509
4563
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
4510
4564
|
const suppressNextTooltip = useRef2(false);
|
|
4511
|
-
const [tooltipOpen, setTooltipOpen] =
|
|
4512
|
-
const [selectOpen, setSelectOpen] =
|
|
4565
|
+
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
|
4566
|
+
const [selectOpen, setSelectOpen] = useState3(false);
|
|
4513
4567
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
|
|
4514
4568
|
open: tooltipOpen,
|
|
4515
4569
|
onOpenChange: (nextOpen) => {
|
|
@@ -4520,58 +4574,48 @@ var MarkdownHeading = () => {
|
|
|
4520
4574
|
return setTooltipOpen(nextOpen);
|
|
4521
4575
|
}
|
|
4522
4576
|
}
|
|
4523
|
-
}, /* @__PURE__ */ React2.createElement(
|
|
4524
|
-
disabled: value === null,
|
|
4525
|
-
value: value ?? "0",
|
|
4577
|
+
}, /* @__PURE__ */ React2.createElement(DropdownMenu.Root, {
|
|
4526
4578
|
open: selectOpen,
|
|
4527
4579
|
onOpenChange: (nextOpen) => {
|
|
4528
4580
|
if (!nextOpen) {
|
|
4529
4581
|
suppressNextTooltip.current = true;
|
|
4530
4582
|
}
|
|
4531
4583
|
return setSelectOpen(nextOpen);
|
|
4532
|
-
}
|
|
4533
|
-
onValueChange: (value2) => onAction?.({
|
|
4534
|
-
type: "heading",
|
|
4535
|
-
data: parseInt(value2)
|
|
4536
|
-
})
|
|
4584
|
+
}
|
|
4537
4585
|
}, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4538
4586
|
asChild: true
|
|
4539
4587
|
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
|
|
4540
4588
|
asChild: true
|
|
4541
|
-
}, /* @__PURE__ */ React2.createElement(
|
|
4589
|
+
}, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
|
|
4590
|
+
asChild: true
|
|
4591
|
+
}, /* @__PURE__ */ React2.createElement(Button, {
|
|
4542
4592
|
variant: "ghost",
|
|
4543
|
-
classNames: buttonStyles
|
|
4593
|
+
classNames: buttonStyles,
|
|
4594
|
+
disabled: value === null
|
|
4544
4595
|
}, /* @__PURE__ */ React2.createElement("span", {
|
|
4545
4596
|
className: "sr-only"
|
|
4546
4597
|
}, t("heading label")), /* @__PURE__ */ React2.createElement(HeadingIcon, {
|
|
4547
4598
|
className: iconStyles
|
|
4548
|
-
})
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
}), level === 4 && /* @__PURE__ */ React2.createElement(TextHFour, {
|
|
4569
|
-
className: iconStyles
|
|
4570
|
-
}), level === 5 && /* @__PURE__ */ React2.createElement(TextHFive, {
|
|
4571
|
-
className: iconStyles
|
|
4572
|
-
}), level === 6 && /* @__PURE__ */ React2.createElement(TextHSix, {
|
|
4573
|
-
className: iconStyles
|
|
4574
|
-
})))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null)))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4599
|
+
}), /* @__PURE__ */ React2.createElement(CaretDown, null))))), /* @__PURE__ */ React2.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Content, {
|
|
4600
|
+
classNames: "is-min md:is-min",
|
|
4601
|
+
onCloseAutoFocus: (e) => e.preventDefault()
|
|
4602
|
+
}, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, Object.keys(HeadingIcons).map((level) => {
|
|
4603
|
+
const Icon = HeadingIcons[level];
|
|
4604
|
+
return /* @__PURE__ */ React2.createElement(DropdownMenu.CheckboxItem, {
|
|
4605
|
+
key: level,
|
|
4606
|
+
checked: value === level,
|
|
4607
|
+
onClick: () => onAction?.({
|
|
4608
|
+
type: "heading",
|
|
4609
|
+
data: level
|
|
4610
|
+
})
|
|
4611
|
+
}, /* @__PURE__ */ React2.createElement("span", {
|
|
4612
|
+
className: "sr-only"
|
|
4613
|
+
}, t("heading level label", {
|
|
4614
|
+
count: parseInt(level)
|
|
4615
|
+
})), /* @__PURE__ */ React2.createElement(Icon, {
|
|
4616
|
+
className: iconStyles
|
|
4617
|
+
}), /* @__PURE__ */ React2.createElement(DropdownMenu.ItemIndicator, null, /* @__PURE__ */ React2.createElement(Check, null)));
|
|
4618
|
+
})), /* @__PURE__ */ React2.createElement(DropdownMenu.Arrow, null)))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("heading label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4575
4619
|
};
|
|
4576
4620
|
var markdownStyles = [
|
|
4577
4621
|
{
|
|
@@ -4704,7 +4748,7 @@ var MarkdownCustom = ({ onUpload } = {}) => {
|
|
|
4704
4748
|
});
|
|
4705
4749
|
useEffect3(() => {
|
|
4706
4750
|
if (onUpload && acceptedFiles.length) {
|
|
4707
|
-
|
|
4751
|
+
requestAnimationFrame(async () => {
|
|
4708
4752
|
const f = acceptedFiles[0];
|
|
4709
4753
|
const file = new File([
|
|
4710
4754
|
f
|
|
@@ -4736,6 +4780,7 @@ var MarkdownActions = () => {
|
|
|
4736
4780
|
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4737
4781
|
value: "comment",
|
|
4738
4782
|
Icon: ChatText,
|
|
4783
|
+
"data-testid": "editor.toolbar.comment",
|
|
4739
4784
|
onClick: () => onAction?.({
|
|
4740
4785
|
type: "comment"
|
|
4741
4786
|
})
|
|
@@ -4752,56 +4797,7 @@ var Toolbar = {
|
|
|
4752
4797
|
|
|
4753
4798
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4754
4799
|
var useActionHandler = (view) => {
|
|
4755
|
-
return (action) =>
|
|
4756
|
-
if (!view) {
|
|
4757
|
-
return;
|
|
4758
|
-
}
|
|
4759
|
-
let inlineType, listType;
|
|
4760
|
-
switch (action.type) {
|
|
4761
|
-
case "heading":
|
|
4762
|
-
setHeading(parseInt(action.data))(view);
|
|
4763
|
-
break;
|
|
4764
|
-
case "strong":
|
|
4765
|
-
case "emphasis":
|
|
4766
|
-
case "strikethrough":
|
|
4767
|
-
case "code":
|
|
4768
|
-
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4769
|
-
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
4770
|
-
break;
|
|
4771
|
-
case "list-ordered":
|
|
4772
|
-
case "list-bullet":
|
|
4773
|
-
case "list-task":
|
|
4774
|
-
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4775
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4776
|
-
break;
|
|
4777
|
-
case "blockquote":
|
|
4778
|
-
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
4779
|
-
break;
|
|
4780
|
-
case "codeblock":
|
|
4781
|
-
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
4782
|
-
break;
|
|
4783
|
-
case "table":
|
|
4784
|
-
insertTable(view);
|
|
4785
|
-
break;
|
|
4786
|
-
case "link":
|
|
4787
|
-
(action.data === false ? removeLink : addLink())(view);
|
|
4788
|
-
break;
|
|
4789
|
-
case "image":
|
|
4790
|
-
addLink({
|
|
4791
|
-
url: action.data,
|
|
4792
|
-
image: true
|
|
4793
|
-
})(view);
|
|
4794
|
-
break;
|
|
4795
|
-
case "comment":
|
|
4796
|
-
createComment(view);
|
|
4797
|
-
break;
|
|
4798
|
-
}
|
|
4799
|
-
setTimeout(() => {
|
|
4800
|
-
if (!view.hasFocus) {
|
|
4801
|
-
view.focus();
|
|
4802
|
-
}
|
|
4803
|
-
});
|
|
4804
|
-
};
|
|
4800
|
+
return (action) => view && processAction(view, action);
|
|
4805
4801
|
};
|
|
4806
4802
|
|
|
4807
4803
|
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
@@ -4819,23 +4815,23 @@ var useDocAccessor = (text) => {
|
|
|
4819
4815
|
|
|
4820
4816
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4821
4817
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4822
|
-
import { EditorView as
|
|
4823
|
-
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as
|
|
4824
|
-
import { log as
|
|
4818
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4819
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4820
|
+
import { log as log8 } from "@dxos/log";
|
|
4825
4821
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4826
|
-
var
|
|
4822
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4827
4823
|
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4828
4824
|
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4829
4825
|
const onUpdate = useRef3();
|
|
4830
|
-
const [view, setView] =
|
|
4826
|
+
const [view, setView] = useState4();
|
|
4831
4827
|
const parentRef = useRef3(null);
|
|
4832
4828
|
useEffect4(() => {
|
|
4833
4829
|
let view2;
|
|
4834
4830
|
if (parentRef.current) {
|
|
4835
|
-
|
|
4831
|
+
log8("create", {
|
|
4836
4832
|
id
|
|
4837
4833
|
}, {
|
|
4838
|
-
F:
|
|
4834
|
+
F: __dxlog_file11,
|
|
4839
4835
|
L: 36,
|
|
4840
4836
|
S: void 0,
|
|
4841
4837
|
C: (f, a) => f(...a)
|
|
@@ -4846,21 +4842,21 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4846
4842
|
extensions: [
|
|
4847
4843
|
id && documentId2.of(id),
|
|
4848
4844
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
F:
|
|
4845
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4846
|
+
log8.catch(err, void 0, {
|
|
4847
|
+
F: __dxlog_file11,
|
|
4852
4848
|
L: 46,
|
|
4853
4849
|
S: void 0,
|
|
4854
4850
|
C: (f, a) => f(...a)
|
|
4855
4851
|
});
|
|
4856
4852
|
}),
|
|
4857
4853
|
extensions,
|
|
4858
|
-
|
|
4854
|
+
EditorView17.updateListener.of(() => {
|
|
4859
4855
|
onUpdate.current?.();
|
|
4860
4856
|
})
|
|
4861
4857
|
].filter(isNotFalsy5)
|
|
4862
4858
|
});
|
|
4863
|
-
view2 = new
|
|
4859
|
+
view2 = new EditorView17({
|
|
4864
4860
|
parent: parentRef.current,
|
|
4865
4861
|
scrollTo,
|
|
4866
4862
|
state: state2,
|
|
@@ -4876,10 +4872,10 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4876
4872
|
setView(view2);
|
|
4877
4873
|
}
|
|
4878
4874
|
return () => {
|
|
4879
|
-
|
|
4875
|
+
log8("destroy", {
|
|
4880
4876
|
id
|
|
4881
4877
|
}, {
|
|
4882
|
-
F:
|
|
4878
|
+
F: __dxlog_file11,
|
|
4883
4879
|
L: 74,
|
|
4884
4880
|
S: void 0,
|
|
4885
4881
|
C: (f, a) => f(...a)
|
|
@@ -4921,7 +4917,6 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4921
4917
|
};
|
|
4922
4918
|
export {
|
|
4923
4919
|
Cursor,
|
|
4924
|
-
Doc,
|
|
4925
4920
|
EditorModes,
|
|
4926
4921
|
Inline,
|
|
4927
4922
|
List,
|
|
@@ -4930,8 +4925,6 @@ export {
|
|
|
4930
4925
|
TextEditor,
|
|
4931
4926
|
TextKind,
|
|
4932
4927
|
Toolbar,
|
|
4933
|
-
YText,
|
|
4934
|
-
YXmlFragment,
|
|
4935
4928
|
addBlockquote,
|
|
4936
4929
|
addCodeblock,
|
|
4937
4930
|
addLink,
|
|
@@ -4951,12 +4944,11 @@ export {
|
|
|
4951
4944
|
createDataExtensions,
|
|
4952
4945
|
createMarkdownExtensions,
|
|
4953
4946
|
createThemeExtensions,
|
|
4954
|
-
cursorLineMargin,
|
|
4955
4947
|
decorateMarkdown,
|
|
4956
4948
|
defaultOptions,
|
|
4957
4949
|
defaultTheme,
|
|
4958
|
-
dnd,
|
|
4959
4950
|
documentId2 as documentId,
|
|
4951
|
+
dropFile,
|
|
4960
4952
|
editorFillLayoutEditor,
|
|
4961
4953
|
editorFillLayoutRoot,
|
|
4962
4954
|
editorMode,
|
|
@@ -4970,7 +4962,7 @@ export {
|
|
|
4970
4962
|
image,
|
|
4971
4963
|
imageUpload,
|
|
4972
4964
|
insertTable,
|
|
4973
|
-
|
|
4965
|
+
keymap11 as keymap,
|
|
4974
4966
|
linkTooltip,
|
|
4975
4967
|
listener,
|
|
4976
4968
|
localStorageStateStoreAdapter,
|
|
@@ -4979,6 +4971,7 @@ export {
|
|
|
4979
4971
|
markdownTags,
|
|
4980
4972
|
markdownTagsExtensions,
|
|
4981
4973
|
mention,
|
|
4974
|
+
processAction,
|
|
4982
4975
|
removeBlockquote,
|
|
4983
4976
|
removeCodeblock,
|
|
4984
4977
|
removeLink,
|