@dxos/react-ui-editor 0.4.8-main.46f461d → 0.4.8-main.49cea32
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 +1289 -1328
- 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 +2 -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/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.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/package.json +24 -24
- package/src/components/TextEditor/TextEditor.stories.tsx +14 -2
- package/src/components/Toolbar/Toolbar.tsx +2 -26
- package/src/extensions/command/state.ts +2 -2
- package/src/extensions/dnd.ts +31 -9
- package/src/extensions/factories.ts +19 -16
- package/src/extensions/index.ts +0 -1
- package/src/extensions/markdown/action.ts +112 -0
- package/src/extensions/markdown/index.ts +1 -0
- package/src/hooks/useActionHandler.ts +4 -89
- 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
|
@@ -31,10 +31,10 @@ 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
36
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
37
|
-
import { log as
|
|
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);
|
|
@@ -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,34 +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
1910
|
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1956
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1911
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1957
1912
|
import { bracketMatching } from "@codemirror/language";
|
|
1958
1913
|
import { searchKeymap } from "@codemirror/search";
|
|
1959
1914
|
import { EditorState } from "@codemirror/state";
|
|
1960
|
-
import { EditorView as
|
|
1915
|
+
import { EditorView as EditorView9, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap5, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
|
1961
1916
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1962
1917
|
import { generateName } from "@dxos/display-name";
|
|
1963
|
-
import { log as
|
|
1918
|
+
import { log as log5 } from "@dxos/log";
|
|
1964
1919
|
import { hueTokens } from "@dxos/react-ui-theme";
|
|
1965
1920
|
import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1966
1921
|
|
|
@@ -2208,25 +2163,32 @@ var defaultTheme = {
|
|
|
2208
2163
|
};
|
|
2209
2164
|
|
|
2210
2165
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2211
|
-
var
|
|
2212
|
-
var
|
|
2166
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
|
2167
|
+
var defaultBasicOptions = {
|
|
2213
2168
|
allowMultipleSelections: true,
|
|
2214
2169
|
bracketMatching: true,
|
|
2215
2170
|
closeBrackets: true,
|
|
2216
2171
|
drawSelection: true,
|
|
2217
2172
|
editable: true,
|
|
2218
2173
|
history: true,
|
|
2174
|
+
keymap: "standard",
|
|
2219
2175
|
lineWrapping: true,
|
|
2220
2176
|
search: true
|
|
2221
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
|
|
2183
|
+
};
|
|
2222
2184
|
var createBasicExtensions = (_props) => {
|
|
2223
|
-
const props = defaultsDeep2({}, _props,
|
|
2185
|
+
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
|
2224
2186
|
return [
|
|
2225
|
-
//
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
F:
|
|
2229
|
-
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,
|
|
2230
2192
|
S: void 0,
|
|
2231
2193
|
C: (f, a) => f(...a)
|
|
2232
2194
|
});
|
|
@@ -2234,27 +2196,26 @@ var createBasicExtensions = (_props) => {
|
|
|
2234
2196
|
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2235
2197
|
props.bracketMatching && bracketMatching(),
|
|
2236
2198
|
props.closeBrackets && closeBrackets(),
|
|
2237
|
-
props.
|
|
2238
|
-
props.dropCursor && dropCursor(),
|
|
2199
|
+
props.dropCursor && dropCursor2(),
|
|
2239
2200
|
props.drawSelection && drawSelection(),
|
|
2240
2201
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2241
|
-
highlightSpecialChars(),
|
|
2242
2202
|
props.history && history(),
|
|
2243
2203
|
props.lineNumbers && lineNumbers(),
|
|
2244
|
-
props.lineWrapping &&
|
|
2204
|
+
props.lineWrapping && EditorView9.lineWrapping,
|
|
2245
2205
|
props.placeholder && placeholder(props.placeholder),
|
|
2246
2206
|
props.readonly && [
|
|
2247
2207
|
EditorState.readOnly.of(true),
|
|
2248
|
-
|
|
2208
|
+
EditorView9.editable.of(false)
|
|
2249
2209
|
],
|
|
2250
2210
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2251
2211
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
2252
2212
|
// https://codemirror.net/docs/ref/#view.KeyBinding
|
|
2253
2213
|
keymap5.of([
|
|
2254
|
-
|
|
2255
|
-
...standardKeymap,
|
|
2214
|
+
...(props.keymap && keymaps[props.keymap]) ?? [],
|
|
2256
2215
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2257
|
-
props.indentWithTab
|
|
2216
|
+
...props.indentWithTab ? [
|
|
2217
|
+
indentWithTab
|
|
2218
|
+
] : [],
|
|
2258
2219
|
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2259
2220
|
...props.closeBrackets ? closeBracketsKeymap : [],
|
|
2260
2221
|
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
@@ -2264,21 +2225,21 @@ var createBasicExtensions = (_props) => {
|
|
|
2264
2225
|
].filter(isNotFalsy2))
|
|
2265
2226
|
].filter(isNotFalsy2);
|
|
2266
2227
|
};
|
|
2267
|
-
var
|
|
2228
|
+
var defaultThemeSlots = {
|
|
2268
2229
|
editor: {
|
|
2269
2230
|
className: "w-full bs-full"
|
|
2270
2231
|
}
|
|
2271
2232
|
};
|
|
2272
2233
|
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2273
|
-
const slots = defaultsDeep2({}, _slots,
|
|
2234
|
+
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
|
2274
2235
|
return [
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
theme &&
|
|
2278
|
-
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({
|
|
2279
2240
|
class: slots.editor.className
|
|
2280
2241
|
}),
|
|
2281
|
-
slots.content?.className &&
|
|
2242
|
+
slots.content?.className && EditorView9.contentAttributes.of({
|
|
2282
2243
|
class: slots.content.className
|
|
2283
2244
|
})
|
|
2284
2245
|
].filter(isNotFalsy2);
|
|
@@ -2306,917 +2267,415 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
|
2306
2267
|
};
|
|
2307
2268
|
|
|
2308
2269
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
2309
|
-
import { EditorView as
|
|
2270
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
2310
2271
|
var listener = ({ onFocus, onChange }) => {
|
|
2311
2272
|
const extensions = [];
|
|
2312
|
-
onFocus && extensions.push(
|
|
2273
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
2313
2274
|
onFocus(focusing);
|
|
2314
2275
|
return null;
|
|
2315
2276
|
}));
|
|
2316
|
-
onChange && extensions.push(
|
|
2277
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
2317
2278
|
onChange(update2.state.doc.toString());
|
|
2318
2279
|
}));
|
|
2319
2280
|
return extensions;
|
|
2320
2281
|
};
|
|
2321
2282
|
|
|
2322
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
2323
|
-
import {
|
|
2324
|
-
import {
|
|
2325
|
-
import {
|
|
2326
|
-
import {
|
|
2327
|
-
import {
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
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
|
+
});
|
|
2357
2368
|
}
|
|
2358
2369
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
Table,
|
|
2362
|
-
{
|
|
2363
|
-
props: [
|
|
2364
|
-
styleTags(markdownTags)
|
|
2365
|
-
]
|
|
2366
|
-
}
|
|
2367
|
-
];
|
|
2368
|
-
var markdownHighlightStyle = (readonly) => {
|
|
2369
|
-
return HighlightStyle.define([
|
|
2370
|
-
{
|
|
2371
|
-
tag: [
|
|
2372
|
-
tags.keyword,
|
|
2373
|
-
tags.name,
|
|
2374
|
-
tags.deleted,
|
|
2375
|
-
tags.character,
|
|
2376
|
-
tags.propertyName,
|
|
2377
|
-
tags.macroName,
|
|
2378
|
-
tags.color,
|
|
2379
|
-
tags.constant(tags.name),
|
|
2380
|
-
tags.standard(tags.name),
|
|
2381
|
-
tags.definition(tags.name),
|
|
2382
|
-
tags.separator,
|
|
2383
|
-
tags.typeName,
|
|
2384
|
-
tags.className,
|
|
2385
|
-
tags.number,
|
|
2386
|
-
tags.changed,
|
|
2387
|
-
tags.annotation,
|
|
2388
|
-
tags.modifier,
|
|
2389
|
-
tags.self,
|
|
2390
|
-
tags.namespace,
|
|
2391
|
-
tags.operator,
|
|
2392
|
-
tags.operatorKeyword,
|
|
2393
|
-
tags.escape,
|
|
2394
|
-
tags.regexp,
|
|
2395
|
-
tags.special(tags.string),
|
|
2396
|
-
tags.meta,
|
|
2397
|
-
tags.comment,
|
|
2398
|
-
tags.atom,
|
|
2399
|
-
tags.bool,
|
|
2400
|
-
tags.special(tags.variableName),
|
|
2401
|
-
tags.processingInstruction,
|
|
2402
|
-
tags.string,
|
|
2403
|
-
tags.inserted,
|
|
2404
|
-
tags.invalid
|
|
2405
|
-
],
|
|
2406
|
-
color: "inherit !important"
|
|
2407
|
-
},
|
|
2408
|
-
// Markdown marks.
|
|
2409
|
-
{
|
|
2410
|
-
tag: [
|
|
2411
|
-
tags.meta,
|
|
2412
|
-
tags.processingInstruction,
|
|
2413
|
-
markdownTags.LinkLabel,
|
|
2414
|
-
markdownTags.LinkReference,
|
|
2415
|
-
markdownTags.ListMark
|
|
2416
|
-
],
|
|
2417
|
-
class: mark
|
|
2418
|
-
},
|
|
2419
|
-
// Markdown marks.
|
|
2420
|
-
{
|
|
2421
|
-
tag: [
|
|
2422
|
-
markdownTags.CodeMark,
|
|
2423
|
-
markdownTags.HeaderMark,
|
|
2424
|
-
markdownTags.QuoteMark,
|
|
2425
|
-
markdownTags.EmphasisMark
|
|
2426
|
-
],
|
|
2427
|
-
class: mark
|
|
2428
|
-
},
|
|
2429
|
-
// E.g., code block language (after ```).
|
|
2430
|
-
{
|
|
2431
|
-
tag: [
|
|
2432
|
-
tags.function(tags.variableName),
|
|
2433
|
-
tags.labelName
|
|
2434
|
-
],
|
|
2435
|
-
class: codeMark
|
|
2436
|
-
},
|
|
2437
|
-
{
|
|
2438
|
-
tag: [
|
|
2439
|
-
tags.monospace
|
|
2440
|
-
],
|
|
2441
|
-
class: "font-mono"
|
|
2442
|
-
},
|
|
2443
|
-
// Headings.
|
|
2444
|
-
{
|
|
2445
|
-
tag: tags.heading1,
|
|
2446
|
-
class: heading(1)
|
|
2447
|
-
},
|
|
2448
|
-
{
|
|
2449
|
-
tag: tags.heading2,
|
|
2450
|
-
class: heading(2)
|
|
2451
|
-
},
|
|
2452
|
-
{
|
|
2453
|
-
tag: tags.heading3,
|
|
2454
|
-
class: heading(3)
|
|
2455
|
-
},
|
|
2456
|
-
{
|
|
2457
|
-
tag: tags.heading4,
|
|
2458
|
-
class: heading(4)
|
|
2459
|
-
},
|
|
2460
|
-
{
|
|
2461
|
-
tag: tags.heading5,
|
|
2462
|
-
class: heading(5)
|
|
2463
|
-
},
|
|
2464
|
-
{
|
|
2465
|
-
tag: tags.heading6,
|
|
2466
|
-
class: heading(6)
|
|
2467
|
-
},
|
|
2468
|
-
// Emphasis.
|
|
2469
|
-
{
|
|
2470
|
-
tag: tags.emphasis,
|
|
2471
|
-
class: italic
|
|
2472
|
-
},
|
|
2473
|
-
{
|
|
2474
|
-
tag: tags.strong,
|
|
2475
|
-
class: bold
|
|
2476
|
-
},
|
|
2477
|
-
{
|
|
2478
|
-
tag: tags.strikethrough,
|
|
2479
|
-
class: strikethrough
|
|
2480
|
-
},
|
|
2481
|
-
// Naked URLs.
|
|
2482
|
-
{
|
|
2483
|
-
tag: [
|
|
2484
|
-
markdownTags.URL
|
|
2485
|
-
],
|
|
2486
|
-
class: inlineUrl
|
|
2487
|
-
},
|
|
2488
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
2489
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
2490
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
2491
|
-
// the code, but all other CSS properties will be inherited.
|
|
2492
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
2493
|
-
{
|
|
2494
|
-
tag: [
|
|
2495
|
-
markdownTags.CodeText,
|
|
2496
|
-
markdownTags.InlineCode
|
|
2497
|
-
],
|
|
2498
|
-
class: code
|
|
2499
|
-
},
|
|
2500
|
-
{
|
|
2501
|
-
tag: [
|
|
2502
|
-
markdownTags.QuoteMark
|
|
2503
|
-
],
|
|
2504
|
-
class: blockquote
|
|
2505
|
-
},
|
|
2506
|
-
{
|
|
2507
|
-
tag: [
|
|
2508
|
-
markdownTags.TableCell
|
|
2509
|
-
],
|
|
2510
|
-
class: "font-mono"
|
|
2511
|
-
}
|
|
2512
|
-
], {
|
|
2513
|
-
scope: markdownLanguage2,
|
|
2514
|
-
all: {
|
|
2515
|
-
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
2516
|
-
}
|
|
2517
|
-
});
|
|
2518
|
-
};
|
|
2519
|
-
|
|
2520
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
2521
|
-
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
2522
|
-
return [
|
|
2523
|
-
// Main extension.
|
|
2524
|
-
// https://github.com/codemirror/lang-markdown
|
|
2525
|
-
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
2526
|
-
markdown({
|
|
2527
|
-
// GRM by default (vs strict CommonMark):
|
|
2528
|
-
// Table, TaskList, Strikethrough, and Autolink.
|
|
2529
|
-
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
2530
|
-
// https://github.github.com/gfm
|
|
2531
|
-
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
2532
|
-
base: markdownLanguage3,
|
|
2533
|
-
// Languages for syntax highlighting fenced code blocks.
|
|
2534
|
-
codeLanguages: languages,
|
|
2535
|
-
// Parser extensions.
|
|
2536
|
-
extensions: [
|
|
2537
|
-
// GFM provided by default.
|
|
2538
|
-
markdownTagsExtensions
|
|
2539
|
-
]
|
|
2540
|
-
}),
|
|
2541
|
-
// https://github.com/codemirror/theme-one-dark
|
|
2542
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
2543
|
-
// Custom styles.
|
|
2544
|
-
syntaxHighlighting(markdownHighlightStyle()),
|
|
2545
|
-
keymap6.of([
|
|
2546
|
-
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2547
|
-
indentWithTab2,
|
|
2548
|
-
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
2549
|
-
...defaultKeymap,
|
|
2550
|
-
...completionKeymap2,
|
|
2551
|
-
...lintKeymap
|
|
2552
|
-
])
|
|
2553
|
-
];
|
|
2554
|
-
};
|
|
2555
|
-
|
|
2556
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
2557
|
-
import { syntaxTree } from "@codemirror/language";
|
|
2558
|
-
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
2559
|
-
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
2560
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
2561
|
-
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2562
|
-
toDOM() {
|
|
2563
|
-
const el = document.createElement("span");
|
|
2564
|
-
el.className = "cm-hr";
|
|
2565
|
-
return el;
|
|
2566
|
-
}
|
|
2567
|
-
};
|
|
2568
|
-
var LinkButton = class extends WidgetType3 {
|
|
2569
|
-
constructor(url, render) {
|
|
2570
|
-
super();
|
|
2571
|
-
this.url = url;
|
|
2572
|
-
this.render = render;
|
|
2573
|
-
}
|
|
2574
|
-
eq(other) {
|
|
2575
|
-
return this.url === other.url;
|
|
2576
|
-
}
|
|
2577
|
-
toDOM(view) {
|
|
2578
|
-
const el = document.createElement("span");
|
|
2579
|
-
this.render(el, this.url);
|
|
2580
|
-
return el;
|
|
2370
|
+
if (!changes.length) {
|
|
2371
|
+
return false;
|
|
2581
2372
|
}
|
|
2373
|
+
const changeSet = state2.changes(changes);
|
|
2374
|
+
dispatch(state2.update({
|
|
2375
|
+
changes: changeSet,
|
|
2376
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2377
|
+
userEvent: "format.setHeading",
|
|
2378
|
+
scrollIntoView: true
|
|
2379
|
+
}));
|
|
2380
|
+
return true;
|
|
2582
2381
|
};
|
|
2583
|
-
var
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
insert: this._checked ? " " : "x"
|
|
2608
|
-
}
|
|
2609
|
-
});
|
|
2610
|
-
event.preventDefault();
|
|
2382
|
+
var setStyle = (type, enable) => ({ state: state2, dispatch }) => {
|
|
2383
|
+
const marker = inlineMarkerText(type);
|
|
2384
|
+
const changes = state2.changeByRange((range) => {
|
|
2385
|
+
if (!enable && range.empty) {
|
|
2386
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2387
|
+
const found = after.indexOf(marker);
|
|
2388
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2389
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2390
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2391
|
+
...before.slice(before.length - found)
|
|
2392
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
2393
|
+
return {
|
|
2394
|
+
changes: [
|
|
2395
|
+
{
|
|
2396
|
+
from: range.head - marker.length - found,
|
|
2397
|
+
to: range.head - found
|
|
2398
|
+
},
|
|
2399
|
+
{
|
|
2400
|
+
from: range.head + found,
|
|
2401
|
+
to: range.head + found + marker.length
|
|
2402
|
+
}
|
|
2403
|
+
],
|
|
2404
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
2405
|
+
};
|
|
2611
2406
|
}
|
|
2612
|
-
}
|
|
2407
|
+
}
|
|
2613
2408
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
var fencedCodeLine = Decoration5.line({
|
|
2622
|
-
class: mx2("cm-code cm-codeblock-line")
|
|
2623
|
-
});
|
|
2624
|
-
var fencedCodeLineFirst = Decoration5.line({
|
|
2625
|
-
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
|
2626
|
-
});
|
|
2627
|
-
var fencedCodeLineLast = Decoration5.line({
|
|
2628
|
-
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
2629
|
-
});
|
|
2630
|
-
var horizontalRule = Decoration5.replace({
|
|
2631
|
-
widget: new HorizontalRuleWidget()
|
|
2632
|
-
});
|
|
2633
|
-
var checkedTask = Decoration5.replace({
|
|
2634
|
-
widget: new CheckboxWidget(true)
|
|
2635
|
-
});
|
|
2636
|
-
var uncheckedTask = Decoration5.replace({
|
|
2637
|
-
widget: new CheckboxWidget(false)
|
|
2638
|
-
});
|
|
2639
|
-
var editingRange = (state2, range, focus) => {
|
|
2640
|
-
const { readOnly, selection: { main: { head } } } = state2;
|
|
2641
|
-
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
2642
|
-
};
|
|
2643
|
-
var MarksByParent = /* @__PURE__ */ new Set([
|
|
2644
|
-
"CodeMark",
|
|
2645
|
-
"EmphasisMark",
|
|
2646
|
-
"StrikethroughMark",
|
|
2647
|
-
"SubscriptMark",
|
|
2648
|
-
"SuperscriptMark"
|
|
2649
|
-
]);
|
|
2650
|
-
var buildDecorations = (view, options, focus) => {
|
|
2651
|
-
const deco = new RangeSetBuilder2();
|
|
2652
|
-
const atomicDeco = new RangeSetBuilder2();
|
|
2653
|
-
const { state: state2 } = view;
|
|
2654
|
-
for (const { from, to } of view.visibleRanges) {
|
|
2409
|
+
const changes2 = [];
|
|
2410
|
+
const changesAtEnd = [];
|
|
2411
|
+
let blockStart = -1;
|
|
2412
|
+
let blockEnd = -1;
|
|
2413
|
+
let startCovered = false;
|
|
2414
|
+
let endCovered = false;
|
|
2415
|
+
let { from, to } = range;
|
|
2655
2416
|
syntaxTree(state2).iterate({
|
|
2656
2417
|
from,
|
|
2657
2418
|
to,
|
|
2658
2419
|
enter: (node) => {
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
2670
|
-
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
2671
|
-
if (!editing && (first || last)) {
|
|
2672
|
-
atomicDeco.add(block.from, block.to, hide);
|
|
2673
|
-
}
|
|
2420
|
+
const { name } = node;
|
|
2421
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2422
|
+
blockStart = blockContentStart(node);
|
|
2423
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2424
|
+
startCovered = endCovered = false;
|
|
2425
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
2426
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
2427
|
+
to = node.to;
|
|
2428
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2429
|
+
from = node.from;
|
|
2674
2430
|
}
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
const editing = editingRange(state2, node, focus);
|
|
2680
|
-
if (urlNode && marks.length >= 2) {
|
|
2681
|
-
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
2682
|
-
if (!editing) {
|
|
2683
|
-
atomicDeco.add(node.from, marks[0].to, hide);
|
|
2684
|
-
}
|
|
2685
|
-
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
2686
|
-
tagName: "a",
|
|
2687
|
-
attributes: {
|
|
2688
|
-
class: "cm-link",
|
|
2689
|
-
href: url,
|
|
2690
|
-
rel: "noreferrer",
|
|
2691
|
-
target: "_blank"
|
|
2692
|
-
}
|
|
2693
|
-
}));
|
|
2694
|
-
if (!editing) {
|
|
2695
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
2696
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
|
2697
|
-
}) : hide);
|
|
2431
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
2432
|
+
if (node.from < from && node.to > from) {
|
|
2433
|
+
if (to === from) {
|
|
2434
|
+
to = node.to;
|
|
2698
2435
|
}
|
|
2436
|
+
from = node.to;
|
|
2699
2437
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
2703
|
-
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
2704
|
-
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2438
|
+
if (node.from < to && node.to > to) {
|
|
2439
|
+
to = node.from;
|
|
2705
2440
|
}
|
|
2706
|
-
} else if (
|
|
2707
|
-
|
|
2708
|
-
|
|
2441
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2442
|
+
const markType = InlineMarker[name];
|
|
2443
|
+
const size = inlineMarkerText(markType).length;
|
|
2444
|
+
const openEnd = node.from + size;
|
|
2445
|
+
const closeStart = node.to - size;
|
|
2446
|
+
if (markType === type) {
|
|
2447
|
+
if (openEnd <= from && closeStart >= from) {
|
|
2448
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2449
|
+
from: node.from,
|
|
2450
|
+
to: openEnd
|
|
2451
|
+
} : true;
|
|
2452
|
+
}
|
|
2453
|
+
if (openEnd <= to && closeStart >= to) {
|
|
2454
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2455
|
+
from: closeStart,
|
|
2456
|
+
to: node.to
|
|
2457
|
+
} : true;
|
|
2458
|
+
}
|
|
2709
2459
|
}
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2460
|
+
if (markType === type || type === 3 && enable) {
|
|
2461
|
+
if (node.from >= from && openEnd <= to) {
|
|
2462
|
+
changes2.push({
|
|
2463
|
+
from: node.from,
|
|
2464
|
+
to: openEnd
|
|
2465
|
+
});
|
|
2466
|
+
if (markType !== type && closeStart >= to) {
|
|
2467
|
+
changesAtEnd.push({
|
|
2468
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2469
|
+
insert: inlineMarkerText(markType)
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
if (closeStart >= from && node.to <= to) {
|
|
2474
|
+
changes2.push({
|
|
2475
|
+
from: closeStart,
|
|
2476
|
+
to: node.to
|
|
2477
|
+
});
|
|
2478
|
+
if (markType !== type && openEnd <= from) {
|
|
2479
|
+
changes2.push({
|
|
2480
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2481
|
+
insert: inlineMarkerText(markType)
|
|
2482
|
+
});
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2717
2485
|
}
|
|
2718
|
-
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2486
|
+
}
|
|
2487
|
+
},
|
|
2488
|
+
leave: (node) => {
|
|
2489
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2490
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2491
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2492
|
+
if (enable) {
|
|
2493
|
+
if (!startCovered) {
|
|
2494
|
+
changes2.push({
|
|
2495
|
+
from: rangeStart,
|
|
2496
|
+
insert: marker
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
if (!endCovered) {
|
|
2500
|
+
changes2.push({
|
|
2501
|
+
from: rangeEnd,
|
|
2502
|
+
insert: marker
|
|
2503
|
+
});
|
|
2504
|
+
}
|
|
2505
|
+
} else {
|
|
2506
|
+
if (typeof startCovered === "object") {
|
|
2507
|
+
changes2.push(startCovered);
|
|
2508
|
+
} else if (startCovered) {
|
|
2509
|
+
changes2.push({
|
|
2510
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
2511
|
+
insert: marker
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
if (typeof endCovered === "object") {
|
|
2515
|
+
changes2.push(endCovered);
|
|
2516
|
+
} else if (endCovered) {
|
|
2517
|
+
changes2.push({
|
|
2518
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
2519
|
+
insert: marker
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2721
2522
|
}
|
|
2722
2523
|
}
|
|
2723
2524
|
}
|
|
2724
2525
|
});
|
|
2526
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2527
|
+
return {
|
|
2528
|
+
changes: {
|
|
2529
|
+
from: range.head,
|
|
2530
|
+
insert: marker + marker
|
|
2531
|
+
},
|
|
2532
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
2536
|
+
return {
|
|
2537
|
+
changes: changeSet,
|
|
2538
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2539
|
+
};
|
|
2540
|
+
});
|
|
2541
|
+
dispatch(state2.update(changes, {
|
|
2542
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2543
|
+
scrollIntoView: true
|
|
2544
|
+
}));
|
|
2545
|
+
return true;
|
|
2546
|
+
};
|
|
2547
|
+
var addStyle = (style) => setStyle(style, true);
|
|
2548
|
+
var removeStyle = (style) => setStyle(style, false);
|
|
2549
|
+
var toggleStyle = (style) => (arg) => {
|
|
2550
|
+
const form = getFormatting(arg.state);
|
|
2551
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2552
|
+
};
|
|
2553
|
+
var toggleStrong = toggleStyle(0);
|
|
2554
|
+
var toggleEmphasis = toggleStyle(1);
|
|
2555
|
+
var toggleStrikethrough = toggleStyle(2);
|
|
2556
|
+
var toggleInlineCode = toggleStyle(3);
|
|
2557
|
+
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
2558
|
+
var blockContentStart = (node) => {
|
|
2559
|
+
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
2560
|
+
if (atx) {
|
|
2561
|
+
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
2725
2562
|
}
|
|
2726
|
-
return
|
|
2727
|
-
deco: deco.finish(),
|
|
2728
|
-
atomicDeco: atomicDeco.finish()
|
|
2729
|
-
};
|
|
2563
|
+
return node.from;
|
|
2730
2564
|
};
|
|
2731
|
-
var
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
update(update2) {
|
|
2739
|
-
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
2740
|
-
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
2741
|
-
this.clearUpdate();
|
|
2742
|
-
} else if (update2.selectionSet) {
|
|
2743
|
-
this.scheduleUpdate(update2.view);
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
2747
|
-
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
2748
|
-
scheduleUpdate(view) {
|
|
2749
|
-
this.clearUpdate();
|
|
2750
|
-
this.pendingUpdate = setTimeout(() => {
|
|
2751
|
-
view.dispatch({
|
|
2752
|
-
effects: forceUpdate.of(null)
|
|
2753
|
-
});
|
|
2754
|
-
}, options.selectionChangeDelay);
|
|
2755
|
-
}
|
|
2756
|
-
clearUpdate() {
|
|
2757
|
-
if (this.pendingUpdate) {
|
|
2758
|
-
clearTimeout(this.pendingUpdate);
|
|
2759
|
-
this.pendingUpdate = void 0;
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
destroy() {
|
|
2763
|
-
this.clearUpdate();
|
|
2764
|
-
}
|
|
2765
|
-
}, {
|
|
2766
|
-
provide: (plugin) => [
|
|
2767
|
-
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2768
|
-
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2769
|
-
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
2770
|
-
]
|
|
2771
|
-
}),
|
|
2772
|
-
formattingStyles
|
|
2773
|
-
];
|
|
2565
|
+
var blockContentEnd = (node, doc) => {
|
|
2566
|
+
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
2567
|
+
const lastLine = doc.lineAt(node.to);
|
|
2568
|
+
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
2569
|
+
return lastLine.from - 1;
|
|
2570
|
+
}
|
|
2571
|
+
return node.to;
|
|
2774
2572
|
};
|
|
2775
|
-
var
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
position: "absolute",
|
|
2788
|
-
inset: 0,
|
|
2789
|
-
content: '""'
|
|
2573
|
+
var skipSpaces = (pos, doc, dir, limit) => {
|
|
2574
|
+
const line = doc.lineAt(pos);
|
|
2575
|
+
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
2576
|
+
pos += dir;
|
|
2577
|
+
}
|
|
2578
|
+
return pos;
|
|
2579
|
+
};
|
|
2580
|
+
var skipMarkers = (pos, tree, dir, limit) => {
|
|
2581
|
+
for (; ; ) {
|
|
2582
|
+
const next = tree.resolve(pos, dir);
|
|
2583
|
+
if (!IgnoreInline.has(next.name)) {
|
|
2584
|
+
return pos;
|
|
2790
2585
|
}
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
"& .cm-codeblock-last": {
|
|
2797
|
-
borderBottomLeftRadius: ".5rem",
|
|
2798
|
-
borderBottomRightRadius: ".5rem"
|
|
2799
|
-
},
|
|
2800
|
-
"&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
|
|
2801
|
-
background: getToken("extend.semanticColors.input.light"),
|
|
2802
|
-
mixBlendMode: "darken"
|
|
2803
|
-
},
|
|
2804
|
-
"&dark .cm-codeblock-line, &dark .cm-activeLine.cm-codeblock-line": {
|
|
2805
|
-
background: getToken("extend.semanticColors.input.dark"),
|
|
2806
|
-
mixBlendMode: "lighten"
|
|
2807
|
-
},
|
|
2808
|
-
"& .cm-hr": {
|
|
2809
|
-
display: "inline-block",
|
|
2810
|
-
width: "100%",
|
|
2811
|
-
height: "0",
|
|
2812
|
-
verticalAlign: "middle",
|
|
2813
|
-
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2814
|
-
},
|
|
2815
|
-
"& .cm-task": {
|
|
2816
|
-
color: getToken("extend.colors.blue.500")
|
|
2817
|
-
},
|
|
2818
|
-
"& .cm-task-checkbox": {
|
|
2819
|
-
marginLeft: "4px",
|
|
2820
|
-
marginRight: "4px"
|
|
2586
|
+
const moveTo = dir < 0 ? next.from : next.to;
|
|
2587
|
+
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
2588
|
+
return pos;
|
|
2589
|
+
}
|
|
2590
|
+
pos = moveTo;
|
|
2821
2591
|
}
|
|
2822
|
-
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
(
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
2855
|
-
return;
|
|
2856
|
-
}
|
|
2857
|
-
sawBlock = true;
|
|
2858
|
-
prevBlock = node.from;
|
|
2859
|
-
const blockType = Textblocks[node.name];
|
|
2860
|
-
const isHeading = /heading(\d)/.exec(blockType);
|
|
2861
|
-
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2862
|
-
if (curLevel < 0 || curLevel === level) {
|
|
2863
|
-
return;
|
|
2864
|
-
}
|
|
2865
|
-
if (curLevel === 0) {
|
|
2866
|
-
changes.push({
|
|
2867
|
-
from: node.from,
|
|
2868
|
-
insert: "#".repeat(level) + " "
|
|
2869
|
-
});
|
|
2870
|
-
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
2871
|
-
const nextLine = doc.lineAt(node.to);
|
|
2872
|
-
if (level) {
|
|
2873
|
-
changes.push({
|
|
2874
|
-
from: node.from,
|
|
2875
|
-
insert: "#".repeat(level) + " "
|
|
2876
|
-
});
|
|
2877
|
-
}
|
|
2878
|
-
changes.push({
|
|
2879
|
-
from: nextLine.from - 1,
|
|
2880
|
-
to: nextLine.to
|
|
2881
|
-
});
|
|
2882
|
-
} else {
|
|
2883
|
-
if (level === 0) {
|
|
2884
|
-
changes.push({
|
|
2885
|
-
from: node.from,
|
|
2886
|
-
to: Math.min(node.to, node.from + curLevel + 1)
|
|
2887
|
-
});
|
|
2888
|
-
} else if (level < curLevel) {
|
|
2592
|
+
};
|
|
2593
|
+
var snippets = {
|
|
2594
|
+
codeblock: snippet([
|
|
2595
|
+
//
|
|
2596
|
+
"```#{}",
|
|
2597
|
+
"",
|
|
2598
|
+
"```"
|
|
2599
|
+
].join("\n")),
|
|
2600
|
+
table: snippet([
|
|
2601
|
+
//
|
|
2602
|
+
"| #{col1} | #{col2} |",
|
|
2603
|
+
"| ---- | ---- |",
|
|
2604
|
+
"| #{val1} | #{val2} |",
|
|
2605
|
+
"| #{val3} | #{val4} |",
|
|
2606
|
+
""
|
|
2607
|
+
].join("\n"))
|
|
2608
|
+
};
|
|
2609
|
+
var insertTable = (view) => {
|
|
2610
|
+
const { selection: { main }, doc } = view.state;
|
|
2611
|
+
const { number } = doc.lineAt(main.anchor);
|
|
2612
|
+
const { from } = doc.line(number);
|
|
2613
|
+
snippets.table(view, null, from, from);
|
|
2614
|
+
};
|
|
2615
|
+
var removeLinkInner = (from, to, changes, state2) => {
|
|
2616
|
+
syntaxTree(state2).iterate({
|
|
2617
|
+
from,
|
|
2618
|
+
to,
|
|
2619
|
+
enter: (node) => {
|
|
2620
|
+
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
2621
|
+
node.node.cursor().iterate((node2) => {
|
|
2622
|
+
const { name } = node2;
|
|
2623
|
+
if (name === "LinkMark" || name === "LinkLabel") {
|
|
2889
2624
|
changes.push({
|
|
2890
|
-
from:
|
|
2891
|
-
to:
|
|
2625
|
+
from: node2.from,
|
|
2626
|
+
to: node2.to
|
|
2892
2627
|
});
|
|
2893
|
-
} else {
|
|
2628
|
+
} else if (name === "LinkTitle" || name === "URL") {
|
|
2894
2629
|
changes.push({
|
|
2895
|
-
from:
|
|
2896
|
-
|
|
2630
|
+
from: skipSpaces(node2.from, state2.doc, -1),
|
|
2631
|
+
to: skipSpaces(node2.to, state2.doc, 1)
|
|
2897
2632
|
});
|
|
2898
2633
|
}
|
|
2899
|
-
}
|
|
2634
|
+
});
|
|
2635
|
+
return false;
|
|
2900
2636
|
}
|
|
2901
|
-
});
|
|
2902
|
-
let line;
|
|
2903
|
-
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2904
|
-
changes.push({
|
|
2905
|
-
from: line.from,
|
|
2906
|
-
to: line.to,
|
|
2907
|
-
insert: "#".repeat(level) + " "
|
|
2908
|
-
});
|
|
2909
2637
|
}
|
|
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);
|
|
2910
2644
|
}
|
|
2911
|
-
if (!changes
|
|
2645
|
+
if (!changes) {
|
|
2912
2646
|
return false;
|
|
2913
2647
|
}
|
|
2914
|
-
const changeSet = state2.changes(changes);
|
|
2915
2648
|
dispatch(state2.update({
|
|
2916
|
-
changes
|
|
2917
|
-
|
|
2918
|
-
userEvent: "format.setHeading",
|
|
2649
|
+
changes,
|
|
2650
|
+
userEvent: "format.link.remove",
|
|
2919
2651
|
scrollIntoView: true
|
|
2920
2652
|
}));
|
|
2921
2653
|
return true;
|
|
2922
2654
|
};
|
|
2923
|
-
var
|
|
2924
|
-
const marker = inlineMarkerText(type);
|
|
2655
|
+
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
2925
2656
|
const changes = state2.changeByRange((range) => {
|
|
2926
|
-
if (!enable && range.empty) {
|
|
2927
|
-
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2928
|
-
const found = after.indexOf(marker);
|
|
2929
|
-
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2930
|
-
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2931
|
-
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2932
|
-
...before.slice(before.length - found)
|
|
2933
|
-
].reverse().join("") === after.slice(0, found)) {
|
|
2934
|
-
return {
|
|
2935
|
-
changes: [
|
|
2936
|
-
{
|
|
2937
|
-
from: range.head - marker.length - found,
|
|
2938
|
-
to: range.head - found
|
|
2939
|
-
},
|
|
2940
|
-
{
|
|
2941
|
-
from: range.head + found,
|
|
2942
|
-
to: range.head + found + marker.length
|
|
2943
|
-
}
|
|
2944
|
-
],
|
|
2945
|
-
range: EditorSelection.cursor(range.from - marker.length)
|
|
2946
|
-
};
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
|
-
}
|
|
2950
|
-
const changes2 = [];
|
|
2951
|
-
const changesAtEnd = [];
|
|
2952
|
-
let blockStart = -1;
|
|
2953
|
-
let blockEnd = -1;
|
|
2954
|
-
let startCovered = false;
|
|
2955
|
-
let endCovered = false;
|
|
2956
2657
|
let { from, to } = range;
|
|
2957
|
-
|
|
2658
|
+
const cutStyles = [];
|
|
2659
|
+
let okay = null;
|
|
2660
|
+
syntaxTree(state2).iterate({
|
|
2958
2661
|
from,
|
|
2959
2662
|
to,
|
|
2960
2663
|
enter: (node) => {
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
from = node.from;
|
|
2971
|
-
}
|
|
2972
|
-
} else if (IgnoreInline.has(name) && enable) {
|
|
2973
|
-
if (node.from < from && node.to > from) {
|
|
2974
|
-
if (to === from) {
|
|
2975
|
-
to = node.to;
|
|
2976
|
-
}
|
|
2977
|
-
from = node.to;
|
|
2978
|
-
}
|
|
2979
|
-
if (node.from < to && node.to > to) {
|
|
2980
|
-
to = node.from;
|
|
2981
|
-
}
|
|
2982
|
-
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2983
|
-
const markType = InlineMarker[name];
|
|
2984
|
-
const size = inlineMarkerText(markType).length;
|
|
2985
|
-
const openEnd = node.from + size;
|
|
2986
|
-
const closeStart = node.to - size;
|
|
2987
|
-
if (markType === type) {
|
|
2988
|
-
if (openEnd <= from && closeStart >= from) {
|
|
2989
|
-
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2990
|
-
from: node.from,
|
|
2991
|
-
to: openEnd
|
|
2992
|
-
} : true;
|
|
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);
|
|
2993
2673
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
if (markType === type || type === 3 && enable) {
|
|
3002
|
-
if (node.from >= from && openEnd <= to) {
|
|
3003
|
-
changes2.push({
|
|
3004
|
-
from: node.from,
|
|
3005
|
-
to: openEnd
|
|
3006
|
-
});
|
|
3007
|
-
if (markType !== type && closeStart >= to) {
|
|
3008
|
-
changesAtEnd.push({
|
|
3009
|
-
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
3010
|
-
insert: inlineMarkerText(markType)
|
|
3011
|
-
});
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
if (closeStart >= from && node.to <= to) {
|
|
3015
|
-
changes2.push({
|
|
3016
|
-
from: closeStart,
|
|
3017
|
-
to: node.to
|
|
3018
|
-
});
|
|
3019
|
-
if (markType !== type && openEnd <= from) {
|
|
3020
|
-
changes2.push({
|
|
3021
|
-
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
3022
|
-
insert: inlineMarkerText(markType)
|
|
3023
|
-
});
|
|
3024
|
-
}
|
|
3025
|
-
}
|
|
3026
|
-
}
|
|
3027
|
-
}
|
|
3028
|
-
},
|
|
3029
|
-
leave: (node) => {
|
|
3030
|
-
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
3031
|
-
const rangeStart = Math.max(from, blockStart);
|
|
3032
|
-
const rangeEnd = Math.min(to, blockEnd);
|
|
3033
|
-
if (enable) {
|
|
3034
|
-
if (!startCovered) {
|
|
3035
|
-
changes2.push({
|
|
3036
|
-
from: rangeStart,
|
|
3037
|
-
insert: marker
|
|
3038
|
-
});
|
|
3039
|
-
}
|
|
3040
|
-
if (!endCovered) {
|
|
3041
|
-
changes2.push({
|
|
3042
|
-
from: rangeEnd,
|
|
3043
|
-
insert: marker
|
|
3044
|
-
});
|
|
3045
|
-
}
|
|
3046
|
-
} else {
|
|
3047
|
-
if (typeof startCovered === "object") {
|
|
3048
|
-
changes2.push(startCovered);
|
|
3049
|
-
} else if (startCovered) {
|
|
3050
|
-
changes2.push({
|
|
3051
|
-
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
3052
|
-
insert: marker
|
|
3053
|
-
});
|
|
3054
|
-
}
|
|
3055
|
-
if (typeof endCovered === "object") {
|
|
3056
|
-
changes2.push(endCovered);
|
|
3057
|
-
} else if (endCovered) {
|
|
3058
|
-
changes2.push({
|
|
3059
|
-
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
3060
|
-
insert: marker
|
|
3061
|
-
});
|
|
3062
|
-
}
|
|
3063
|
-
}
|
|
3064
|
-
}
|
|
3065
|
-
}
|
|
3066
|
-
});
|
|
3067
|
-
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
3068
|
-
return {
|
|
3069
|
-
changes: {
|
|
3070
|
-
from: range.head,
|
|
3071
|
-
insert: marker + marker
|
|
3072
|
-
},
|
|
3073
|
-
range: EditorSelection.cursor(range.head + marker.length)
|
|
3074
|
-
};
|
|
3075
|
-
}
|
|
3076
|
-
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
3077
|
-
return {
|
|
3078
|
-
changes: changeSet,
|
|
3079
|
-
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
3080
|
-
};
|
|
3081
|
-
});
|
|
3082
|
-
dispatch(state2.update(changes, {
|
|
3083
|
-
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
3084
|
-
scrollIntoView: true
|
|
3085
|
-
}));
|
|
3086
|
-
return true;
|
|
3087
|
-
};
|
|
3088
|
-
var addStyle = (style) => setStyle(style, true);
|
|
3089
|
-
var removeStyle = (style) => setStyle(style, false);
|
|
3090
|
-
var toggleStyle = (style) => (arg) => {
|
|
3091
|
-
const form = getFormatting(arg.state);
|
|
3092
|
-
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
3093
|
-
};
|
|
3094
|
-
var toggleStrong = toggleStyle(0);
|
|
3095
|
-
var toggleEmphasis = toggleStyle(1);
|
|
3096
|
-
var toggleStrikethrough = toggleStyle(2);
|
|
3097
|
-
var toggleInlineCode = toggleStyle(3);
|
|
3098
|
-
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
3099
|
-
var blockContentStart = (node) => {
|
|
3100
|
-
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
3101
|
-
if (atx) {
|
|
3102
|
-
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
3103
|
-
}
|
|
3104
|
-
return node.from;
|
|
3105
|
-
};
|
|
3106
|
-
var blockContentEnd = (node, doc) => {
|
|
3107
|
-
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
3108
|
-
const lastLine = doc.lineAt(node.to);
|
|
3109
|
-
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
3110
|
-
return lastLine.from - 1;
|
|
3111
|
-
}
|
|
3112
|
-
return node.to;
|
|
3113
|
-
};
|
|
3114
|
-
var skipSpaces = (pos, doc, dir, limit) => {
|
|
3115
|
-
const line = doc.lineAt(pos);
|
|
3116
|
-
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
3117
|
-
pos += dir;
|
|
3118
|
-
}
|
|
3119
|
-
return pos;
|
|
3120
|
-
};
|
|
3121
|
-
var skipMarkers = (pos, tree, dir, limit) => {
|
|
3122
|
-
for (; ; ) {
|
|
3123
|
-
const next = tree.resolve(pos, dir);
|
|
3124
|
-
if (!IgnoreInline.has(next.name)) {
|
|
3125
|
-
return pos;
|
|
3126
|
-
}
|
|
3127
|
-
const moveTo = dir < 0 ? next.from : next.to;
|
|
3128
|
-
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
3129
|
-
return pos;
|
|
3130
|
-
}
|
|
3131
|
-
pos = moveTo;
|
|
3132
|
-
}
|
|
3133
|
-
};
|
|
3134
|
-
var snippets = {
|
|
3135
|
-
codeblock: snippet([
|
|
3136
|
-
//
|
|
3137
|
-
"```#{}",
|
|
3138
|
-
"",
|
|
3139
|
-
"```"
|
|
3140
|
-
].join("\n")),
|
|
3141
|
-
table: snippet([
|
|
3142
|
-
//
|
|
3143
|
-
"| #{col1} | #{col2} |",
|
|
3144
|
-
"| ---- | ---- |",
|
|
3145
|
-
"| #{val1} | #{val2} |",
|
|
3146
|
-
"| #{val3} | #{val4} |",
|
|
3147
|
-
""
|
|
3148
|
-
].join("\n"))
|
|
3149
|
-
};
|
|
3150
|
-
var insertTable = (view) => {
|
|
3151
|
-
const { selection: { main }, doc } = view.state;
|
|
3152
|
-
const { number } = doc.lineAt(main.anchor);
|
|
3153
|
-
const { from } = doc.line(number);
|
|
3154
|
-
snippets.table(view, null, from, from);
|
|
3155
|
-
};
|
|
3156
|
-
var removeLinkInner = (from, to, changes, state2) => {
|
|
3157
|
-
syntaxTree2(state2).iterate({
|
|
3158
|
-
from,
|
|
3159
|
-
to,
|
|
3160
|
-
enter: (node) => {
|
|
3161
|
-
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
3162
|
-
node.node.cursor().iterate((node2) => {
|
|
3163
|
-
const { name } = node2;
|
|
3164
|
-
if (name === "LinkMark" || name === "LinkLabel") {
|
|
3165
|
-
changes.push({
|
|
3166
|
-
from: node2.from,
|
|
3167
|
-
to: node2.to
|
|
3168
|
-
});
|
|
3169
|
-
} else if (name === "LinkTitle" || name === "URL") {
|
|
3170
|
-
changes.push({
|
|
3171
|
-
from: skipSpaces(node2.from, state2.doc, -1),
|
|
3172
|
-
to: skipSpaces(node2.to, state2.doc, 1)
|
|
3173
|
-
});
|
|
3174
|
-
}
|
|
3175
|
-
});
|
|
3176
|
-
return false;
|
|
3177
|
-
}
|
|
3178
|
-
}
|
|
3179
|
-
});
|
|
3180
|
-
};
|
|
3181
|
-
var removeLink = ({ state: state2, dispatch }) => {
|
|
3182
|
-
const changes = [];
|
|
3183
|
-
for (const { from, to } of state2.selection.ranges) {
|
|
3184
|
-
removeLinkInner(from, to, changes, state2);
|
|
3185
|
-
}
|
|
3186
|
-
if (!changes) {
|
|
3187
|
-
return false;
|
|
3188
|
-
}
|
|
3189
|
-
dispatch(state2.update({
|
|
3190
|
-
changes,
|
|
3191
|
-
userEvent: "format.link.remove",
|
|
3192
|
-
scrollIntoView: true
|
|
3193
|
-
}));
|
|
3194
|
-
return true;
|
|
3195
|
-
};
|
|
3196
|
-
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
3197
|
-
const changes = state2.changeByRange((range) => {
|
|
3198
|
-
let { from, to } = range;
|
|
3199
|
-
const cutStyles = [];
|
|
3200
|
-
let okay = null;
|
|
3201
|
-
syntaxTree2(state2).iterate({
|
|
3202
|
-
from,
|
|
3203
|
-
to,
|
|
3204
|
-
enter: (node) => {
|
|
3205
|
-
if (Object.hasOwn(Textblocks, node.name)) {
|
|
3206
|
-
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
3207
|
-
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
3208
|
-
const sNode = node.node;
|
|
3209
|
-
if (node.from < from && node.to <= to) {
|
|
3210
|
-
if (sNode.firstChild.to === from) {
|
|
3211
|
-
from = node.from;
|
|
3212
|
-
} else {
|
|
3213
|
-
cutStyles.push(sNode);
|
|
3214
|
-
}
|
|
3215
|
-
} else if (node.from >= from && node.to > to) {
|
|
3216
|
-
if (sNode.lastChild.from === to) {
|
|
3217
|
-
to = node.to;
|
|
3218
|
-
} else {
|
|
3219
|
-
cutStyles.push(sNode);
|
|
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);
|
|
3220
2679
|
}
|
|
3221
2680
|
}
|
|
3222
2681
|
}
|
|
@@ -3291,7 +2750,7 @@ var addList = (type) => ({ state: state2, dispatch }) => {
|
|
|
3291
2750
|
let parentColumn = null;
|
|
3292
2751
|
const blocks = [];
|
|
3293
2752
|
for (const { from, to } of state2.selection.ranges) {
|
|
3294
|
-
|
|
2753
|
+
syntaxTree(state2).iterate({
|
|
3295
2754
|
from,
|
|
3296
2755
|
to,
|
|
3297
2756
|
enter: (node) => {
|
|
@@ -3424,7 +2883,7 @@ var removeList = (type) => ({ state: state2, dispatch }) => {
|
|
|
3424
2883
|
const stack = [];
|
|
3425
2884
|
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
3426
2885
|
for (const { from, to } of state2.selection.ranges) {
|
|
3427
|
-
|
|
2886
|
+
syntaxTree(state2).iterate({
|
|
3428
2887
|
from,
|
|
3429
2888
|
to,
|
|
3430
2889
|
enter: (node) => {
|
|
@@ -3507,7 +2966,7 @@ var setBlockquote = (enable) => ({ state: state2, dispatch }) => {
|
|
|
3507
2966
|
let lastBlock = -1;
|
|
3508
2967
|
for (const { from, to } of state2.selection.ranges) {
|
|
3509
2968
|
const sawBlock = false;
|
|
3510
|
-
|
|
2969
|
+
syntaxTree(state2).iterate({
|
|
3511
2970
|
from,
|
|
3512
2971
|
to,
|
|
3513
2972
|
enter: (node) => {
|
|
@@ -3596,7 +3055,7 @@ var addCodeblock = (target) => {
|
|
|
3596
3055
|
for (const { from, to } of selection.ranges) {
|
|
3597
3056
|
let blockFrom = from;
|
|
3598
3057
|
let blockTo = to;
|
|
3599
|
-
|
|
3058
|
+
syntaxTree(state2).iterate({
|
|
3600
3059
|
from,
|
|
3601
3060
|
to,
|
|
3602
3061
|
enter: (node) => {
|
|
@@ -3620,304 +3079,855 @@ var addCodeblock = (target) => {
|
|
|
3620
3079
|
});
|
|
3621
3080
|
}
|
|
3622
3081
|
}
|
|
3623
|
-
if (!ranges.length) {
|
|
3624
|
-
return false;
|
|
3082
|
+
if (!ranges.length) {
|
|
3083
|
+
return false;
|
|
3084
|
+
}
|
|
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",
|
|
3101
|
+
scrollIntoView: true
|
|
3102
|
+
}));
|
|
3103
|
+
return true;
|
|
3104
|
+
};
|
|
3105
|
+
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3106
|
+
const changes = [];
|
|
3107
|
+
let lastBlock = -1;
|
|
3108
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3109
|
+
syntaxTree(state2).iterate({
|
|
3110
|
+
from,
|
|
3111
|
+
to,
|
|
3112
|
+
enter: (node) => {
|
|
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
|
+
});
|
|
3127
|
+
}
|
|
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;
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
});
|
|
3143
|
+
}
|
|
3144
|
+
if (!changes.length) {
|
|
3145
|
+
return false;
|
|
3146
|
+
}
|
|
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;
|
|
3222
|
+
}
|
|
3223
|
+
upto = Math.min(upto, currentBlock.end);
|
|
3224
|
+
if (upto <= currentBlock.pos) {
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
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;
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
currentBlock.pos = upto;
|
|
3237
|
+
};
|
|
3238
|
+
const skipInline = (upto) => {
|
|
3239
|
+
if (currentBlock && upto > currentBlock.pos) {
|
|
3240
|
+
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3241
|
+
}
|
|
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
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
syntaxTree(state2).iterate({
|
|
3268
|
+
from: range.from,
|
|
3269
|
+
to: range.to,
|
|
3270
|
+
enter: (node) => {
|
|
3271
|
+
advanceInline(node.from);
|
|
3272
|
+
const { name } = node;
|
|
3273
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3274
|
+
stack.push(name);
|
|
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);
|
|
3307
|
+
}
|
|
3308
|
+
},
|
|
3309
|
+
leave: (node) => {
|
|
3310
|
+
advanceInline(node.to);
|
|
3311
|
+
const { name } = node;
|
|
3312
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3313
|
+
stack.pop();
|
|
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";
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
if (blockQuote === null) {
|
|
3325
|
+
blockQuote = hasQuote;
|
|
3326
|
+
} else if (!hasQuote && blockQuote) {
|
|
3327
|
+
blockQuote = false;
|
|
3328
|
+
}
|
|
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;
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
});
|
|
3340
|
+
}
|
|
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
|
+
};
|
|
3354
|
+
};
|
|
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;
|
|
3365
|
+
});
|
|
3366
|
+
}
|
|
3367
|
+
}), [
|
|
3368
|
+
setState
|
|
3369
|
+
]);
|
|
3370
|
+
return [
|
|
3371
|
+
state2,
|
|
3372
|
+
observer
|
|
3373
|
+
];
|
|
3374
|
+
};
|
|
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;
|
|
3417
|
+
}
|
|
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;
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
});
|
|
3463
|
+
var markdownTagsExtensions = [
|
|
3464
|
+
Table,
|
|
3465
|
+
{
|
|
3466
|
+
props: [
|
|
3467
|
+
styleTags(markdownTags)
|
|
3468
|
+
]
|
|
3469
|
+
}
|
|
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"
|
|
3614
|
+
}
|
|
3615
|
+
], {
|
|
3616
|
+
scope: markdownLanguage2,
|
|
3617
|
+
all: {
|
|
3618
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
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;
|
|
3669
|
+
}
|
|
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;
|
|
3625
3684
|
}
|
|
3626
|
-
const changes = ranges.map(({ from, to }) => {
|
|
3627
|
-
const column = from - state2.doc.lineAt(from).from;
|
|
3628
|
-
return [
|
|
3629
|
-
{
|
|
3630
|
-
from,
|
|
3631
|
-
insert: "```\n" + " ".repeat(column)
|
|
3632
|
-
},
|
|
3633
|
-
{
|
|
3634
|
-
from: to,
|
|
3635
|
-
insert: "\n" + " ".repeat(column) + "```"
|
|
3636
|
-
}
|
|
3637
|
-
];
|
|
3638
|
-
});
|
|
3639
|
-
dispatch(state2.update({
|
|
3640
|
-
changes,
|
|
3641
|
-
userEvent: "format.codeblock.add",
|
|
3642
|
-
scrollIntoView: true
|
|
3643
|
-
}));
|
|
3644
|
-
return true;
|
|
3645
3685
|
};
|
|
3646
|
-
var
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3672
|
-
changes.push({
|
|
3673
|
-
from: line.from + column - 4,
|
|
3674
|
-
to: line.from + column
|
|
3675
|
-
});
|
|
3676
|
-
if (line.to >= node.to) {
|
|
3677
|
-
break;
|
|
3678
|
-
}
|
|
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"
|
|
3679
3711
|
}
|
|
3680
|
-
}
|
|
3712
|
+
});
|
|
3713
|
+
event.preventDefault();
|
|
3681
3714
|
}
|
|
3682
|
-
}
|
|
3683
|
-
}
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
return input;
|
|
3684
3718
|
}
|
|
3685
|
-
|
|
3719
|
+
ignoreEvent() {
|
|
3686
3720
|
return false;
|
|
3687
3721
|
}
|
|
3688
|
-
dispatch(state2.update({
|
|
3689
|
-
changes,
|
|
3690
|
-
userEvent: "format.codeblock.remove",
|
|
3691
|
-
scrollIntoView: true
|
|
3692
|
-
}));
|
|
3693
|
-
return true;
|
|
3694
|
-
};
|
|
3695
|
-
var toggleCodeblock = (target) => {
|
|
3696
|
-
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3697
|
-
};
|
|
3698
|
-
var formattingKeymap = (options = {}) => {
|
|
3699
|
-
return [
|
|
3700
|
-
keymap7.of([
|
|
3701
|
-
{
|
|
3702
|
-
key: "meta-b",
|
|
3703
|
-
run: toggleStrong
|
|
3704
|
-
}
|
|
3705
|
-
])
|
|
3706
|
-
];
|
|
3707
3722
|
};
|
|
3708
|
-
var
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
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;
|
|
3713
3745
|
};
|
|
3714
|
-
var
|
|
3715
|
-
"Autolink",
|
|
3746
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
3716
3747
|
"CodeMark",
|
|
3717
|
-
"CodeText",
|
|
3718
|
-
"Comment",
|
|
3719
3748
|
"EmphasisMark",
|
|
3720
|
-
"
|
|
3721
|
-
"
|
|
3722
|
-
"
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
let blockType = null;
|
|
3749
|
-
const inline = [
|
|
3750
|
-
null,
|
|
3751
|
-
null,
|
|
3752
|
-
null,
|
|
3753
|
-
null
|
|
3754
|
-
];
|
|
3755
|
-
let link = false;
|
|
3756
|
-
let blockQuote = null;
|
|
3757
|
-
let listStyle = null;
|
|
3758
|
-
const stack = [];
|
|
3759
|
-
let currentBlock = null;
|
|
3760
|
-
const advanceInline = (upto) => {
|
|
3761
|
-
if (!currentBlock) {
|
|
3762
|
-
return;
|
|
3763
|
-
}
|
|
3764
|
-
upto = Math.min(upto, currentBlock.end);
|
|
3765
|
-
if (upto <= currentBlock.pos) {
|
|
3766
|
-
return;
|
|
3767
|
-
}
|
|
3768
|
-
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
3769
|
-
if (inline[i] === false) {
|
|
3770
|
-
continue;
|
|
3771
|
-
} else if (currentBlock.active[i]) {
|
|
3772
|
-
inline[i] = true;
|
|
3773
|
-
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3774
|
-
inline[i] = false;
|
|
3775
|
-
}
|
|
3776
|
-
}
|
|
3777
|
-
currentBlock.pos = upto;
|
|
3778
|
-
};
|
|
3779
|
-
const skipInline = (upto) => {
|
|
3780
|
-
if (currentBlock && upto > currentBlock.pos) {
|
|
3781
|
-
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3782
|
-
}
|
|
3783
|
-
};
|
|
3784
|
-
const { selection } = state2;
|
|
3785
|
-
for (const range of selection.ranges) {
|
|
3786
|
-
if (range.empty && inline.some((v) => v === null)) {
|
|
3787
|
-
const contextSize = Math.min(range.head, 6);
|
|
3788
|
-
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3789
|
-
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3790
|
-
for (let i = 0; i < contextSize; i++) {
|
|
3791
|
-
const ch = contextAfter[i];
|
|
3792
|
-
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
3793
|
-
contextAfter = contextAfter.slice(0, i);
|
|
3794
|
-
break;
|
|
3795
|
-
}
|
|
3796
|
-
}
|
|
3797
|
-
for (let i = 0; i < inline.length; i++) {
|
|
3798
|
-
const mark2 = inlineMarkerText(i);
|
|
3799
|
-
const found = contextAfter.indexOf(mark2);
|
|
3800
|
-
if (found > -1) {
|
|
3801
|
-
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
3802
|
-
if (inline[i] === null) {
|
|
3803
|
-
inline[i] = true;
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
}
|
|
3807
|
-
}
|
|
3808
|
-
syntaxTree2(state2).iterate({
|
|
3809
|
-
from: range.from,
|
|
3810
|
-
to: range.to,
|
|
3811
|
-
enter: (node) => {
|
|
3812
|
-
advanceInline(node.from);
|
|
3813
|
-
const { name } = node;
|
|
3814
|
-
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3815
|
-
stack.push(name);
|
|
3816
|
-
} else if (name === "Link") {
|
|
3817
|
-
link = true;
|
|
3818
|
-
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
3819
|
-
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
3820
|
-
stack[stack.length - 1] = "TaskList";
|
|
3821
|
-
}
|
|
3822
|
-
const blockCode = Textblocks[name];
|
|
3823
|
-
if (blockType === null) {
|
|
3824
|
-
blockType = blockCode;
|
|
3825
|
-
} else if (blockType !== blockCode) {
|
|
3826
|
-
blockType = false;
|
|
3749
|
+
"StrikethroughMark",
|
|
3750
|
+
"SubscriptMark",
|
|
3751
|
+
"SuperscriptMark"
|
|
3752
|
+
]);
|
|
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,
|
|
3761
|
+
enter: (node) => {
|
|
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
|
+
}
|
|
3827
3777
|
}
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
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
|
+
}
|
|
3839
3802
|
}
|
|
3840
|
-
} else if (
|
|
3841
|
-
const
|
|
3842
|
-
if (
|
|
3843
|
-
|
|
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);
|
|
3844
3808
|
}
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
}
|
|
3849
|
-
},
|
|
3850
|
-
leave: (node) => {
|
|
3851
|
-
advanceInline(node.to);
|
|
3852
|
-
const { name } = node;
|
|
3853
|
-
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3854
|
-
stack.pop();
|
|
3855
|
-
} else if (Object.hasOwn(Textblocks, name)) {
|
|
3856
|
-
let hasList = false;
|
|
3857
|
-
let hasQuote = false;
|
|
3858
|
-
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3859
|
-
if (stack[i] === "Blockquote") {
|
|
3860
|
-
hasQuote = true;
|
|
3861
|
-
} else if (!hasList) {
|
|
3862
|
-
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
3863
|
-
}
|
|
3809
|
+
} else if (node.name === "HorizontalRule") {
|
|
3810
|
+
if (!editingRange(state2, node, focus)) {
|
|
3811
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
3864
3812
|
}
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
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);
|
|
3869
3820
|
}
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
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);
|
|
3874
3824
|
}
|
|
3875
|
-
currentBlock = null;
|
|
3876
|
-
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3877
|
-
currentBlock.active[InlineMarker[name]] = false;
|
|
3878
3825
|
}
|
|
3879
3826
|
}
|
|
3880
3827
|
});
|
|
3881
3828
|
}
|
|
3882
|
-
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3883
|
-
const blankLine = from === to;
|
|
3884
3829
|
return {
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
blockQuote: blockQuote ?? false,
|
|
3888
|
-
code: inline[3] ?? false,
|
|
3889
|
-
emphasis: inline[1] ?? false,
|
|
3890
|
-
strong: inline[0] ?? false,
|
|
3891
|
-
strikethrough: inline[2] ?? false,
|
|
3892
|
-
link,
|
|
3893
|
-
listStyle: listStyle || null
|
|
3830
|
+
deco: deco.finish(),
|
|
3831
|
+
atomicDeco: atomicDeco.finish()
|
|
3894
3832
|
};
|
|
3895
3833
|
};
|
|
3896
|
-
var
|
|
3897
|
-
|
|
3898
|
-
const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
|
|
3899
|
-
if (update2.docChanged || update2.selectionSet) {
|
|
3900
|
-
setState((prevState) => {
|
|
3901
|
-
const newState = getFormatting(update2.state);
|
|
3902
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
|
3903
|
-
return newState;
|
|
3904
|
-
}
|
|
3905
|
-
return prevState;
|
|
3906
|
-
});
|
|
3907
|
-
}
|
|
3908
|
-
}), [
|
|
3909
|
-
setState
|
|
3910
|
-
]);
|
|
3834
|
+
var forceUpdate = StateEffect4.define();
|
|
3835
|
+
var decorateMarkdown = (options = {}) => {
|
|
3911
3836
|
return [
|
|
3912
|
-
|
|
3913
|
-
|
|
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
|
|
3914
3876
|
];
|
|
3915
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
|
+
});
|
|
3916
3926
|
|
|
3917
3927
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3918
3928
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3919
3929
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
3920
|
-
import { Decoration as Decoration6, EditorView as
|
|
3930
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3921
3931
|
var image = (options = {}) => {
|
|
3922
3932
|
return StateField5.define({
|
|
3923
3933
|
create: (state2) => {
|
|
@@ -3944,7 +3954,7 @@ var image = (options = {}) => {
|
|
|
3944
3954
|
add: buildDecorations2(from, to, tr.state)
|
|
3945
3955
|
});
|
|
3946
3956
|
},
|
|
3947
|
-
provide: (field) =>
|
|
3957
|
+
provide: (field) => EditorView13.decorations.from(field)
|
|
3948
3958
|
});
|
|
3949
3959
|
};
|
|
3950
3960
|
var preloaded = /* @__PURE__ */ new Set();
|
|
@@ -4034,12 +4044,12 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
|
4034
4044
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
4035
4045
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4036
4046
|
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
4037
|
-
import { Decoration as Decoration7, EditorView as
|
|
4047
|
+
import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4038
4048
|
var table = (options = {}) => {
|
|
4039
4049
|
return StateField6.define({
|
|
4040
4050
|
create: (state2) => update(state2, options),
|
|
4041
4051
|
update: (_, tr) => update(tr.state, options),
|
|
4042
|
-
provide: (field) =>
|
|
4052
|
+
provide: (field) => EditorView14.decorations.from(field)
|
|
4043
4053
|
});
|
|
4044
4054
|
};
|
|
4045
4055
|
var update = (state2, options) => {
|
|
@@ -4133,8 +4143,8 @@ var TableWidget = class extends WidgetType5 {
|
|
|
4133
4143
|
|
|
4134
4144
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
4135
4145
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
4136
|
-
import { log as
|
|
4137
|
-
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";
|
|
4138
4148
|
var mention = ({ onSearch }) => {
|
|
4139
4149
|
return autocompletion2({
|
|
4140
4150
|
// TODO(burdon): Not working.
|
|
@@ -4146,10 +4156,10 @@ var mention = ({ onSearch }) => {
|
|
|
4146
4156
|
icons: false,
|
|
4147
4157
|
override: [
|
|
4148
4158
|
(context) => {
|
|
4149
|
-
|
|
4159
|
+
log6.info("completion context", {
|
|
4150
4160
|
context
|
|
4151
4161
|
}, {
|
|
4152
|
-
F:
|
|
4162
|
+
F: __dxlog_file8,
|
|
4153
4163
|
L: 26,
|
|
4154
4164
|
S: void 0,
|
|
4155
4165
|
C: (f, a) => f(...a)
|
|
@@ -4209,18 +4219,18 @@ var EditorModes = {
|
|
|
4209
4219
|
};
|
|
4210
4220
|
|
|
4211
4221
|
// packages/ui/react-ui-editor/src/extensions/state.ts
|
|
4212
|
-
import { Transaction
|
|
4213
|
-
import { EditorView as
|
|
4222
|
+
import { Transaction } from "@codemirror/state";
|
|
4223
|
+
import { EditorView as EditorView15, keymap as keymap9 } from "@codemirror/view";
|
|
4214
4224
|
import { debounce as debounce2 } from "@dxos/async";
|
|
4215
4225
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4216
4226
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4217
|
-
var
|
|
4227
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4218
4228
|
var scrollAnnotation = "dxos.org/cm/scrolling";
|
|
4219
4229
|
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4220
4230
|
var localStorageStateStoreAdapter = {
|
|
4221
4231
|
setState: (id, state2) => {
|
|
4222
4232
|
invariant4(id, void 0, {
|
|
4223
|
-
F:
|
|
4233
|
+
F: __dxlog_file9,
|
|
4224
4234
|
L: 35,
|
|
4225
4235
|
S: void 0,
|
|
4226
4236
|
A: [
|
|
@@ -4232,7 +4242,7 @@ var localStorageStateStoreAdapter = {
|
|
|
4232
4242
|
},
|
|
4233
4243
|
getState: (id) => {
|
|
4234
4244
|
invariant4(id, void 0, {
|
|
4235
|
-
F:
|
|
4245
|
+
F: __dxlog_file9,
|
|
4236
4246
|
L: 39,
|
|
4237
4247
|
S: void 0,
|
|
4238
4248
|
A: [
|
|
@@ -4248,7 +4258,7 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4248
4258
|
const setStateDebounced = debounce2(setState, 1e3);
|
|
4249
4259
|
return [
|
|
4250
4260
|
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4251
|
-
|
|
4261
|
+
EditorView15.updateListener.of(({ view, changes, transactions }) => {
|
|
4252
4262
|
const id = view.state.facet(documentId2);
|
|
4253
4263
|
if (!id || transactions.some((tr) => tr.isUserEvent(scrollAnnotation))) {
|
|
4254
4264
|
return;
|
|
@@ -4281,11 +4291,11 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4281
4291
|
const state2 = getState(view.state.facet(documentId2));
|
|
4282
4292
|
if (state2) {
|
|
4283
4293
|
view.dispatch({
|
|
4284
|
-
effects:
|
|
4294
|
+
effects: EditorView15.scrollIntoView(state2.scrollTo.from, {
|
|
4285
4295
|
yMargin: 0
|
|
4286
4296
|
}),
|
|
4287
4297
|
selection: state2.selection,
|
|
4288
|
-
annotations:
|
|
4298
|
+
annotations: Transaction.userEvent.of(scrollAnnotation)
|
|
4289
4299
|
});
|
|
4290
4300
|
}
|
|
4291
4301
|
return true;
|
|
@@ -4353,9 +4363,9 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4353
4363
|
};
|
|
4354
4364
|
|
|
4355
4365
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4356
|
-
var
|
|
4366
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4357
4367
|
var instanceCount = 0;
|
|
4358
|
-
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, {
|
|
4359
4369
|
yMargin: 0
|
|
4360
4370
|
}), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
|
|
4361
4371
|
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
@@ -4376,11 +4386,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4376
4386
|
autoFocus
|
|
4377
4387
|
]);
|
|
4378
4388
|
useEffect2(() => {
|
|
4379
|
-
|
|
4389
|
+
log7("create", {
|
|
4380
4390
|
id,
|
|
4381
4391
|
instanceId
|
|
4382
4392
|
}, {
|
|
4383
|
-
F:
|
|
4393
|
+
F: __dxlog_file10,
|
|
4384
4394
|
L: 88,
|
|
4385
4395
|
S: void 0,
|
|
4386
4396
|
C: (f, a) => f(...a)
|
|
@@ -4391,16 +4401,16 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4391
4401
|
extensions: [
|
|
4392
4402
|
id && documentId2.of(id),
|
|
4393
4403
|
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
F:
|
|
4404
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4405
|
+
log7.catch(err, void 0, {
|
|
4406
|
+
F: __dxlog_file10,
|
|
4397
4407
|
L: 101,
|
|
4398
4408
|
S: void 0,
|
|
4399
4409
|
C: (f, a) => f(...a)
|
|
4400
4410
|
});
|
|
4401
4411
|
}),
|
|
4402
4412
|
// Focus.
|
|
4403
|
-
|
|
4413
|
+
EditorView16.updateListener.of((update2) => {
|
|
4404
4414
|
update2.transactions.forEach((transaction) => {
|
|
4405
4415
|
if (transaction.isUserEvent(focusEvent)) {
|
|
4406
4416
|
rootRef.current?.focus();
|
|
@@ -4410,7 +4420,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4410
4420
|
extensions
|
|
4411
4421
|
].filter(isNotFalsy4)
|
|
4412
4422
|
});
|
|
4413
|
-
const view2 = new
|
|
4423
|
+
const view2 = new EditorView16({
|
|
4414
4424
|
state: state2,
|
|
4415
4425
|
parent: rootRef.current,
|
|
4416
4426
|
scrollTo,
|
|
@@ -4436,11 +4446,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4436
4446
|
}
|
|
4437
4447
|
setView(view2);
|
|
4438
4448
|
return () => {
|
|
4439
|
-
|
|
4449
|
+
log7("destroy", {
|
|
4440
4450
|
id,
|
|
4441
4451
|
instanceId
|
|
4442
4452
|
}, {
|
|
4443
|
-
F:
|
|
4453
|
+
F: __dxlog_file10,
|
|
4444
4454
|
L: 150,
|
|
4445
4455
|
S: void 0,
|
|
4446
4456
|
C: (f, a) => f(...a)
|
|
@@ -4746,7 +4756,7 @@ var MarkdownCustom = ({ onUpload } = {}) => {
|
|
|
4746
4756
|
});
|
|
4747
4757
|
useEffect3(() => {
|
|
4748
4758
|
if (onUpload && acceptedFiles.length) {
|
|
4749
|
-
|
|
4759
|
+
requestAnimationFrame(async () => {
|
|
4750
4760
|
const f = acceptedFiles[0];
|
|
4751
4761
|
const file = new File([
|
|
4752
4762
|
f
|
|
@@ -4795,56 +4805,7 @@ var Toolbar = {
|
|
|
4795
4805
|
|
|
4796
4806
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4797
4807
|
var useActionHandler = (view) => {
|
|
4798
|
-
return (action) =>
|
|
4799
|
-
if (!view) {
|
|
4800
|
-
return;
|
|
4801
|
-
}
|
|
4802
|
-
let inlineType, listType;
|
|
4803
|
-
switch (action.type) {
|
|
4804
|
-
case "heading":
|
|
4805
|
-
setHeading(parseInt(action.data))(view);
|
|
4806
|
-
break;
|
|
4807
|
-
case "strong":
|
|
4808
|
-
case "emphasis":
|
|
4809
|
-
case "strikethrough":
|
|
4810
|
-
case "code":
|
|
4811
|
-
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4812
|
-
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
4813
|
-
break;
|
|
4814
|
-
case "list-ordered":
|
|
4815
|
-
case "list-bullet":
|
|
4816
|
-
case "list-task":
|
|
4817
|
-
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4818
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4819
|
-
break;
|
|
4820
|
-
case "blockquote":
|
|
4821
|
-
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
4822
|
-
break;
|
|
4823
|
-
case "codeblock":
|
|
4824
|
-
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
4825
|
-
break;
|
|
4826
|
-
case "table":
|
|
4827
|
-
insertTable(view);
|
|
4828
|
-
break;
|
|
4829
|
-
case "link":
|
|
4830
|
-
(action.data === false ? removeLink : addLink())(view);
|
|
4831
|
-
break;
|
|
4832
|
-
case "image":
|
|
4833
|
-
addLink({
|
|
4834
|
-
url: action.data,
|
|
4835
|
-
image: true
|
|
4836
|
-
})(view);
|
|
4837
|
-
break;
|
|
4838
|
-
case "comment":
|
|
4839
|
-
createComment(view);
|
|
4840
|
-
break;
|
|
4841
|
-
}
|
|
4842
|
-
setTimeout(() => {
|
|
4843
|
-
if (!view.hasFocus) {
|
|
4844
|
-
view.focus();
|
|
4845
|
-
}
|
|
4846
|
-
});
|
|
4847
|
-
};
|
|
4808
|
+
return (action) => view && processAction(view, action);
|
|
4848
4809
|
};
|
|
4849
4810
|
|
|
4850
4811
|
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
@@ -4862,11 +4823,11 @@ var useDocAccessor = (text) => {
|
|
|
4862
4823
|
|
|
4863
4824
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4864
4825
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4865
|
-
import { EditorView as
|
|
4826
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4866
4827
|
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4867
|
-
import { log as
|
|
4828
|
+
import { log as log8 } from "@dxos/log";
|
|
4868
4829
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4869
|
-
var
|
|
4830
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4870
4831
|
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4871
4832
|
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4872
4833
|
const onUpdate = useRef3();
|
|
@@ -4875,10 +4836,10 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4875
4836
|
useEffect4(() => {
|
|
4876
4837
|
let view2;
|
|
4877
4838
|
if (parentRef.current) {
|
|
4878
|
-
|
|
4839
|
+
log8("create", {
|
|
4879
4840
|
id
|
|
4880
4841
|
}, {
|
|
4881
|
-
F:
|
|
4842
|
+
F: __dxlog_file11,
|
|
4882
4843
|
L: 36,
|
|
4883
4844
|
S: void 0,
|
|
4884
4845
|
C: (f, a) => f(...a)
|
|
@@ -4889,21 +4850,21 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4889
4850
|
extensions: [
|
|
4890
4851
|
id && documentId2.of(id),
|
|
4891
4852
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
F:
|
|
4853
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4854
|
+
log8.catch(err, void 0, {
|
|
4855
|
+
F: __dxlog_file11,
|
|
4895
4856
|
L: 46,
|
|
4896
4857
|
S: void 0,
|
|
4897
4858
|
C: (f, a) => f(...a)
|
|
4898
4859
|
});
|
|
4899
4860
|
}),
|
|
4900
4861
|
extensions,
|
|
4901
|
-
|
|
4862
|
+
EditorView17.updateListener.of(() => {
|
|
4902
4863
|
onUpdate.current?.();
|
|
4903
4864
|
})
|
|
4904
4865
|
].filter(isNotFalsy5)
|
|
4905
4866
|
});
|
|
4906
|
-
view2 = new
|
|
4867
|
+
view2 = new EditorView17({
|
|
4907
4868
|
parent: parentRef.current,
|
|
4908
4869
|
scrollTo,
|
|
4909
4870
|
state: state2,
|
|
@@ -4919,10 +4880,10 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4919
4880
|
setView(view2);
|
|
4920
4881
|
}
|
|
4921
4882
|
return () => {
|
|
4922
|
-
|
|
4883
|
+
log8("destroy", {
|
|
4923
4884
|
id
|
|
4924
4885
|
}, {
|
|
4925
|
-
F:
|
|
4886
|
+
F: __dxlog_file11,
|
|
4926
4887
|
L: 74,
|
|
4927
4888
|
S: void 0,
|
|
4928
4889
|
C: (f, a) => f(...a)
|
|
@@ -4994,12 +4955,11 @@ export {
|
|
|
4994
4955
|
createDataExtensions,
|
|
4995
4956
|
createMarkdownExtensions,
|
|
4996
4957
|
createThemeExtensions,
|
|
4997
|
-
cursorLineMargin,
|
|
4998
4958
|
decorateMarkdown,
|
|
4999
4959
|
defaultOptions,
|
|
5000
4960
|
defaultTheme,
|
|
5001
|
-
dnd,
|
|
5002
4961
|
documentId2 as documentId,
|
|
4962
|
+
dropFile,
|
|
5003
4963
|
editorFillLayoutEditor,
|
|
5004
4964
|
editorFillLayoutRoot,
|
|
5005
4965
|
editorMode,
|
|
@@ -5022,6 +4982,7 @@ export {
|
|
|
5022
4982
|
markdownTags,
|
|
5023
4983
|
markdownTagsExtensions,
|
|
5024
4984
|
mention,
|
|
4985
|
+
processAction,
|
|
5025
4986
|
removeBlockquote,
|
|
5026
4987
|
removeCodeblock,
|
|
5027
4988
|
removeLink,
|