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