@dxos/react-ui-editor 0.4.8-main.46f461d → 0.4.8-main.4ad174a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +1285 -1323
- 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 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +0 -1
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts +9 -0
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/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 +14 -8
- 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, crosshairCursor, 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,7 +2163,7 @@ var defaultTheme = {
|
|
|
2208
2163
|
};
|
|
2209
2164
|
|
|
2210
2165
|
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2211
|
-
var
|
|
2166
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
|
2212
2167
|
var defaults = {
|
|
2213
2168
|
allowMultipleSelections: true,
|
|
2214
2169
|
bracketMatching: true,
|
|
@@ -2217,16 +2172,23 @@ var defaults = {
|
|
|
2217
2172
|
editable: true,
|
|
2218
2173
|
history: true,
|
|
2219
2174
|
lineWrapping: true,
|
|
2220
|
-
search: true
|
|
2175
|
+
search: true,
|
|
2176
|
+
keymap: "standard"
|
|
2177
|
+
};
|
|
2178
|
+
var keymaps = {
|
|
2179
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2180
|
+
standard: standardKeymap,
|
|
2181
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
2182
|
+
default: defaultKeymap
|
|
2221
2183
|
};
|
|
2222
2184
|
var createBasicExtensions = (_props) => {
|
|
2223
2185
|
const props = defaultsDeep2({}, _props, defaults);
|
|
2224
2186
|
return [
|
|
2225
2187
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
F:
|
|
2229
|
-
L:
|
|
2188
|
+
EditorView9.exceptionSink.of((err) => {
|
|
2189
|
+
log5.catch(err, void 0, {
|
|
2190
|
+
F: __dxlog_file7,
|
|
2191
|
+
L: 93,
|
|
2230
2192
|
S: void 0,
|
|
2231
2193
|
C: (f, a) => f(...a)
|
|
2232
2194
|
});
|
|
@@ -2235,26 +2197,26 @@ var createBasicExtensions = (_props) => {
|
|
|
2235
2197
|
props.bracketMatching && bracketMatching(),
|
|
2236
2198
|
props.closeBrackets && closeBrackets(),
|
|
2237
2199
|
props.crosshairCursor && crosshairCursor(),
|
|
2238
|
-
props.dropCursor &&
|
|
2200
|
+
props.dropCursor && dropCursor2(),
|
|
2239
2201
|
props.drawSelection && drawSelection(),
|
|
2240
2202
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2241
|
-
highlightSpecialChars(),
|
|
2242
2203
|
props.history && history(),
|
|
2243
2204
|
props.lineNumbers && lineNumbers(),
|
|
2244
|
-
props.lineWrapping &&
|
|
2205
|
+
props.lineWrapping && EditorView9.lineWrapping,
|
|
2245
2206
|
props.placeholder && placeholder(props.placeholder),
|
|
2246
2207
|
props.readonly && [
|
|
2247
2208
|
EditorState.readOnly.of(true),
|
|
2248
|
-
|
|
2209
|
+
EditorView9.editable.of(false)
|
|
2249
2210
|
],
|
|
2250
2211
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2251
2212
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
2252
2213
|
// https://codemirror.net/docs/ref/#view.KeyBinding
|
|
2253
2214
|
keymap5.of([
|
|
2254
|
-
|
|
2255
|
-
...standardKeymap,
|
|
2215
|
+
...(props.keymap && keymaps[props.keymap]) ?? [],
|
|
2256
2216
|
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2257
|
-
props.indentWithTab
|
|
2217
|
+
...props.indentWithTab ? [
|
|
2218
|
+
indentWithTab
|
|
2219
|
+
] : [],
|
|
2258
2220
|
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2259
2221
|
...props.closeBrackets ? closeBracketsKeymap : [],
|
|
2260
2222
|
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
@@ -2272,13 +2234,13 @@ var defaultSlots = {
|
|
|
2272
2234
|
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2273
2235
|
const slots = defaultsDeep2({}, _slots, defaultSlots);
|
|
2274
2236
|
return [
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
theme &&
|
|
2278
|
-
slots.editor?.className &&
|
|
2237
|
+
EditorView9.baseTheme(defaultTheme),
|
|
2238
|
+
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
2239
|
+
theme && EditorView9.theme(theme),
|
|
2240
|
+
slots.editor?.className && EditorView9.editorAttributes.of({
|
|
2279
2241
|
class: slots.editor.className
|
|
2280
2242
|
}),
|
|
2281
|
-
slots.content?.className &&
|
|
2243
|
+
slots.content?.className && EditorView9.contentAttributes.of({
|
|
2282
2244
|
class: slots.content.className
|
|
2283
2245
|
})
|
|
2284
2246
|
].filter(isNotFalsy2);
|
|
@@ -2306,917 +2268,415 @@ var createDataExtensions = ({ id, text, space, identity }) => {
|
|
|
2306
2268
|
};
|
|
2307
2269
|
|
|
2308
2270
|
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
2309
|
-
import { EditorView as
|
|
2271
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
2310
2272
|
var listener = ({ onFocus, onChange }) => {
|
|
2311
2273
|
const extensions = [];
|
|
2312
|
-
onFocus && extensions.push(
|
|
2274
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
2313
2275
|
onFocus(focusing);
|
|
2314
2276
|
return null;
|
|
2315
2277
|
}));
|
|
2316
|
-
onChange && extensions.push(
|
|
2278
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
2317
2279
|
onChange(update2.state.doc.toString());
|
|
2318
2280
|
}));
|
|
2319
2281
|
return extensions;
|
|
2320
2282
|
};
|
|
2321
2283
|
|
|
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
|
-
|
|
2284
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
2285
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
2286
|
+
import { syntaxTree } from "@codemirror/language";
|
|
2287
|
+
import { EditorSelection } from "@codemirror/state";
|
|
2288
|
+
import { EditorView as EditorView11, keymap as keymap6 } from "@codemirror/view";
|
|
2289
|
+
import { useMemo, useState } from "react";
|
|
2290
|
+
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
|
2291
|
+
var Inline;
|
|
2292
|
+
(function(Inline2) {
|
|
2293
|
+
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
2294
|
+
Inline2[Inline2["Emphasis"] = 1] = "Emphasis";
|
|
2295
|
+
Inline2[Inline2["Strikethrough"] = 2] = "Strikethrough";
|
|
2296
|
+
Inline2[Inline2["Code"] = 3] = "Code";
|
|
2297
|
+
})(Inline || (Inline = {}));
|
|
2298
|
+
var List;
|
|
2299
|
+
(function(List2) {
|
|
2300
|
+
List2[List2["Ordered"] = 0] = "Ordered";
|
|
2301
|
+
List2[List2["Bullet"] = 1] = "Bullet";
|
|
2302
|
+
List2[List2["Task"] = 2] = "Task";
|
|
2303
|
+
})(List || (List = {}));
|
|
2304
|
+
var setHeading = (level) => ({ state: state2, dispatch }) => {
|
|
2305
|
+
const { selection: { ranges }, doc } = state2;
|
|
2306
|
+
const changes = [];
|
|
2307
|
+
let prevBlock = -1;
|
|
2308
|
+
for (const range of ranges) {
|
|
2309
|
+
let sawBlock = false;
|
|
2310
|
+
syntaxTree(state2).iterate({
|
|
2311
|
+
from: range.from,
|
|
2312
|
+
to: range.to,
|
|
2313
|
+
enter: (node) => {
|
|
2314
|
+
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
sawBlock = true;
|
|
2318
|
+
prevBlock = node.from;
|
|
2319
|
+
const blockType = Textblocks[node.name];
|
|
2320
|
+
const isHeading = /heading(\d)/.exec(blockType);
|
|
2321
|
+
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2322
|
+
if (curLevel < 0 || curLevel === level) {
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
if (curLevel === 0) {
|
|
2326
|
+
changes.push({
|
|
2327
|
+
from: node.from,
|
|
2328
|
+
insert: "#".repeat(level) + " "
|
|
2329
|
+
});
|
|
2330
|
+
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
2331
|
+
const nextLine = doc.lineAt(node.to);
|
|
2332
|
+
if (level) {
|
|
2333
|
+
changes.push({
|
|
2334
|
+
from: node.from,
|
|
2335
|
+
insert: "#".repeat(level) + " "
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
changes.push({
|
|
2339
|
+
from: nextLine.from - 1,
|
|
2340
|
+
to: nextLine.to
|
|
2341
|
+
});
|
|
2342
|
+
} else {
|
|
2343
|
+
if (level === 0) {
|
|
2344
|
+
changes.push({
|
|
2345
|
+
from: node.from,
|
|
2346
|
+
to: Math.min(node.to, node.from + curLevel + 1)
|
|
2347
|
+
});
|
|
2348
|
+
} else if (level < curLevel) {
|
|
2349
|
+
changes.push({
|
|
2350
|
+
from: node.from,
|
|
2351
|
+
to: node.from + (curLevel - level)
|
|
2352
|
+
});
|
|
2353
|
+
} else {
|
|
2354
|
+
changes.push({
|
|
2355
|
+
from: node.from,
|
|
2356
|
+
insert: "#".repeat(level - curLevel)
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
});
|
|
2362
|
+
let line;
|
|
2363
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2364
|
+
changes.push({
|
|
2365
|
+
from: line.from,
|
|
2366
|
+
to: line.to,
|
|
2367
|
+
insert: "#".repeat(level) + " "
|
|
2368
|
+
});
|
|
2357
2369
|
}
|
|
2358
2370
|
}
|
|
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;
|
|
2371
|
+
if (!changes.length) {
|
|
2372
|
+
return false;
|
|
2581
2373
|
}
|
|
2374
|
+
const changeSet = state2.changes(changes);
|
|
2375
|
+
dispatch(state2.update({
|
|
2376
|
+
changes: changeSet,
|
|
2377
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2378
|
+
userEvent: "format.setHeading",
|
|
2379
|
+
scrollIntoView: true
|
|
2380
|
+
}));
|
|
2381
|
+
return true;
|
|
2582
2382
|
};
|
|
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();
|
|
2383
|
+
var setStyle = (type, enable) => ({ state: state2, dispatch }) => {
|
|
2384
|
+
const marker = inlineMarkerText(type);
|
|
2385
|
+
const changes = state2.changeByRange((range) => {
|
|
2386
|
+
if (!enable && range.empty) {
|
|
2387
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2388
|
+
const found = after.indexOf(marker);
|
|
2389
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2390
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2391
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2392
|
+
...before.slice(before.length - found)
|
|
2393
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
2394
|
+
return {
|
|
2395
|
+
changes: [
|
|
2396
|
+
{
|
|
2397
|
+
from: range.head - marker.length - found,
|
|
2398
|
+
to: range.head - found
|
|
2399
|
+
},
|
|
2400
|
+
{
|
|
2401
|
+
from: range.head + found,
|
|
2402
|
+
to: range.head + found + marker.length
|
|
2403
|
+
}
|
|
2404
|
+
],
|
|
2405
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
2406
|
+
};
|
|
2611
2407
|
}
|
|
2612
|
-
}
|
|
2408
|
+
}
|
|
2613
2409
|
}
|
|
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) {
|
|
2410
|
+
const changes2 = [];
|
|
2411
|
+
const changesAtEnd = [];
|
|
2412
|
+
let blockStart = -1;
|
|
2413
|
+
let blockEnd = -1;
|
|
2414
|
+
let startCovered = false;
|
|
2415
|
+
let endCovered = false;
|
|
2416
|
+
let { from, to } = range;
|
|
2655
2417
|
syntaxTree(state2).iterate({
|
|
2656
2418
|
from,
|
|
2657
2419
|
to,
|
|
2658
2420
|
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
|
-
}
|
|
2421
|
+
const { name } = node;
|
|
2422
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2423
|
+
blockStart = blockContentStart(node);
|
|
2424
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2425
|
+
startCovered = endCovered = false;
|
|
2426
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
2427
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
2428
|
+
to = node.to;
|
|
2429
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2430
|
+
from = node.from;
|
|
2674
2431
|
}
|
|
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);
|
|
2432
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
2433
|
+
if (node.from < from && node.to > from) {
|
|
2434
|
+
if (to === from) {
|
|
2435
|
+
to = node.to;
|
|
2698
2436
|
}
|
|
2437
|
+
from = node.to;
|
|
2699
2438
|
}
|
|
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);
|
|
2439
|
+
if (node.from < to && node.to > to) {
|
|
2440
|
+
to = node.from;
|
|
2705
2441
|
}
|
|
2706
|
-
} else if (
|
|
2707
|
-
|
|
2708
|
-
|
|
2442
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2443
|
+
const markType = InlineMarker[name];
|
|
2444
|
+
const size = inlineMarkerText(markType).length;
|
|
2445
|
+
const openEnd = node.from + size;
|
|
2446
|
+
const closeStart = node.to - size;
|
|
2447
|
+
if (markType === type) {
|
|
2448
|
+
if (openEnd <= from && closeStart >= from) {
|
|
2449
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2450
|
+
from: node.from,
|
|
2451
|
+
to: openEnd
|
|
2452
|
+
} : true;
|
|
2453
|
+
}
|
|
2454
|
+
if (openEnd <= to && closeStart >= to) {
|
|
2455
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2456
|
+
from: closeStart,
|
|
2457
|
+
to: node.to
|
|
2458
|
+
} : true;
|
|
2459
|
+
}
|
|
2709
2460
|
}
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2461
|
+
if (markType === type || type === 3 && enable) {
|
|
2462
|
+
if (node.from >= from && openEnd <= to) {
|
|
2463
|
+
changes2.push({
|
|
2464
|
+
from: node.from,
|
|
2465
|
+
to: openEnd
|
|
2466
|
+
});
|
|
2467
|
+
if (markType !== type && closeStart >= to) {
|
|
2468
|
+
changesAtEnd.push({
|
|
2469
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2470
|
+
insert: inlineMarkerText(markType)
|
|
2471
|
+
});
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
if (closeStart >= from && node.to <= to) {
|
|
2475
|
+
changes2.push({
|
|
2476
|
+
from: closeStart,
|
|
2477
|
+
to: node.to
|
|
2478
|
+
});
|
|
2479
|
+
if (markType !== type && openEnd <= from) {
|
|
2480
|
+
changes2.push({
|
|
2481
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2482
|
+
insert: inlineMarkerText(markType)
|
|
2483
|
+
});
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2717
2486
|
}
|
|
2718
|
-
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2487
|
+
}
|
|
2488
|
+
},
|
|
2489
|
+
leave: (node) => {
|
|
2490
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2491
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2492
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2493
|
+
if (enable) {
|
|
2494
|
+
if (!startCovered) {
|
|
2495
|
+
changes2.push({
|
|
2496
|
+
from: rangeStart,
|
|
2497
|
+
insert: marker
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
if (!endCovered) {
|
|
2501
|
+
changes2.push({
|
|
2502
|
+
from: rangeEnd,
|
|
2503
|
+
insert: marker
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
} else {
|
|
2507
|
+
if (typeof startCovered === "object") {
|
|
2508
|
+
changes2.push(startCovered);
|
|
2509
|
+
} else if (startCovered) {
|
|
2510
|
+
changes2.push({
|
|
2511
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
2512
|
+
insert: marker
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
if (typeof endCovered === "object") {
|
|
2516
|
+
changes2.push(endCovered);
|
|
2517
|
+
} else if (endCovered) {
|
|
2518
|
+
changes2.push({
|
|
2519
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
2520
|
+
insert: marker
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2721
2523
|
}
|
|
2722
2524
|
}
|
|
2723
2525
|
}
|
|
2724
2526
|
});
|
|
2527
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2528
|
+
return {
|
|
2529
|
+
changes: {
|
|
2530
|
+
from: range.head,
|
|
2531
|
+
insert: marker + marker
|
|
2532
|
+
},
|
|
2533
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
2537
|
+
return {
|
|
2538
|
+
changes: changeSet,
|
|
2539
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2540
|
+
};
|
|
2541
|
+
});
|
|
2542
|
+
dispatch(state2.update(changes, {
|
|
2543
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2544
|
+
scrollIntoView: true
|
|
2545
|
+
}));
|
|
2546
|
+
return true;
|
|
2547
|
+
};
|
|
2548
|
+
var addStyle = (style) => setStyle(style, true);
|
|
2549
|
+
var removeStyle = (style) => setStyle(style, false);
|
|
2550
|
+
var toggleStyle = (style) => (arg) => {
|
|
2551
|
+
const form = getFormatting(arg.state);
|
|
2552
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2553
|
+
};
|
|
2554
|
+
var toggleStrong = toggleStyle(0);
|
|
2555
|
+
var toggleEmphasis = toggleStyle(1);
|
|
2556
|
+
var toggleStrikethrough = toggleStyle(2);
|
|
2557
|
+
var toggleInlineCode = toggleStyle(3);
|
|
2558
|
+
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
2559
|
+
var blockContentStart = (node) => {
|
|
2560
|
+
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
2561
|
+
if (atx) {
|
|
2562
|
+
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
2725
2563
|
}
|
|
2726
|
-
return
|
|
2727
|
-
deco: deco.finish(),
|
|
2728
|
-
atomicDeco: atomicDeco.finish()
|
|
2729
|
-
};
|
|
2564
|
+
return node.from;
|
|
2730
2565
|
};
|
|
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
|
-
];
|
|
2566
|
+
var blockContentEnd = (node, doc) => {
|
|
2567
|
+
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
2568
|
+
const lastLine = doc.lineAt(node.to);
|
|
2569
|
+
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
2570
|
+
return lastLine.from - 1;
|
|
2571
|
+
}
|
|
2572
|
+
return node.to;
|
|
2774
2573
|
};
|
|
2775
|
-
var
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
position: "absolute",
|
|
2788
|
-
inset: 0,
|
|
2789
|
-
content: '""'
|
|
2574
|
+
var skipSpaces = (pos, doc, dir, limit) => {
|
|
2575
|
+
const line = doc.lineAt(pos);
|
|
2576
|
+
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
2577
|
+
pos += dir;
|
|
2578
|
+
}
|
|
2579
|
+
return pos;
|
|
2580
|
+
};
|
|
2581
|
+
var skipMarkers = (pos, tree, dir, limit) => {
|
|
2582
|
+
for (; ; ) {
|
|
2583
|
+
const next = tree.resolve(pos, dir);
|
|
2584
|
+
if (!IgnoreInline.has(next.name)) {
|
|
2585
|
+
return pos;
|
|
2790
2586
|
}
|
|
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"
|
|
2587
|
+
const moveTo = dir < 0 ? next.from : next.to;
|
|
2588
|
+
if (limit != null && (dir < 0 ? moveTo < limit : moveTo > limit)) {
|
|
2589
|
+
return pos;
|
|
2590
|
+
}
|
|
2591
|
+
pos = moveTo;
|
|
2821
2592
|
}
|
|
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) {
|
|
2593
|
+
};
|
|
2594
|
+
var snippets = {
|
|
2595
|
+
codeblock: snippet([
|
|
2596
|
+
//
|
|
2597
|
+
"```#{}",
|
|
2598
|
+
"",
|
|
2599
|
+
"```"
|
|
2600
|
+
].join("\n")),
|
|
2601
|
+
table: snippet([
|
|
2602
|
+
//
|
|
2603
|
+
"| #{col1} | #{col2} |",
|
|
2604
|
+
"| ---- | ---- |",
|
|
2605
|
+
"| #{val1} | #{val2} |",
|
|
2606
|
+
"| #{val3} | #{val4} |",
|
|
2607
|
+
""
|
|
2608
|
+
].join("\n"))
|
|
2609
|
+
};
|
|
2610
|
+
var insertTable = (view) => {
|
|
2611
|
+
const { selection: { main }, doc } = view.state;
|
|
2612
|
+
const { number } = doc.lineAt(main.anchor);
|
|
2613
|
+
const { from } = doc.line(number);
|
|
2614
|
+
snippets.table(view, null, from, from);
|
|
2615
|
+
};
|
|
2616
|
+
var removeLinkInner = (from, to, changes, state2) => {
|
|
2617
|
+
syntaxTree(state2).iterate({
|
|
2618
|
+
from,
|
|
2619
|
+
to,
|
|
2620
|
+
enter: (node) => {
|
|
2621
|
+
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
2622
|
+
node.node.cursor().iterate((node2) => {
|
|
2623
|
+
const { name } = node2;
|
|
2624
|
+
if (name === "LinkMark" || name === "LinkLabel") {
|
|
2889
2625
|
changes.push({
|
|
2890
|
-
from:
|
|
2891
|
-
to:
|
|
2626
|
+
from: node2.from,
|
|
2627
|
+
to: node2.to
|
|
2892
2628
|
});
|
|
2893
|
-
} else {
|
|
2629
|
+
} else if (name === "LinkTitle" || name === "URL") {
|
|
2894
2630
|
changes.push({
|
|
2895
|
-
from:
|
|
2896
|
-
|
|
2631
|
+
from: skipSpaces(node2.from, state2.doc, -1),
|
|
2632
|
+
to: skipSpaces(node2.to, state2.doc, 1)
|
|
2897
2633
|
});
|
|
2898
2634
|
}
|
|
2899
|
-
}
|
|
2635
|
+
});
|
|
2636
|
+
return false;
|
|
2900
2637
|
}
|
|
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
2638
|
}
|
|
2639
|
+
});
|
|
2640
|
+
};
|
|
2641
|
+
var removeLink = ({ state: state2, dispatch }) => {
|
|
2642
|
+
const changes = [];
|
|
2643
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2644
|
+
removeLinkInner(from, to, changes, state2);
|
|
2910
2645
|
}
|
|
2911
|
-
if (!changes
|
|
2646
|
+
if (!changes) {
|
|
2912
2647
|
return false;
|
|
2913
2648
|
}
|
|
2914
|
-
const changeSet = state2.changes(changes);
|
|
2915
2649
|
dispatch(state2.update({
|
|
2916
|
-
changes
|
|
2917
|
-
|
|
2918
|
-
userEvent: "format.setHeading",
|
|
2650
|
+
changes,
|
|
2651
|
+
userEvent: "format.link.remove",
|
|
2919
2652
|
scrollIntoView: true
|
|
2920
2653
|
}));
|
|
2921
2654
|
return true;
|
|
2922
2655
|
};
|
|
2923
|
-
var
|
|
2924
|
-
const marker = inlineMarkerText(type);
|
|
2656
|
+
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
2925
2657
|
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
2658
|
let { from, to } = range;
|
|
2957
|
-
|
|
2659
|
+
const cutStyles = [];
|
|
2660
|
+
let okay = null;
|
|
2661
|
+
syntaxTree(state2).iterate({
|
|
2958
2662
|
from,
|
|
2959
2663
|
to,
|
|
2960
2664
|
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;
|
|
2665
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2666
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
2667
|
+
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2668
|
+
const sNode = node.node;
|
|
2669
|
+
if (node.from < from && node.to <= to) {
|
|
2670
|
+
if (sNode.firstChild.to === from) {
|
|
2671
|
+
from = node.from;
|
|
2672
|
+
} else {
|
|
2673
|
+
cutStyles.push(sNode);
|
|
2993
2674
|
}
|
|
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);
|
|
2675
|
+
} else if (node.from >= from && node.to > to) {
|
|
2676
|
+
if (sNode.lastChild.from === to) {
|
|
2677
|
+
to = node.to;
|
|
2678
|
+
} else {
|
|
2679
|
+
cutStyles.push(sNode);
|
|
3220
2680
|
}
|
|
3221
2681
|
}
|
|
3222
2682
|
}
|
|
@@ -3291,7 +2751,7 @@ var addList = (type) => ({ state: state2, dispatch }) => {
|
|
|
3291
2751
|
let parentColumn = null;
|
|
3292
2752
|
const blocks = [];
|
|
3293
2753
|
for (const { from, to } of state2.selection.ranges) {
|
|
3294
|
-
|
|
2754
|
+
syntaxTree(state2).iterate({
|
|
3295
2755
|
from,
|
|
3296
2756
|
to,
|
|
3297
2757
|
enter: (node) => {
|
|
@@ -3424,7 +2884,7 @@ var removeList = (type) => ({ state: state2, dispatch }) => {
|
|
|
3424
2884
|
const stack = [];
|
|
3425
2885
|
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
3426
2886
|
for (const { from, to } of state2.selection.ranges) {
|
|
3427
|
-
|
|
2887
|
+
syntaxTree(state2).iterate({
|
|
3428
2888
|
from,
|
|
3429
2889
|
to,
|
|
3430
2890
|
enter: (node) => {
|
|
@@ -3507,7 +2967,7 @@ var setBlockquote = (enable) => ({ state: state2, dispatch }) => {
|
|
|
3507
2967
|
let lastBlock = -1;
|
|
3508
2968
|
for (const { from, to } of state2.selection.ranges) {
|
|
3509
2969
|
const sawBlock = false;
|
|
3510
|
-
|
|
2970
|
+
syntaxTree(state2).iterate({
|
|
3511
2971
|
from,
|
|
3512
2972
|
to,
|
|
3513
2973
|
enter: (node) => {
|
|
@@ -3596,7 +3056,7 @@ var addCodeblock = (target) => {
|
|
|
3596
3056
|
for (const { from, to } of selection.ranges) {
|
|
3597
3057
|
let blockFrom = from;
|
|
3598
3058
|
let blockTo = to;
|
|
3599
|
-
|
|
3059
|
+
syntaxTree(state2).iterate({
|
|
3600
3060
|
from,
|
|
3601
3061
|
to,
|
|
3602
3062
|
enter: (node) => {
|
|
@@ -3620,304 +3080,855 @@ var addCodeblock = (target) => {
|
|
|
3620
3080
|
});
|
|
3621
3081
|
}
|
|
3622
3082
|
}
|
|
3623
|
-
if (!ranges.length) {
|
|
3624
|
-
return false;
|
|
3083
|
+
if (!ranges.length) {
|
|
3084
|
+
return false;
|
|
3085
|
+
}
|
|
3086
|
+
const changes = ranges.map(({ from, to }) => {
|
|
3087
|
+
const column = from - state2.doc.lineAt(from).from;
|
|
3088
|
+
return [
|
|
3089
|
+
{
|
|
3090
|
+
from,
|
|
3091
|
+
insert: "```\n" + " ".repeat(column)
|
|
3092
|
+
},
|
|
3093
|
+
{
|
|
3094
|
+
from: to,
|
|
3095
|
+
insert: "\n" + " ".repeat(column) + "```"
|
|
3096
|
+
}
|
|
3097
|
+
];
|
|
3098
|
+
});
|
|
3099
|
+
dispatch(state2.update({
|
|
3100
|
+
changes,
|
|
3101
|
+
userEvent: "format.codeblock.add",
|
|
3102
|
+
scrollIntoView: true
|
|
3103
|
+
}));
|
|
3104
|
+
return true;
|
|
3105
|
+
};
|
|
3106
|
+
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3107
|
+
const changes = [];
|
|
3108
|
+
let lastBlock = -1;
|
|
3109
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3110
|
+
syntaxTree(state2).iterate({
|
|
3111
|
+
from,
|
|
3112
|
+
to,
|
|
3113
|
+
enter: (node) => {
|
|
3114
|
+
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
3115
|
+
lastBlock = node.from;
|
|
3116
|
+
const firstLine = state2.doc.lineAt(node.from);
|
|
3117
|
+
if (node.name === "FencedCode") {
|
|
3118
|
+
changes.push({
|
|
3119
|
+
from: node.from,
|
|
3120
|
+
to: firstLine.to + 1 + node.from - firstLine.from
|
|
3121
|
+
});
|
|
3122
|
+
const lastLine = state2.doc.lineAt(node.to);
|
|
3123
|
+
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
3124
|
+
changes.push({
|
|
3125
|
+
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
3126
|
+
to: lastLine.to
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
} else {
|
|
3130
|
+
const column = node.from - firstLine.from;
|
|
3131
|
+
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3132
|
+
changes.push({
|
|
3133
|
+
from: line.from + column - 4,
|
|
3134
|
+
to: line.from + column
|
|
3135
|
+
});
|
|
3136
|
+
if (line.to >= node.to) {
|
|
3137
|
+
break;
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
if (!changes.length) {
|
|
3146
|
+
return false;
|
|
3147
|
+
}
|
|
3148
|
+
dispatch(state2.update({
|
|
3149
|
+
changes,
|
|
3150
|
+
userEvent: "format.codeblock.remove",
|
|
3151
|
+
scrollIntoView: true
|
|
3152
|
+
}));
|
|
3153
|
+
return true;
|
|
3154
|
+
};
|
|
3155
|
+
var toggleCodeblock = (target) => {
|
|
3156
|
+
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3157
|
+
};
|
|
3158
|
+
var formattingKeymap = (options = {}) => {
|
|
3159
|
+
return [
|
|
3160
|
+
keymap6.of([
|
|
3161
|
+
{
|
|
3162
|
+
key: "meta-b",
|
|
3163
|
+
run: toggleStrong
|
|
3164
|
+
}
|
|
3165
|
+
])
|
|
3166
|
+
];
|
|
3167
|
+
};
|
|
3168
|
+
var InlineMarker = {
|
|
3169
|
+
Emphasis: 1,
|
|
3170
|
+
StrongEmphasis: 0,
|
|
3171
|
+
InlineCode: 3,
|
|
3172
|
+
Strikethrough: 2
|
|
3173
|
+
};
|
|
3174
|
+
var IgnoreInline = /* @__PURE__ */ new Set([
|
|
3175
|
+
"Autolink",
|
|
3176
|
+
"CodeMark",
|
|
3177
|
+
"CodeText",
|
|
3178
|
+
"Comment",
|
|
3179
|
+
"EmphasisMark",
|
|
3180
|
+
"Hardbreak",
|
|
3181
|
+
"HeaderMark",
|
|
3182
|
+
"HTMLTag",
|
|
3183
|
+
"LinkMark",
|
|
3184
|
+
"ListMark",
|
|
3185
|
+
"ProcessingInstruction",
|
|
3186
|
+
"QuoteMark",
|
|
3187
|
+
"StrikethroughMark",
|
|
3188
|
+
"SubscriptMark",
|
|
3189
|
+
"SuperscriptMark",
|
|
3190
|
+
"TaskMarker"
|
|
3191
|
+
]);
|
|
3192
|
+
var Textblocks = {
|
|
3193
|
+
ATXHeading1: "heading1",
|
|
3194
|
+
ATXHeading2: "heading2",
|
|
3195
|
+
ATXHeading3: "heading3",
|
|
3196
|
+
ATXHeading4: "heading4",
|
|
3197
|
+
ATXHeading5: "heading5",
|
|
3198
|
+
ATXHeading6: "heading6",
|
|
3199
|
+
CodeBlock: "codeblock",
|
|
3200
|
+
FencedCode: "codeblock",
|
|
3201
|
+
Paragraph: "paragraph",
|
|
3202
|
+
SetextHeading1: "heading1",
|
|
3203
|
+
SetextHeading2: "heading2",
|
|
3204
|
+
TableCell: "tablecell",
|
|
3205
|
+
Task: "paragraph"
|
|
3206
|
+
};
|
|
3207
|
+
var getFormatting = (state2) => {
|
|
3208
|
+
let blockType = null;
|
|
3209
|
+
const inline = [
|
|
3210
|
+
null,
|
|
3211
|
+
null,
|
|
3212
|
+
null,
|
|
3213
|
+
null
|
|
3214
|
+
];
|
|
3215
|
+
let link = false;
|
|
3216
|
+
let blockQuote = null;
|
|
3217
|
+
let listStyle = null;
|
|
3218
|
+
const stack = [];
|
|
3219
|
+
let currentBlock = null;
|
|
3220
|
+
const advanceInline = (upto) => {
|
|
3221
|
+
if (!currentBlock) {
|
|
3222
|
+
return;
|
|
3223
|
+
}
|
|
3224
|
+
upto = Math.min(upto, currentBlock.end);
|
|
3225
|
+
if (upto <= currentBlock.pos) {
|
|
3226
|
+
return;
|
|
3227
|
+
}
|
|
3228
|
+
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
3229
|
+
if (inline[i] === false) {
|
|
3230
|
+
continue;
|
|
3231
|
+
} else if (currentBlock.active[i]) {
|
|
3232
|
+
inline[i] = true;
|
|
3233
|
+
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3234
|
+
inline[i] = false;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
currentBlock.pos = upto;
|
|
3238
|
+
};
|
|
3239
|
+
const skipInline = (upto) => {
|
|
3240
|
+
if (currentBlock && upto > currentBlock.pos) {
|
|
3241
|
+
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3242
|
+
}
|
|
3243
|
+
};
|
|
3244
|
+
const { selection } = state2;
|
|
3245
|
+
for (const range of selection.ranges) {
|
|
3246
|
+
if (range.empty && inline.some((v) => v === null)) {
|
|
3247
|
+
const contextSize = Math.min(range.head, 6);
|
|
3248
|
+
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3249
|
+
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3250
|
+
for (let i = 0; i < contextSize; i++) {
|
|
3251
|
+
const ch = contextAfter[i];
|
|
3252
|
+
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
3253
|
+
contextAfter = contextAfter.slice(0, i);
|
|
3254
|
+
break;
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
for (let i = 0; i < inline.length; i++) {
|
|
3258
|
+
const mark2 = inlineMarkerText(i);
|
|
3259
|
+
const found = contextAfter.indexOf(mark2);
|
|
3260
|
+
if (found > -1) {
|
|
3261
|
+
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
3262
|
+
if (inline[i] === null) {
|
|
3263
|
+
inline[i] = true;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
syntaxTree(state2).iterate({
|
|
3269
|
+
from: range.from,
|
|
3270
|
+
to: range.to,
|
|
3271
|
+
enter: (node) => {
|
|
3272
|
+
advanceInline(node.from);
|
|
3273
|
+
const { name } = node;
|
|
3274
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3275
|
+
stack.push(name);
|
|
3276
|
+
} else if (name === "Link") {
|
|
3277
|
+
link = true;
|
|
3278
|
+
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
3279
|
+
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
3280
|
+
stack[stack.length - 1] = "TaskList";
|
|
3281
|
+
}
|
|
3282
|
+
const blockCode = Textblocks[name];
|
|
3283
|
+
if (blockType === null) {
|
|
3284
|
+
blockType = blockCode;
|
|
3285
|
+
} else if (blockType !== blockCode) {
|
|
3286
|
+
blockType = false;
|
|
3287
|
+
}
|
|
3288
|
+
if (blockCode !== "codeblock" && inline.some((i) => i !== false)) {
|
|
3289
|
+
currentBlock = {
|
|
3290
|
+
pos: Math.max(range.from, node.from),
|
|
3291
|
+
end: Math.min(range.to, node.to),
|
|
3292
|
+
active: [
|
|
3293
|
+
false,
|
|
3294
|
+
false,
|
|
3295
|
+
false,
|
|
3296
|
+
false
|
|
3297
|
+
]
|
|
3298
|
+
};
|
|
3299
|
+
}
|
|
3300
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3301
|
+
const index = InlineMarker[name];
|
|
3302
|
+
if (range.empty && inline[index] === null) {
|
|
3303
|
+
inline[index] = true;
|
|
3304
|
+
}
|
|
3305
|
+
currentBlock.active[index] = true;
|
|
3306
|
+
} else if (IgnoreInline.has(name)) {
|
|
3307
|
+
skipInline(node.to);
|
|
3308
|
+
}
|
|
3309
|
+
},
|
|
3310
|
+
leave: (node) => {
|
|
3311
|
+
advanceInline(node.to);
|
|
3312
|
+
const { name } = node;
|
|
3313
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
3314
|
+
stack.pop();
|
|
3315
|
+
} else if (Object.hasOwn(Textblocks, name)) {
|
|
3316
|
+
let hasList = false;
|
|
3317
|
+
let hasQuote = false;
|
|
3318
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3319
|
+
if (stack[i] === "Blockquote") {
|
|
3320
|
+
hasQuote = true;
|
|
3321
|
+
} else if (!hasList) {
|
|
3322
|
+
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
if (blockQuote === null) {
|
|
3326
|
+
blockQuote = hasQuote;
|
|
3327
|
+
} else if (!hasQuote && blockQuote) {
|
|
3328
|
+
blockQuote = false;
|
|
3329
|
+
}
|
|
3330
|
+
if (listStyle === null) {
|
|
3331
|
+
listStyle = hasList;
|
|
3332
|
+
} else if (listStyle !== hasList) {
|
|
3333
|
+
listStyle = false;
|
|
3334
|
+
}
|
|
3335
|
+
currentBlock = null;
|
|
3336
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3337
|
+
currentBlock.active[InlineMarker[name]] = false;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
});
|
|
3341
|
+
}
|
|
3342
|
+
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3343
|
+
const blankLine = from === to;
|
|
3344
|
+
return {
|
|
3345
|
+
blankLine,
|
|
3346
|
+
blockType: blockType || null,
|
|
3347
|
+
blockQuote: blockQuote ?? false,
|
|
3348
|
+
code: inline[3] ?? false,
|
|
3349
|
+
emphasis: inline[1] ?? false,
|
|
3350
|
+
strong: inline[0] ?? false,
|
|
3351
|
+
strikethrough: inline[2] ?? false,
|
|
3352
|
+
link,
|
|
3353
|
+
listStyle: listStyle || null
|
|
3354
|
+
};
|
|
3355
|
+
};
|
|
3356
|
+
var useFormattingState = () => {
|
|
3357
|
+
const [state2, setState] = useState();
|
|
3358
|
+
const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
|
|
3359
|
+
if (update2.docChanged || update2.selectionSet) {
|
|
3360
|
+
setState((prevState) => {
|
|
3361
|
+
const newState = getFormatting(update2.state);
|
|
3362
|
+
if (!prevState || !formattingEquals(prevState, newState)) {
|
|
3363
|
+
return newState;
|
|
3364
|
+
}
|
|
3365
|
+
return prevState;
|
|
3366
|
+
});
|
|
3367
|
+
}
|
|
3368
|
+
}), [
|
|
3369
|
+
setState
|
|
3370
|
+
]);
|
|
3371
|
+
return [
|
|
3372
|
+
state2,
|
|
3373
|
+
observer
|
|
3374
|
+
];
|
|
3375
|
+
};
|
|
3376
|
+
|
|
3377
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/action.ts
|
|
3378
|
+
var processAction = (view, action) => {
|
|
3379
|
+
let inlineType, listType;
|
|
3380
|
+
switch (action.type) {
|
|
3381
|
+
case "heading":
|
|
3382
|
+
setHeading(parseInt(action.data))(view);
|
|
3383
|
+
break;
|
|
3384
|
+
case "strong":
|
|
3385
|
+
case "emphasis":
|
|
3386
|
+
case "strikethrough":
|
|
3387
|
+
case "code":
|
|
3388
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
3389
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3390
|
+
break;
|
|
3391
|
+
case "list-ordered":
|
|
3392
|
+
case "list-bullet":
|
|
3393
|
+
case "list-task":
|
|
3394
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3395
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3396
|
+
break;
|
|
3397
|
+
case "blockquote":
|
|
3398
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3399
|
+
break;
|
|
3400
|
+
case "codeblock":
|
|
3401
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3402
|
+
break;
|
|
3403
|
+
case "table":
|
|
3404
|
+
insertTable(view);
|
|
3405
|
+
break;
|
|
3406
|
+
case "link":
|
|
3407
|
+
(action.data === false ? removeLink : addLink())(view);
|
|
3408
|
+
break;
|
|
3409
|
+
case "image":
|
|
3410
|
+
addLink({
|
|
3411
|
+
url: action.data,
|
|
3412
|
+
image: true
|
|
3413
|
+
})(view);
|
|
3414
|
+
break;
|
|
3415
|
+
case "comment":
|
|
3416
|
+
createComment(view);
|
|
3417
|
+
break;
|
|
3418
|
+
}
|
|
3419
|
+
requestAnimationFrame(() => {
|
|
3420
|
+
if (!view.hasFocus) {
|
|
3421
|
+
view.focus();
|
|
3422
|
+
}
|
|
3423
|
+
});
|
|
3424
|
+
};
|
|
3425
|
+
|
|
3426
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3427
|
+
import { completionKeymap as completionKeymap2 } from "@codemirror/autocomplete";
|
|
3428
|
+
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
3429
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
3430
|
+
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3431
|
+
import { languages } from "@codemirror/language-data";
|
|
3432
|
+
import { lintKeymap } from "@codemirror/lint";
|
|
3433
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
3434
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
3435
|
+
|
|
3436
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
3437
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
3438
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
3439
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
3440
|
+
import { Table } from "@lezer/markdown";
|
|
3441
|
+
var markdownTags = {
|
|
3442
|
+
Blockquote: Tag.define(),
|
|
3443
|
+
CodeMark: Tag.define(),
|
|
3444
|
+
CodeText: Tag.define(),
|
|
3445
|
+
EmphasisMark: Tag.define(),
|
|
3446
|
+
HeaderMark: Tag.define(),
|
|
3447
|
+
InlineCode: Tag.define(),
|
|
3448
|
+
LinkLabel: Tag.define(),
|
|
3449
|
+
LinkReference: Tag.define(),
|
|
3450
|
+
ListMark: Tag.define(),
|
|
3451
|
+
QuoteMark: Tag.define(),
|
|
3452
|
+
URL: Tag.define(),
|
|
3453
|
+
// Custom.
|
|
3454
|
+
TableCell: Tag.define()
|
|
3455
|
+
};
|
|
3456
|
+
Table.defineNodes?.forEach((node) => {
|
|
3457
|
+
switch (node?.name) {
|
|
3458
|
+
case "TableCell": {
|
|
3459
|
+
node.style = markdownTags.TableCell;
|
|
3460
|
+
break;
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
});
|
|
3464
|
+
var markdownTagsExtensions = [
|
|
3465
|
+
Table,
|
|
3466
|
+
{
|
|
3467
|
+
props: [
|
|
3468
|
+
styleTags(markdownTags)
|
|
3469
|
+
]
|
|
3470
|
+
}
|
|
3471
|
+
];
|
|
3472
|
+
var markdownHighlightStyle = (readonly) => {
|
|
3473
|
+
return HighlightStyle.define([
|
|
3474
|
+
{
|
|
3475
|
+
tag: [
|
|
3476
|
+
tags.keyword,
|
|
3477
|
+
tags.name,
|
|
3478
|
+
tags.deleted,
|
|
3479
|
+
tags.character,
|
|
3480
|
+
tags.propertyName,
|
|
3481
|
+
tags.macroName,
|
|
3482
|
+
tags.color,
|
|
3483
|
+
tags.constant(tags.name),
|
|
3484
|
+
tags.standard(tags.name),
|
|
3485
|
+
tags.definition(tags.name),
|
|
3486
|
+
tags.separator,
|
|
3487
|
+
tags.typeName,
|
|
3488
|
+
tags.className,
|
|
3489
|
+
tags.number,
|
|
3490
|
+
tags.changed,
|
|
3491
|
+
tags.annotation,
|
|
3492
|
+
tags.modifier,
|
|
3493
|
+
tags.self,
|
|
3494
|
+
tags.namespace,
|
|
3495
|
+
tags.operator,
|
|
3496
|
+
tags.operatorKeyword,
|
|
3497
|
+
tags.escape,
|
|
3498
|
+
tags.regexp,
|
|
3499
|
+
tags.special(tags.string),
|
|
3500
|
+
tags.meta,
|
|
3501
|
+
tags.comment,
|
|
3502
|
+
tags.atom,
|
|
3503
|
+
tags.bool,
|
|
3504
|
+
tags.special(tags.variableName),
|
|
3505
|
+
tags.processingInstruction,
|
|
3506
|
+
tags.string,
|
|
3507
|
+
tags.inserted,
|
|
3508
|
+
tags.invalid
|
|
3509
|
+
],
|
|
3510
|
+
color: "inherit !important"
|
|
3511
|
+
},
|
|
3512
|
+
// Markdown marks.
|
|
3513
|
+
{
|
|
3514
|
+
tag: [
|
|
3515
|
+
tags.meta,
|
|
3516
|
+
tags.processingInstruction,
|
|
3517
|
+
markdownTags.LinkLabel,
|
|
3518
|
+
markdownTags.LinkReference,
|
|
3519
|
+
markdownTags.ListMark
|
|
3520
|
+
],
|
|
3521
|
+
class: mark
|
|
3522
|
+
},
|
|
3523
|
+
// Markdown marks.
|
|
3524
|
+
{
|
|
3525
|
+
tag: [
|
|
3526
|
+
markdownTags.CodeMark,
|
|
3527
|
+
markdownTags.HeaderMark,
|
|
3528
|
+
markdownTags.QuoteMark,
|
|
3529
|
+
markdownTags.EmphasisMark
|
|
3530
|
+
],
|
|
3531
|
+
class: mark
|
|
3532
|
+
},
|
|
3533
|
+
// E.g., code block language (after ```).
|
|
3534
|
+
{
|
|
3535
|
+
tag: [
|
|
3536
|
+
tags.function(tags.variableName),
|
|
3537
|
+
tags.labelName
|
|
3538
|
+
],
|
|
3539
|
+
class: codeMark
|
|
3540
|
+
},
|
|
3541
|
+
{
|
|
3542
|
+
tag: [
|
|
3543
|
+
tags.monospace
|
|
3544
|
+
],
|
|
3545
|
+
class: "font-mono"
|
|
3546
|
+
},
|
|
3547
|
+
// Headings.
|
|
3548
|
+
{
|
|
3549
|
+
tag: tags.heading1,
|
|
3550
|
+
class: heading(1)
|
|
3551
|
+
},
|
|
3552
|
+
{
|
|
3553
|
+
tag: tags.heading2,
|
|
3554
|
+
class: heading(2)
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
tag: tags.heading3,
|
|
3558
|
+
class: heading(3)
|
|
3559
|
+
},
|
|
3560
|
+
{
|
|
3561
|
+
tag: tags.heading4,
|
|
3562
|
+
class: heading(4)
|
|
3563
|
+
},
|
|
3564
|
+
{
|
|
3565
|
+
tag: tags.heading5,
|
|
3566
|
+
class: heading(5)
|
|
3567
|
+
},
|
|
3568
|
+
{
|
|
3569
|
+
tag: tags.heading6,
|
|
3570
|
+
class: heading(6)
|
|
3571
|
+
},
|
|
3572
|
+
// Emphasis.
|
|
3573
|
+
{
|
|
3574
|
+
tag: tags.emphasis,
|
|
3575
|
+
class: italic
|
|
3576
|
+
},
|
|
3577
|
+
{
|
|
3578
|
+
tag: tags.strong,
|
|
3579
|
+
class: bold
|
|
3580
|
+
},
|
|
3581
|
+
{
|
|
3582
|
+
tag: tags.strikethrough,
|
|
3583
|
+
class: strikethrough
|
|
3584
|
+
},
|
|
3585
|
+
// Naked URLs.
|
|
3586
|
+
{
|
|
3587
|
+
tag: [
|
|
3588
|
+
markdownTags.URL
|
|
3589
|
+
],
|
|
3590
|
+
class: inlineUrl
|
|
3591
|
+
},
|
|
3592
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
3593
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
3594
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
3595
|
+
// the code, but all other CSS properties will be inherited.
|
|
3596
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
3597
|
+
{
|
|
3598
|
+
tag: [
|
|
3599
|
+
markdownTags.CodeText,
|
|
3600
|
+
markdownTags.InlineCode
|
|
3601
|
+
],
|
|
3602
|
+
class: code
|
|
3603
|
+
},
|
|
3604
|
+
{
|
|
3605
|
+
tag: [
|
|
3606
|
+
markdownTags.QuoteMark
|
|
3607
|
+
],
|
|
3608
|
+
class: blockquote
|
|
3609
|
+
},
|
|
3610
|
+
{
|
|
3611
|
+
tag: [
|
|
3612
|
+
markdownTags.TableCell
|
|
3613
|
+
],
|
|
3614
|
+
class: "font-mono"
|
|
3615
|
+
}
|
|
3616
|
+
], {
|
|
3617
|
+
scope: markdownLanguage2,
|
|
3618
|
+
all: {
|
|
3619
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
3620
|
+
}
|
|
3621
|
+
});
|
|
3622
|
+
};
|
|
3623
|
+
|
|
3624
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3625
|
+
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
3626
|
+
return [
|
|
3627
|
+
// Main extension.
|
|
3628
|
+
// https://github.com/codemirror/lang-markdown
|
|
3629
|
+
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
3630
|
+
markdown({
|
|
3631
|
+
// GRM by default (vs strict CommonMark):
|
|
3632
|
+
// Table, TaskList, Strikethrough, and Autolink.
|
|
3633
|
+
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
3634
|
+
// https://github.github.com/gfm
|
|
3635
|
+
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
3636
|
+
base: markdownLanguage3,
|
|
3637
|
+
// Languages for syntax highlighting fenced code blocks.
|
|
3638
|
+
codeLanguages: languages,
|
|
3639
|
+
// Parser extensions.
|
|
3640
|
+
extensions: [
|
|
3641
|
+
// GFM provided by default.
|
|
3642
|
+
markdownTagsExtensions
|
|
3643
|
+
]
|
|
3644
|
+
}),
|
|
3645
|
+
// https://github.com/codemirror/theme-one-dark
|
|
3646
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
3647
|
+
// Custom styles.
|
|
3648
|
+
syntaxHighlighting(markdownHighlightStyle()),
|
|
3649
|
+
keymap7.of([
|
|
3650
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
3651
|
+
indentWithTab2,
|
|
3652
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
3653
|
+
...defaultKeymap2,
|
|
3654
|
+
...completionKeymap2,
|
|
3655
|
+
...lintKeymap
|
|
3656
|
+
])
|
|
3657
|
+
];
|
|
3658
|
+
};
|
|
3659
|
+
|
|
3660
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
3661
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3662
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
3663
|
+
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
3664
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
3665
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
3666
|
+
toDOM() {
|
|
3667
|
+
const el = document.createElement("span");
|
|
3668
|
+
el.className = "cm-hr";
|
|
3669
|
+
return el;
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3672
|
+
var LinkButton = class extends WidgetType3 {
|
|
3673
|
+
constructor(url, render) {
|
|
3674
|
+
super();
|
|
3675
|
+
this.url = url;
|
|
3676
|
+
this.render = render;
|
|
3677
|
+
}
|
|
3678
|
+
eq(other) {
|
|
3679
|
+
return this.url === other.url;
|
|
3680
|
+
}
|
|
3681
|
+
toDOM(view) {
|
|
3682
|
+
const el = document.createElement("span");
|
|
3683
|
+
this.render(el, this.url);
|
|
3684
|
+
return el;
|
|
3625
3685
|
}
|
|
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
3686
|
};
|
|
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
|
-
}
|
|
3687
|
+
var CheckboxWidget = class extends WidgetType3 {
|
|
3688
|
+
constructor(_checked) {
|
|
3689
|
+
super();
|
|
3690
|
+
this._checked = _checked;
|
|
3691
|
+
}
|
|
3692
|
+
eq(other) {
|
|
3693
|
+
return this._checked === other._checked;
|
|
3694
|
+
}
|
|
3695
|
+
toDOM(view) {
|
|
3696
|
+
const input = document.createElement("input");
|
|
3697
|
+
input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
|
|
3698
|
+
input.type = "checkbox";
|
|
3699
|
+
input.checked = this._checked;
|
|
3700
|
+
if (view.state.readOnly) {
|
|
3701
|
+
input.setAttribute("disabled", "true");
|
|
3702
|
+
} else {
|
|
3703
|
+
input.onmousedown = (event) => {
|
|
3704
|
+
const pos = view.posAtDOM(input);
|
|
3705
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
3706
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
3707
|
+
view.dispatch({
|
|
3708
|
+
changes: {
|
|
3709
|
+
from: pos + 1,
|
|
3710
|
+
to: pos + 2,
|
|
3711
|
+
insert: this._checked ? " " : "x"
|
|
3679
3712
|
}
|
|
3680
|
-
}
|
|
3713
|
+
});
|
|
3714
|
+
event.preventDefault();
|
|
3681
3715
|
}
|
|
3682
|
-
}
|
|
3683
|
-
}
|
|
3716
|
+
};
|
|
3717
|
+
}
|
|
3718
|
+
return input;
|
|
3684
3719
|
}
|
|
3685
|
-
|
|
3720
|
+
ignoreEvent() {
|
|
3686
3721
|
return false;
|
|
3687
3722
|
}
|
|
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
3723
|
};
|
|
3708
|
-
var
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3724
|
+
var hide = Decoration5.replace({});
|
|
3725
|
+
var fencedCodeLine = Decoration5.line({
|
|
3726
|
+
class: mx2("cm-code cm-codeblock-line")
|
|
3727
|
+
});
|
|
3728
|
+
var fencedCodeLineFirst = Decoration5.line({
|
|
3729
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
|
3730
|
+
});
|
|
3731
|
+
var fencedCodeLineLast = Decoration5.line({
|
|
3732
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
3733
|
+
});
|
|
3734
|
+
var horizontalRule = Decoration5.replace({
|
|
3735
|
+
widget: new HorizontalRuleWidget()
|
|
3736
|
+
});
|
|
3737
|
+
var checkedTask = Decoration5.replace({
|
|
3738
|
+
widget: new CheckboxWidget(true)
|
|
3739
|
+
});
|
|
3740
|
+
var uncheckedTask = Decoration5.replace({
|
|
3741
|
+
widget: new CheckboxWidget(false)
|
|
3742
|
+
});
|
|
3743
|
+
var editingRange = (state2, range, focus) => {
|
|
3744
|
+
const { readOnly, selection: { main: { head } } } = state2;
|
|
3745
|
+
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
3713
3746
|
};
|
|
3714
|
-
var
|
|
3715
|
-
"Autolink",
|
|
3747
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
3716
3748
|
"CodeMark",
|
|
3717
|
-
"CodeText",
|
|
3718
|
-
"Comment",
|
|
3719
3749
|
"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;
|
|
3750
|
+
"StrikethroughMark",
|
|
3751
|
+
"SubscriptMark",
|
|
3752
|
+
"SuperscriptMark"
|
|
3753
|
+
]);
|
|
3754
|
+
var buildDecorations = (view, options, focus) => {
|
|
3755
|
+
const deco = new RangeSetBuilder2();
|
|
3756
|
+
const atomicDeco = new RangeSetBuilder2();
|
|
3757
|
+
const { state: state2 } = view;
|
|
3758
|
+
for (const { from, to } of view.visibleRanges) {
|
|
3759
|
+
syntaxTree2(state2).iterate({
|
|
3760
|
+
from,
|
|
3761
|
+
to,
|
|
3762
|
+
enter: (node) => {
|
|
3763
|
+
if (node.name === "FencedCode") {
|
|
3764
|
+
const editing = editingRange(state2, node, focus);
|
|
3765
|
+
for (const block of view.viewportLineBlocks) {
|
|
3766
|
+
if (block.to < node.from) {
|
|
3767
|
+
continue;
|
|
3768
|
+
}
|
|
3769
|
+
if (block.from > node.to) {
|
|
3770
|
+
break;
|
|
3771
|
+
}
|
|
3772
|
+
const first = block.from <= node.from;
|
|
3773
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
3774
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
3775
|
+
if (!editing && (first || last)) {
|
|
3776
|
+
atomicDeco.add(block.from, block.to, hide);
|
|
3777
|
+
}
|
|
3827
3778
|
}
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3779
|
+
return false;
|
|
3780
|
+
} else if (node.name === "Link") {
|
|
3781
|
+
const marks = node.node.getChildren("LinkMark");
|
|
3782
|
+
const urlNode = node.node.getChild("URL");
|
|
3783
|
+
const editing = editingRange(state2, node, focus);
|
|
3784
|
+
if (urlNode && marks.length >= 2) {
|
|
3785
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3786
|
+
if (!editing) {
|
|
3787
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
|
3788
|
+
}
|
|
3789
|
+
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
3790
|
+
tagName: "a",
|
|
3791
|
+
attributes: {
|
|
3792
|
+
class: "cm-link",
|
|
3793
|
+
href: url,
|
|
3794
|
+
rel: "noreferrer",
|
|
3795
|
+
target: "_blank"
|
|
3796
|
+
}
|
|
3797
|
+
}));
|
|
3798
|
+
if (!editing) {
|
|
3799
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
3800
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
3801
|
+
}) : hide);
|
|
3802
|
+
}
|
|
3839
3803
|
}
|
|
3840
|
-
} else if (
|
|
3841
|
-
const
|
|
3842
|
-
if (
|
|
3843
|
-
|
|
3804
|
+
} else if (node.name === "HeaderMark") {
|
|
3805
|
+
const parent = node.node.parent;
|
|
3806
|
+
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
3807
|
+
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
3808
|
+
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
3844
3809
|
}
|
|
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
|
-
}
|
|
3810
|
+
} else if (node.name === "HorizontalRule") {
|
|
3811
|
+
if (!editingRange(state2, node, focus)) {
|
|
3812
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
3864
3813
|
}
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3814
|
+
} else if (node.name === "TaskMarker") {
|
|
3815
|
+
if (!editingRange(state2, node, focus)) {
|
|
3816
|
+
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3817
|
+
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
3818
|
+
class: "cm-task"
|
|
3819
|
+
}));
|
|
3820
|
+
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
3869
3821
|
}
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
listStyle = false;
|
|
3822
|
+
} else if (MarksByParent.has(node.name)) {
|
|
3823
|
+
if (!editingRange(state2, node.node.parent, focus)) {
|
|
3824
|
+
atomicDeco.add(node.from, node.to, hide);
|
|
3874
3825
|
}
|
|
3875
|
-
currentBlock = null;
|
|
3876
|
-
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
3877
|
-
currentBlock.active[InlineMarker[name]] = false;
|
|
3878
3826
|
}
|
|
3879
3827
|
}
|
|
3880
3828
|
});
|
|
3881
3829
|
}
|
|
3882
|
-
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3883
|
-
const blankLine = from === to;
|
|
3884
3830
|
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
|
|
3831
|
+
deco: deco.finish(),
|
|
3832
|
+
atomicDeco: atomicDeco.finish()
|
|
3894
3833
|
};
|
|
3895
3834
|
};
|
|
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
|
-
]);
|
|
3835
|
+
var forceUpdate = StateEffect4.define();
|
|
3836
|
+
var decorateMarkdown = (options = {}) => {
|
|
3911
3837
|
return [
|
|
3912
|
-
|
|
3913
|
-
|
|
3838
|
+
ViewPlugin4.fromClass(class {
|
|
3839
|
+
constructor(view) {
|
|
3840
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
|
|
3841
|
+
}
|
|
3842
|
+
update(update2) {
|
|
3843
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
3844
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
3845
|
+
this.clearUpdate();
|
|
3846
|
+
} else if (update2.selectionSet) {
|
|
3847
|
+
this.scheduleUpdate(update2.view);
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
3851
|
+
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
3852
|
+
scheduleUpdate(view) {
|
|
3853
|
+
this.clearUpdate();
|
|
3854
|
+
this.pendingUpdate = setTimeout(() => {
|
|
3855
|
+
view.dispatch({
|
|
3856
|
+
effects: forceUpdate.of(null)
|
|
3857
|
+
});
|
|
3858
|
+
}, options.selectionChangeDelay);
|
|
3859
|
+
}
|
|
3860
|
+
clearUpdate() {
|
|
3861
|
+
if (this.pendingUpdate) {
|
|
3862
|
+
clearTimeout(this.pendingUpdate);
|
|
3863
|
+
this.pendingUpdate = void 0;
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
destroy() {
|
|
3867
|
+
this.clearUpdate();
|
|
3868
|
+
}
|
|
3869
|
+
}, {
|
|
3870
|
+
provide: (plugin) => [
|
|
3871
|
+
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3872
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3873
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
3874
|
+
]
|
|
3875
|
+
}),
|
|
3876
|
+
formattingStyles
|
|
3914
3877
|
];
|
|
3915
3878
|
};
|
|
3879
|
+
var formattingStyles = EditorView12.baseTheme({
|
|
3880
|
+
"& .cm-code": {
|
|
3881
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
3882
|
+
},
|
|
3883
|
+
"& .cm-codeblock-line": {
|
|
3884
|
+
paddingInline: "1rem !important"
|
|
3885
|
+
},
|
|
3886
|
+
"& .cm-codeblock-end": {
|
|
3887
|
+
display: "inline-block",
|
|
3888
|
+
width: "100%",
|
|
3889
|
+
position: "relative",
|
|
3890
|
+
"&::after": {
|
|
3891
|
+
position: "absolute",
|
|
3892
|
+
inset: 0,
|
|
3893
|
+
content: '""'
|
|
3894
|
+
}
|
|
3895
|
+
},
|
|
3896
|
+
"& .cm-codeblock-first": {
|
|
3897
|
+
borderTopLeftRadius: ".5rem",
|
|
3898
|
+
borderTopRightRadius: ".5rem"
|
|
3899
|
+
},
|
|
3900
|
+
"& .cm-codeblock-last": {
|
|
3901
|
+
borderBottomLeftRadius: ".5rem",
|
|
3902
|
+
borderBottomRightRadius: ".5rem"
|
|
3903
|
+
},
|
|
3904
|
+
"&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
|
|
3905
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
3906
|
+
mixBlendMode: "darken"
|
|
3907
|
+
},
|
|
3908
|
+
"&dark .cm-codeblock-line, &dark .cm-activeLine.cm-codeblock-line": {
|
|
3909
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
3910
|
+
mixBlendMode: "lighten"
|
|
3911
|
+
},
|
|
3912
|
+
"& .cm-hr": {
|
|
3913
|
+
display: "inline-block",
|
|
3914
|
+
width: "100%",
|
|
3915
|
+
height: "0",
|
|
3916
|
+
verticalAlign: "middle",
|
|
3917
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
3918
|
+
},
|
|
3919
|
+
"& .cm-task": {
|
|
3920
|
+
color: getToken("extend.colors.blue.500")
|
|
3921
|
+
},
|
|
3922
|
+
"& .cm-task-checkbox": {
|
|
3923
|
+
marginLeft: "4px",
|
|
3924
|
+
marginRight: "4px"
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3916
3927
|
|
|
3917
3928
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3918
3929
|
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3919
3930
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
3920
|
-
import { Decoration as Decoration6, EditorView as
|
|
3931
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3921
3932
|
var image = (options = {}) => {
|
|
3922
3933
|
return StateField5.define({
|
|
3923
3934
|
create: (state2) => {
|
|
@@ -3944,7 +3955,7 @@ var image = (options = {}) => {
|
|
|
3944
3955
|
add: buildDecorations2(from, to, tr.state)
|
|
3945
3956
|
});
|
|
3946
3957
|
},
|
|
3947
|
-
provide: (field) =>
|
|
3958
|
+
provide: (field) => EditorView13.decorations.from(field)
|
|
3948
3959
|
});
|
|
3949
3960
|
};
|
|
3950
3961
|
var preloaded = /* @__PURE__ */ new Set();
|
|
@@ -4034,12 +4045,12 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
|
4034
4045
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
4035
4046
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4036
4047
|
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
4037
|
-
import { Decoration as Decoration7, EditorView as
|
|
4048
|
+
import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4038
4049
|
var table = (options = {}) => {
|
|
4039
4050
|
return StateField6.define({
|
|
4040
4051
|
create: (state2) => update(state2, options),
|
|
4041
4052
|
update: (_, tr) => update(tr.state, options),
|
|
4042
|
-
provide: (field) =>
|
|
4053
|
+
provide: (field) => EditorView14.decorations.from(field)
|
|
4043
4054
|
});
|
|
4044
4055
|
};
|
|
4045
4056
|
var update = (state2, options) => {
|
|
@@ -4133,8 +4144,8 @@ var TableWidget = class extends WidgetType5 {
|
|
|
4133
4144
|
|
|
4134
4145
|
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
4135
4146
|
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
4136
|
-
import { log as
|
|
4137
|
-
var
|
|
4147
|
+
import { log as log6 } from "@dxos/log";
|
|
4148
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
|
4138
4149
|
var mention = ({ onSearch }) => {
|
|
4139
4150
|
return autocompletion2({
|
|
4140
4151
|
// TODO(burdon): Not working.
|
|
@@ -4146,10 +4157,10 @@ var mention = ({ onSearch }) => {
|
|
|
4146
4157
|
icons: false,
|
|
4147
4158
|
override: [
|
|
4148
4159
|
(context) => {
|
|
4149
|
-
|
|
4160
|
+
log6.info("completion context", {
|
|
4150
4161
|
context
|
|
4151
4162
|
}, {
|
|
4152
|
-
F:
|
|
4163
|
+
F: __dxlog_file8,
|
|
4153
4164
|
L: 26,
|
|
4154
4165
|
S: void 0,
|
|
4155
4166
|
C: (f, a) => f(...a)
|
|
@@ -4209,18 +4220,18 @@ var EditorModes = {
|
|
|
4209
4220
|
};
|
|
4210
4221
|
|
|
4211
4222
|
// packages/ui/react-ui-editor/src/extensions/state.ts
|
|
4212
|
-
import { Transaction
|
|
4213
|
-
import { EditorView as
|
|
4223
|
+
import { Transaction } from "@codemirror/state";
|
|
4224
|
+
import { EditorView as EditorView15, keymap as keymap9 } from "@codemirror/view";
|
|
4214
4225
|
import { debounce as debounce2 } from "@dxos/async";
|
|
4215
4226
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4216
4227
|
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4217
|
-
var
|
|
4228
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4218
4229
|
var scrollAnnotation = "dxos.org/cm/scrolling";
|
|
4219
4230
|
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4220
4231
|
var localStorageStateStoreAdapter = {
|
|
4221
4232
|
setState: (id, state2) => {
|
|
4222
4233
|
invariant4(id, void 0, {
|
|
4223
|
-
F:
|
|
4234
|
+
F: __dxlog_file9,
|
|
4224
4235
|
L: 35,
|
|
4225
4236
|
S: void 0,
|
|
4226
4237
|
A: [
|
|
@@ -4232,7 +4243,7 @@ var localStorageStateStoreAdapter = {
|
|
|
4232
4243
|
},
|
|
4233
4244
|
getState: (id) => {
|
|
4234
4245
|
invariant4(id, void 0, {
|
|
4235
|
-
F:
|
|
4246
|
+
F: __dxlog_file9,
|
|
4236
4247
|
L: 39,
|
|
4237
4248
|
S: void 0,
|
|
4238
4249
|
A: [
|
|
@@ -4248,7 +4259,7 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4248
4259
|
const setStateDebounced = debounce2(setState, 1e3);
|
|
4249
4260
|
return [
|
|
4250
4261
|
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4251
|
-
|
|
4262
|
+
EditorView15.updateListener.of(({ view, changes, transactions }) => {
|
|
4252
4263
|
const id = view.state.facet(documentId2);
|
|
4253
4264
|
if (!id || transactions.some((tr) => tr.isUserEvent(scrollAnnotation))) {
|
|
4254
4265
|
return;
|
|
@@ -4281,11 +4292,11 @@ var state = ({ getState, setState } = {}) => {
|
|
|
4281
4292
|
const state2 = getState(view.state.facet(documentId2));
|
|
4282
4293
|
if (state2) {
|
|
4283
4294
|
view.dispatch({
|
|
4284
|
-
effects:
|
|
4295
|
+
effects: EditorView15.scrollIntoView(state2.scrollTo.from, {
|
|
4285
4296
|
yMargin: 0
|
|
4286
4297
|
}),
|
|
4287
4298
|
selection: state2.selection,
|
|
4288
|
-
annotations:
|
|
4299
|
+
annotations: Transaction.userEvent.of(scrollAnnotation)
|
|
4289
4300
|
});
|
|
4290
4301
|
}
|
|
4291
4302
|
return true;
|
|
@@ -4353,9 +4364,9 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4353
4364
|
};
|
|
4354
4365
|
|
|
4355
4366
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4356
|
-
var
|
|
4367
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4357
4368
|
var instanceCount = 0;
|
|
4358
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo =
|
|
4369
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView16.scrollIntoView(0, {
|
|
4359
4370
|
yMargin: 0
|
|
4360
4371
|
}), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
|
|
4361
4372
|
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
@@ -4376,11 +4387,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4376
4387
|
autoFocus
|
|
4377
4388
|
]);
|
|
4378
4389
|
useEffect2(() => {
|
|
4379
|
-
|
|
4390
|
+
log7("create", {
|
|
4380
4391
|
id,
|
|
4381
4392
|
instanceId
|
|
4382
4393
|
}, {
|
|
4383
|
-
F:
|
|
4394
|
+
F: __dxlog_file10,
|
|
4384
4395
|
L: 88,
|
|
4385
4396
|
S: void 0,
|
|
4386
4397
|
C: (f, a) => f(...a)
|
|
@@ -4391,16 +4402,16 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4391
4402
|
extensions: [
|
|
4392
4403
|
id && documentId2.of(id),
|
|
4393
4404
|
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
F:
|
|
4405
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4406
|
+
log7.catch(err, void 0, {
|
|
4407
|
+
F: __dxlog_file10,
|
|
4397
4408
|
L: 101,
|
|
4398
4409
|
S: void 0,
|
|
4399
4410
|
C: (f, a) => f(...a)
|
|
4400
4411
|
});
|
|
4401
4412
|
}),
|
|
4402
4413
|
// Focus.
|
|
4403
|
-
|
|
4414
|
+
EditorView16.updateListener.of((update2) => {
|
|
4404
4415
|
update2.transactions.forEach((transaction) => {
|
|
4405
4416
|
if (transaction.isUserEvent(focusEvent)) {
|
|
4406
4417
|
rootRef.current?.focus();
|
|
@@ -4410,7 +4421,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4410
4421
|
extensions
|
|
4411
4422
|
].filter(isNotFalsy4)
|
|
4412
4423
|
});
|
|
4413
|
-
const view2 = new
|
|
4424
|
+
const view2 = new EditorView16({
|
|
4414
4425
|
state: state2,
|
|
4415
4426
|
parent: rootRef.current,
|
|
4416
4427
|
scrollTo,
|
|
@@ -4436,11 +4447,11 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4436
4447
|
}
|
|
4437
4448
|
setView(view2);
|
|
4438
4449
|
return () => {
|
|
4439
|
-
|
|
4450
|
+
log7("destroy", {
|
|
4440
4451
|
id,
|
|
4441
4452
|
instanceId
|
|
4442
4453
|
}, {
|
|
4443
|
-
F:
|
|
4454
|
+
F: __dxlog_file10,
|
|
4444
4455
|
L: 150,
|
|
4445
4456
|
S: void 0,
|
|
4446
4457
|
C: (f, a) => f(...a)
|
|
@@ -4746,7 +4757,7 @@ var MarkdownCustom = ({ onUpload } = {}) => {
|
|
|
4746
4757
|
});
|
|
4747
4758
|
useEffect3(() => {
|
|
4748
4759
|
if (onUpload && acceptedFiles.length) {
|
|
4749
|
-
|
|
4760
|
+
requestAnimationFrame(async () => {
|
|
4750
4761
|
const f = acceptedFiles[0];
|
|
4751
4762
|
const file = new File([
|
|
4752
4763
|
f
|
|
@@ -4795,56 +4806,7 @@ var Toolbar = {
|
|
|
4795
4806
|
|
|
4796
4807
|
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4797
4808
|
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
|
-
};
|
|
4809
|
+
return (action) => view && processAction(view, action);
|
|
4848
4810
|
};
|
|
4849
4811
|
|
|
4850
4812
|
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
@@ -4862,11 +4824,11 @@ var useDocAccessor = (text) => {
|
|
|
4862
4824
|
|
|
4863
4825
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4864
4826
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4865
|
-
import { EditorView as
|
|
4827
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4866
4828
|
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4867
|
-
import { log as
|
|
4829
|
+
import { log as log8 } from "@dxos/log";
|
|
4868
4830
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4869
|
-
var
|
|
4831
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4870
4832
|
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4871
4833
|
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4872
4834
|
const onUpdate = useRef3();
|
|
@@ -4875,10 +4837,10 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4875
4837
|
useEffect4(() => {
|
|
4876
4838
|
let view2;
|
|
4877
4839
|
if (parentRef.current) {
|
|
4878
|
-
|
|
4840
|
+
log8("create", {
|
|
4879
4841
|
id
|
|
4880
4842
|
}, {
|
|
4881
|
-
F:
|
|
4843
|
+
F: __dxlog_file11,
|
|
4882
4844
|
L: 36,
|
|
4883
4845
|
S: void 0,
|
|
4884
4846
|
C: (f, a) => f(...a)
|
|
@@ -4889,21 +4851,21 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4889
4851
|
extensions: [
|
|
4890
4852
|
id && documentId2.of(id),
|
|
4891
4853
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
F:
|
|
4854
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4855
|
+
log8.catch(err, void 0, {
|
|
4856
|
+
F: __dxlog_file11,
|
|
4895
4857
|
L: 46,
|
|
4896
4858
|
S: void 0,
|
|
4897
4859
|
C: (f, a) => f(...a)
|
|
4898
4860
|
});
|
|
4899
4861
|
}),
|
|
4900
4862
|
extensions,
|
|
4901
|
-
|
|
4863
|
+
EditorView17.updateListener.of(() => {
|
|
4902
4864
|
onUpdate.current?.();
|
|
4903
4865
|
})
|
|
4904
4866
|
].filter(isNotFalsy5)
|
|
4905
4867
|
});
|
|
4906
|
-
view2 = new
|
|
4868
|
+
view2 = new EditorView17({
|
|
4907
4869
|
parent: parentRef.current,
|
|
4908
4870
|
scrollTo,
|
|
4909
4871
|
state: state2,
|
|
@@ -4919,10 +4881,10 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4919
4881
|
setView(view2);
|
|
4920
4882
|
}
|
|
4921
4883
|
return () => {
|
|
4922
|
-
|
|
4884
|
+
log8("destroy", {
|
|
4923
4885
|
id
|
|
4924
4886
|
}, {
|
|
4925
|
-
F:
|
|
4887
|
+
F: __dxlog_file11,
|
|
4926
4888
|
L: 74,
|
|
4927
4889
|
S: void 0,
|
|
4928
4890
|
C: (f, a) => f(...a)
|
|
@@ -4994,12 +4956,11 @@ export {
|
|
|
4994
4956
|
createDataExtensions,
|
|
4995
4957
|
createMarkdownExtensions,
|
|
4996
4958
|
createThemeExtensions,
|
|
4997
|
-
cursorLineMargin,
|
|
4998
4959
|
decorateMarkdown,
|
|
4999
4960
|
defaultOptions,
|
|
5000
4961
|
defaultTheme,
|
|
5001
|
-
dnd,
|
|
5002
4962
|
documentId2 as documentId,
|
|
4963
|
+
dropFile,
|
|
5003
4964
|
editorFillLayoutEditor,
|
|
5004
4965
|
editorFillLayoutRoot,
|
|
5005
4966
|
editorMode,
|
|
@@ -5022,6 +4983,7 @@ export {
|
|
|
5022
4983
|
markdownTags,
|
|
5023
4984
|
markdownTagsExtensions,
|
|
5024
4985
|
mention,
|
|
4986
|
+
processAction,
|
|
5025
4987
|
removeBlockquote,
|
|
5026
4988
|
removeCodeblock,
|
|
5027
4989
|
removeLink,
|