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