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