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