@dxos/react-ui-editor 0.4.10-main.fa5a270 → 0.4.10-main.fd8ea31
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 +707 -694
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +2 -2
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +2 -3
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/package.json +30 -29
- package/src/components/TextEditor/TextEditor.stories.tsx +21 -18
- package/src/components/TextEditor/TextEditor.tsx +6 -3
- package/src/components/Toolbar/Toolbar.stories.tsx +10 -9
- package/src/extensions/automerge/automerge.stories.tsx +7 -6
- package/src/extensions/automerge/automerge.ts +1 -1
- package/src/extensions/automerge/cursor.ts +4 -37
- package/src/extensions/automerge/sync.ts +1 -1
- package/src/extensions/automerge/update-automerge.ts +1 -1
- package/src/extensions/factories.ts +3 -4
- package/src/extensions/markdown/decorate.ts +90 -62
- package/src/extensions/markdown/formatting.ts +42 -35
- package/src/extensions/markdown/highlight.ts +3 -1
- package/src/extensions/markdown/table.ts +7 -6
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useTextEditor.ts +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +0 -9
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +0 -1
- package/src/hooks/useDocAccessor.ts +0 -27
|
@@ -37,6 +37,7 @@ import { EditorView as EditorView16 } from "@codemirror/view";
|
|
|
37
37
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
38
38
|
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
39
39
|
import { log as log7 } from "@dxos/log";
|
|
40
|
+
import { useDefaultValue } from "@dxos/react-ui";
|
|
40
41
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
41
42
|
|
|
42
43
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
|
@@ -180,30 +181,21 @@ var autocomplete = ({ onSearch }) => {
|
|
|
180
181
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
181
182
|
import { StateField as StateField2 } from "@codemirror/state";
|
|
182
183
|
import { EditorView as EditorView2, ViewPlugin } from "@codemirror/view";
|
|
183
|
-
import { next as
|
|
184
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
184
185
|
|
|
185
186
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
186
|
-
import get from "lodash.get";
|
|
187
|
-
import { next as A } from "@dxos/automerge/automerge";
|
|
188
187
|
import { log } from "@dxos/log";
|
|
188
|
+
import { toCursor, fromCursor } from "@dxos/react-client/echo";
|
|
189
189
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts";
|
|
190
|
-
var cursorConverter = (
|
|
190
|
+
var cursorConverter = (accessor) => ({
|
|
191
191
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
192
192
|
toCursor: (pos) => {
|
|
193
|
-
const doc = handle.docSync();
|
|
194
|
-
if (!doc) {
|
|
195
|
-
return "";
|
|
196
|
-
}
|
|
197
|
-
const value = get(doc, path);
|
|
198
|
-
if (typeof value === "string" && value.length <= pos) {
|
|
199
|
-
return "end";
|
|
200
|
-
}
|
|
201
193
|
try {
|
|
202
|
-
return
|
|
194
|
+
return toCursor(accessor, pos);
|
|
203
195
|
} catch (err) {
|
|
204
196
|
log.catch(err, void 0, {
|
|
205
197
|
F: __dxlog_file,
|
|
206
|
-
L:
|
|
198
|
+
L: 16,
|
|
207
199
|
S: void 0,
|
|
208
200
|
C: (f, a) => f(...a)
|
|
209
201
|
});
|
|
@@ -211,27 +203,12 @@ var cursorConverter = ({ handle, path }) => ({
|
|
|
211
203
|
}
|
|
212
204
|
},
|
|
213
205
|
fromCursor: (cursor) => {
|
|
214
|
-
if (cursor === "") {
|
|
215
|
-
return 0;
|
|
216
|
-
}
|
|
217
|
-
const doc = handle.docSync();
|
|
218
|
-
if (!doc) {
|
|
219
|
-
return 0;
|
|
220
|
-
}
|
|
221
|
-
if (cursor === "end") {
|
|
222
|
-
const value = get(doc, path);
|
|
223
|
-
if (typeof value === "string") {
|
|
224
|
-
return value.length;
|
|
225
|
-
} else {
|
|
226
|
-
return 0;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
206
|
try {
|
|
230
|
-
return
|
|
207
|
+
return fromCursor(accessor, cursor);
|
|
231
208
|
} catch (err) {
|
|
232
209
|
log.catch(err, void 0, {
|
|
233
210
|
F: __dxlog_file,
|
|
234
|
-
L:
|
|
211
|
+
L: 25,
|
|
235
212
|
S: void 0,
|
|
236
213
|
C: (f, a) => f(...a)
|
|
237
214
|
});
|
|
@@ -254,10 +231,10 @@ var isReconcile = (tr) => {
|
|
|
254
231
|
};
|
|
255
232
|
|
|
256
233
|
// packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
|
|
257
|
-
import { next as
|
|
234
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
258
235
|
|
|
259
236
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
260
|
-
import { next as
|
|
237
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
261
238
|
var updateAutomerge = (field, handle, transactions, state2) => {
|
|
262
239
|
const { lastHeads, path } = state2.field(field);
|
|
263
240
|
let hasChanges = false;
|
|
@@ -281,7 +258,7 @@ var updateAutomerge = (field, handle, transactions, state2) => {
|
|
|
281
258
|
});
|
|
282
259
|
}
|
|
283
260
|
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
284
|
-
|
|
261
|
+
A.splice(doc, path.slice(), from, del, insert.toString());
|
|
285
262
|
});
|
|
286
263
|
});
|
|
287
264
|
return newHeads ?? void 0;
|
|
@@ -426,8 +403,8 @@ var Syncer = class {
|
|
|
426
403
|
}
|
|
427
404
|
onAutomergeChange(view) {
|
|
428
405
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
429
|
-
const newHeads =
|
|
430
|
-
const diff =
|
|
406
|
+
const newHeads = A2.getHeads(this._handle.docSync());
|
|
407
|
+
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
431
408
|
const selection = view.state.selection;
|
|
432
409
|
const path = getPath(view.state, this._state);
|
|
433
410
|
updateCodeMirror(view, selection, path, diff);
|
|
@@ -443,7 +420,7 @@ var automerge = (accessor) => {
|
|
|
443
420
|
const syncState = StateField2.define({
|
|
444
421
|
create: () => ({
|
|
445
422
|
path: accessor.path.slice(),
|
|
446
|
-
lastHeads:
|
|
423
|
+
lastHeads: A3.getHeads(accessor.handle.docSync()),
|
|
447
424
|
unreconciledTransactions: []
|
|
448
425
|
}),
|
|
449
426
|
update: (value, tr) => {
|
|
@@ -1395,10 +1372,10 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1395
1372
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1396
1373
|
|
|
1397
1374
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1398
|
-
import
|
|
1375
|
+
import get from "lodash.get";
|
|
1399
1376
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1400
1377
|
var tokens = tailwindConfig({}).theme;
|
|
1401
|
-
var getToken = (path, defaultValue = void 0) =>
|
|
1378
|
+
var getToken = (path, defaultValue = void 0) => get(tokens, path, defaultValue);
|
|
1402
1379
|
|
|
1403
1380
|
// packages/ui/react-ui-editor/src/styles/layout.ts
|
|
1404
1381
|
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
@@ -1922,7 +1899,7 @@ import { hueTokens } from "@dxos/react-ui-theme";
|
|
|
1922
1899
|
import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1923
1900
|
|
|
1924
1901
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
1925
|
-
import
|
|
1902
|
+
import get2 from "lodash.get";
|
|
1926
1903
|
var defaultTheme = {
|
|
1927
1904
|
//
|
|
1928
1905
|
// Main layout:
|
|
@@ -1956,7 +1933,7 @@ var defaultTheme = {
|
|
|
1956
1933
|
// TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
|
|
1957
1934
|
// Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
|
|
1958
1935
|
overflowY: "auto",
|
|
1959
|
-
fontFamily:
|
|
1936
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(","),
|
|
1960
1937
|
lineHeight: 1.5
|
|
1961
1938
|
},
|
|
1962
1939
|
".cm-content": {
|
|
@@ -1966,11 +1943,11 @@ var defaultTheme = {
|
|
|
1966
1943
|
fontSize: "16px"
|
|
1967
1944
|
},
|
|
1968
1945
|
"&light .cm-content": {
|
|
1969
|
-
color:
|
|
1946
|
+
color: get2(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
1970
1947
|
caretColor: "black"
|
|
1971
1948
|
},
|
|
1972
1949
|
"&dark .cm-content": {
|
|
1973
|
-
color:
|
|
1950
|
+
color: get2(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
1974
1951
|
caretColor: "white"
|
|
1975
1952
|
},
|
|
1976
1953
|
//
|
|
@@ -1983,10 +1960,10 @@ var defaultTheme = {
|
|
|
1983
1960
|
borderLeft: "2px solid white"
|
|
1984
1961
|
},
|
|
1985
1962
|
"&light .cm-placeholder": {
|
|
1986
|
-
color:
|
|
1963
|
+
color: get2(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
1987
1964
|
},
|
|
1988
1965
|
"&dark .cm-placeholder": {
|
|
1989
|
-
color:
|
|
1966
|
+
color: get2(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
1990
1967
|
},
|
|
1991
1968
|
//
|
|
1992
1969
|
// line
|
|
@@ -2007,36 +1984,36 @@ var defaultTheme = {
|
|
|
2007
1984
|
// Selection
|
|
2008
1985
|
//
|
|
2009
1986
|
"&light .cm-selectionBackground": {
|
|
2010
|
-
background:
|
|
1987
|
+
background: get2(tokens, "extend.colors.primary.100")
|
|
2011
1988
|
},
|
|
2012
1989
|
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2013
|
-
background:
|
|
1990
|
+
background: get2(tokens, "extend.colors.primary.200")
|
|
2014
1991
|
},
|
|
2015
1992
|
"&dark .cm-selectionBackground": {
|
|
2016
|
-
background:
|
|
1993
|
+
background: get2(tokens, "extend.colors.primary.700")
|
|
2017
1994
|
},
|
|
2018
1995
|
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2019
|
-
background:
|
|
1996
|
+
background: get2(tokens, "extend.colors.primary.600")
|
|
2020
1997
|
},
|
|
2021
1998
|
//
|
|
2022
1999
|
// Search
|
|
2023
2000
|
//
|
|
2024
2001
|
"&light .cm-searchMatch": {
|
|
2025
|
-
backgroundColor:
|
|
2002
|
+
backgroundColor: get2(tokens, "extend.colors.yellow.100")
|
|
2026
2003
|
},
|
|
2027
2004
|
"&dark .cm-searchMatch": {
|
|
2028
|
-
backgroundColor:
|
|
2005
|
+
backgroundColor: get2(tokens, "extend.colors.yellow.700")
|
|
2029
2006
|
},
|
|
2030
2007
|
//
|
|
2031
2008
|
// link
|
|
2032
2009
|
//
|
|
2033
2010
|
".cm-link": {
|
|
2034
|
-
color:
|
|
2011
|
+
color: get2(tokens, "extend.colors.primary.500"),
|
|
2035
2012
|
textDecorationLine: "underline",
|
|
2036
2013
|
textDecorationThickness: "1px",
|
|
2037
2014
|
textUnderlineOffset: "2px",
|
|
2038
2015
|
borderRadius: ".125rem",
|
|
2039
|
-
fontFamily:
|
|
2016
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
2040
2017
|
},
|
|
2041
2018
|
//
|
|
2042
2019
|
// tooltip
|
|
@@ -2059,7 +2036,7 @@ var defaultTheme = {
|
|
|
2059
2036
|
display: "none"
|
|
2060
2037
|
},
|
|
2061
2038
|
".cm-completionLabel": {
|
|
2062
|
-
fontFamily:
|
|
2039
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
2063
2040
|
},
|
|
2064
2041
|
".cm-completionMatchedText": {
|
|
2065
2042
|
textDecoration: "none"
|
|
@@ -2068,15 +2045,15 @@ var defaultTheme = {
|
|
|
2068
2045
|
// table
|
|
2069
2046
|
//
|
|
2070
2047
|
".cm-table *": {
|
|
2071
|
-
fontFamily: `${
|
|
2048
|
+
fontFamily: `${get2(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2072
2049
|
textDecoration: "none !important"
|
|
2073
2050
|
},
|
|
2074
2051
|
".cm-table-head": {
|
|
2075
2052
|
padding: "2px 16px 2px 0px",
|
|
2076
|
-
borderBottom: `1px solid ${
|
|
2053
|
+
borderBottom: `1px solid ${get2(tokens, "extend.colors.neutral.500")}`,
|
|
2077
2054
|
fontWeight: 100,
|
|
2078
2055
|
textAlign: "left",
|
|
2079
|
-
color:
|
|
2056
|
+
color: get2(tokens, "extend.colors.neutral.500")
|
|
2080
2057
|
},
|
|
2081
2058
|
".cm-table-cell": {
|
|
2082
2059
|
padding: "2px 16px 2px 0px"
|
|
@@ -2124,20 +2101,20 @@ var defaultTheme = {
|
|
|
2124
2101
|
*/
|
|
2125
2102
|
".cm-panels": {},
|
|
2126
2103
|
".cm-panel": {
|
|
2127
|
-
fontFamily:
|
|
2104
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(",")
|
|
2128
2105
|
},
|
|
2129
2106
|
".cm-panel input[type=checkbox]": {
|
|
2130
2107
|
marginRight: "0.4rem !important"
|
|
2131
2108
|
},
|
|
2132
2109
|
"&light .cm-panel": {
|
|
2133
|
-
background:
|
|
2110
|
+
background: get2(tokens, "extend.colors.neutral.50")
|
|
2134
2111
|
},
|
|
2135
2112
|
"&dark .cm-panel": {
|
|
2136
|
-
background:
|
|
2113
|
+
background: get2(tokens, "extend.colors.neutral.850")
|
|
2137
2114
|
},
|
|
2138
2115
|
".cm-button": {
|
|
2139
2116
|
margin: "4px",
|
|
2140
|
-
fontFamily:
|
|
2117
|
+
fontFamily: get2(tokens, "fontFamily.body", []).join(","),
|
|
2141
2118
|
backgroundImage: "none",
|
|
2142
2119
|
border: "none",
|
|
2143
2120
|
"&:active": {
|
|
@@ -2145,21 +2122,21 @@ var defaultTheme = {
|
|
|
2145
2122
|
}
|
|
2146
2123
|
},
|
|
2147
2124
|
"&light .cm-button": {
|
|
2148
|
-
background:
|
|
2125
|
+
background: get2(tokens, "extend.colors.neutral.100"),
|
|
2149
2126
|
"&:hover": {
|
|
2150
|
-
background:
|
|
2127
|
+
background: get2(tokens, "extend.colors.neutral.200")
|
|
2151
2128
|
},
|
|
2152
2129
|
"&:active": {
|
|
2153
|
-
background:
|
|
2130
|
+
background: get2(tokens, "extend.colors.neutral.300")
|
|
2154
2131
|
}
|
|
2155
2132
|
},
|
|
2156
2133
|
"&dark .cm-button": {
|
|
2157
|
-
background:
|
|
2134
|
+
background: get2(tokens, "extend.colors.neutral.800"),
|
|
2158
2135
|
"&:hover": {
|
|
2159
|
-
background:
|
|
2136
|
+
background: get2(tokens, "extend.colors.neutral.700")
|
|
2160
2137
|
},
|
|
2161
2138
|
"&:active": {
|
|
2162
|
-
background:
|
|
2139
|
+
background: get2(tokens, "extend.colors.neutral.600")
|
|
2163
2140
|
}
|
|
2164
2141
|
}
|
|
2165
2142
|
};
|
|
@@ -2190,7 +2167,7 @@ var createBasicExtensions = (_props) => {
|
|
|
2190
2167
|
EditorView9.exceptionSink.of((err) => {
|
|
2191
2168
|
log5.catch(err, void 0, {
|
|
2192
2169
|
F: __dxlog_file7,
|
|
2193
|
-
L:
|
|
2170
|
+
L: 90,
|
|
2194
2171
|
S: void 0,
|
|
2195
2172
|
C: (f, a) => f(...a)
|
|
2196
2173
|
});
|
|
@@ -2247,9 +2224,9 @@ var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
|
2247
2224
|
].filter(isNotFalsy2);
|
|
2248
2225
|
};
|
|
2249
2226
|
var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2250
|
-
const extensions = [
|
|
2227
|
+
const extensions = text ? [
|
|
2251
2228
|
automerge(text)
|
|
2252
|
-
];
|
|
2229
|
+
] : [];
|
|
2253
2230
|
if (space && identity) {
|
|
2254
2231
|
const peerId = identity?.identityKey.toHex();
|
|
2255
2232
|
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
@@ -2302,255 +2279,261 @@ var List;
|
|
|
2302
2279
|
List2[List2["Bullet"] = 1] = "Bullet";
|
|
2303
2280
|
List2[List2["Task"] = 2] = "Task";
|
|
2304
2281
|
})(List || (List = {}));
|
|
2305
|
-
var setHeading = (level) =>
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
sawBlock = true;
|
|
2319
|
-
prevBlock = node.from;
|
|
2320
|
-
const blockType = Textblocks[node.name];
|
|
2321
|
-
const isHeading = /heading(\d)/.exec(blockType);
|
|
2322
|
-
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2323
|
-
if (curLevel < 0 || curLevel === level) {
|
|
2324
|
-
return;
|
|
2325
|
-
}
|
|
2326
|
-
if (curLevel === 0) {
|
|
2327
|
-
changes.push({
|
|
2328
|
-
from: node.from,
|
|
2329
|
-
insert: "#".repeat(level) + " "
|
|
2330
|
-
});
|
|
2331
|
-
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
2332
|
-
const nextLine = doc.lineAt(node.to);
|
|
2333
|
-
if (level) {
|
|
2334
|
-
changes.push({
|
|
2335
|
-
from: node.from,
|
|
2336
|
-
insert: "#".repeat(level) + " "
|
|
2337
|
-
});
|
|
2282
|
+
var setHeading = (level) => {
|
|
2283
|
+
return ({ state: state2, dispatch }) => {
|
|
2284
|
+
const { selection: { ranges }, doc } = state2;
|
|
2285
|
+
const changes = [];
|
|
2286
|
+
let prevBlock = -1;
|
|
2287
|
+
for (const range of ranges) {
|
|
2288
|
+
let sawBlock = false;
|
|
2289
|
+
syntaxTree(state2).iterate({
|
|
2290
|
+
from: range.from,
|
|
2291
|
+
to: range.to,
|
|
2292
|
+
enter: (node) => {
|
|
2293
|
+
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
2294
|
+
return;
|
|
2338
2295
|
}
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
if (
|
|
2296
|
+
sawBlock = true;
|
|
2297
|
+
prevBlock = node.from;
|
|
2298
|
+
const blockType = Textblocks[node.name];
|
|
2299
|
+
const isHeading = /heading(\d)/.exec(blockType);
|
|
2300
|
+
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
2301
|
+
if (curLevel < 0 || curLevel === level) {
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2304
|
+
if (curLevel === 0) {
|
|
2345
2305
|
changes.push({
|
|
2346
2306
|
from: node.from,
|
|
2347
|
-
|
|
2307
|
+
insert: "#".repeat(level) + " "
|
|
2348
2308
|
});
|
|
2349
|
-
} else if (
|
|
2309
|
+
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
2310
|
+
const nextLine = doc.lineAt(node.to);
|
|
2311
|
+
if (level) {
|
|
2312
|
+
changes.push({
|
|
2313
|
+
from: node.from,
|
|
2314
|
+
insert: "#".repeat(level) + " "
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2350
2317
|
changes.push({
|
|
2351
|
-
from:
|
|
2352
|
-
to:
|
|
2318
|
+
from: nextLine.from - 1,
|
|
2319
|
+
to: nextLine.to
|
|
2353
2320
|
});
|
|
2354
2321
|
} else {
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2322
|
+
if (level === 0) {
|
|
2323
|
+
changes.push({
|
|
2324
|
+
from: node.from,
|
|
2325
|
+
to: Math.min(node.to, node.from + curLevel + 1)
|
|
2326
|
+
});
|
|
2327
|
+
} else if (level < curLevel) {
|
|
2328
|
+
changes.push({
|
|
2329
|
+
from: node.from,
|
|
2330
|
+
to: node.from + (curLevel - level)
|
|
2331
|
+
});
|
|
2332
|
+
} else {
|
|
2333
|
+
changes.push({
|
|
2334
|
+
from: node.from,
|
|
2335
|
+
insert: "#".repeat(level - curLevel)
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2359
2338
|
}
|
|
2360
2339
|
}
|
|
2361
|
-
}
|
|
2362
|
-
});
|
|
2363
|
-
let line;
|
|
2364
|
-
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2365
|
-
changes.push({
|
|
2366
|
-
from: line.from,
|
|
2367
|
-
to: line.to,
|
|
2368
|
-
insert: "#".repeat(level) + " "
|
|
2369
2340
|
});
|
|
2341
|
+
let line;
|
|
2342
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2343
|
+
changes.push({
|
|
2344
|
+
from: line.from,
|
|
2345
|
+
to: line.to,
|
|
2346
|
+
insert: "#".repeat(level) + " "
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2370
2349
|
}
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2350
|
+
if (!changes.length) {
|
|
2351
|
+
return false;
|
|
2352
|
+
}
|
|
2353
|
+
const changeSet = state2.changes(changes);
|
|
2354
|
+
dispatch(state2.update({
|
|
2355
|
+
changes: changeSet,
|
|
2356
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2357
|
+
userEvent: "format.setHeading",
|
|
2358
|
+
scrollIntoView: true
|
|
2359
|
+
}));
|
|
2360
|
+
return true;
|
|
2361
|
+
};
|
|
2383
2362
|
};
|
|
2384
|
-
var setStyle = (type, enable) =>
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2363
|
+
var setStyle = (type, enable) => {
|
|
2364
|
+
return ({ state: state2, dispatch }) => {
|
|
2365
|
+
const marker = inlineMarkerText(type);
|
|
2366
|
+
const changes = state2.changeByRange((range) => {
|
|
2367
|
+
if (!enable && range.empty) {
|
|
2368
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2369
|
+
const found = after.indexOf(marker);
|
|
2370
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2371
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2372
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2373
|
+
...before.slice(before.length - found)
|
|
2374
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
2375
|
+
return {
|
|
2376
|
+
changes: [
|
|
2377
|
+
{
|
|
2378
|
+
from: range.head - marker.length - found,
|
|
2379
|
+
to: range.head - found
|
|
2380
|
+
},
|
|
2381
|
+
{
|
|
2382
|
+
from: range.head + found,
|
|
2383
|
+
to: range.head + found + marker.length
|
|
2384
|
+
}
|
|
2385
|
+
],
|
|
2386
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2408
2389
|
}
|
|
2409
2390
|
}
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
if (from < node.from && to > node.from && to <= node.to) {
|
|
2429
|
-
to = node.to;
|
|
2430
|
-
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2431
|
-
from = node.from;
|
|
2432
|
-
}
|
|
2433
|
-
} else if (IgnoreInline.has(name) && enable) {
|
|
2434
|
-
if (node.from < from && node.to > from) {
|
|
2435
|
-
if (to === from) {
|
|
2391
|
+
const changes2 = [];
|
|
2392
|
+
const changesAtEnd = [];
|
|
2393
|
+
let blockStart = -1;
|
|
2394
|
+
let blockEnd = -1;
|
|
2395
|
+
let startCovered = false;
|
|
2396
|
+
let endCovered = false;
|
|
2397
|
+
let { from, to } = range;
|
|
2398
|
+
syntaxTree(state2).iterate({
|
|
2399
|
+
from,
|
|
2400
|
+
to,
|
|
2401
|
+
enter: (node) => {
|
|
2402
|
+
const { name } = node;
|
|
2403
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2404
|
+
blockStart = blockContentStart(node);
|
|
2405
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2406
|
+
startCovered = endCovered = false;
|
|
2407
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
2408
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
2436
2409
|
to = node.to;
|
|
2410
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
2411
|
+
from = node.from;
|
|
2437
2412
|
}
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
const markType = InlineMarker[name];
|
|
2445
|
-
const size = inlineMarkerText(markType).length;
|
|
2446
|
-
const openEnd = node.from + size;
|
|
2447
|
-
const closeStart = node.to - size;
|
|
2448
|
-
if (markType === type) {
|
|
2449
|
-
if (openEnd <= from && closeStart >= from) {
|
|
2450
|
-
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2451
|
-
from: node.from,
|
|
2452
|
-
to: openEnd
|
|
2453
|
-
} : true;
|
|
2413
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
2414
|
+
if (node.from < from && node.to > from) {
|
|
2415
|
+
if (to === from) {
|
|
2416
|
+
to = node.to;
|
|
2417
|
+
}
|
|
2418
|
+
from = node.to;
|
|
2454
2419
|
}
|
|
2455
|
-
if (
|
|
2456
|
-
|
|
2457
|
-
from: closeStart,
|
|
2458
|
-
to: node.to
|
|
2459
|
-
} : true;
|
|
2420
|
+
if (node.from < to && node.to > to) {
|
|
2421
|
+
to = node.from;
|
|
2460
2422
|
}
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2423
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
2424
|
+
const markType = InlineMarker[name];
|
|
2425
|
+
const size = inlineMarkerText(markType).length;
|
|
2426
|
+
const openEnd = node.from + size;
|
|
2427
|
+
const closeStart = node.to - size;
|
|
2428
|
+
if (markType === type) {
|
|
2429
|
+
if (openEnd <= from && closeStart >= from) {
|
|
2430
|
+
startCovered = !enable && openEnd === skipMarkers(from, node.node, -1, openEnd) ? {
|
|
2431
|
+
from: node.from,
|
|
2432
|
+
to: openEnd
|
|
2433
|
+
} : true;
|
|
2434
|
+
}
|
|
2435
|
+
if (openEnd <= to && closeStart >= to) {
|
|
2436
|
+
endCovered = !enable && closeStart === skipMarkers(to, node.node, 1, closeStart) ? {
|
|
2437
|
+
from: closeStart,
|
|
2438
|
+
to: node.to
|
|
2439
|
+
} : true;
|
|
2473
2440
|
}
|
|
2474
2441
|
}
|
|
2475
|
-
if (
|
|
2476
|
-
|
|
2477
|
-
from: closeStart,
|
|
2478
|
-
to: node.to
|
|
2479
|
-
});
|
|
2480
|
-
if (markType !== type && openEnd <= from) {
|
|
2442
|
+
if (markType === type || type === 3 && enable) {
|
|
2443
|
+
if (node.from >= from && openEnd <= to) {
|
|
2481
2444
|
changes2.push({
|
|
2482
|
-
from:
|
|
2483
|
-
|
|
2445
|
+
from: node.from,
|
|
2446
|
+
to: openEnd
|
|
2484
2447
|
});
|
|
2448
|
+
if (markType !== type && closeStart >= to) {
|
|
2449
|
+
changesAtEnd.push({
|
|
2450
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2451
|
+
insert: inlineMarkerText(markType)
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
if (closeStart >= from && node.to <= to) {
|
|
2456
|
+
changes2.push({
|
|
2457
|
+
from: closeStart,
|
|
2458
|
+
to: node.to
|
|
2459
|
+
});
|
|
2460
|
+
if (markType !== type && openEnd <= from) {
|
|
2461
|
+
changes2.push({
|
|
2462
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2463
|
+
insert: inlineMarkerText(markType)
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
2485
2466
|
}
|
|
2486
2467
|
}
|
|
2487
2468
|
}
|
|
2488
|
-
}
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
}
|
|
2469
|
+
},
|
|
2470
|
+
leave: (node) => {
|
|
2471
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2472
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2473
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2474
|
+
if (enable) {
|
|
2475
|
+
if (!startCovered) {
|
|
2476
|
+
changes2.push({
|
|
2477
|
+
from: rangeStart,
|
|
2478
|
+
insert: marker
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
if (!endCovered) {
|
|
2482
|
+
changes2.push({
|
|
2483
|
+
from: rangeEnd,
|
|
2484
|
+
insert: marker
|
|
2485
|
+
});
|
|
2486
|
+
}
|
|
2487
|
+
} else {
|
|
2488
|
+
if (typeof startCovered === "object") {
|
|
2489
|
+
changes2.push(startCovered);
|
|
2490
|
+
} else if (startCovered) {
|
|
2491
|
+
changes2.push({
|
|
2492
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
2493
|
+
insert: marker
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
if (typeof endCovered === "object") {
|
|
2497
|
+
changes2.push(endCovered);
|
|
2498
|
+
} else if (endCovered) {
|
|
2499
|
+
changes2.push({
|
|
2500
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
2501
|
+
insert: marker
|
|
2502
|
+
});
|
|
2503
|
+
}
|
|
2523
2504
|
}
|
|
2524
2505
|
}
|
|
2525
2506
|
}
|
|
2507
|
+
});
|
|
2508
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2509
|
+
return {
|
|
2510
|
+
changes: {
|
|
2511
|
+
from: range.head,
|
|
2512
|
+
insert: marker + marker
|
|
2513
|
+
},
|
|
2514
|
+
range: EditorSelection.cursor(range.head + marker.length)
|
|
2515
|
+
};
|
|
2526
2516
|
}
|
|
2527
|
-
|
|
2528
|
-
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2517
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
2529
2518
|
return {
|
|
2530
|
-
changes:
|
|
2531
|
-
|
|
2532
|
-
insert: marker + marker
|
|
2533
|
-
},
|
|
2534
|
-
range: EditorSelection.cursor(range.head + marker.length)
|
|
2519
|
+
changes: changeSet,
|
|
2520
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2535
2521
|
};
|
|
2536
|
-
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
}
|
|
2543
|
-
dispatch(state2.update(changes, {
|
|
2544
|
-
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2545
|
-
scrollIntoView: true
|
|
2546
|
-
}));
|
|
2547
|
-
return true;
|
|
2522
|
+
});
|
|
2523
|
+
dispatch(state2.update(changes, {
|
|
2524
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2525
|
+
scrollIntoView: true
|
|
2526
|
+
}));
|
|
2527
|
+
return true;
|
|
2528
|
+
};
|
|
2548
2529
|
};
|
|
2549
2530
|
var addStyle = (style) => setStyle(style, true);
|
|
2550
2531
|
var removeStyle = (style) => setStyle(style, false);
|
|
2551
|
-
var toggleStyle = (style) =>
|
|
2552
|
-
|
|
2553
|
-
|
|
2532
|
+
var toggleStyle = (style) => {
|
|
2533
|
+
return (arg) => {
|
|
2534
|
+
const form = getFormatting(arg.state);
|
|
2535
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2536
|
+
};
|
|
2554
2537
|
};
|
|
2555
2538
|
var toggleStrong = toggleStyle(0);
|
|
2556
2539
|
var toggleEmphasis = toggleStyle(1);
|
|
@@ -2654,296 +2637,305 @@ var removeLink = ({ state: state2, dispatch }) => {
|
|
|
2654
2637
|
}));
|
|
2655
2638
|
return true;
|
|
2656
2639
|
};
|
|
2657
|
-
var addLink = ({ url, image: image2 } = {}) =>
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
if (
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
if (
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2640
|
+
var addLink = ({ url, image: image2 } = {}) => {
|
|
2641
|
+
return ({ state: state2, dispatch }) => {
|
|
2642
|
+
const changes = state2.changeByRange((range) => {
|
|
2643
|
+
let { from, to } = range;
|
|
2644
|
+
const cutStyles = [];
|
|
2645
|
+
let okay = null;
|
|
2646
|
+
syntaxTree(state2).iterate({
|
|
2647
|
+
from,
|
|
2648
|
+
to,
|
|
2649
|
+
enter: (node) => {
|
|
2650
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2651
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
2652
|
+
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2653
|
+
const sNode = node.node;
|
|
2654
|
+
if (node.from < from && node.to <= to) {
|
|
2655
|
+
if (sNode.firstChild.to === from) {
|
|
2656
|
+
from = node.from;
|
|
2657
|
+
} else {
|
|
2658
|
+
cutStyles.push(sNode);
|
|
2659
|
+
}
|
|
2660
|
+
} else if (node.from >= from && node.to > to) {
|
|
2661
|
+
if (sNode.lastChild.from === to) {
|
|
2662
|
+
to = node.to;
|
|
2663
|
+
} else {
|
|
2664
|
+
cutStyles.push(sNode);
|
|
2665
|
+
}
|
|
2681
2666
|
}
|
|
2682
2667
|
}
|
|
2683
2668
|
}
|
|
2669
|
+
});
|
|
2670
|
+
if (okay === null) {
|
|
2671
|
+
const line = state2.doc.lineAt(from);
|
|
2672
|
+
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
2684
2673
|
}
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2674
|
+
if (!okay) {
|
|
2675
|
+
return {
|
|
2676
|
+
range
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
const changes2 = [];
|
|
2680
|
+
const changesAfter = [];
|
|
2681
|
+
removeLinkInner(from, to, changesAfter, state2);
|
|
2682
|
+
let cursorOffset = 1;
|
|
2683
|
+
for (const style of cutStyles) {
|
|
2684
|
+
const type = InlineMarker[style.name];
|
|
2685
|
+
const mark2 = inlineMarkerText(type);
|
|
2686
|
+
if (style.from < from) {
|
|
2687
|
+
changes2.push({
|
|
2688
|
+
from: skipSpaces(from, state2.doc, -1),
|
|
2689
|
+
insert: mark2
|
|
2690
|
+
});
|
|
2691
|
+
changesAfter.push({
|
|
2692
|
+
from: skipSpaces(from, state2.doc, 1, to),
|
|
2693
|
+
insert: mark2
|
|
2694
|
+
});
|
|
2695
|
+
} else {
|
|
2696
|
+
changes2.push({
|
|
2697
|
+
from: skipSpaces(to, state2.doc, -1, from),
|
|
2698
|
+
insert: mark2
|
|
2699
|
+
});
|
|
2700
|
+
const after = skipSpaces(to, state2.doc, 1);
|
|
2701
|
+
if (after === to) {
|
|
2702
|
+
cursorOffset += mark2.length;
|
|
2703
|
+
}
|
|
2704
|
+
changesAfter.push({
|
|
2705
|
+
from: after,
|
|
2706
|
+
insert: mark2
|
|
2707
|
+
});
|
|
2719
2708
|
}
|
|
2720
|
-
changesAfter.push({
|
|
2721
|
-
from: after,
|
|
2722
|
-
insert: mark2
|
|
2723
|
-
});
|
|
2724
2709
|
}
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2710
|
+
changes2.push({
|
|
2711
|
+
from,
|
|
2712
|
+
insert: image2 ? "`
|
|
2716
|
+
});
|
|
2717
|
+
const changeSet = state2.changes(changes2.concat(changesAfter));
|
|
2718
|
+
return {
|
|
2719
|
+
changes: changeSet,
|
|
2720
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset - (url ? url.length + 2 : 0))
|
|
2721
|
+
};
|
|
2732
2722
|
});
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
return
|
|
2741
|
-
}
|
|
2742
|
-
dispatch(state2.update(changes, {
|
|
2743
|
-
userEvent: "format.link.add",
|
|
2744
|
-
scrollIntoView: true
|
|
2745
|
-
}));
|
|
2746
|
-
return true;
|
|
2723
|
+
if (changes.changes.empty) {
|
|
2724
|
+
return false;
|
|
2725
|
+
}
|
|
2726
|
+
dispatch(state2.update(changes, {
|
|
2727
|
+
userEvent: "format.link.add",
|
|
2728
|
+
scrollIntoView: true
|
|
2729
|
+
}));
|
|
2730
|
+
return true;
|
|
2731
|
+
};
|
|
2747
2732
|
};
|
|
2748
|
-
var addList = (type) =>
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
if (
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
before
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2733
|
+
var addList = (type) => {
|
|
2734
|
+
return ({ state: state2, dispatch }) => {
|
|
2735
|
+
let lastBlock = -1;
|
|
2736
|
+
let counter = 1;
|
|
2737
|
+
let first = true;
|
|
2738
|
+
let parentColumn = null;
|
|
2739
|
+
const blocks = [];
|
|
2740
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2741
|
+
syntaxTree(state2).iterate({
|
|
2742
|
+
from,
|
|
2743
|
+
to,
|
|
2744
|
+
enter: (node) => {
|
|
2745
|
+
if (Object.hasOwn(Textblocks, node.name) && node.name !== "TableCell" || node.name === "Table") {
|
|
2746
|
+
if (first) {
|
|
2747
|
+
let before = node.node.prevSibling;
|
|
2748
|
+
while (before && /Mark$/.test(before.name)) {
|
|
2749
|
+
before = before.prevSibling;
|
|
2750
|
+
}
|
|
2751
|
+
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
2752
|
+
const item = before.lastChild;
|
|
2753
|
+
const itemLine = state2.doc.lineAt(item.from);
|
|
2754
|
+
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2755
|
+
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2756
|
+
if (type === 0) {
|
|
2757
|
+
const mark2 = /^\s*(\d+)[.)]/.exec(itemText);
|
|
2758
|
+
if (mark2) {
|
|
2759
|
+
parentColumn += mark2[1].length;
|
|
2760
|
+
counter = +mark2[1] + 1;
|
|
2761
|
+
}
|
|
2775
2762
|
}
|
|
2776
2763
|
}
|
|
2764
|
+
first = false;
|
|
2765
|
+
}
|
|
2766
|
+
if (node.from === lastBlock) {
|
|
2767
|
+
return;
|
|
2777
2768
|
}
|
|
2778
|
-
|
|
2769
|
+
lastBlock = node.from;
|
|
2770
|
+
blocks.push({
|
|
2771
|
+
node: node.node,
|
|
2772
|
+
counter,
|
|
2773
|
+
parentColumn
|
|
2774
|
+
});
|
|
2775
|
+
counter++;
|
|
2776
|
+
return false;
|
|
2779
2777
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2778
|
+
},
|
|
2779
|
+
leave: (node) => {
|
|
2780
|
+
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
2781
|
+
counter = 1;
|
|
2782
|
+
parentColumn = null;
|
|
2782
2783
|
}
|
|
2783
|
-
lastBlock = node.from;
|
|
2784
|
-
blocks.push({
|
|
2785
|
-
node: node.node,
|
|
2786
|
-
counter,
|
|
2787
|
-
parentColumn
|
|
2788
|
-
});
|
|
2789
|
-
counter++;
|
|
2790
|
-
return false;
|
|
2791
|
-
}
|
|
2792
|
-
},
|
|
2793
|
-
leave: (node) => {
|
|
2794
|
-
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
2795
|
-
counter = 1;
|
|
2796
|
-
parentColumn = null;
|
|
2797
2784
|
}
|
|
2798
|
-
}
|
|
2799
|
-
});
|
|
2800
|
-
}
|
|
2801
|
-
if (!blocks.length) {
|
|
2802
|
-
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
2803
|
-
if (from === to) {
|
|
2804
|
-
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
2805
|
-
dispatch(state2.update({
|
|
2806
|
-
changes: [
|
|
2807
|
-
{
|
|
2808
|
-
from,
|
|
2809
|
-
insert
|
|
2810
|
-
}
|
|
2811
|
-
],
|
|
2812
|
-
selection: {
|
|
2813
|
-
anchor: from + insert.length
|
|
2814
|
-
},
|
|
2815
|
-
userEvent: "format.list.add",
|
|
2816
|
-
scrollIntoView: true
|
|
2817
|
-
}));
|
|
2818
|
-
return true;
|
|
2819
|
-
}
|
|
2820
|
-
return false;
|
|
2821
|
-
}
|
|
2822
|
-
const changes = [];
|
|
2823
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
2824
|
-
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2825
|
-
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2826
|
-
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2827
|
-
if (type === 0) {
|
|
2828
|
-
padding += String(counter2).length;
|
|
2785
|
+
});
|
|
2829
2786
|
}
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2787
|
+
if (!blocks.length) {
|
|
2788
|
+
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
2789
|
+
if (from === to) {
|
|
2790
|
+
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
2791
|
+
dispatch(state2.update({
|
|
2792
|
+
changes: [
|
|
2793
|
+
{
|
|
2794
|
+
from,
|
|
2795
|
+
insert
|
|
2796
|
+
}
|
|
2797
|
+
],
|
|
2798
|
+
selection: {
|
|
2799
|
+
anchor: from + insert.length
|
|
2800
|
+
},
|
|
2801
|
+
userEvent: "format.list.add",
|
|
2802
|
+
scrollIntoView: true
|
|
2803
|
+
}));
|
|
2804
|
+
return true;
|
|
2805
|
+
}
|
|
2806
|
+
return false;
|
|
2834
2807
|
}
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2808
|
+
const changes = [];
|
|
2809
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
2810
|
+
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2811
|
+
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2812
|
+
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2813
|
+
if (type === 0) {
|
|
2814
|
+
padding += String(counter2).length;
|
|
2815
|
+
}
|
|
2816
|
+
let line = state2.doc.lineAt(nodeFrom);
|
|
2817
|
+
const column = nodeFrom - line.from;
|
|
2818
|
+
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
2819
|
+
padding = Math.max(padding, parentColumn2 - column);
|
|
2820
|
+
}
|
|
2821
|
+
let mark2;
|
|
2822
|
+
if (type === 0) {
|
|
2823
|
+
let max = counter2;
|
|
2824
|
+
for (let j = i + 1; j < blocks.length; j++) {
|
|
2825
|
+
if (blocks[j].counter !== max + 1) {
|
|
2826
|
+
break;
|
|
2827
|
+
}
|
|
2828
|
+
max++;
|
|
2841
2829
|
}
|
|
2842
|
-
|
|
2830
|
+
const num = String(counter2);
|
|
2831
|
+
padding = Math.max(String(max).length, padding);
|
|
2832
|
+
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
2833
|
+
} else {
|
|
2834
|
+
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
2843
2835
|
}
|
|
2844
|
-
const num = String(counter2);
|
|
2845
|
-
padding = Math.max(String(max).length, padding);
|
|
2846
|
-
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
2847
|
-
} else {
|
|
2848
|
-
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
2849
|
-
}
|
|
2850
|
-
changes.push({
|
|
2851
|
-
from: nodeFrom,
|
|
2852
|
-
insert: mark2
|
|
2853
|
-
});
|
|
2854
|
-
while (line.to < node.to) {
|
|
2855
|
-
line = state2.doc.lineAt(line.to + 1);
|
|
2856
|
-
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2857
2836
|
changes.push({
|
|
2858
|
-
from:
|
|
2859
|
-
insert:
|
|
2837
|
+
from: nodeFrom,
|
|
2838
|
+
insert: mark2
|
|
2860
2839
|
});
|
|
2840
|
+
while (line.to < node.to) {
|
|
2841
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2842
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2843
|
+
changes.push({
|
|
2844
|
+
from: line.from + Math.min(open, column),
|
|
2845
|
+
insert: " ".repeat(mark2.length)
|
|
2846
|
+
});
|
|
2847
|
+
}
|
|
2861
2848
|
}
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2849
|
+
if (type === 0) {
|
|
2850
|
+
const last = blocks[blocks.length - 1];
|
|
2851
|
+
let next = last.node.nextSibling;
|
|
2852
|
+
while (next && /Mark$/.test(next.name)) {
|
|
2853
|
+
next = next.nextSibling;
|
|
2854
|
+
}
|
|
2855
|
+
if (next?.name === "OrderedList") {
|
|
2856
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
|
|
2857
|
+
}
|
|
2871
2858
|
}
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2859
|
+
"Oeswe";
|
|
2860
|
+
const changeSet = state2.changes(changes);
|
|
2861
|
+
dispatch(state2.update({
|
|
2862
|
+
changes: changeSet,
|
|
2863
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2864
|
+
userEvent: "format.list.add",
|
|
2865
|
+
scrollIntoView: true
|
|
2866
|
+
}));
|
|
2867
|
+
return true;
|
|
2868
|
+
};
|
|
2881
2869
|
};
|
|
2882
|
-
var removeList = (type) =>
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
stack[stack.length - 1]
|
|
2897
|
-
|
|
2898
|
-
},
|
|
2899
|
-
leave: (node) => {
|
|
2900
|
-
const { name } = node;
|
|
2901
|
-
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2902
|
-
stack.pop();
|
|
2903
|
-
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2904
|
-
lastBlock = node.from;
|
|
2905
|
-
let line = state2.doc.lineAt(node.from);
|
|
2906
|
-
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2907
|
-
if (!mark2) {
|
|
2908
|
-
return false;
|
|
2870
|
+
var removeList = (type) => {
|
|
2871
|
+
return ({ state: state2, dispatch }) => {
|
|
2872
|
+
let lastBlock = -1;
|
|
2873
|
+
const changes = [];
|
|
2874
|
+
const stack = [];
|
|
2875
|
+
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
2876
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2877
|
+
syntaxTree(state2).iterate({
|
|
2878
|
+
from,
|
|
2879
|
+
to,
|
|
2880
|
+
enter: (node) => {
|
|
2881
|
+
const { name } = node;
|
|
2882
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2883
|
+
stack.push(name);
|
|
2884
|
+
} else if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2885
|
+
stack[stack.length - 1] = "TaskList";
|
|
2909
2886
|
}
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
to: line.from + Math.min(column + mark2[0].length, open)
|
|
2922
|
-
});
|
|
2887
|
+
},
|
|
2888
|
+
leave: (node) => {
|
|
2889
|
+
const { name } = node;
|
|
2890
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2891
|
+
stack.pop();
|
|
2892
|
+
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2893
|
+
lastBlock = node.from;
|
|
2894
|
+
let line = state2.doc.lineAt(node.from);
|
|
2895
|
+
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2896
|
+
if (!mark2) {
|
|
2897
|
+
return false;
|
|
2923
2898
|
}
|
|
2899
|
+
const column = node.from - line.from;
|
|
2900
|
+
changes.push({
|
|
2901
|
+
from: node.from,
|
|
2902
|
+
to: node.from + mark2[0].length
|
|
2903
|
+
});
|
|
2904
|
+
while (line.to < node.to) {
|
|
2905
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2906
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2907
|
+
if (open > column) {
|
|
2908
|
+
changes.push({
|
|
2909
|
+
from: line.from + column,
|
|
2910
|
+
to: line.from + Math.min(column + mark2[0].length, open)
|
|
2911
|
+
});
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
if (node.to >= to) {
|
|
2915
|
+
renumberListItems(node.node.nextSibling, 1, changes, state2.doc);
|
|
2916
|
+
}
|
|
2917
|
+
return false;
|
|
2924
2918
|
}
|
|
2925
|
-
if (node.to >= to) {
|
|
2926
|
-
renumberListItems(node.node.nextSibling, 1, changes, state2.doc);
|
|
2927
|
-
}
|
|
2928
|
-
return false;
|
|
2929
2919
|
}
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2920
|
+
});
|
|
2921
|
+
}
|
|
2922
|
+
if (!changes.length) {
|
|
2923
|
+
return false;
|
|
2924
|
+
}
|
|
2925
|
+
dispatch(state2.update({
|
|
2926
|
+
changes,
|
|
2927
|
+
userEvent: "format.list.remove",
|
|
2928
|
+
scrollIntoView: true
|
|
2929
|
+
}));
|
|
2930
|
+
return true;
|
|
2931
|
+
};
|
|
2942
2932
|
};
|
|
2943
|
-
var toggleList = (type) =>
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2933
|
+
var toggleList = (type) => {
|
|
2934
|
+
return (target) => {
|
|
2935
|
+
const formatting = getFormatting(target.state);
|
|
2936
|
+
const active = formatting.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
2937
|
+
return (active ? removeList(type) : addList(type))(target);
|
|
2938
|
+
};
|
|
2947
2939
|
};
|
|
2948
2940
|
var renumberListItems = (item, counter, changes, doc) => {
|
|
2949
2941
|
for (; item; item = item.nextSibling) {
|
|
@@ -2963,79 +2955,81 @@ var renumberListItems = (item, counter, changes, doc) => {
|
|
|
2963
2955
|
}
|
|
2964
2956
|
}
|
|
2965
2957
|
};
|
|
2966
|
-
var setBlockquote = (enable) =>
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
const
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
if (node.
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
if (
|
|
2985
|
-
lines.
|
|
2958
|
+
var setBlockquote = (enable) => {
|
|
2959
|
+
return ({ state: state2, dispatch }) => {
|
|
2960
|
+
const lines = [];
|
|
2961
|
+
let lastBlock = -1;
|
|
2962
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2963
|
+
const sawBlock = false;
|
|
2964
|
+
syntaxTree(state2).iterate({
|
|
2965
|
+
from,
|
|
2966
|
+
to,
|
|
2967
|
+
enter: (node) => {
|
|
2968
|
+
if (Object.hasOwn(Textblocks, node.name) || node.name === "Table") {
|
|
2969
|
+
if (node.from === lastBlock) {
|
|
2970
|
+
return false;
|
|
2971
|
+
}
|
|
2972
|
+
lastBlock = node.from;
|
|
2973
|
+
let line2 = state2.doc.lineAt(node.from);
|
|
2974
|
+
if (line2.number > 1) {
|
|
2975
|
+
const prevLine = state2.doc.line(line2.number - 1);
|
|
2976
|
+
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2977
|
+
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2978
|
+
lines.push(prevLine);
|
|
2979
|
+
}
|
|
2986
2980
|
}
|
|
2987
2981
|
}
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2982
|
+
for (; ; ) {
|
|
2983
|
+
lines.push(line2);
|
|
2984
|
+
if (line2.to >= node.to) {
|
|
2985
|
+
break;
|
|
2986
|
+
}
|
|
2987
|
+
line2 = state2.doc.line(line2.number + 1);
|
|
2993
2988
|
}
|
|
2994
|
-
line2
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
lines.push(nextLine);
|
|
2989
|
+
if (!enable && line2.number < state2.doc.lines) {
|
|
2990
|
+
const nextLine = state2.doc.line(line2.number + 1);
|
|
2991
|
+
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2992
|
+
lines.push(nextLine);
|
|
2993
|
+
}
|
|
3000
2994
|
}
|
|
2995
|
+
return false;
|
|
3001
2996
|
}
|
|
3002
|
-
return false;
|
|
3003
2997
|
}
|
|
2998
|
+
});
|
|
2999
|
+
let line;
|
|
3000
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state2.doc.lineAt(from)).text)) {
|
|
3001
|
+
lines.push(line);
|
|
3004
3002
|
}
|
|
3005
|
-
});
|
|
3006
|
-
let line;
|
|
3007
|
-
if (!sawBlock && enable && from === to && !/\S/.test((line = state2.doc.lineAt(from)).text)) {
|
|
3008
|
-
lines.push(line);
|
|
3009
3003
|
}
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
if (enable) {
|
|
3014
|
-
changes.push({
|
|
3015
|
-
from: line.from,
|
|
3016
|
-
insert: /\S/.test(line.text) ? "> " : ">"
|
|
3017
|
-
});
|
|
3018
|
-
} else {
|
|
3019
|
-
const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
|
|
3020
|
-
if (quote) {
|
|
3004
|
+
const changes = [];
|
|
3005
|
+
for (const line of lines) {
|
|
3006
|
+
if (enable) {
|
|
3021
3007
|
changes.push({
|
|
3022
|
-
from: line.from
|
|
3023
|
-
|
|
3008
|
+
from: line.from,
|
|
3009
|
+
insert: /\S/.test(line.text) ? "> " : ">"
|
|
3024
3010
|
});
|
|
3011
|
+
} else {
|
|
3012
|
+
const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
|
|
3013
|
+
if (quote) {
|
|
3014
|
+
changes.push({
|
|
3015
|
+
from: line.from + quote[1].length,
|
|
3016
|
+
to: line.from + quote[0].length
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3025
3019
|
}
|
|
3026
3020
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3021
|
+
if (!changes.length) {
|
|
3022
|
+
return false;
|
|
3023
|
+
}
|
|
3024
|
+
const changeSet = state2.changes(changes);
|
|
3025
|
+
dispatch(state2.update({
|
|
3026
|
+
changes: changeSet,
|
|
3027
|
+
selection: state2.selection.map(changeSet, 1),
|
|
3028
|
+
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
3029
|
+
scrollIntoView: true
|
|
3030
|
+
}));
|
|
3031
|
+
return true;
|
|
3032
|
+
};
|
|
3039
3033
|
};
|
|
3040
3034
|
var addBlockquote = setBlockquote(true);
|
|
3041
3035
|
var removeBlockquote = setBlockquote(false);
|
|
@@ -3105,8 +3099,8 @@ var addCodeblock = (target) => {
|
|
|
3105
3099
|
return true;
|
|
3106
3100
|
};
|
|
3107
3101
|
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3108
|
-
const changes = [];
|
|
3109
3102
|
let lastBlock = -1;
|
|
3103
|
+
const changes = [];
|
|
3110
3104
|
for (const { from, to } of state2.selection.ranges) {
|
|
3111
3105
|
syntaxTree(state2).iterate({
|
|
3112
3106
|
from,
|
|
@@ -3761,68 +3755,88 @@ var buildDecorations = (view, options, focus) => {
|
|
|
3761
3755
|
from,
|
|
3762
3756
|
to,
|
|
3763
3757
|
enter: (node) => {
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3758
|
+
switch (node.name) {
|
|
3759
|
+
case "FencedCode": {
|
|
3760
|
+
const editing = editingRange(state2, node, focus);
|
|
3761
|
+
for (const block of view.viewportLineBlocks) {
|
|
3762
|
+
if (block.to < node.from) {
|
|
3763
|
+
continue;
|
|
3764
|
+
}
|
|
3765
|
+
if (block.from > node.to) {
|
|
3766
|
+
break;
|
|
3767
|
+
}
|
|
3768
|
+
const first = block.from <= node.from;
|
|
3769
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
3770
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
3771
|
+
if (!editing && (first || last)) {
|
|
3772
|
+
atomicDeco.add(block.from, block.to, hide);
|
|
3773
|
+
}
|
|
3778
3774
|
}
|
|
3775
|
+
return false;
|
|
3779
3776
|
}
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3777
|
+
case "Link": {
|
|
3778
|
+
const marks = node.node.getChildren("LinkMark");
|
|
3779
|
+
const urlNode = node.node.getChild("URL");
|
|
3780
|
+
const editing = editingRange(state2, node, focus);
|
|
3781
|
+
if (urlNode && marks.length >= 2) {
|
|
3782
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3783
|
+
if (!editing) {
|
|
3784
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
|
3785
|
+
}
|
|
3786
|
+
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
3787
|
+
tagName: "a",
|
|
3788
|
+
attributes: {
|
|
3789
|
+
class: "cm-link",
|
|
3790
|
+
href: url,
|
|
3791
|
+
rel: "noreferrer",
|
|
3792
|
+
target: "_blank"
|
|
3793
|
+
}
|
|
3794
|
+
}));
|
|
3795
|
+
if (!editing) {
|
|
3796
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
3797
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
3798
|
+
}) : hide);
|
|
3797
3799
|
}
|
|
3798
|
-
}));
|
|
3799
|
-
if (!editing) {
|
|
3800
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
3801
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
|
3802
|
-
}) : hide);
|
|
3803
3800
|
}
|
|
3801
|
+
break;
|
|
3804
3802
|
}
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3803
|
+
case "HeaderMark": {
|
|
3804
|
+
const parent = node.node.parent;
|
|
3805
|
+
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
3806
|
+
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
3807
|
+
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
3808
|
+
}
|
|
3809
|
+
break;
|
|
3810
3810
|
}
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3811
|
+
case "HorizontalRule": {
|
|
3812
|
+
if (!editingRange(state2, node, focus)) {
|
|
3813
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
3814
|
+
}
|
|
3815
|
+
break;
|
|
3814
3816
|
}
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3817
|
+
case "TaskMarker": {
|
|
3818
|
+
if (!editingRange(state2, node, focus)) {
|
|
3819
|
+
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3820
|
+
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
3821
|
+
class: "cm-task"
|
|
3822
|
+
}));
|
|
3823
|
+
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
3824
|
+
}
|
|
3825
|
+
break;
|
|
3826
|
+
}
|
|
3827
|
+
case "ListItem": {
|
|
3828
|
+
const start = state2.doc.lineAt(node.from);
|
|
3829
|
+
deco.add(start.from, start.from, Decoration5.line({
|
|
3830
|
+
class: "cm-list-item"
|
|
3820
3831
|
}));
|
|
3821
|
-
|
|
3832
|
+
break;
|
|
3822
3833
|
}
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3834
|
+
default: {
|
|
3835
|
+
if (MarksByParent.has(node.name)) {
|
|
3836
|
+
if (!editingRange(state2, node.node.parent, focus)) {
|
|
3837
|
+
atomicDeco.add(node.from, node.to, hide);
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3826
3840
|
}
|
|
3827
3841
|
}
|
|
3828
3842
|
}
|
|
@@ -3848,8 +3862,6 @@ var decorateMarkdown = (options = {}) => {
|
|
|
3848
3862
|
this.scheduleUpdate(update2.view);
|
|
3849
3863
|
}
|
|
3850
3864
|
}
|
|
3851
|
-
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
3852
|
-
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
3853
3865
|
scheduleUpdate(view) {
|
|
3854
3866
|
this.clearUpdate();
|
|
3855
3867
|
this.pendingUpdate = setTimeout(() => {
|
|
@@ -4094,15 +4106,17 @@ var update = (state2, options) => {
|
|
|
4094
4106
|
}
|
|
4095
4107
|
});
|
|
4096
4108
|
tables.forEach((table2) => {
|
|
4097
|
-
const
|
|
4098
|
-
if (
|
|
4109
|
+
const replace = state2.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4110
|
+
if (replace) {
|
|
4099
4111
|
builder.add(table2.from, table2.to, Decoration7.replace({
|
|
4112
|
+
block: true,
|
|
4100
4113
|
widget: new TableWidget(table2)
|
|
4101
4114
|
}));
|
|
4115
|
+
} else {
|
|
4116
|
+
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
4117
|
+
class: "cm-table"
|
|
4118
|
+
}));
|
|
4102
4119
|
}
|
|
4103
|
-
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
4104
|
-
class: "cm-table"
|
|
4105
|
-
}));
|
|
4106
4120
|
});
|
|
4107
4121
|
return builder.finish();
|
|
4108
4122
|
};
|
|
@@ -4367,10 +4381,23 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
4367
4381
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4368
4382
|
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4369
4383
|
var instanceCount = 0;
|
|
4370
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({
|
|
4371
|
-
|
|
4372
|
-
|
|
4384
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({
|
|
4385
|
+
id,
|
|
4386
|
+
// TODO(wittjosiah): Rename initialText?
|
|
4387
|
+
doc,
|
|
4388
|
+
selection,
|
|
4389
|
+
extensions,
|
|
4390
|
+
className,
|
|
4391
|
+
autoFocus,
|
|
4392
|
+
scrollTo: propsScrollTo,
|
|
4393
|
+
moveToEndOfLine,
|
|
4394
|
+
debug,
|
|
4395
|
+
dataTestId
|
|
4396
|
+
}, forwardedRef) => {
|
|
4373
4397
|
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
4398
|
+
const scrollTo = useDefaultValue(propsScrollTo, EditorView16.scrollIntoView(0, {
|
|
4399
|
+
yMargin: 0
|
|
4400
|
+
}));
|
|
4374
4401
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
4375
4402
|
tabBehavior: "limited"
|
|
4376
4403
|
});
|
|
@@ -4393,20 +4420,19 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4393
4420
|
instanceId
|
|
4394
4421
|
}, {
|
|
4395
4422
|
F: __dxlog_file10,
|
|
4396
|
-
L:
|
|
4423
|
+
L: 91,
|
|
4397
4424
|
S: void 0,
|
|
4398
4425
|
C: (f, a) => f(...a)
|
|
4399
4426
|
});
|
|
4400
4427
|
const state2 = EditorState2.create({
|
|
4401
4428
|
doc,
|
|
4402
|
-
selection,
|
|
4403
4429
|
extensions: [
|
|
4404
4430
|
id && documentId2.of(id),
|
|
4405
4431
|
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4406
4432
|
EditorView16.exceptionSink.of((err) => {
|
|
4407
4433
|
log7.catch(err, void 0, {
|
|
4408
4434
|
F: __dxlog_file10,
|
|
4409
|
-
L:
|
|
4435
|
+
L: 104,
|
|
4410
4436
|
S: void 0,
|
|
4411
4437
|
C: (f, a) => f(...a)
|
|
4412
4438
|
});
|
|
@@ -4453,15 +4479,17 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, c
|
|
|
4453
4479
|
instanceId
|
|
4454
4480
|
}, {
|
|
4455
4481
|
F: __dxlog_file10,
|
|
4456
|
-
L:
|
|
4482
|
+
L: 153,
|
|
4457
4483
|
S: void 0,
|
|
4458
4484
|
C: (f, a) => f(...a)
|
|
4459
4485
|
});
|
|
4460
4486
|
view2?.destroy();
|
|
4461
4487
|
};
|
|
4462
4488
|
}, [
|
|
4463
|
-
|
|
4489
|
+
id,
|
|
4464
4490
|
selection,
|
|
4491
|
+
scrollTo,
|
|
4492
|
+
editorMode,
|
|
4465
4493
|
extensions
|
|
4466
4494
|
]);
|
|
4467
4495
|
const handleKeyUp = useCallback((event) => {
|
|
@@ -4800,28 +4828,15 @@ var useActionHandler = (view) => {
|
|
|
4800
4828
|
return (action) => view && processAction(view, action);
|
|
4801
4829
|
};
|
|
4802
4830
|
|
|
4803
|
-
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
4804
|
-
import { useMemo as useMemo2 } from "react";
|
|
4805
|
-
import { createDocAccessor, getTextContent } from "@dxos/echo-schema";
|
|
4806
|
-
var useDocAccessor = (text) => {
|
|
4807
|
-
return useMemo2(() => ({
|
|
4808
|
-
id: text.id,
|
|
4809
|
-
doc: getTextContent(text),
|
|
4810
|
-
accessor: createDocAccessor(text)
|
|
4811
|
-
}), [
|
|
4812
|
-
text
|
|
4813
|
-
]);
|
|
4814
|
-
};
|
|
4815
|
-
|
|
4816
4831
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4817
4832
|
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4818
4833
|
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4819
|
-
import { useEffect as useEffect4, useMemo as
|
|
4834
|
+
import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState4 } from "react";
|
|
4820
4835
|
import { log as log8 } from "@dxos/log";
|
|
4821
4836
|
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4822
4837
|
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4823
4838
|
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4824
|
-
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } =
|
|
4839
|
+
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo2(cb, deps ?? []);
|
|
4825
4840
|
const onUpdate = useRef3();
|
|
4826
4841
|
const [view, setView] = useState4();
|
|
4827
4842
|
const parentRef = useRef3(null);
|
|
@@ -4838,7 +4853,6 @@ var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
|
4838
4853
|
});
|
|
4839
4854
|
const state2 = EditorState3.create({
|
|
4840
4855
|
doc,
|
|
4841
|
-
selection,
|
|
4842
4856
|
extensions: [
|
|
4843
4857
|
id && documentId2.of(id),
|
|
4844
4858
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
@@ -4997,7 +5011,6 @@ export {
|
|
|
4997
5011
|
typewriter,
|
|
4998
5012
|
useActionHandler,
|
|
4999
5013
|
useComments,
|
|
5000
|
-
useDocAccessor,
|
|
5001
5014
|
useFormattingState,
|
|
5002
5015
|
useTextEditor,
|
|
5003
5016
|
useToolbarContext
|