@dxos/react-ui-editor 0.3.11-main.514e6e4 → 0.3.11-main.525300b
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 +1886 -329
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +1 -2
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +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/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/{comments.stories.d.ts → hooks.stories.d.ts} +9 -12
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +29 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +25 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/index.d.ts +2 -0
- package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +5 -5
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +2 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +1 -1
- package/dist/types/src/extensions/basic.d.ts +1 -1
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +11 -3
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +2 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +57 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useEditorView.d.ts +17 -0
- package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +36 -14
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +12 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +39 -26
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +11 -17
- package/src/components/TextEditor/TextEditor.tsx +27 -16
- package/src/components/TextEditor/automerge.stories.tsx +1 -2
- package/src/components/TextEditor/hooks.stories.tsx +111 -0
- package/src/components/Toolbar/Toolbar.stories.tsx +102 -0
- package/src/components/Toolbar/Toolbar.tsx +245 -0
- package/src/components/Toolbar/index.ts +5 -0
- package/src/components/index.ts +1 -0
- package/src/extensions/automerge/automerge.spec.tsx +76 -0
- package/src/extensions/automerge/automerge.test.ts +13 -0
- package/src/extensions/automerge/automerge.ts +26 -11
- package/src/extensions/automerge/cursor.ts +3 -3
- package/src/extensions/automerge/defs.ts +9 -9
- package/src/extensions/automerge/semaphore.ts +17 -19
- package/src/extensions/automerge/update-automerge.ts +12 -6
- package/src/extensions/automerge/update-codemirror.ts +5 -5
- package/src/extensions/awareness.ts +7 -4
- package/src/extensions/basic.ts +15 -13
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +126 -68
- package/src/extensions/markdown/bundle.ts +10 -5
- package/src/extensions/markdown/code.ts +36 -13
- package/src/extensions/markdown/formatting.test.ts +481 -0
- package/src/extensions/markdown/formatting.ts +1198 -0
- package/src/extensions/markdown/heading.ts +1 -1
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/markdown/link.ts +12 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useActionHandler.ts +93 -0
- package/src/hooks/useEditorView.ts +29 -0
- package/src/hooks/useTextEditor.ts +143 -19
- package/src/hooks/useTextModel.ts +28 -9
- package/src/index.ts +1 -1
- package/src/themes/default.ts +11 -6
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/src/components/TextEditor/comments.stories.tsx +0 -357
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
// packages/ui/react-ui-editor/src/index.ts
|
|
2
2
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
3
3
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
4
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
4
5
|
|
|
5
6
|
// packages/ui/react-ui-editor/src/components/TextEditor/index.ts
|
|
6
7
|
import { tags as tags2 } from "@lezer/highlight";
|
|
7
8
|
|
|
8
9
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
10
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
11
|
-
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
11
|
+
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
17
|
+
import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
18
19
|
|
|
19
20
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
21
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -53,14 +54,14 @@ var autocomplete = ({ onSearch }) => {
|
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
57
|
+
import { invertedEffects } from "@codemirror/commands";
|
|
56
58
|
import { StateField } from "@codemirror/state";
|
|
57
59
|
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
58
|
-
import { next as
|
|
59
|
-
import { invariant } from "@dxos/invariant";
|
|
60
|
+
import { next as A4 } from "@dxos/automerge/automerge";
|
|
60
61
|
|
|
61
62
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
62
63
|
import get from "lodash.get";
|
|
63
|
-
import { next as
|
|
64
|
+
import { next as A } from "@dxos/automerge/automerge";
|
|
64
65
|
var cursorConverter = (handle, path) => ({
|
|
65
66
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
66
67
|
toCursor: (pos) => {
|
|
@@ -72,7 +73,7 @@ var cursorConverter = (handle, path) => ({
|
|
|
72
73
|
if (typeof value === "string" && value.length <= pos) {
|
|
73
74
|
return "end";
|
|
74
75
|
}
|
|
75
|
-
return
|
|
76
|
+
return A.getCursor(doc, path.slice(), pos);
|
|
76
77
|
},
|
|
77
78
|
fromCursor: (cursor) => {
|
|
78
79
|
if (cursor === "") {
|
|
@@ -90,26 +91,28 @@ var cursorConverter = (handle, path) => ({
|
|
|
90
91
|
return 0;
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
return
|
|
94
|
+
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
94
95
|
}
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
98
99
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
99
|
-
var effectType = StateEffect.define({});
|
|
100
|
-
var reconcileAnnotationType = Annotation.define();
|
|
101
100
|
var getPath = (state, field) => state.field(field).path;
|
|
102
101
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
103
|
-
var
|
|
102
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
103
|
+
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
104
104
|
newHeads
|
|
105
105
|
});
|
|
106
|
-
var
|
|
106
|
+
var reconcileAnnotation = Annotation.define();
|
|
107
|
+
var isReconcile = (tr) => {
|
|
108
|
+
return !!tr.annotation(reconcileAnnotation);
|
|
109
|
+
};
|
|
107
110
|
|
|
108
111
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
109
|
-
import { next as
|
|
112
|
+
import { next as A3 } from "@dxos/automerge/automerge";
|
|
110
113
|
|
|
111
114
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
112
|
-
import { next as
|
|
115
|
+
import { next as A2 } from "@dxos/automerge/automerge";
|
|
113
116
|
var updateAutomerge = (field, handle, transactions, state) => {
|
|
114
117
|
const { lastHeads, path } = state.field(field);
|
|
115
118
|
let hasChanges = false;
|
|
@@ -122,11 +125,19 @@ var updateAutomerge = (field, handle, transactions, state) => {
|
|
|
122
125
|
return void 0;
|
|
123
126
|
}
|
|
124
127
|
const newHeads = handle.changeAt(lastHeads, (doc) => {
|
|
128
|
+
const invertedTransactions = [];
|
|
125
129
|
for (const tr of transactions) {
|
|
126
|
-
tr.changes.iterChanges((fromA, toA, _fromB, _toB,
|
|
127
|
-
|
|
130
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
|
|
131
|
+
invertedTransactions.push({
|
|
132
|
+
from: fromA,
|
|
133
|
+
del: toA - fromA,
|
|
134
|
+
insert
|
|
135
|
+
});
|
|
128
136
|
});
|
|
129
137
|
}
|
|
138
|
+
invertedTransactions.reverse().forEach(({ from, del, insert }) => {
|
|
139
|
+
A2.splice(doc, path.slice(), from, del, insert.toString());
|
|
140
|
+
});
|
|
130
141
|
});
|
|
131
142
|
return newHeads ?? void 0;
|
|
132
143
|
};
|
|
@@ -141,13 +152,13 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
141
152
|
selection = selection.map(changeSet, 1);
|
|
142
153
|
view.dispatch({
|
|
143
154
|
changes: changeSet,
|
|
144
|
-
annotations:
|
|
155
|
+
annotations: reconcileAnnotation.of(false)
|
|
145
156
|
});
|
|
146
157
|
}
|
|
147
158
|
}
|
|
148
159
|
view.dispatch({
|
|
149
160
|
selection,
|
|
150
|
-
annotations:
|
|
161
|
+
annotations: reconcileAnnotation.of(false)
|
|
151
162
|
});
|
|
152
163
|
};
|
|
153
164
|
var handlePatch = (patch, target, state) => {
|
|
@@ -168,7 +179,7 @@ var handleInsert = (target, patch) => {
|
|
|
168
179
|
if (index == null) {
|
|
169
180
|
return [];
|
|
170
181
|
}
|
|
171
|
-
const text = patch.values.map((
|
|
182
|
+
const text = patch.values.map((value) => value ? value.toString() : "").join("");
|
|
172
183
|
return [
|
|
173
184
|
{
|
|
174
185
|
from: index,
|
|
@@ -246,36 +257,37 @@ var PatchSemaphore = class {
|
|
|
246
257
|
this._state = _state;
|
|
247
258
|
this._inReconcile = false;
|
|
248
259
|
}
|
|
249
|
-
// NOTE: Cannot destruct view.state.
|
|
250
260
|
reconcile(view) {
|
|
251
|
-
if (this._inReconcile) {
|
|
252
|
-
|
|
261
|
+
if (!this._inReconcile) {
|
|
262
|
+
this._inReconcile = true;
|
|
263
|
+
this.doReconcile(view);
|
|
264
|
+
this._inReconcile = false;
|
|
253
265
|
}
|
|
254
|
-
|
|
266
|
+
}
|
|
267
|
+
doReconcile(view) {
|
|
255
268
|
const path = getPath(view.state, this._state);
|
|
256
269
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
257
270
|
let selection = view.state.selection;
|
|
258
|
-
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !
|
|
271
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
259
272
|
const toInvert = transactions.slice().reverse();
|
|
260
|
-
for (const
|
|
261
|
-
const inverted =
|
|
273
|
+
for (const tr of toInvert) {
|
|
274
|
+
const inverted = tr.changes.invert(tr.startState.doc);
|
|
262
275
|
selection = selection.map(inverted);
|
|
263
276
|
view.dispatch({
|
|
264
277
|
changes: inverted,
|
|
265
|
-
annotations:
|
|
278
|
+
annotations: reconcileAnnotation.of(true)
|
|
266
279
|
});
|
|
267
280
|
}
|
|
268
281
|
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
269
282
|
if (newHeads === null || newHeads === void 0) {
|
|
270
|
-
newHeads =
|
|
283
|
+
newHeads = A3.getHeads(this._handle.docSync());
|
|
271
284
|
}
|
|
272
|
-
const diff =
|
|
285
|
+
const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
273
286
|
updateCodeMirror(view, selection, path, diff);
|
|
274
287
|
view.dispatch({
|
|
275
288
|
effects: updateHeads(newHeads),
|
|
276
|
-
annotations:
|
|
289
|
+
annotations: reconcileAnnotation.of(false)
|
|
277
290
|
});
|
|
278
|
-
this._inReconcile = false;
|
|
279
291
|
}
|
|
280
292
|
};
|
|
281
293
|
|
|
@@ -317,12 +329,11 @@ var Cursor = class _Cursor {
|
|
|
317
329
|
};
|
|
318
330
|
|
|
319
331
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
320
|
-
var
|
|
321
|
-
|
|
322
|
-
const state = StateField.define({
|
|
332
|
+
var automerge = ({ handle, path }) => {
|
|
333
|
+
const syncState = StateField.define({
|
|
323
334
|
create: () => ({
|
|
324
335
|
path: path.slice(),
|
|
325
|
-
lastHeads:
|
|
336
|
+
lastHeads: A4.getHeads(handle.docSync()),
|
|
326
337
|
unreconciledTransactions: []
|
|
327
338
|
}),
|
|
328
339
|
update: (value, tr) => {
|
|
@@ -333,7 +344,7 @@ var automerge3 = ({ handle, path }) => {
|
|
|
333
344
|
};
|
|
334
345
|
let clearUnreconciled = false;
|
|
335
346
|
for (const effect of tr.effects) {
|
|
336
|
-
if (effect.is(
|
|
347
|
+
if (effect.is(updateHeadsEffect)) {
|
|
337
348
|
result.lastHeads = effect.value.newHeads;
|
|
338
349
|
clearUnreconciled = true;
|
|
339
350
|
}
|
|
@@ -341,29 +352,21 @@ var automerge3 = ({ handle, path }) => {
|
|
|
341
352
|
if (clearUnreconciled) {
|
|
342
353
|
result.unreconciledTransactions = [];
|
|
343
354
|
} else {
|
|
344
|
-
if (!
|
|
355
|
+
if (!isReconcile(tr)) {
|
|
345
356
|
result.unreconciledTransactions.push(tr);
|
|
346
357
|
}
|
|
347
358
|
}
|
|
348
359
|
return result;
|
|
349
360
|
}
|
|
350
361
|
});
|
|
351
|
-
const semaphore = new PatchSemaphore(handle,
|
|
362
|
+
const semaphore = new PatchSemaphore(handle, syncState);
|
|
352
363
|
return [
|
|
353
364
|
Cursor.converter.of(cursorConverter(handle, path)),
|
|
365
|
+
syncState,
|
|
354
366
|
// Reconcile external updates.
|
|
355
367
|
ViewPlugin.fromClass(class {
|
|
356
368
|
constructor(_view) {
|
|
357
369
|
this._view = _view;
|
|
358
|
-
invariant(this._view, void 0, {
|
|
359
|
-
F: __dxlog_file,
|
|
360
|
-
L: 66,
|
|
361
|
-
S: this,
|
|
362
|
-
A: [
|
|
363
|
-
"this._view",
|
|
364
|
-
""
|
|
365
|
-
]
|
|
366
|
-
});
|
|
367
370
|
handle.addListener("change", this._handleChange.bind(this));
|
|
368
371
|
}
|
|
369
372
|
destroy() {
|
|
@@ -379,7 +382,17 @@ var automerge3 = ({ handle, path }) => {
|
|
|
379
382
|
semaphore.reconcile(view);
|
|
380
383
|
}
|
|
381
384
|
}),
|
|
382
|
-
|
|
385
|
+
// TODO(burdon): Record undo transactions.
|
|
386
|
+
// See https://github.com/yjs/y-codemirror.next/tree/main
|
|
387
|
+
// https://codemirror.net/examples/inverted-effect
|
|
388
|
+
invertedEffects.of((tr) => {
|
|
389
|
+
const effects = [];
|
|
390
|
+
if (!tr.changes.empty) {
|
|
391
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
return effects;
|
|
395
|
+
})
|
|
383
396
|
];
|
|
384
397
|
};
|
|
385
398
|
|
|
@@ -398,13 +411,13 @@ var dummyProvider = {
|
|
|
398
411
|
update: () => {
|
|
399
412
|
}
|
|
400
413
|
};
|
|
401
|
-
var
|
|
414
|
+
var awarenessProvider = Facet2.define({
|
|
402
415
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
403
416
|
});
|
|
404
417
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
405
418
|
var awareness = (provider = dummyProvider) => {
|
|
406
419
|
return [
|
|
407
|
-
|
|
420
|
+
awarenessProvider.of(provider),
|
|
408
421
|
ViewPlugin2.fromClass(RemoteSelectionsDecorator, {
|
|
409
422
|
decorations: (value) => value.decorations
|
|
410
423
|
}),
|
|
@@ -418,7 +431,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
418
431
|
this._lastAnchor = void 0;
|
|
419
432
|
this._lastHead = void 0;
|
|
420
433
|
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
421
|
-
this._provider = view.state.facet(
|
|
434
|
+
this._provider = view.state.facet(awarenessProvider);
|
|
422
435
|
this._provider.open();
|
|
423
436
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
424
437
|
view.dispatch({
|
|
@@ -624,24 +637,25 @@ import { history } from "@codemirror/commands";
|
|
|
624
637
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
625
638
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
626
639
|
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
627
|
-
|
|
628
|
-
|
|
640
|
+
import { isNotFalsy } from "@dxos/util";
|
|
641
|
+
var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => [
|
|
642
|
+
lineWrapping && EditorView3.lineWrapping,
|
|
629
643
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
630
644
|
bracketMatching(),
|
|
631
645
|
closeBrackets(),
|
|
632
646
|
drawSelection(),
|
|
633
647
|
highlightActiveLine(),
|
|
634
648
|
history(),
|
|
635
|
-
_placeholder
|
|
649
|
+
_placeholder && placeholder(_placeholder),
|
|
636
650
|
// https://github.com/codemirror/theme-one-dark
|
|
637
651
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
638
|
-
];
|
|
652
|
+
].filter(isNotFalsy);
|
|
639
653
|
|
|
640
654
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
641
655
|
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
642
656
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
643
|
-
import { invariant
|
|
644
|
-
var
|
|
657
|
+
import { invariant } from "@dxos/invariant";
|
|
658
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
645
659
|
var defaultOptions = {
|
|
646
660
|
effect: 2,
|
|
647
661
|
maxParticles: 200,
|
|
@@ -767,9 +781,9 @@ var Blaster = class {
|
|
|
767
781
|
return this._node;
|
|
768
782
|
}
|
|
769
783
|
initialize() {
|
|
770
|
-
|
|
771
|
-
F:
|
|
772
|
-
L:
|
|
784
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
785
|
+
F: __dxlog_file,
|
|
786
|
+
L: 141,
|
|
773
787
|
S: this,
|
|
774
788
|
A: [
|
|
775
789
|
"!this._canvas && !this._ctx",
|
|
@@ -804,9 +818,9 @@ var Blaster = class {
|
|
|
804
818
|
}
|
|
805
819
|
}
|
|
806
820
|
start() {
|
|
807
|
-
|
|
808
|
-
F:
|
|
809
|
-
L:
|
|
821
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
822
|
+
F: __dxlog_file,
|
|
823
|
+
L: 180,
|
|
810
824
|
S: this,
|
|
811
825
|
A: [
|
|
812
826
|
"this._canvas && this._ctx",
|
|
@@ -948,12 +962,12 @@ var random = (min, max) => {
|
|
|
948
962
|
};
|
|
949
963
|
|
|
950
964
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
-
import {
|
|
965
|
+
import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
|
|
966
|
+
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
967
|
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
968
|
import sortBy from "lodash.sortby";
|
|
954
969
|
import { useEffect } from "react";
|
|
955
970
|
import { debounce } from "@dxos/async";
|
|
956
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
971
|
import { nonNullable } from "@dxos/util";
|
|
958
972
|
|
|
959
973
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1025,13 +1039,13 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1025
1039
|
|
|
1026
1040
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1027
1041
|
import { log } from "@dxos/log";
|
|
1028
|
-
var
|
|
1042
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1029
1043
|
var callbackWrapper = (fn) => (...args) => {
|
|
1030
1044
|
try {
|
|
1031
1045
|
return fn(...args);
|
|
1032
1046
|
} catch (err) {
|
|
1033
1047
|
log.catch(err, void 0, {
|
|
1034
|
-
F:
|
|
1048
|
+
F: __dxlog_file2,
|
|
1035
1049
|
L: 18,
|
|
1036
1050
|
S: void 0,
|
|
1037
1051
|
C: (f, a) => f(...a)
|
|
@@ -1059,24 +1073,35 @@ var logChanges = (trs) => {
|
|
|
1059
1073
|
};
|
|
1060
1074
|
|
|
1061
1075
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1062
|
-
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1063
1076
|
var styles2 = EditorView5.baseTheme({
|
|
1064
|
-
"& .cm-comment": {
|
|
1077
|
+
"&light .cm-comment, &light .cm-comment-current": {
|
|
1078
|
+
mixBlendMode: "darken"
|
|
1079
|
+
},
|
|
1080
|
+
"&dark .cm-comment, &dark .cm-comment-current": {
|
|
1081
|
+
mixBlendMode: "plus-lighter"
|
|
1082
|
+
},
|
|
1083
|
+
"&light .cm-comment": {
|
|
1065
1084
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1066
1085
|
},
|
|
1067
|
-
"& .cm-comment-current": {
|
|
1086
|
+
"&light .cm-comment-current": {
|
|
1068
1087
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1088
|
+
},
|
|
1089
|
+
"&dark .cm-comment": {
|
|
1090
|
+
color: getToken("extend.colors.yellow.50"),
|
|
1091
|
+
backgroundColor: getToken("extend.colors.yellow.900")
|
|
1092
|
+
},
|
|
1093
|
+
"&dark .cm-comment-current": {
|
|
1094
|
+
color: getToken("extend.colors.yellow.100"),
|
|
1095
|
+
backgroundColor: getToken("extend.colors.yellow.950")
|
|
1069
1096
|
}
|
|
1070
1097
|
});
|
|
1071
|
-
var
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
};
|
|
1079
|
-
var setFocus = (view, id, center = true) => {
|
|
1098
|
+
var commentMark = Decoration2.mark({
|
|
1099
|
+
class: "cm-comment"
|
|
1100
|
+
});
|
|
1101
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1102
|
+
class: "cm-comment-current"
|
|
1103
|
+
});
|
|
1104
|
+
var focusComment = (view, id, center = true) => {
|
|
1080
1105
|
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1081
1106
|
if (!comment?.comment.cursor) {
|
|
1082
1107
|
return;
|
|
@@ -1138,7 +1163,7 @@ var commentsState = StateField2.define({
|
|
|
1138
1163
|
return value;
|
|
1139
1164
|
}
|
|
1140
1165
|
});
|
|
1141
|
-
var
|
|
1166
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1142
1167
|
commentsState
|
|
1143
1168
|
], (state) => {
|
|
1144
1169
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
@@ -1149,9 +1174,9 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1149
1174
|
return void 0;
|
|
1150
1175
|
}
|
|
1151
1176
|
if (comment.comment.id === current) {
|
|
1152
|
-
return
|
|
1177
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1153
1178
|
} else {
|
|
1154
|
-
return
|
|
1179
|
+
return commentMark.range(range.from, range.to);
|
|
1155
1180
|
}
|
|
1156
1181
|
}).filter(nonNullable);
|
|
1157
1182
|
return Decoration2.set(decorations);
|
|
@@ -1180,84 +1205,128 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1180
1205
|
cut: handleTrack,
|
|
1181
1206
|
copy: handleTrack
|
|
1182
1207
|
}),
|
|
1183
|
-
//
|
|
1184
|
-
|
|
1208
|
+
// Track deleted comments.
|
|
1209
|
+
invertedEffects2.of((tr) => {
|
|
1210
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1211
|
+
const effects = [];
|
|
1212
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1213
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1214
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1215
|
+
effects.push(restoreCommentEffect.of({
|
|
1216
|
+
id,
|
|
1217
|
+
from,
|
|
1218
|
+
to
|
|
1219
|
+
}));
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
return effects;
|
|
1224
|
+
}),
|
|
1225
|
+
// Handle paste or the undo of comment deletion.
|
|
1226
|
+
EditorView5.updateListener.of((update2) => {
|
|
1227
|
+
const restore = [];
|
|
1228
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1229
|
+
const tr = update2.transactions[i];
|
|
1230
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1231
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1232
|
+
}
|
|
1233
|
+
for (const effect of tr.effects) {
|
|
1234
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1235
|
+
restore.push(effect.value);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1185
1239
|
if (tracked) {
|
|
1186
|
-
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1240
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1187
1241
|
if (paste) {
|
|
1188
1242
|
let found = -1;
|
|
1189
1243
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1190
1244
|
if (text.eq(tracked.text)) {
|
|
1191
|
-
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1192
|
-
fromB = transactions[i].changes.mapPos(fromB);
|
|
1245
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1246
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1193
1247
|
}
|
|
1194
1248
|
found = fromB;
|
|
1195
1249
|
}
|
|
1196
1250
|
});
|
|
1197
1251
|
if (found > -1) {
|
|
1198
1252
|
for (const moved of tracked.comments) {
|
|
1199
|
-
|
|
1253
|
+
restore.push({
|
|
1254
|
+
id: moved.id,
|
|
1200
1255
|
from: found + moved.from,
|
|
1201
1256
|
to: found + moved.to
|
|
1202
|
-
};
|
|
1203
|
-
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1204
|
-
onUpdate(moved.id, cursor);
|
|
1257
|
+
});
|
|
1205
1258
|
}
|
|
1206
1259
|
}
|
|
1207
1260
|
tracked = null;
|
|
1208
1261
|
}
|
|
1209
1262
|
}
|
|
1263
|
+
for (const comment of restore) {
|
|
1264
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1265
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1266
|
+
if (!exists) {
|
|
1267
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1268
|
+
onUpdate(comment.id, cursor);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1210
1271
|
})
|
|
1211
1272
|
];
|
|
1212
1273
|
};
|
|
1213
|
-
var
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1274
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1275
|
+
id: comment.id,
|
|
1276
|
+
from: changes.mapPos(comment.from, 1),
|
|
1277
|
+
to: changes.mapPos(comment.to, 1)
|
|
1278
|
+
});
|
|
1279
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1280
|
+
map: mapTrackedComment
|
|
1281
|
+
});
|
|
1282
|
+
var optionsFacet = Facet3.define({
|
|
1283
|
+
combine: (providers) => providers[0]
|
|
1284
|
+
});
|
|
1285
|
+
var createComment = (view) => {
|
|
1286
|
+
const options = view.state.facet(optionsFacet);
|
|
1287
|
+
const { from, to } = view.state.selection.main;
|
|
1288
|
+
if (from === to) {
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
if (to === view.state.doc.length) {
|
|
1292
|
+
view.dispatch({
|
|
1293
|
+
changes: {
|
|
1294
|
+
from: to,
|
|
1295
|
+
insert: "\n"
|
|
1296
|
+
}
|
|
1225
1297
|
});
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1298
|
+
}
|
|
1299
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1300
|
+
from,
|
|
1301
|
+
to
|
|
1302
|
+
});
|
|
1303
|
+
if (cursor) {
|
|
1304
|
+
const id = options.onCreate?.({
|
|
1305
|
+
cursor,
|
|
1306
|
+
from,
|
|
1307
|
+
location: view.coordsAtPos(from)
|
|
1308
|
+
});
|
|
1309
|
+
if (id) {
|
|
1231
1310
|
view.dispatch({
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1311
|
+
effects: setSelection.of({
|
|
1312
|
+
current: id
|
|
1313
|
+
}),
|
|
1314
|
+
selection: {
|
|
1315
|
+
anchor: to
|
|
1235
1316
|
}
|
|
1236
1317
|
});
|
|
1318
|
+
return true;
|
|
1237
1319
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
if (id) {
|
|
1245
|
-
view.dispatch({
|
|
1246
|
-
effects: setSelection.of({
|
|
1247
|
-
current: id
|
|
1248
|
-
}),
|
|
1249
|
-
selection: {
|
|
1250
|
-
anchor: from
|
|
1251
|
-
}
|
|
1252
|
-
});
|
|
1253
|
-
return true;
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
return false;
|
|
1257
|
-
};
|
|
1320
|
+
}
|
|
1321
|
+
return false;
|
|
1322
|
+
};
|
|
1323
|
+
var comments = (options = {}) => {
|
|
1324
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1325
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1258
1326
|
return [
|
|
1327
|
+
optionsFacet.of(options),
|
|
1259
1328
|
commentsState,
|
|
1260
|
-
|
|
1329
|
+
commentsDecorations,
|
|
1261
1330
|
styles2,
|
|
1262
1331
|
//
|
|
1263
1332
|
// Keymap.
|
|
@@ -1265,7 +1334,7 @@ var comments = (options = {}) => {
|
|
|
1265
1334
|
options.onCreate ? keymap3.of([
|
|
1266
1335
|
{
|
|
1267
1336
|
key: shortcut,
|
|
1268
|
-
run: callbackWrapper(
|
|
1337
|
+
run: callbackWrapper(createComment)
|
|
1269
1338
|
}
|
|
1270
1339
|
]) : [],
|
|
1271
1340
|
//
|
|
@@ -1403,6 +1472,7 @@ import { searchKeymap } from "@codemirror/search";
|
|
|
1403
1472
|
import { EditorState } from "@codemirror/state";
|
|
1404
1473
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1405
1474
|
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1475
|
+
import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1406
1476
|
|
|
1407
1477
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1408
1478
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1593,11 +1663,11 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1593
1663
|
};
|
|
1594
1664
|
|
|
1595
1665
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1596
|
-
var
|
|
1666
|
+
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
1597
1667
|
return [
|
|
1668
|
+
lineWrapping && EditorView7.lineWrapping,
|
|
1598
1669
|
EditorState.allowMultipleSelections.of(true),
|
|
1599
1670
|
EditorState.tabSize.of(2),
|
|
1600
|
-
EditorView7.lineWrapping,
|
|
1601
1671
|
// https://github.com/codemirror/basic-setup
|
|
1602
1672
|
bracketMatching2(),
|
|
1603
1673
|
closeBrackets2(),
|
|
@@ -1607,7 +1677,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
1607
1677
|
highlightActiveLine2(),
|
|
1608
1678
|
history2(),
|
|
1609
1679
|
indentOnInput(),
|
|
1610
|
-
_placeholder
|
|
1680
|
+
_placeholder && placeholder2(_placeholder),
|
|
1611
1681
|
// Main extension.
|
|
1612
1682
|
// https://github.com/codemirror/lang-markdown
|
|
1613
1683
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1642,7 +1712,7 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
|
1642
1712
|
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1643
1713
|
...standardKeymap
|
|
1644
1714
|
])
|
|
1645
|
-
];
|
|
1715
|
+
].filter(isNotFalsy2);
|
|
1646
1716
|
};
|
|
1647
1717
|
|
|
1648
1718
|
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
@@ -1652,26 +1722,43 @@ import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Dec
|
|
|
1652
1722
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1653
1723
|
var styles3 = EditorView8.baseTheme({
|
|
1654
1724
|
"& .cm-code": {
|
|
1655
|
-
paddingInline: "1rem !important",
|
|
1656
1725
|
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1657
1726
|
},
|
|
1658
1727
|
"& .cm-codeblock": {
|
|
1659
|
-
|
|
1660
|
-
|
|
1728
|
+
width: "100%",
|
|
1729
|
+
paddingInline: "1rem !important",
|
|
1730
|
+
position: "relative",
|
|
1731
|
+
"&::after": {
|
|
1732
|
+
content: '""',
|
|
1733
|
+
position: "absolute",
|
|
1734
|
+
inset: 0
|
|
1735
|
+
}
|
|
1661
1736
|
},
|
|
1662
|
-
"&light .cm-codeblock
|
|
1663
|
-
|
|
1737
|
+
"&light .cm-codeblock": {
|
|
1738
|
+
"&::after": {
|
|
1739
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1740
|
+
mixBlendMode: "darken"
|
|
1741
|
+
}
|
|
1664
1742
|
},
|
|
1665
|
-
"&dark .cm-codeblock
|
|
1666
|
-
|
|
1743
|
+
"&dark .cm-codeblock": {
|
|
1744
|
+
"&::after": {
|
|
1745
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1746
|
+
mixBlendMode: "lighten"
|
|
1747
|
+
}
|
|
1667
1748
|
},
|
|
1668
1749
|
"& .cm-codeblock-first": {
|
|
1669
|
-
|
|
1670
|
-
|
|
1750
|
+
display: "inline-block",
|
|
1751
|
+
"&::after": {
|
|
1752
|
+
borderTopLeftRadius: ".5rem",
|
|
1753
|
+
borderTopRightRadius: ".5rem"
|
|
1754
|
+
}
|
|
1671
1755
|
},
|
|
1672
1756
|
"& .cm-codeblock-last": {
|
|
1673
|
-
|
|
1674
|
-
|
|
1757
|
+
display: "inline-block",
|
|
1758
|
+
"&::after": {
|
|
1759
|
+
borderBottomLeftRadius: ".5rem",
|
|
1760
|
+
borderBottomRightRadius: ".5rem"
|
|
1761
|
+
}
|
|
1675
1762
|
}
|
|
1676
1763
|
});
|
|
1677
1764
|
var getLineRange = (lines, from, to) => {
|
|
@@ -1715,7 +1802,7 @@ var buildDecorations = (view) => {
|
|
|
1715
1802
|
}));
|
|
1716
1803
|
} else {
|
|
1717
1804
|
builder.add(block.from, block.from, Decoration3.line({
|
|
1718
|
-
class: mx2("cm-code cm-codeblock")
|
|
1805
|
+
class: mx2("cm-code cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1719
1806
|
}));
|
|
1720
1807
|
}
|
|
1721
1808
|
}
|
|
@@ -1743,101 +1830,1171 @@ var code2 = () => {
|
|
|
1743
1830
|
];
|
|
1744
1831
|
};
|
|
1745
1832
|
|
|
1746
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
1833
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1834
|
+
import { snippet } from "@codemirror/autocomplete";
|
|
1747
1835
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1748
|
-
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1749
|
-
import { Decoration as Decoration4, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1836
|
+
import { RangeSetBuilder as RangeSetBuilder2, EditorSelection } from "@codemirror/state";
|
|
1837
|
+
import { Decoration as Decoration4, EditorView as EditorView9, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1838
|
+
import { useState, useMemo } from "react";
|
|
1839
|
+
var compareFormatting = (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;
|
|
1840
|
+
var Inline;
|
|
1841
|
+
(function(Inline2) {
|
|
1842
|
+
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
1843
|
+
Inline2[Inline2["Emphasis"] = 1] = "Emphasis";
|
|
1844
|
+
Inline2[Inline2["Strikethrough"] = 2] = "Strikethrough";
|
|
1845
|
+
Inline2[Inline2["Code"] = 3] = "Code";
|
|
1846
|
+
})(Inline || (Inline = {}));
|
|
1847
|
+
var List;
|
|
1848
|
+
(function(List2) {
|
|
1849
|
+
List2[List2["Ordered"] = 0] = "Ordered";
|
|
1850
|
+
List2[List2["Bullet"] = 1] = "Bullet";
|
|
1851
|
+
List2[List2["Task"] = 2] = "Task";
|
|
1852
|
+
})(List || (List = {}));
|
|
1853
|
+
var setHeading = (level) => ({ state, dispatch }) => {
|
|
1854
|
+
const { selection: { ranges }, doc } = state;
|
|
1855
|
+
const changes = [];
|
|
1856
|
+
let prevBlock = -1;
|
|
1857
|
+
for (const range of ranges) {
|
|
1755
1858
|
syntaxTree2(state).iterate({
|
|
1859
|
+
from: range.from,
|
|
1860
|
+
to: range.to,
|
|
1756
1861
|
enter: (node) => {
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1862
|
+
if (!Object.hasOwn(Textblocks, node.name) || prevBlock === node.from) {
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
prevBlock = node.from;
|
|
1866
|
+
const blockType = Textblocks[node.name];
|
|
1867
|
+
const isHeading = /heading(\d)/.exec(blockType);
|
|
1868
|
+
const curLevel = isHeading ? +isHeading[1] : node.name === "Paragraph" ? 0 : -1;
|
|
1869
|
+
if (curLevel < 0 || curLevel === level) {
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
if (curLevel === 0) {
|
|
1873
|
+
changes.push({
|
|
1874
|
+
from: node.from,
|
|
1875
|
+
insert: "#".repeat(level) + " "
|
|
1876
|
+
});
|
|
1877
|
+
} else if (node.name === "SetextHeading1" || node.name === "SetextHeading2") {
|
|
1878
|
+
const nextLine = doc.lineAt(node.to);
|
|
1879
|
+
if (level) {
|
|
1880
|
+
changes.push({
|
|
1881
|
+
from: node.from,
|
|
1882
|
+
insert: "#".repeat(level) + " "
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
changes.push({
|
|
1886
|
+
from: nextLine.from - 1,
|
|
1887
|
+
to: nextLine.to
|
|
1888
|
+
});
|
|
1889
|
+
} else {
|
|
1890
|
+
if (level === 0) {
|
|
1891
|
+
changes.push({
|
|
1892
|
+
from: node.from,
|
|
1893
|
+
to: Math.min(node.to, node.from + curLevel + 1)
|
|
1894
|
+
});
|
|
1895
|
+
} else if (level < curLevel) {
|
|
1896
|
+
changes.push({
|
|
1897
|
+
from: node.from,
|
|
1898
|
+
to: node.from + (curLevel - level)
|
|
1899
|
+
});
|
|
1900
|
+
} else {
|
|
1901
|
+
changes.push({
|
|
1902
|
+
from: node.from,
|
|
1903
|
+
insert: "#".repeat(level - curLevel)
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
if (!changes.length) {
|
|
1911
|
+
return false;
|
|
1912
|
+
}
|
|
1913
|
+
dispatch(state.update({
|
|
1914
|
+
changes,
|
|
1915
|
+
userEvent: "format.setHeading",
|
|
1916
|
+
scrollIntoView: true
|
|
1917
|
+
}));
|
|
1918
|
+
return true;
|
|
1919
|
+
};
|
|
1920
|
+
var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
1921
|
+
const marker = inlineMarkerText(type);
|
|
1922
|
+
const changes = state.changeByRange((range) => {
|
|
1923
|
+
if (!enable && range.empty) {
|
|
1924
|
+
const after = state.doc.sliceString(range.head, range.head + 6);
|
|
1925
|
+
const found = after.indexOf(marker);
|
|
1926
|
+
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
1927
|
+
const before = state.doc.sliceString(range.head - 6, range.head);
|
|
1928
|
+
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
1929
|
+
...before.slice(before.length - found)
|
|
1930
|
+
].reverse().join("") === after.slice(0, found)) {
|
|
1931
|
+
return {
|
|
1932
|
+
changes: [
|
|
1933
|
+
{
|
|
1934
|
+
from: range.head - marker.length - found,
|
|
1935
|
+
to: range.head - found
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
from: range.head + found,
|
|
1939
|
+
to: range.head + found + marker.length
|
|
1940
|
+
}
|
|
1941
|
+
],
|
|
1942
|
+
range: EditorSelection.cursor(range.from - marker.length)
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
const changes2 = [];
|
|
1948
|
+
const changesAtEnd = [];
|
|
1949
|
+
let blockStart = -1;
|
|
1950
|
+
let blockEnd = -1;
|
|
1951
|
+
let startCovered = false;
|
|
1952
|
+
let endCovered = false;
|
|
1953
|
+
let { from, to } = range;
|
|
1954
|
+
syntaxTree2(state).iterate({
|
|
1955
|
+
from,
|
|
1956
|
+
to,
|
|
1957
|
+
enter: (node) => {
|
|
1958
|
+
const { name } = node;
|
|
1959
|
+
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
1960
|
+
blockStart = blockContentStart(node);
|
|
1961
|
+
blockEnd = blockContentEnd(node, state.doc);
|
|
1962
|
+
startCovered = endCovered = false;
|
|
1963
|
+
} else if (name === "Link" || name === "Image" && enable) {
|
|
1964
|
+
if (from < node.from && to > node.from && to <= node.to) {
|
|
1965
|
+
to = node.to;
|
|
1966
|
+
} else if (to > node.to && from >= node.from && from < node.to) {
|
|
1967
|
+
from = node.from;
|
|
1968
|
+
}
|
|
1969
|
+
} else if (IgnoreInline.has(name) && enable) {
|
|
1970
|
+
if (node.from < from && node.to > from) {
|
|
1971
|
+
if (to === from) {
|
|
1972
|
+
to = node.to;
|
|
1973
|
+
}
|
|
1974
|
+
from = node.to;
|
|
1975
|
+
}
|
|
1976
|
+
if (node.from < to && node.to > to) {
|
|
1977
|
+
to = node.from;
|
|
1978
|
+
}
|
|
1979
|
+
} else if (Object.hasOwn(InlineMarker, name)) {
|
|
1980
|
+
const markType = InlineMarker[name];
|
|
1981
|
+
const size = inlineMarkerText(markType).length;
|
|
1982
|
+
const openEnd = node.from + size;
|
|
1983
|
+
const closeStart = node.to - size;
|
|
1984
|
+
if (markType === type) {
|
|
1985
|
+
if (openEnd <= from && closeStart >= from) {
|
|
1986
|
+
startCovered = openEnd === from ? "adjacent" : true;
|
|
1987
|
+
}
|
|
1988
|
+
if (openEnd <= to && closeStart >= to) {
|
|
1989
|
+
endCovered = closeStart === to ? "adjacent" : true;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
if (markType === type || type === 3 && enable) {
|
|
1993
|
+
if (node.from >= from && openEnd <= to) {
|
|
1994
|
+
changes2.push({
|
|
1995
|
+
from: node.from,
|
|
1996
|
+
to: openEnd
|
|
1997
|
+
});
|
|
1998
|
+
if (markType !== type && closeStart >= to) {
|
|
1999
|
+
changesAtEnd.push({
|
|
2000
|
+
from: skipSpaces(Math.min(to, blockEnd), state.doc, 1, blockEnd),
|
|
2001
|
+
insert: inlineMarkerText(markType)
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (closeStart >= from && node.to <= to) {
|
|
2006
|
+
changes2.push({
|
|
2007
|
+
from: closeStart,
|
|
2008
|
+
to: node.to
|
|
2009
|
+
});
|
|
2010
|
+
if (markType !== type && openEnd <= from) {
|
|
2011
|
+
changes2.push({
|
|
2012
|
+
from: skipSpaces(Math.max(from, blockStart), state.doc, -1, blockStart),
|
|
2013
|
+
insert: inlineMarkerText(markType)
|
|
2014
|
+
});
|
|
1768
2015
|
}
|
|
1769
2016
|
}
|
|
1770
2017
|
}
|
|
1771
2018
|
}
|
|
1772
2019
|
},
|
|
1773
|
-
|
|
1774
|
-
|
|
2020
|
+
leave: (node) => {
|
|
2021
|
+
if (Object.hasOwn(Textblocks, node.name) && Textblocks[node.name] !== "codeblock") {
|
|
2022
|
+
const rangeStart = Math.max(from, blockStart);
|
|
2023
|
+
const rangeEnd = Math.min(to, blockEnd);
|
|
2024
|
+
if (enable) {
|
|
2025
|
+
if (!startCovered) {
|
|
2026
|
+
changes2.push({
|
|
2027
|
+
from: rangeStart,
|
|
2028
|
+
insert: marker
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
if (!endCovered) {
|
|
2032
|
+
changes2.push({
|
|
2033
|
+
from: rangeEnd,
|
|
2034
|
+
insert: marker
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
} else {
|
|
2038
|
+
if (startCovered === "adjacent") {
|
|
2039
|
+
changes2.push({
|
|
2040
|
+
from: from - marker.length,
|
|
2041
|
+
to: from
|
|
2042
|
+
});
|
|
2043
|
+
} else if (startCovered) {
|
|
2044
|
+
changes2.push({
|
|
2045
|
+
from: skipSpaces(rangeStart, state.doc, -1, blockStart),
|
|
2046
|
+
insert: marker
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
if (endCovered === "adjacent") {
|
|
2050
|
+
changes2.push({
|
|
2051
|
+
from: to,
|
|
2052
|
+
to: to + marker.length
|
|
2053
|
+
});
|
|
2054
|
+
} else if (endCovered) {
|
|
2055
|
+
changes2.push({
|
|
2056
|
+
from: skipSpaces(rangeEnd, state.doc, 1, blockEnd),
|
|
2057
|
+
insert: marker
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
1775
2063
|
});
|
|
2064
|
+
const changeSet = state.changes(changes2.concat(changesAtEnd));
|
|
2065
|
+
return {
|
|
2066
|
+
changes: changeSet,
|
|
2067
|
+
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2068
|
+
};
|
|
2069
|
+
});
|
|
2070
|
+
dispatch(state.update(changes, {
|
|
2071
|
+
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2072
|
+
scrollIntoView: true
|
|
2073
|
+
}));
|
|
2074
|
+
return true;
|
|
2075
|
+
};
|
|
2076
|
+
var addStyle = (style) => setStyle(style, true);
|
|
2077
|
+
var removeStyle = (style) => setStyle(style, false);
|
|
2078
|
+
var toggleStyle = (style) => (arg) => {
|
|
2079
|
+
const form = getFormatting(arg.state);
|
|
2080
|
+
return setStyle(style, style === 0 ? !form.strong : style === 1 ? !form.emphasis : style === 2 ? !form.strikethrough : !form.code)(arg);
|
|
2081
|
+
};
|
|
2082
|
+
var toggleStrong = toggleStyle(0);
|
|
2083
|
+
var toggleEmphasis = toggleStyle(1);
|
|
2084
|
+
var toggleStrikethrough = toggleStyle(2);
|
|
2085
|
+
var toggleInlineCode = toggleStyle(3);
|
|
2086
|
+
var inlineMarkerText = (type) => type === 0 ? "**" : type === 2 ? "~~" : type === 1 ? "*" : "`";
|
|
2087
|
+
var blockContentStart = (node) => {
|
|
2088
|
+
const atx = /^ATXHeading(\d)/.exec(node.name);
|
|
2089
|
+
if (atx) {
|
|
2090
|
+
return Math.min(node.to, node.from + +atx[1] + 1);
|
|
1776
2091
|
}
|
|
1777
|
-
return
|
|
2092
|
+
return node.from;
|
|
1778
2093
|
};
|
|
1779
|
-
var
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
2094
|
+
var blockContentEnd = (node, doc) => {
|
|
2095
|
+
const setext = /^SetextHeading(\d)/.exec(node.name);
|
|
2096
|
+
const lastLine = doc.lineAt(node.to);
|
|
2097
|
+
if (setext || /^[\s>]*$/.exec(lastLine.text)) {
|
|
2098
|
+
return lastLine.from - 1;
|
|
2099
|
+
}
|
|
2100
|
+
return node.to;
|
|
2101
|
+
};
|
|
2102
|
+
var skipSpaces = (pos, doc, dir, limit) => {
|
|
2103
|
+
const line = doc.lineAt(pos);
|
|
2104
|
+
while (pos !== limit && line.text[pos - line.from - (dir < 0 ? 1 : 0)] === " ") {
|
|
2105
|
+
pos += dir;
|
|
2106
|
+
}
|
|
2107
|
+
return pos;
|
|
2108
|
+
};
|
|
2109
|
+
var snippets = {
|
|
2110
|
+
codeblock: snippet([
|
|
2111
|
+
"```#{lang}",
|
|
2112
|
+
"#{}",
|
|
2113
|
+
"```"
|
|
2114
|
+
].join("\n")),
|
|
2115
|
+
table: snippet([
|
|
2116
|
+
"| #{col1} | #{col2} |",
|
|
2117
|
+
"| ---- | ---- |",
|
|
2118
|
+
"| #{val1} | #{val2} |",
|
|
2119
|
+
"| #{val3} | #{val4} |"
|
|
2120
|
+
].join("\n"))
|
|
2121
|
+
};
|
|
2122
|
+
var insertTable = (view) => {
|
|
2123
|
+
const { selection: { main }, doc } = view.state;
|
|
2124
|
+
const { number } = doc.lineAt(main.anchor);
|
|
2125
|
+
const { from } = doc.line(number);
|
|
2126
|
+
snippets.table(view, null, from, from);
|
|
2127
|
+
};
|
|
2128
|
+
var removeLinkInner = (from, to, changes, state) => {
|
|
2129
|
+
syntaxTree2(state).iterate({
|
|
2130
|
+
from,
|
|
2131
|
+
to,
|
|
2132
|
+
enter: (node) => {
|
|
2133
|
+
if (node.name === "Link" && node.from < to && node.to > from) {
|
|
2134
|
+
node.node.cursor().iterate((node2) => {
|
|
2135
|
+
const { name } = node2;
|
|
2136
|
+
if (name === "LinkMark" || name === "LinkLabel") {
|
|
2137
|
+
changes.push({
|
|
2138
|
+
from: node2.from,
|
|
2139
|
+
to: node2.to
|
|
2140
|
+
});
|
|
2141
|
+
} else if (name === "LinkTitle" || name === "URL") {
|
|
2142
|
+
changes.push({
|
|
2143
|
+
from: skipSpaces(node2.from, state.doc, -1),
|
|
2144
|
+
to: skipSpaces(node2.to, state.doc, 1)
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
return false;
|
|
1787
2149
|
}
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
})
|
|
1791
|
-
];
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
1792
2152
|
};
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
import { Decoration as Decoration5, EditorView as EditorView9, ViewPlugin as ViewPlugin5, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1798
|
-
var styles4 = EditorView9.baseTheme({
|
|
1799
|
-
"& .cm-hr": {
|
|
1800
|
-
// Note that block-level decorations should not have vertical margins,
|
|
1801
|
-
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2153
|
+
var removeLink = ({ state, dispatch }) => {
|
|
2154
|
+
const changes = [];
|
|
2155
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2156
|
+
removeLinkInner(from, to, changes, state);
|
|
1802
2157
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
toDOM() {
|
|
1806
|
-
const el = document.createElement("div");
|
|
1807
|
-
el.className = "cm-hr";
|
|
1808
|
-
return el;
|
|
2158
|
+
if (!changes) {
|
|
2159
|
+
return false;
|
|
1809
2160
|
}
|
|
2161
|
+
dispatch(state.update({
|
|
2162
|
+
changes,
|
|
2163
|
+
userEvent: "format.link.remove",
|
|
2164
|
+
scrollIntoView: true
|
|
2165
|
+
}));
|
|
2166
|
+
return true;
|
|
1810
2167
|
};
|
|
1811
|
-
var
|
|
1812
|
-
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
syntaxTree3(state).iterate({
|
|
2168
|
+
var addLink = ({ state, dispatch }) => {
|
|
2169
|
+
const changes = state.changeByRange((range) => {
|
|
2170
|
+
let { from, to } = range;
|
|
2171
|
+
const cutStyles = [];
|
|
2172
|
+
let okay = null;
|
|
2173
|
+
syntaxTree2(state).iterate({
|
|
2174
|
+
from,
|
|
2175
|
+
to,
|
|
1820
2176
|
enter: (node) => {
|
|
1821
|
-
if (node.name
|
|
1822
|
-
|
|
1823
|
-
|
|
2177
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2178
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state.doc);
|
|
2179
|
+
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2180
|
+
const sNode = node.node;
|
|
2181
|
+
if (node.from < from && node.to <= to) {
|
|
2182
|
+
if (sNode.firstChild.to === from) {
|
|
2183
|
+
from = node.from;
|
|
2184
|
+
} else {
|
|
2185
|
+
cutStyles.push(sNode);
|
|
2186
|
+
}
|
|
2187
|
+
} else if (node.from >= from && node.to > to) {
|
|
2188
|
+
if (sNode.lastChild.from === to) {
|
|
2189
|
+
to = node.to;
|
|
2190
|
+
} else {
|
|
2191
|
+
cutStyles.push(sNode);
|
|
2192
|
+
}
|
|
1824
2193
|
}
|
|
1825
2194
|
}
|
|
1826
|
-
}
|
|
2195
|
+
}
|
|
2196
|
+
});
|
|
2197
|
+
if (okay === null) {
|
|
2198
|
+
const line = state.doc.lineAt(from);
|
|
2199
|
+
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
2200
|
+
}
|
|
2201
|
+
if (!okay) {
|
|
2202
|
+
return {
|
|
2203
|
+
range
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
const changes2 = [];
|
|
2207
|
+
const changesAfter = [];
|
|
2208
|
+
removeLinkInner(from, to, changesAfter, state);
|
|
2209
|
+
let cursorOffset = 1;
|
|
2210
|
+
for (const style of cutStyles) {
|
|
2211
|
+
const type = InlineMarker[style.name];
|
|
2212
|
+
const mark2 = inlineMarkerText(type);
|
|
2213
|
+
if (style.from < from) {
|
|
2214
|
+
changes2.push({
|
|
2215
|
+
from: skipSpaces(from, state.doc, -1),
|
|
2216
|
+
insert: mark2
|
|
2217
|
+
});
|
|
2218
|
+
changesAfter.push({
|
|
2219
|
+
from: skipSpaces(from, state.doc, 1, to),
|
|
2220
|
+
insert: mark2
|
|
2221
|
+
});
|
|
2222
|
+
} else {
|
|
2223
|
+
changes2.push({
|
|
2224
|
+
from: skipSpaces(to, state.doc, -1, from),
|
|
2225
|
+
insert: mark2
|
|
2226
|
+
});
|
|
2227
|
+
const after = skipSpaces(to, state.doc, 1);
|
|
2228
|
+
if (after === to) {
|
|
2229
|
+
cursorOffset += mark2.length;
|
|
2230
|
+
}
|
|
2231
|
+
changesAfter.push({
|
|
2232
|
+
from: after,
|
|
2233
|
+
insert: mark2
|
|
2234
|
+
});
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
changes2.push({
|
|
1827
2238
|
from,
|
|
1828
|
-
|
|
2239
|
+
insert: "["
|
|
2240
|
+
}, {
|
|
2241
|
+
from: to,
|
|
2242
|
+
insert: "]()"
|
|
1829
2243
|
});
|
|
2244
|
+
const changeSet = state.changes(changes2.concat(changesAfter));
|
|
2245
|
+
return {
|
|
2246
|
+
changes: changeSet,
|
|
2247
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset)
|
|
2248
|
+
};
|
|
2249
|
+
});
|
|
2250
|
+
if (changes.changes.empty) {
|
|
2251
|
+
return false;
|
|
1830
2252
|
}
|
|
1831
|
-
|
|
2253
|
+
dispatch(state.update(changes, {
|
|
2254
|
+
userEvent: "format.link.add",
|
|
2255
|
+
scrollIntoView: true
|
|
2256
|
+
}));
|
|
2257
|
+
return true;
|
|
1832
2258
|
};
|
|
1833
|
-
var
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2259
|
+
var addList = (type) => ({ state, dispatch }) => {
|
|
2260
|
+
let lastBlock = -1;
|
|
2261
|
+
let counter = 1;
|
|
2262
|
+
let first = true;
|
|
2263
|
+
let parentColumn = null;
|
|
2264
|
+
const blocks = [];
|
|
2265
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2266
|
+
syntaxTree2(state).iterate({
|
|
2267
|
+
from,
|
|
2268
|
+
to,
|
|
2269
|
+
enter: (node) => {
|
|
2270
|
+
if (Object.hasOwn(Textblocks, node.name) && node.name !== "TableCell" || node.name === "Table") {
|
|
2271
|
+
if (first) {
|
|
2272
|
+
let before = node.node.prevSibling;
|
|
2273
|
+
while (before && /Mark$/.test(before.name)) {
|
|
2274
|
+
before = before.prevSibling;
|
|
2275
|
+
}
|
|
2276
|
+
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
2277
|
+
const item = before.lastChild;
|
|
2278
|
+
const itemLine = state.doc.lineAt(item.from);
|
|
2279
|
+
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2280
|
+
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2281
|
+
if (type === 0) {
|
|
2282
|
+
const mark2 = /^\s*(\d+)[.)]/.exec(itemText);
|
|
2283
|
+
if (mark2) {
|
|
2284
|
+
parentColumn += mark2[1].length;
|
|
2285
|
+
counter = +mark2[1] + 1;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
first = false;
|
|
2290
|
+
}
|
|
2291
|
+
if (node.from === lastBlock) {
|
|
2292
|
+
return;
|
|
2293
|
+
}
|
|
2294
|
+
lastBlock = node.from;
|
|
2295
|
+
blocks.push({
|
|
2296
|
+
node: node.node,
|
|
2297
|
+
counter,
|
|
2298
|
+
parentColumn
|
|
2299
|
+
});
|
|
2300
|
+
counter++;
|
|
2301
|
+
return false;
|
|
2302
|
+
}
|
|
2303
|
+
},
|
|
2304
|
+
leave: (node) => {
|
|
2305
|
+
if (node.name === "BulletList" || node.name === "OrderedList" || node.name === "Blockquote") {
|
|
2306
|
+
counter = 1;
|
|
2307
|
+
parentColumn = null;
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
if (!blocks.length) {
|
|
2313
|
+
return false;
|
|
2314
|
+
}
|
|
2315
|
+
const changes = [];
|
|
2316
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
2317
|
+
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2318
|
+
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2319
|
+
let padding = nodeFrom > 0 && !/\s/.test(state.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2320
|
+
if (type === 0) {
|
|
2321
|
+
padding += String(counter2).length;
|
|
2322
|
+
}
|
|
2323
|
+
let line = state.doc.lineAt(nodeFrom);
|
|
2324
|
+
const column = nodeFrom - line.from;
|
|
2325
|
+
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
2326
|
+
padding = Math.max(padding, parentColumn2 - column);
|
|
2327
|
+
}
|
|
2328
|
+
let mark2;
|
|
2329
|
+
if (type === 0) {
|
|
2330
|
+
let max = counter2;
|
|
2331
|
+
for (let j = i + 1; j < blocks.length; j++) {
|
|
2332
|
+
if (blocks[j].counter !== max + 1) {
|
|
2333
|
+
break;
|
|
2334
|
+
}
|
|
2335
|
+
max++;
|
|
2336
|
+
}
|
|
2337
|
+
const num = String(counter2);
|
|
2338
|
+
padding = Math.max(String(max).length, padding);
|
|
2339
|
+
mark2 = " ".repeat(Math.max(0, padding - num.length)) + num + ". ";
|
|
2340
|
+
} else {
|
|
2341
|
+
mark2 = " ".repeat(padding) + "- " + (type === 2 ? "[ ] " : "");
|
|
2342
|
+
}
|
|
2343
|
+
changes.push({
|
|
2344
|
+
from: nodeFrom,
|
|
2345
|
+
insert: mark2
|
|
2346
|
+
});
|
|
2347
|
+
while (line.to < node.to) {
|
|
2348
|
+
line = state.doc.lineAt(line.to + 1);
|
|
2349
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2350
|
+
changes.push({
|
|
2351
|
+
from: line.from + Math.min(open, column),
|
|
2352
|
+
insert: " ".repeat(mark2.length)
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
if (type === 0) {
|
|
2357
|
+
const last = blocks[blocks.length - 1];
|
|
2358
|
+
let next = last.node.nextSibling;
|
|
2359
|
+
while (next && /Mark$/.test(next.name)) {
|
|
2360
|
+
next = next.nextSibling;
|
|
2361
|
+
}
|
|
2362
|
+
if (next?.name === "OrderedList") {
|
|
2363
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
dispatch(state.update({
|
|
2367
|
+
changes,
|
|
2368
|
+
userEvent: "format.list.add",
|
|
2369
|
+
scrollIntoView: true
|
|
2370
|
+
}));
|
|
2371
|
+
return true;
|
|
2372
|
+
};
|
|
2373
|
+
var removeList = (type) => ({ state, dispatch }) => {
|
|
2374
|
+
let lastBlock = -1;
|
|
2375
|
+
const changes = [];
|
|
2376
|
+
const stack = [];
|
|
2377
|
+
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
2378
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2379
|
+
syntaxTree2(state).iterate({
|
|
2380
|
+
from,
|
|
2381
|
+
to,
|
|
2382
|
+
enter: (node) => {
|
|
2383
|
+
const { name } = node;
|
|
2384
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2385
|
+
stack.push(name);
|
|
2386
|
+
} else if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2387
|
+
stack[stack.length - 1] = "TaskList";
|
|
2388
|
+
}
|
|
2389
|
+
},
|
|
2390
|
+
leave: (node) => {
|
|
2391
|
+
const { name } = node;
|
|
2392
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2393
|
+
stack.pop();
|
|
2394
|
+
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2395
|
+
lastBlock = node.from;
|
|
2396
|
+
let line = state.doc.lineAt(node.from);
|
|
2397
|
+
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2398
|
+
if (!mark2) {
|
|
2399
|
+
return false;
|
|
2400
|
+
}
|
|
2401
|
+
const column = node.from - line.from;
|
|
2402
|
+
changes.push({
|
|
2403
|
+
from: node.from,
|
|
2404
|
+
to: node.from + mark2[0].length
|
|
2405
|
+
});
|
|
2406
|
+
while (line.to < node.to) {
|
|
2407
|
+
line = state.doc.lineAt(line.to + 1);
|
|
2408
|
+
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2409
|
+
if (open > column) {
|
|
2410
|
+
changes.push({
|
|
2411
|
+
from: line.from + column,
|
|
2412
|
+
to: line.from + Math.min(column + mark2[0].length, open)
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
if (node.to >= to) {
|
|
2417
|
+
renumberListItems(node.node.nextSibling, 1, changes, state.doc);
|
|
2418
|
+
}
|
|
2419
|
+
return false;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
});
|
|
2423
|
+
}
|
|
2424
|
+
if (!changes.length) {
|
|
2425
|
+
return false;
|
|
2426
|
+
}
|
|
2427
|
+
dispatch(state.update({
|
|
2428
|
+
changes,
|
|
2429
|
+
userEvent: "format.list.remove",
|
|
2430
|
+
scrollIntoView: true
|
|
2431
|
+
}));
|
|
2432
|
+
return true;
|
|
2433
|
+
};
|
|
2434
|
+
var toggleList = (type) => (target) => {
|
|
2435
|
+
const formatting2 = getFormatting(target.state);
|
|
2436
|
+
const active = formatting2.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
2437
|
+
return (active ? removeList(type) : addList(type))(target);
|
|
2438
|
+
};
|
|
2439
|
+
var renumberListItems = (item, counter, changes, doc) => {
|
|
2440
|
+
for (; item; item = item.nextSibling) {
|
|
2441
|
+
if (item.name === "ListItem") {
|
|
2442
|
+
const number = /(\s*)(\d+)[.)]/.exec(doc.sliceString(item.from, item.from + 10));
|
|
2443
|
+
if (!number || +number[2] === counter) {
|
|
2444
|
+
break;
|
|
2445
|
+
}
|
|
2446
|
+
const size = number[1].length + number[2].length;
|
|
2447
|
+
const newNum = String(counter);
|
|
2448
|
+
changes.push({
|
|
2449
|
+
from: item.from + Math.max(0, size - newNum.length),
|
|
2450
|
+
to: item.from + size,
|
|
2451
|
+
insert: newNum
|
|
2452
|
+
});
|
|
2453
|
+
counter++;
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
};
|
|
2457
|
+
var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
2458
|
+
const lines = [];
|
|
2459
|
+
let lastBlock = -1;
|
|
2460
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2461
|
+
syntaxTree2(state).iterate({
|
|
2462
|
+
from,
|
|
2463
|
+
to,
|
|
2464
|
+
enter: (node) => {
|
|
2465
|
+
if (Object.hasOwn(Textblocks, node.name) || node.name === "Table") {
|
|
2466
|
+
if (node.from === lastBlock) {
|
|
2467
|
+
return false;
|
|
2468
|
+
}
|
|
2469
|
+
lastBlock = node.from;
|
|
2470
|
+
let line = state.doc.lineAt(node.from);
|
|
2471
|
+
if (line.number > 1) {
|
|
2472
|
+
const prevLine = state.doc.line(line.number - 1);
|
|
2473
|
+
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
2474
|
+
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
2475
|
+
lines.push(prevLine);
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
for (; ; ) {
|
|
2480
|
+
lines.push(line);
|
|
2481
|
+
if (line.to >= node.to) {
|
|
2482
|
+
break;
|
|
2483
|
+
}
|
|
2484
|
+
line = state.doc.line(line.number + 1);
|
|
2485
|
+
}
|
|
2486
|
+
if (!enable && line.number < state.doc.lines) {
|
|
2487
|
+
const nextLine = state.doc.line(line.number + 1);
|
|
2488
|
+
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
2489
|
+
lines.push(nextLine);
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
return false;
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
}
|
|
2497
|
+
const changes = [];
|
|
2498
|
+
for (const line of lines) {
|
|
2499
|
+
if (enable) {
|
|
2500
|
+
changes.push({
|
|
2501
|
+
from: line.from,
|
|
2502
|
+
insert: /\S/.test(line.text) ? "> " : ">"
|
|
2503
|
+
});
|
|
2504
|
+
} else {
|
|
2505
|
+
const quote = /((?:[\s>\-+*]|\d+[.)])*?)> ?/.exec(line.text);
|
|
2506
|
+
if (quote) {
|
|
2507
|
+
changes.push({
|
|
2508
|
+
from: line.from + quote[1].length,
|
|
2509
|
+
to: line.from + quote[0].length
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
if (!changes.length) {
|
|
2515
|
+
return false;
|
|
2516
|
+
}
|
|
2517
|
+
dispatch(state.update({
|
|
2518
|
+
changes,
|
|
2519
|
+
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
2520
|
+
scrollIntoView: true
|
|
2521
|
+
}));
|
|
2522
|
+
return true;
|
|
2523
|
+
};
|
|
2524
|
+
var addBlockquote = setBlockquote(true);
|
|
2525
|
+
var removeBlockquote = setBlockquote(false);
|
|
2526
|
+
var toggleBlockquote = (target) => {
|
|
2527
|
+
return (getFormatting(target.state).blockquote ? removeBlockquote : addBlockquote)(target);
|
|
2528
|
+
};
|
|
2529
|
+
var addCodeblock = (target) => {
|
|
2530
|
+
const { state, dispatch } = target;
|
|
2531
|
+
const { selection } = state;
|
|
2532
|
+
if (selection.ranges.length === 1 && selection.main.empty) {
|
|
2533
|
+
const { head } = selection.main;
|
|
2534
|
+
const line = state.doc.lineAt(head);
|
|
2535
|
+
if (!/\S/.test(line.text) && head === line.from) {
|
|
2536
|
+
snippets.codeblock(target, null, line.from, line.to);
|
|
2537
|
+
return true;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
const ranges = [];
|
|
2541
|
+
for (const { from, to } of selection.ranges) {
|
|
2542
|
+
let blockFrom = from;
|
|
2543
|
+
let blockTo = to;
|
|
2544
|
+
syntaxTree2(state).iterate({
|
|
2545
|
+
from,
|
|
2546
|
+
to,
|
|
2547
|
+
enter: (node) => {
|
|
2548
|
+
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2549
|
+
if (from >= node.from && to <= node.to) {
|
|
2550
|
+
blockFrom = node.from;
|
|
2551
|
+
blockTo = node.to;
|
|
2552
|
+
} else {
|
|
2553
|
+
blockFrom = Math.min(blockFrom, state.doc.lineAt(node.from).from);
|
|
2554
|
+
blockTo = Math.max(blockTo, state.doc.lineAt(node.to).to);
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
});
|
|
2559
|
+
if (ranges.length && ranges[ranges.length - 1].to >= blockFrom - 1) {
|
|
2560
|
+
ranges[ranges.length - 1].to = blockTo;
|
|
2561
|
+
} else {
|
|
2562
|
+
ranges.push({
|
|
2563
|
+
from: blockFrom,
|
|
2564
|
+
to: blockTo
|
|
2565
|
+
});
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
if (!ranges.length) {
|
|
2569
|
+
return false;
|
|
2570
|
+
}
|
|
2571
|
+
const changes = ranges.map(({ from, to }) => {
|
|
2572
|
+
const column = from - state.doc.lineAt(from).from;
|
|
2573
|
+
return [
|
|
2574
|
+
{
|
|
2575
|
+
from,
|
|
2576
|
+
insert: "```\n" + " ".repeat(column)
|
|
2577
|
+
},
|
|
2578
|
+
{
|
|
2579
|
+
from: to,
|
|
2580
|
+
insert: "\n" + " ".repeat(column) + "```"
|
|
2581
|
+
}
|
|
2582
|
+
];
|
|
2583
|
+
});
|
|
2584
|
+
dispatch(state.update({
|
|
2585
|
+
changes,
|
|
2586
|
+
userEvent: "format.codeblock.add",
|
|
2587
|
+
scrollIntoView: true
|
|
2588
|
+
}));
|
|
2589
|
+
return true;
|
|
2590
|
+
};
|
|
2591
|
+
var removeCodeblock = ({ state, dispatch }) => {
|
|
2592
|
+
const changes = [];
|
|
2593
|
+
let lastBlock = -1;
|
|
2594
|
+
for (const { from, to } of state.selection.ranges) {
|
|
2595
|
+
syntaxTree2(state).iterate({
|
|
2596
|
+
from,
|
|
2597
|
+
to,
|
|
2598
|
+
enter: (node) => {
|
|
2599
|
+
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
2600
|
+
lastBlock = node.from;
|
|
2601
|
+
const firstLine = state.doc.lineAt(node.from);
|
|
2602
|
+
if (node.name === "FencedCode") {
|
|
2603
|
+
changes.push({
|
|
2604
|
+
from: node.from,
|
|
2605
|
+
to: firstLine.to + 1 + node.from - firstLine.from
|
|
2606
|
+
});
|
|
2607
|
+
const lastLine = state.doc.lineAt(node.to);
|
|
2608
|
+
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
2609
|
+
changes.push({
|
|
2610
|
+
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
2611
|
+
to: lastLine.to
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
} else {
|
|
2615
|
+
const column = node.from - firstLine.from;
|
|
2616
|
+
for (let line = firstLine; ; line = state.doc.line(line.number + 1)) {
|
|
2617
|
+
changes.push({
|
|
2618
|
+
from: line.from + column - 4,
|
|
2619
|
+
to: line.from + column
|
|
2620
|
+
});
|
|
2621
|
+
if (line.to >= node.to) {
|
|
2622
|
+
break;
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
if (!changes.length) {
|
|
2631
|
+
return false;
|
|
2632
|
+
}
|
|
2633
|
+
dispatch(state.update({
|
|
2634
|
+
changes,
|
|
2635
|
+
userEvent: "format.codeblock.remove",
|
|
2636
|
+
scrollIntoView: true
|
|
2637
|
+
}));
|
|
2638
|
+
return true;
|
|
2639
|
+
};
|
|
2640
|
+
var toggleCodeblock = (target) => {
|
|
2641
|
+
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
2642
|
+
};
|
|
2643
|
+
var formatting = (options = {}) => {
|
|
2644
|
+
return [
|
|
2645
|
+
keymap5.of([
|
|
2646
|
+
{
|
|
2647
|
+
key: "meta-b",
|
|
2648
|
+
run: toggleStrong
|
|
2649
|
+
}
|
|
2650
|
+
]),
|
|
2651
|
+
styling()
|
|
2652
|
+
];
|
|
2653
|
+
};
|
|
2654
|
+
var styling = () => {
|
|
2655
|
+
const buildDecorations7 = (view) => {
|
|
2656
|
+
const builder = new RangeSetBuilder2();
|
|
2657
|
+
const { state } = view;
|
|
2658
|
+
const cursor = state.selection.main.head;
|
|
2659
|
+
const replace = (node, marks) => {
|
|
2660
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2661
|
+
for (const mark2 of marks) {
|
|
2662
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
};
|
|
2666
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2667
|
+
syntaxTree2(state).iterate({
|
|
2668
|
+
enter: (node) => {
|
|
2669
|
+
switch (node.name) {
|
|
2670
|
+
case "Emphasis":
|
|
2671
|
+
case "StrongEmphasis": {
|
|
2672
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
2673
|
+
replace(node, marks);
|
|
2674
|
+
break;
|
|
2675
|
+
}
|
|
2676
|
+
case "Strikethrough": {
|
|
2677
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
2678
|
+
replace(node, marks);
|
|
2679
|
+
break;
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
2683
|
+
from,
|
|
2684
|
+
to
|
|
2685
|
+
});
|
|
2686
|
+
}
|
|
2687
|
+
return builder.finish();
|
|
2688
|
+
};
|
|
2689
|
+
return [
|
|
2690
|
+
ViewPlugin4.fromClass(class {
|
|
2691
|
+
constructor(view) {
|
|
2692
|
+
this.decorations = buildDecorations7(view);
|
|
2693
|
+
}
|
|
2694
|
+
update(update2) {
|
|
2695
|
+
this.decorations = buildDecorations7(update2.view);
|
|
2696
|
+
}
|
|
2697
|
+
}, {
|
|
2698
|
+
decorations: (value) => value.decorations
|
|
2699
|
+
})
|
|
2700
|
+
];
|
|
2701
|
+
};
|
|
2702
|
+
var InlineMarker = {
|
|
2703
|
+
Emphasis: 1,
|
|
2704
|
+
StrongEmphasis: 0,
|
|
2705
|
+
InlineCode: 3,
|
|
2706
|
+
Strikethrough: 2
|
|
2707
|
+
};
|
|
2708
|
+
var IgnoreInline = /* @__PURE__ */ new Set([
|
|
2709
|
+
"Hardbreak",
|
|
2710
|
+
"HTMLTag",
|
|
2711
|
+
"Comment",
|
|
2712
|
+
"ProcessingInstruction",
|
|
2713
|
+
"Autolink",
|
|
2714
|
+
"HeaderMark",
|
|
2715
|
+
"QuoteMark",
|
|
2716
|
+
"ListMark",
|
|
2717
|
+
"LinkMark",
|
|
2718
|
+
"EmphasisMark",
|
|
2719
|
+
"CodeMark",
|
|
2720
|
+
"CodeText",
|
|
2721
|
+
"StrikethroughMark",
|
|
2722
|
+
"TaskMarker",
|
|
2723
|
+
"SuperscriptMark",
|
|
2724
|
+
"SubscriptMark"
|
|
2725
|
+
]);
|
|
2726
|
+
var Textblocks = {
|
|
2727
|
+
Paragraph: "paragraph",
|
|
2728
|
+
Task: "paragraph",
|
|
2729
|
+
CodeBlock: "codeblock",
|
|
2730
|
+
FencedCode: "codeblock",
|
|
2731
|
+
ATXHeading1: "heading1",
|
|
2732
|
+
ATXHeading2: "heading2",
|
|
2733
|
+
ATXHeading3: "heading3",
|
|
2734
|
+
ATXHeading4: "heading4",
|
|
2735
|
+
ATXHeading5: "heading5",
|
|
2736
|
+
ATXHeading6: "heading6",
|
|
2737
|
+
SetextHeading1: "heading1",
|
|
2738
|
+
SetextHeading2: "heading2",
|
|
2739
|
+
TableCell: "tablecell"
|
|
2740
|
+
};
|
|
2741
|
+
var getFormatting = (state) => {
|
|
2742
|
+
let blockType = null;
|
|
2743
|
+
const inline = [
|
|
2744
|
+
null,
|
|
2745
|
+
null,
|
|
2746
|
+
null,
|
|
2747
|
+
null
|
|
2748
|
+
];
|
|
2749
|
+
let link2 = false;
|
|
2750
|
+
let blockquote2 = null;
|
|
2751
|
+
let listStyle = null;
|
|
2752
|
+
const stack = [];
|
|
2753
|
+
let currentBlock = null;
|
|
2754
|
+
const advanceInline = (upto) => {
|
|
2755
|
+
if (!currentBlock) {
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
upto = Math.min(upto, currentBlock.end);
|
|
2759
|
+
if (upto <= currentBlock.pos) {
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
for (let i = 0; i < currentBlock.active.length; i++) {
|
|
2763
|
+
if (inline[i] === false) {
|
|
2764
|
+
continue;
|
|
2765
|
+
} else if (currentBlock.active[i]) {
|
|
2766
|
+
inline[i] = true;
|
|
2767
|
+
} else if (/\S/.test(state.doc.sliceString(currentBlock.pos, upto))) {
|
|
2768
|
+
inline[i] = false;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
currentBlock.pos = upto;
|
|
2772
|
+
};
|
|
2773
|
+
const skipInline = (upto) => {
|
|
2774
|
+
if (currentBlock && upto > currentBlock.pos) {
|
|
2775
|
+
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
2776
|
+
}
|
|
2777
|
+
};
|
|
2778
|
+
const { selection } = state;
|
|
2779
|
+
for (const range of selection.ranges) {
|
|
2780
|
+
if (range.empty && inline.some((v) => v === null)) {
|
|
2781
|
+
const contextSize = Math.min(range.head, 6);
|
|
2782
|
+
const contextBefore = state.doc.sliceString(range.head - contextSize, range.head);
|
|
2783
|
+
let contextAfter = state.doc.sliceString(range.head, range.head + contextSize);
|
|
2784
|
+
for (let i = 0; i < contextSize; i++) {
|
|
2785
|
+
const ch = contextAfter[i];
|
|
2786
|
+
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
2787
|
+
contextAfter = contextAfter.slice(0, i);
|
|
2788
|
+
break;
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
for (let i = 0; i < inline.length; i++) {
|
|
2792
|
+
const mark2 = inlineMarkerText(i);
|
|
2793
|
+
const found = contextAfter.indexOf(mark2);
|
|
2794
|
+
if (found > -1) {
|
|
2795
|
+
contextAfter = contextAfter.slice(0, found) + contextAfter.slice(found + mark2.length);
|
|
2796
|
+
if (inline[i] === null) {
|
|
2797
|
+
inline[i] = true;
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
syntaxTree2(state).iterate({
|
|
2803
|
+
from: range.from,
|
|
2804
|
+
to: range.to,
|
|
2805
|
+
enter: (node) => {
|
|
2806
|
+
advanceInline(node.from);
|
|
2807
|
+
const { name } = node;
|
|
2808
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2809
|
+
stack.push(name);
|
|
2810
|
+
} else if (name === "Link") {
|
|
2811
|
+
link2 = true;
|
|
2812
|
+
} else if (Object.hasOwn(Textblocks, name) && (range.empty || node.to > range.from || node.from < range.to)) {
|
|
2813
|
+
if (name === "Task" && stack[stack.length - 1] === "BulletList") {
|
|
2814
|
+
stack[stack.length - 1] = "TaskList";
|
|
2815
|
+
}
|
|
2816
|
+
const blockCode = Textblocks[name];
|
|
2817
|
+
if (blockType === null) {
|
|
2818
|
+
blockType = blockCode;
|
|
2819
|
+
} else if (blockType !== blockCode) {
|
|
2820
|
+
blockType = false;
|
|
2821
|
+
}
|
|
2822
|
+
if (blockCode !== "codeblock" && inline.some((i) => i !== false)) {
|
|
2823
|
+
currentBlock = {
|
|
2824
|
+
pos: Math.max(range.from, node.from),
|
|
2825
|
+
end: Math.min(range.to, node.to),
|
|
2826
|
+
active: [
|
|
2827
|
+
false,
|
|
2828
|
+
false,
|
|
2829
|
+
false,
|
|
2830
|
+
false
|
|
2831
|
+
]
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
2835
|
+
const index = InlineMarker[name];
|
|
2836
|
+
if (range.empty && inline[index] === null) {
|
|
2837
|
+
inline[index] = true;
|
|
2838
|
+
}
|
|
2839
|
+
currentBlock.active[index] = true;
|
|
2840
|
+
} else if (IgnoreInline.has(name)) {
|
|
2841
|
+
skipInline(node.to);
|
|
2842
|
+
}
|
|
2843
|
+
},
|
|
2844
|
+
leave: (node) => {
|
|
2845
|
+
advanceInline(node.to);
|
|
2846
|
+
const { name } = node;
|
|
2847
|
+
if (name === "BulletList" || name === "OrderedList" || name === "Blockquote") {
|
|
2848
|
+
stack.pop();
|
|
2849
|
+
} else if (Object.hasOwn(Textblocks, name)) {
|
|
2850
|
+
let hasList = false;
|
|
2851
|
+
let hasQuote = false;
|
|
2852
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
2853
|
+
if (stack[i] === "Blockquote") {
|
|
2854
|
+
hasQuote = true;
|
|
2855
|
+
} else if (!hasList) {
|
|
2856
|
+
hasList = stack[i] === "TaskList" ? "task" : stack[i] === "BulletList" ? "bullet" : "ordered";
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
if (blockquote2 === null) {
|
|
2860
|
+
blockquote2 = hasQuote;
|
|
2861
|
+
} else if (!hasQuote && blockquote2) {
|
|
2862
|
+
blockquote2 = false;
|
|
2863
|
+
}
|
|
2864
|
+
if (listStyle === null) {
|
|
2865
|
+
listStyle = hasList;
|
|
2866
|
+
} else if (listStyle !== hasList) {
|
|
2867
|
+
listStyle = false;
|
|
2868
|
+
}
|
|
2869
|
+
currentBlock = null;
|
|
2870
|
+
} else if (Object.hasOwn(InlineMarker, name) && currentBlock) {
|
|
2871
|
+
currentBlock.active[InlineMarker[name]] = false;
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
return {
|
|
2877
|
+
blockType: blockType || null,
|
|
2878
|
+
strong: inline[0] ?? false,
|
|
2879
|
+
emphasis: inline[1] ?? false,
|
|
2880
|
+
code: inline[3] ?? false,
|
|
2881
|
+
strikethrough: inline[2] ?? false,
|
|
2882
|
+
link: link2,
|
|
2883
|
+
blockquote: blockquote2 ?? false,
|
|
2884
|
+
listStyle: listStyle || null
|
|
2885
|
+
};
|
|
2886
|
+
};
|
|
2887
|
+
var useFormattingState = () => {
|
|
2888
|
+
const [state, setState] = useState(null);
|
|
2889
|
+
const observer = useMemo(() => EditorView9.updateListener.of((update2) => {
|
|
2890
|
+
if (update2.docChanged || update2.selectionSet) {
|
|
2891
|
+
const newState = getFormatting(update2.state);
|
|
2892
|
+
if (!state || !compareFormatting(state, newState)) {
|
|
2893
|
+
setState(newState);
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
}), []);
|
|
2897
|
+
return [
|
|
2898
|
+
state,
|
|
2899
|
+
observer
|
|
2900
|
+
];
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
2904
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
2905
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
2906
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
2907
|
+
var buildDecorations2 = (view) => {
|
|
2908
|
+
const builder = new RangeSetBuilder3();
|
|
2909
|
+
const { state } = view;
|
|
2910
|
+
const cursor = state.selection.main.head;
|
|
2911
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2912
|
+
syntaxTree3(state).iterate({
|
|
2913
|
+
enter: (node) => {
|
|
2914
|
+
switch (node.name) {
|
|
2915
|
+
case "ATXHeading1":
|
|
2916
|
+
case "ATXHeading2":
|
|
2917
|
+
case "ATXHeading3":
|
|
2918
|
+
case "ATXHeading4":
|
|
2919
|
+
case "ATXHeading5":
|
|
2920
|
+
case "ATXHeading6": {
|
|
2921
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
2922
|
+
if (mark2) {
|
|
2923
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2924
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
},
|
|
2930
|
+
from,
|
|
2931
|
+
to
|
|
2932
|
+
});
|
|
2933
|
+
}
|
|
2934
|
+
return builder.finish();
|
|
2935
|
+
};
|
|
2936
|
+
var heading2 = () => {
|
|
2937
|
+
return [
|
|
2938
|
+
ViewPlugin5.fromClass(class {
|
|
2939
|
+
constructor(view) {
|
|
2940
|
+
this.decorations = buildDecorations2(view);
|
|
2941
|
+
}
|
|
2942
|
+
update(update2) {
|
|
2943
|
+
this.decorations = buildDecorations2(update2.view);
|
|
2944
|
+
}
|
|
2945
|
+
}, {
|
|
2946
|
+
decorations: (value) => value.decorations
|
|
2947
|
+
})
|
|
2948
|
+
];
|
|
2949
|
+
};
|
|
2950
|
+
|
|
2951
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
2952
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2953
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
2954
|
+
import { Decoration as Decoration6, EditorView as EditorView10, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
2955
|
+
var styles4 = EditorView10.baseTheme({
|
|
2956
|
+
"& .cm-hr": {
|
|
2957
|
+
// Note that block-level decorations should not have vertical margins,
|
|
2958
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2962
|
+
toDOM() {
|
|
2963
|
+
const el = document.createElement("div");
|
|
2964
|
+
el.className = "cm-hr";
|
|
2965
|
+
return el;
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2968
|
+
var decoration = Decoration6.replace({
|
|
2969
|
+
widget: new HorizontalRuleWidget()
|
|
2970
|
+
});
|
|
2971
|
+
var buildDecorations3 = (view) => {
|
|
2972
|
+
const builder = new RangeSetBuilder4();
|
|
2973
|
+
const { state } = view;
|
|
2974
|
+
const cursor = state.selection.main.head;
|
|
2975
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2976
|
+
syntaxTree4(state).iterate({
|
|
2977
|
+
enter: (node) => {
|
|
2978
|
+
if (node.name === "HorizontalRule") {
|
|
2979
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
2980
|
+
builder.add(node.from, node.to, decoration);
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
},
|
|
2984
|
+
from,
|
|
2985
|
+
to
|
|
2986
|
+
});
|
|
2987
|
+
}
|
|
2988
|
+
return builder.finish();
|
|
2989
|
+
};
|
|
2990
|
+
var hr = () => {
|
|
2991
|
+
return [
|
|
2992
|
+
ViewPlugin6.fromClass(class {
|
|
2993
|
+
constructor(view) {
|
|
2994
|
+
this.decorations = buildDecorations3(view);
|
|
2995
|
+
}
|
|
2996
|
+
update(update2) {
|
|
2997
|
+
this.decorations = buildDecorations3(update2.view);
|
|
1841
2998
|
}
|
|
1842
2999
|
}, {
|
|
1843
3000
|
decorations: (value) => value.decorations
|
|
@@ -1847,13 +3004,13 @@ var hr = () => {
|
|
|
1847
3004
|
};
|
|
1848
3005
|
|
|
1849
3006
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1850
|
-
import { syntaxTree as
|
|
3007
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
1851
3008
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1852
|
-
import { Decoration as
|
|
3009
|
+
import { Decoration as Decoration7, EditorView as EditorView11, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1853
3010
|
var image = (options = {}) => {
|
|
1854
3011
|
return StateField3.define({
|
|
1855
3012
|
create: (state) => {
|
|
1856
|
-
return
|
|
3013
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
1857
3014
|
},
|
|
1858
3015
|
update: (value, tr) => {
|
|
1859
3016
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1876,20 +3033,20 @@ var image = (options = {}) => {
|
|
|
1876
3033
|
add: buildDecorations4(from, to, tr.state)
|
|
1877
3034
|
});
|
|
1878
3035
|
},
|
|
1879
|
-
provide: (field) =>
|
|
3036
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
1880
3037
|
});
|
|
1881
3038
|
};
|
|
1882
3039
|
var buildDecorations4 = (from, to, state) => {
|
|
1883
3040
|
const decorations = [];
|
|
1884
3041
|
const cursor = state.selection.main.head;
|
|
1885
|
-
|
|
3042
|
+
syntaxTree5(state).iterate({
|
|
1886
3043
|
enter: (node) => {
|
|
1887
3044
|
if (node.name === "Image") {
|
|
1888
3045
|
const urlNode = node.node.getChild("URL");
|
|
1889
3046
|
if (urlNode) {
|
|
1890
3047
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1891
3048
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1892
|
-
decorations.push(
|
|
3049
|
+
decorations.push(Decoration7.replace({
|
|
1893
3050
|
block: true,
|
|
1894
3051
|
widget: new ImageWidget(url)
|
|
1895
3052
|
}).range(hide ? node.from : node.to, node.to));
|
|
@@ -1919,13 +3076,13 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1919
3076
|
};
|
|
1920
3077
|
|
|
1921
3078
|
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
1922
|
-
import { syntaxTree as
|
|
1923
|
-
import { RangeSetBuilder as
|
|
1924
|
-
import { hoverTooltip as hoverTooltip2, Decoration as
|
|
3079
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
3080
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
3081
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1925
3082
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1926
3083
|
var link = (options = {}) => {
|
|
1927
3084
|
const extensions = [
|
|
1928
|
-
|
|
3085
|
+
ViewPlugin7.fromClass(class {
|
|
1929
3086
|
constructor(view) {
|
|
1930
3087
|
this.decorations = buildDecorations5(view, options);
|
|
1931
3088
|
}
|
|
@@ -1944,7 +3101,7 @@ var link = (options = {}) => {
|
|
|
1944
3101
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1945
3102
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1946
3103
|
hoverTooltip2((view, pos, side) => {
|
|
1947
|
-
const syntax =
|
|
3104
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
1948
3105
|
let link2 = null;
|
|
1949
3106
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1950
3107
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -2021,27 +3178,27 @@ var LinkText = class extends WidgetType5 {
|
|
|
2021
3178
|
}
|
|
2022
3179
|
};
|
|
2023
3180
|
var buildDecorations5 = (view, options) => {
|
|
2024
|
-
const builder = new
|
|
3181
|
+
const builder = new RangeSetBuilder5();
|
|
2025
3182
|
const { state } = view;
|
|
2026
3183
|
const cursor = state.selection.main.head;
|
|
2027
3184
|
for (const { from, to } of view.visibleRanges) {
|
|
2028
|
-
|
|
3185
|
+
syntaxTree6(state).iterate({
|
|
2029
3186
|
enter: (node) => {
|
|
2030
3187
|
if (node.name === "Link") {
|
|
2031
|
-
const
|
|
2032
|
-
const text =
|
|
3188
|
+
const marks = node.node.getChildren("LinkMark");
|
|
3189
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2033
3190
|
const urlNode = node.node.getChild("URL");
|
|
2034
3191
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2035
3192
|
if (!url) {
|
|
2036
3193
|
return false;
|
|
2037
3194
|
}
|
|
2038
3195
|
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2039
|
-
builder.add(node.from, node.to,
|
|
3196
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2040
3197
|
widget: new LinkText(text, options.link ? url : void 0)
|
|
2041
3198
|
}));
|
|
2042
3199
|
}
|
|
2043
3200
|
if (options.onRender) {
|
|
2044
|
-
builder.add(node.to, node.to,
|
|
3201
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2045
3202
|
widget: new LinkButton(url, options.onRender)
|
|
2046
3203
|
}));
|
|
2047
3204
|
}
|
|
@@ -2056,18 +3213,18 @@ var buildDecorations5 = (view, options) => {
|
|
|
2056
3213
|
};
|
|
2057
3214
|
|
|
2058
3215
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2059
|
-
import { syntaxTree as
|
|
2060
|
-
import { RangeSetBuilder as
|
|
2061
|
-
import { Decoration as
|
|
3216
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
3217
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
3218
|
+
import { Decoration as Decoration9, EditorView as EditorView12, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2062
3219
|
var table = (options = {}) => {
|
|
2063
3220
|
return StateField4.define({
|
|
2064
3221
|
create: (state) => update(state, options),
|
|
2065
3222
|
update: (_, tr) => update(tr.state, options),
|
|
2066
|
-
provide: (field) =>
|
|
3223
|
+
provide: (field) => EditorView12.decorations.from(field)
|
|
2067
3224
|
});
|
|
2068
3225
|
};
|
|
2069
3226
|
var update = (state, options) => {
|
|
2070
|
-
const builder = new
|
|
3227
|
+
const builder = new RangeSetBuilder6();
|
|
2071
3228
|
const cursor = state.selection.main.head;
|
|
2072
3229
|
const tables = [];
|
|
2073
3230
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2075,7 +3232,7 @@ var update = (state, options) => {
|
|
|
2075
3232
|
const table2 = getTable();
|
|
2076
3233
|
return table2.rows?.[table2.rows.length - 1];
|
|
2077
3234
|
};
|
|
2078
|
-
|
|
3235
|
+
syntaxTree7(state).iterate({
|
|
2079
3236
|
enter: (node) => {
|
|
2080
3237
|
switch (node.name) {
|
|
2081
3238
|
case "Table": {
|
|
@@ -2107,10 +3264,10 @@ var update = (state, options) => {
|
|
|
2107
3264
|
});
|
|
2108
3265
|
tables.forEach((table2) => {
|
|
2109
3266
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2110
|
-
hide && builder.add(table2.from, table2.to,
|
|
3267
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2111
3268
|
widget: new TableWidget(table2)
|
|
2112
3269
|
}));
|
|
2113
|
-
builder.add(table2.from, table2.to,
|
|
3270
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2114
3271
|
class: "cm-table"
|
|
2115
3272
|
}));
|
|
2116
3273
|
});
|
|
@@ -2154,10 +3311,10 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2154
3311
|
};
|
|
2155
3312
|
|
|
2156
3313
|
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2157
|
-
import { syntaxTree as
|
|
2158
|
-
import { RangeSetBuilder as
|
|
2159
|
-
import { EditorView as
|
|
2160
|
-
var styles5 =
|
|
3314
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
3315
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
3316
|
+
import { EditorView as EditorView13, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
3317
|
+
var styles5 = EditorView13.baseTheme({
|
|
2161
3318
|
"& .cm-task": {
|
|
2162
3319
|
color: getToken("extend.colors.blue.500")
|
|
2163
3320
|
},
|
|
@@ -2203,23 +3360,23 @@ var CheckboxWidget = class extends WidgetType7 {
|
|
|
2203
3360
|
return false;
|
|
2204
3361
|
}
|
|
2205
3362
|
};
|
|
2206
|
-
var checkedDecoration =
|
|
3363
|
+
var checkedDecoration = Decoration10.replace({
|
|
2207
3364
|
widget: new CheckboxWidget(true)
|
|
2208
3365
|
});
|
|
2209
|
-
var uncheckedDecoration =
|
|
3366
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2210
3367
|
widget: new CheckboxWidget(false)
|
|
2211
3368
|
});
|
|
2212
3369
|
var buildDecorations6 = (view) => {
|
|
2213
|
-
const builder = new
|
|
3370
|
+
const builder = new RangeSetBuilder7();
|
|
2214
3371
|
const { state } = view;
|
|
2215
3372
|
const cursor = state.selection.main.head;
|
|
2216
3373
|
for (const { from, to } of view.visibleRanges) {
|
|
2217
|
-
|
|
3374
|
+
syntaxTree8(state).iterate({
|
|
2218
3375
|
enter: (node) => {
|
|
2219
3376
|
if (node.name === "TaskMarker") {
|
|
2220
3377
|
if (cursor < node.from || cursor > node.to) {
|
|
2221
3378
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2222
|
-
builder.add(node.from - 2, node.from - 1,
|
|
3379
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2223
3380
|
class: "cm-task"
|
|
2224
3381
|
}));
|
|
2225
3382
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2234,7 +3391,7 @@ var buildDecorations6 = (view) => {
|
|
|
2234
3391
|
};
|
|
2235
3392
|
var tasklist = (options = {}) => {
|
|
2236
3393
|
return [
|
|
2237
|
-
|
|
3394
|
+
ViewPlugin8.fromClass(class {
|
|
2238
3395
|
constructor(view) {
|
|
2239
3396
|
this.decorations = buildDecorations6(view);
|
|
2240
3397
|
}
|
|
@@ -2285,7 +3442,7 @@ var outliner = (options = {}) => {
|
|
|
2285
3442
|
};
|
|
2286
3443
|
|
|
2287
3444
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2288
|
-
import { keymap as
|
|
3445
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2289
3446
|
var defaultItems = [
|
|
2290
3447
|
"hello world!",
|
|
2291
3448
|
"this is a test.",
|
|
@@ -2295,7 +3452,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2295
3452
|
let t;
|
|
2296
3453
|
let idx = 0;
|
|
2297
3454
|
return [
|
|
2298
|
-
|
|
3455
|
+
keymap6.of([
|
|
2299
3456
|
{
|
|
2300
3457
|
// Reset.
|
|
2301
3458
|
key: "alt-meta-'",
|
|
@@ -2372,8 +3529,9 @@ var defaultTheme = {
|
|
|
2372
3529
|
outline: "none"
|
|
2373
3530
|
},
|
|
2374
3531
|
".cm-scroller": {
|
|
2375
|
-
overflow:
|
|
2376
|
-
fontFamily: get3(tokens, "fontFamily.mono", []).join(",")
|
|
3532
|
+
// overflow: 'visible',
|
|
3533
|
+
fontFamily: get3(tokens, "fontFamily.mono", []).join(","),
|
|
3534
|
+
lineHeight: 1.4
|
|
2377
3535
|
},
|
|
2378
3536
|
".cm-content": {
|
|
2379
3537
|
padding: 0,
|
|
@@ -2381,11 +3539,11 @@ var defaultTheme = {
|
|
|
2381
3539
|
fontSize: "16px"
|
|
2382
3540
|
},
|
|
2383
3541
|
"&light .cm-content": {
|
|
2384
|
-
color: get3(tokens, "extend.
|
|
3542
|
+
color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
2385
3543
|
caretColor: "black"
|
|
2386
3544
|
},
|
|
2387
3545
|
"&dark .cm-content": {
|
|
2388
|
-
color: get3(tokens, "extend.
|
|
3546
|
+
color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
2389
3547
|
caretColor: "white"
|
|
2390
3548
|
},
|
|
2391
3549
|
//
|
|
@@ -2397,8 +3555,11 @@ var defaultTheme = {
|
|
|
2397
3555
|
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
2398
3556
|
borderLeft: "2px solid white"
|
|
2399
3557
|
},
|
|
2400
|
-
".cm-placeholder": {
|
|
2401
|
-
|
|
3558
|
+
"&light .cm-placeholder": {
|
|
3559
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
3560
|
+
},
|
|
3561
|
+
"&dark .cm-placeholder": {
|
|
3562
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
2402
3563
|
},
|
|
2403
3564
|
//
|
|
2404
3565
|
// line
|
|
@@ -2407,7 +3568,7 @@ var defaultTheme = {
|
|
|
2407
3568
|
paddingInline: 0
|
|
2408
3569
|
},
|
|
2409
3570
|
".cm-activeLine": {
|
|
2410
|
-
background: "
|
|
3571
|
+
background: "transparent"
|
|
2411
3572
|
},
|
|
2412
3573
|
//
|
|
2413
3574
|
// Selection
|
|
@@ -2578,23 +3739,28 @@ var codeTheme = {
|
|
|
2578
3739
|
};
|
|
2579
3740
|
|
|
2580
3741
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2581
|
-
var
|
|
3742
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2582
3743
|
var EditorModes = [
|
|
2583
3744
|
"default",
|
|
2584
3745
|
"vim"
|
|
2585
3746
|
];
|
|
2586
3747
|
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2587
|
-
const tabsterDOMAttribute = useFocusableGroup({
|
|
2588
|
-
tabBehavior: "limited"
|
|
2589
|
-
});
|
|
2590
3748
|
const { themeMode } = useThemeContext();
|
|
2591
3749
|
const rootRef = useRef(null);
|
|
2592
|
-
const [view, setView] =
|
|
3750
|
+
const [view, setView] = useState2(null);
|
|
2593
3751
|
useImperativeHandle(forwardedRef, () => view, [
|
|
2594
3752
|
view
|
|
2595
3753
|
]);
|
|
2596
3754
|
useEffect2(() => {
|
|
2597
|
-
if (autoFocus) {
|
|
3755
|
+
if (autoFocus && !view?.hasFocus) {
|
|
3756
|
+
if (view?.state.selection.main?.from === 0) {
|
|
3757
|
+
const { to } = view.state.doc.lineAt(0);
|
|
3758
|
+
view?.dispatch({
|
|
3759
|
+
selection: {
|
|
3760
|
+
anchor: to
|
|
3761
|
+
}
|
|
3762
|
+
});
|
|
3763
|
+
}
|
|
2598
3764
|
view?.focus();
|
|
2599
3765
|
}
|
|
2600
3766
|
}, [
|
|
@@ -2610,37 +3776,38 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2610
3776
|
selection,
|
|
2611
3777
|
extensions: [
|
|
2612
3778
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2613
|
-
|
|
3779
|
+
EditorView14.exceptionSink.of((err) => {
|
|
2614
3780
|
log2.catch(err, void 0, {
|
|
2615
|
-
F:
|
|
2616
|
-
L:
|
|
3781
|
+
F: __dxlog_file3,
|
|
3782
|
+
L: 134,
|
|
2617
3783
|
S: void 0,
|
|
2618
3784
|
C: (f, a) => f(...a)
|
|
2619
3785
|
});
|
|
2620
3786
|
}),
|
|
2621
3787
|
// Theme.
|
|
2622
3788
|
// TODO(burdon): Make configurable.
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
3789
|
+
EditorView14.baseTheme(defaultTheme),
|
|
3790
|
+
EditorView14.theme(theme ?? {}),
|
|
3791
|
+
EditorView14.darkTheme.of(themeMode === "dark"),
|
|
3792
|
+
EditorView14.editorAttributes.of({
|
|
2627
3793
|
class: slots.editor?.className ?? ""
|
|
2628
3794
|
}),
|
|
2629
|
-
|
|
3795
|
+
EditorView14.contentAttributes.of({
|
|
2630
3796
|
class: slots.content?.className ?? ""
|
|
2631
3797
|
}),
|
|
2632
3798
|
// State.
|
|
3799
|
+
EditorView14.editable.of(!readonly),
|
|
2633
3800
|
EditorState2.readOnly.of(!!readonly),
|
|
2634
3801
|
// Storage and replication.
|
|
2635
3802
|
// NOTE: This must come before user extensions.
|
|
2636
3803
|
model.extension,
|
|
2637
|
-
// TODO(burdon): Factor out (
|
|
3804
|
+
// TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
|
|
2638
3805
|
editorMode === "vim" && vim(),
|
|
2639
3806
|
// Custom.
|
|
2640
3807
|
...extensions
|
|
2641
|
-
].filter(
|
|
3808
|
+
].filter(isNotFalsy3)
|
|
2642
3809
|
});
|
|
2643
|
-
const newView = new
|
|
3810
|
+
const newView = new EditorView14({
|
|
2644
3811
|
state,
|
|
2645
3812
|
parent: rootRef.current,
|
|
2646
3813
|
scrollTo,
|
|
@@ -2675,7 +3842,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2675
3842
|
}
|
|
2676
3843
|
case "Escape": {
|
|
2677
3844
|
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2678
|
-
|
|
3845
|
+
view?.focus();
|
|
2679
3846
|
}
|
|
2680
3847
|
break;
|
|
2681
3848
|
}
|
|
@@ -2688,9 +3855,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2688
3855
|
key: model.id,
|
|
2689
3856
|
role: "none",
|
|
2690
3857
|
tabIndex: 0,
|
|
2691
|
-
onKeyUp: handleKeyUp,
|
|
2692
3858
|
...slots.root,
|
|
2693
|
-
...editorMode !==
|
|
3859
|
+
// {...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
3860
|
+
onKeyUp: handleKeyUp,
|
|
2694
3861
|
ref: rootRef
|
|
2695
3862
|
});
|
|
2696
3863
|
});
|
|
@@ -2701,7 +3868,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
|
|
|
2701
3868
|
ref: forwardedRef,
|
|
2702
3869
|
readonly,
|
|
2703
3870
|
extensions: [
|
|
2704
|
-
|
|
3871
|
+
createBasicBundle({
|
|
2705
3872
|
themeMode,
|
|
2706
3873
|
placeholder: placeholder3,
|
|
2707
3874
|
lineWrapping
|
|
@@ -2720,7 +3887,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2720
3887
|
ref: forwardedRef,
|
|
2721
3888
|
readonly,
|
|
2722
3889
|
extensions: [
|
|
2723
|
-
|
|
3890
|
+
createMarkdownExtensions({
|
|
2724
3891
|
themeMode,
|
|
2725
3892
|
placeholder: placeholder3
|
|
2726
3893
|
}),
|
|
@@ -2733,11 +3900,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
|
|
|
2733
3900
|
});
|
|
2734
3901
|
var defaultSlots = {
|
|
2735
3902
|
root: {
|
|
2736
|
-
|
|
2737
|
-
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
3903
|
+
className: mx3("grow", focusRing)
|
|
2738
3904
|
},
|
|
2739
3905
|
editor: {
|
|
2740
|
-
className: "
|
|
3906
|
+
className: "bs-full"
|
|
2741
3907
|
}
|
|
2742
3908
|
};
|
|
2743
3909
|
var defaultTextSlots = {
|
|
@@ -2747,12 +3913,200 @@ var defaultMarkdownSlots = {
|
|
|
2747
3913
|
...defaultSlots
|
|
2748
3914
|
};
|
|
2749
3915
|
|
|
3916
|
+
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
3917
|
+
import { CaretRight, ChatText, Code, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextItalic } from "@phosphor-icons/react";
|
|
3918
|
+
import { createContext } from "@radix-ui/react-context";
|
|
3919
|
+
import React2 from "react";
|
|
3920
|
+
import { Button, DensityProvider, Select } from "@dxos/react-ui";
|
|
3921
|
+
import { getSize, mx as mx4 } from "@dxos/react-ui-theme";
|
|
3922
|
+
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
3923
|
+
var ToolbarRoot = ({ children, onAction, state }) => {
|
|
3924
|
+
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
3925
|
+
onAction,
|
|
3926
|
+
state
|
|
3927
|
+
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
3928
|
+
density: "fine"
|
|
3929
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
3930
|
+
role: "toolbar",
|
|
3931
|
+
className: "flex w-full shrink-0 p-1 gap-2 items-center whitespace-nowrap overflow-hidden"
|
|
3932
|
+
}, children)));
|
|
3933
|
+
};
|
|
3934
|
+
var ToolbarButton = ({ Icon, onClick, title, getState, disable }) => {
|
|
3935
|
+
const { onAction, state } = useToolbarContext("ToolbarButton");
|
|
3936
|
+
const active = getState && state ? getState(state) : false;
|
|
3937
|
+
const disabled = disable && state ? disable(state) : false;
|
|
3938
|
+
const handleClick = (event) => {
|
|
3939
|
+
const action = onClick(state);
|
|
3940
|
+
if (action) {
|
|
3941
|
+
onAction?.(action);
|
|
3942
|
+
event.preventDefault();
|
|
3943
|
+
}
|
|
3944
|
+
};
|
|
3945
|
+
return /* @__PURE__ */ React2.createElement(Button, {
|
|
3946
|
+
variant: "ghost",
|
|
3947
|
+
classNames: mx4("p-2", active && "ring-[1px]"),
|
|
3948
|
+
onMouseDown: handleClick,
|
|
3949
|
+
title,
|
|
3950
|
+
disabled
|
|
3951
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
3952
|
+
className: getSize(5)
|
|
3953
|
+
}));
|
|
3954
|
+
};
|
|
3955
|
+
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3956
|
+
className: "grow"
|
|
3957
|
+
});
|
|
3958
|
+
var MarkdownHeading = () => {
|
|
3959
|
+
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
|
3960
|
+
const blockType = state ? state.blockType : "paragraph";
|
|
3961
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
|
3962
|
+
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : null;
|
|
3963
|
+
return /* @__PURE__ */ React2.createElement(Select.Root, {
|
|
3964
|
+
disabled: value === null,
|
|
3965
|
+
value: value ?? "0",
|
|
3966
|
+
onValueChange: (value2) => onAction?.({
|
|
3967
|
+
type: "heading",
|
|
3968
|
+
data: parseInt(value2)
|
|
3969
|
+
})
|
|
3970
|
+
}, /* @__PURE__ */ React2.createElement(Select.TriggerButton, null, /* @__PURE__ */ React2.createElement(Paragraph, {
|
|
3971
|
+
className: getSize(5)
|
|
3972
|
+
})), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3973
|
+
value: "0"
|
|
3974
|
+
}, "Paragraph"), [
|
|
3975
|
+
1,
|
|
3976
|
+
2,
|
|
3977
|
+
3,
|
|
3978
|
+
4,
|
|
3979
|
+
5,
|
|
3980
|
+
6
|
|
3981
|
+
].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
|
|
3982
|
+
key: level,
|
|
3983
|
+
value: String(level)
|
|
3984
|
+
}, "Heading ", level))))));
|
|
3985
|
+
};
|
|
3986
|
+
var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
|
|
3987
|
+
role: "none"
|
|
3988
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3989
|
+
Icon: TextB,
|
|
3990
|
+
title: "String",
|
|
3991
|
+
disable: (s) => s.blockType === "codeblock",
|
|
3992
|
+
getState: (s) => s.strong,
|
|
3993
|
+
onClick: (s) => ({
|
|
3994
|
+
type: "strong",
|
|
3995
|
+
data: s ? !s.strong : null
|
|
3996
|
+
})
|
|
3997
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
3998
|
+
Icon: TextItalic,
|
|
3999
|
+
title: "Emphasis",
|
|
4000
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4001
|
+
getState: (s) => s.emphasis,
|
|
4002
|
+
onClick: (s) => ({
|
|
4003
|
+
type: "emphasis",
|
|
4004
|
+
data: s ? !s.emphasis : null
|
|
4005
|
+
})
|
|
4006
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4007
|
+
Icon: TextStrikethrough,
|
|
4008
|
+
title: "Strike-through",
|
|
4009
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4010
|
+
getState: (s) => s.strikethrough,
|
|
4011
|
+
onClick: (s) => ({
|
|
4012
|
+
type: "strikethrough",
|
|
4013
|
+
data: s ? !s.strikethrough : null
|
|
4014
|
+
})
|
|
4015
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4016
|
+
Icon: Code,
|
|
4017
|
+
title: "Inline code",
|
|
4018
|
+
disable: (s) => s.blockType === "codeblock",
|
|
4019
|
+
getState: (s) => s.code,
|
|
4020
|
+
onClick: (s) => ({
|
|
4021
|
+
type: "code",
|
|
4022
|
+
data: s ? !s.code : null
|
|
4023
|
+
})
|
|
4024
|
+
}));
|
|
4025
|
+
var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4026
|
+
role: "none"
|
|
4027
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4028
|
+
Icon: ListBullets,
|
|
4029
|
+
title: "Bullet list",
|
|
4030
|
+
getState: (s) => s.listStyle === "bullet",
|
|
4031
|
+
onClick: (s) => ({
|
|
4032
|
+
type: "list-bullet",
|
|
4033
|
+
data: s ? s.listStyle !== "bullet" : null
|
|
4034
|
+
})
|
|
4035
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4036
|
+
Icon: ListNumbers,
|
|
4037
|
+
title: "Numbered list",
|
|
4038
|
+
getState: (s) => s.listStyle === "ordered",
|
|
4039
|
+
onClick: (s) => ({
|
|
4040
|
+
type: "list-ordered",
|
|
4041
|
+
data: s ? s.listStyle !== "ordered" : null
|
|
4042
|
+
})
|
|
4043
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4044
|
+
Icon: ListChecks,
|
|
4045
|
+
title: "Task list",
|
|
4046
|
+
getState: (s) => s.listStyle === "task",
|
|
4047
|
+
onClick: (s) => ({
|
|
4048
|
+
type: "list-tasks",
|
|
4049
|
+
data: s ? s.listStyle !== "task" : null
|
|
4050
|
+
})
|
|
4051
|
+
}));
|
|
4052
|
+
var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4053
|
+
role: "none"
|
|
4054
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4055
|
+
Icon: CaretRight,
|
|
4056
|
+
title: "Block quote",
|
|
4057
|
+
getState: (s) => s.blockquote,
|
|
4058
|
+
onClick: (s) => ({
|
|
4059
|
+
type: "blockquote",
|
|
4060
|
+
data: s ? !s.blockquote : null
|
|
4061
|
+
})
|
|
4062
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4063
|
+
Icon: Code,
|
|
4064
|
+
title: "Code block",
|
|
4065
|
+
getState: (s) => s.blockType === "codeblock",
|
|
4066
|
+
onClick: (s) => ({
|
|
4067
|
+
type: "codeblock",
|
|
4068
|
+
data: s ? s.blockType !== "codeblock" : null
|
|
4069
|
+
})
|
|
4070
|
+
}), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4071
|
+
Icon: Table2,
|
|
4072
|
+
title: "Table",
|
|
4073
|
+
onClick: () => ({
|
|
4074
|
+
type: "table"
|
|
4075
|
+
})
|
|
4076
|
+
}));
|
|
4077
|
+
var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4078
|
+
role: "none"
|
|
4079
|
+
}, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4080
|
+
Icon: Link,
|
|
4081
|
+
title: "Link",
|
|
4082
|
+
getState: (s) => s.link,
|
|
4083
|
+
onClick: (s) => ({
|
|
4084
|
+
type: "link",
|
|
4085
|
+
data: s ? !s.link : null
|
|
4086
|
+
})
|
|
4087
|
+
}));
|
|
4088
|
+
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
|
|
4089
|
+
var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
|
|
4090
|
+
Icon: ChatText,
|
|
4091
|
+
title: "Create comment",
|
|
4092
|
+
onClick: () => ({
|
|
4093
|
+
type: "comment"
|
|
4094
|
+
})
|
|
4095
|
+
});
|
|
4096
|
+
var Toolbar = {
|
|
4097
|
+
Root: ToolbarRoot,
|
|
4098
|
+
Button: ToolbarButton,
|
|
4099
|
+
Separator: ToolbarSeparator,
|
|
4100
|
+
Markdown: MarkdownStandard,
|
|
4101
|
+
Extended: MarkdownExtended
|
|
4102
|
+
};
|
|
4103
|
+
|
|
2750
4104
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2751
4105
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2752
4106
|
import { Context as Context2 } from "@dxos/context";
|
|
2753
|
-
import { invariant as
|
|
4107
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2754
4108
|
import { log as log3 } from "@dxos/log";
|
|
2755
|
-
var
|
|
4109
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2756
4110
|
var DEBOUNCE_INTERVAL = 100;
|
|
2757
4111
|
var SpaceAwarenessProvider = class {
|
|
2758
4112
|
constructor(params) {
|
|
@@ -2792,7 +4146,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2792
4146
|
log3.debug("failed to query awareness", {
|
|
2793
4147
|
err
|
|
2794
4148
|
}, {
|
|
2795
|
-
F:
|
|
4149
|
+
F: __dxlog_file4,
|
|
2796
4150
|
L: 89,
|
|
2797
4151
|
S: this,
|
|
2798
4152
|
C: (f, a) => f(...a)
|
|
@@ -2808,8 +4162,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2808
4162
|
return Array.from(this._remoteStates.values());
|
|
2809
4163
|
}
|
|
2810
4164
|
update(position) {
|
|
2811
|
-
|
|
2812
|
-
F:
|
|
4165
|
+
invariant2(this._postTask, void 0, {
|
|
4166
|
+
F: __dxlog_file4,
|
|
2813
4167
|
L: 104,
|
|
2814
4168
|
S: this,
|
|
2815
4169
|
A: [
|
|
@@ -2825,8 +4179,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2825
4179
|
this._postTask.schedule();
|
|
2826
4180
|
}
|
|
2827
4181
|
_handleQueryMessage() {
|
|
2828
|
-
|
|
2829
|
-
F:
|
|
4182
|
+
invariant2(this._postTask, void 0, {
|
|
4183
|
+
F: __dxlog_file4,
|
|
2830
4184
|
L: 115,
|
|
2831
4185
|
S: this,
|
|
2832
4186
|
A: [
|
|
@@ -2837,8 +4191,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2837
4191
|
this._postTask.schedule();
|
|
2838
4192
|
}
|
|
2839
4193
|
_handlePostMessage(message) {
|
|
2840
|
-
|
|
2841
|
-
F:
|
|
4194
|
+
invariant2(message.kind === "post", void 0, {
|
|
4195
|
+
F: __dxlog_file4,
|
|
2842
4196
|
L: 120,
|
|
2843
4197
|
S: this,
|
|
2844
4198
|
A: [
|
|
@@ -2858,10 +4212,58 @@ var modelState = StateField5.define({
|
|
|
2858
4212
|
update: (model) => model
|
|
2859
4213
|
});
|
|
2860
4214
|
|
|
2861
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
4215
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4216
|
+
var useActionHandler = (view) => {
|
|
4217
|
+
return (action) => {
|
|
4218
|
+
if (!view) {
|
|
4219
|
+
return;
|
|
4220
|
+
}
|
|
4221
|
+
let inlineType, listType;
|
|
4222
|
+
switch (action.type) {
|
|
4223
|
+
case "heading":
|
|
4224
|
+
setHeading(parseInt(action.data))(view);
|
|
4225
|
+
break;
|
|
4226
|
+
case "strong":
|
|
4227
|
+
case "emphasis":
|
|
4228
|
+
case "strikethrough":
|
|
4229
|
+
case "code":
|
|
4230
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
4231
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
4232
|
+
break;
|
|
4233
|
+
case "list-ordered":
|
|
4234
|
+
case "list-bullet":
|
|
4235
|
+
case "list-tasks":
|
|
4236
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
4237
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
4238
|
+
break;
|
|
4239
|
+
case "blockquote":
|
|
4240
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
4241
|
+
break;
|
|
4242
|
+
case "codeblock":
|
|
4243
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
4244
|
+
break;
|
|
4245
|
+
case "table":
|
|
4246
|
+
insertTable(view);
|
|
4247
|
+
break;
|
|
4248
|
+
case "link":
|
|
4249
|
+
(action.data === false ? removeLink : addLink)(view);
|
|
4250
|
+
break;
|
|
4251
|
+
case "comment":
|
|
4252
|
+
createComment(view);
|
|
4253
|
+
break;
|
|
4254
|
+
}
|
|
4255
|
+
setTimeout(() => {
|
|
4256
|
+
if (!view.hasFocus) {
|
|
4257
|
+
view.focus();
|
|
4258
|
+
}
|
|
4259
|
+
});
|
|
4260
|
+
};
|
|
4261
|
+
};
|
|
4262
|
+
|
|
4263
|
+
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
4264
|
+
import { useState as useState3 } from "react";
|
|
4265
|
+
var useEditorView = () => {
|
|
4266
|
+
const [view, setView] = useState3(null);
|
|
2865
4267
|
return [
|
|
2866
4268
|
(ref) => {
|
|
2867
4269
|
setView(ref);
|
|
@@ -2870,29 +4272,144 @@ var useTextEditor = () => {
|
|
|
2870
4272
|
];
|
|
2871
4273
|
};
|
|
2872
4274
|
|
|
4275
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4276
|
+
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4277
|
+
import { EditorView as EditorView15 } from "@codemirror/view";
|
|
4278
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
|
|
4279
|
+
import { log as log4 } from "@dxos/log";
|
|
4280
|
+
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
4281
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4282
|
+
var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}) => {
|
|
4283
|
+
const onUpdate = useRef2();
|
|
4284
|
+
const [view, setView] = useState4();
|
|
4285
|
+
const parentRef = useRef2(null);
|
|
4286
|
+
useEffect3(() => {
|
|
4287
|
+
if (parentRef.current) {
|
|
4288
|
+
const state = EditorState3.create({
|
|
4289
|
+
doc,
|
|
4290
|
+
selection,
|
|
4291
|
+
extensions: [
|
|
4292
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4293
|
+
EditorView15.exceptionSink.of((err) => {
|
|
4294
|
+
log4.catch(err, void 0, {
|
|
4295
|
+
F: __dxlog_file5,
|
|
4296
|
+
L: 57,
|
|
4297
|
+
S: void 0,
|
|
4298
|
+
C: (f, a) => f(...a)
|
|
4299
|
+
});
|
|
4300
|
+
}),
|
|
4301
|
+
extensions,
|
|
4302
|
+
EditorView15.updateListener.of(() => {
|
|
4303
|
+
onUpdate.current?.();
|
|
4304
|
+
})
|
|
4305
|
+
].filter(isNotFalsy4)
|
|
4306
|
+
});
|
|
4307
|
+
const view2 = new EditorView15({
|
|
4308
|
+
parent: parentRef.current,
|
|
4309
|
+
scrollTo,
|
|
4310
|
+
state,
|
|
4311
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4312
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4313
|
+
dispatchTransactions: (trs, view3) => {
|
|
4314
|
+
if (debug) {
|
|
4315
|
+
logChanges(trs);
|
|
4316
|
+
}
|
|
4317
|
+
view3.update(trs);
|
|
4318
|
+
}
|
|
4319
|
+
});
|
|
4320
|
+
setView(view2);
|
|
4321
|
+
}
|
|
4322
|
+
return () => {
|
|
4323
|
+
view?.destroy();
|
|
4324
|
+
};
|
|
4325
|
+
}, [
|
|
4326
|
+
parentRef
|
|
4327
|
+
]);
|
|
4328
|
+
useEffect3(() => {
|
|
4329
|
+
if (view) {
|
|
4330
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
4331
|
+
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4332
|
+
}
|
|
4333
|
+
if (selection || scrollTo) {
|
|
4334
|
+
onUpdate.current = () => {
|
|
4335
|
+
onUpdate.current = void 0;
|
|
4336
|
+
view.dispatch({
|
|
4337
|
+
selection,
|
|
4338
|
+
effects: scrollTo && [
|
|
4339
|
+
scrollTo
|
|
4340
|
+
],
|
|
4341
|
+
scrollIntoView: !scrollTo
|
|
4342
|
+
});
|
|
4343
|
+
};
|
|
4344
|
+
}
|
|
4345
|
+
if (autoFocus) {
|
|
4346
|
+
view.focus();
|
|
4347
|
+
}
|
|
4348
|
+
}
|
|
4349
|
+
}, [
|
|
4350
|
+
view,
|
|
4351
|
+
autoFocus,
|
|
4352
|
+
selection,
|
|
4353
|
+
scrollTo
|
|
4354
|
+
]);
|
|
4355
|
+
return {
|
|
4356
|
+
parentRef,
|
|
4357
|
+
view
|
|
4358
|
+
};
|
|
4359
|
+
};
|
|
4360
|
+
var createDataExtensions = ({ readonly = false } = {}) => {
|
|
4361
|
+
return [
|
|
4362
|
+
//
|
|
4363
|
+
EditorState3.readOnly.of(readonly),
|
|
4364
|
+
EditorView15.editable.of(!readonly)
|
|
4365
|
+
];
|
|
4366
|
+
};
|
|
4367
|
+
var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
|
|
4368
|
+
return [
|
|
4369
|
+
//
|
|
4370
|
+
EditorView15.baseTheme(defaultTheme),
|
|
4371
|
+
theme && EditorView15.theme(theme),
|
|
4372
|
+
EditorView15.darkTheme.of(themeMode === "dark"),
|
|
4373
|
+
EditorView15.editorAttributes.of({
|
|
4374
|
+
class: slots?.editor?.className ?? ""
|
|
4375
|
+
}),
|
|
4376
|
+
EditorView15.contentAttributes.of({
|
|
4377
|
+
class: slots?.content?.className ?? ""
|
|
4378
|
+
})
|
|
4379
|
+
].filter(isNotFalsy4);
|
|
4380
|
+
};
|
|
4381
|
+
|
|
2873
4382
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2874
4383
|
import get4 from "lodash.get";
|
|
2875
|
-
import { useEffect as
|
|
4384
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
2876
4385
|
import { generateName } from "@dxos/display-name";
|
|
2877
4386
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2878
|
-
import { invariant as
|
|
4387
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2879
4388
|
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2880
|
-
|
|
2881
|
-
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
4389
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2882
4390
|
var useTextModel = (props) => {
|
|
2883
4391
|
const { identity, space, text } = props;
|
|
2884
|
-
const [model, setModel] =
|
|
2885
|
-
|
|
4392
|
+
const [model, setModel] = useState5();
|
|
4393
|
+
useEffect4(() => setModel(createModel(props)), [
|
|
2886
4394
|
identity,
|
|
2887
4395
|
space,
|
|
2888
4396
|
text
|
|
2889
4397
|
]);
|
|
2890
4398
|
return model;
|
|
2891
4399
|
};
|
|
4400
|
+
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4401
|
+
const [content, setContent] = useState5(defaultContent ?? "");
|
|
4402
|
+
return {
|
|
4403
|
+
id,
|
|
4404
|
+
content,
|
|
4405
|
+
setContent,
|
|
4406
|
+
text: () => content
|
|
4407
|
+
};
|
|
4408
|
+
};
|
|
2892
4409
|
var createModel = ({ space, identity, text }) => {
|
|
2893
|
-
|
|
2894
|
-
F:
|
|
2895
|
-
L:
|
|
4410
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
4411
|
+
F: __dxlog_file6,
|
|
4412
|
+
L: 50,
|
|
2896
4413
|
S: void 0,
|
|
2897
4414
|
A: [
|
|
2898
4415
|
"isAutomergeObject(text)",
|
|
@@ -2903,7 +4420,7 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2903
4420
|
const doc = getRawDoc(obj, [
|
|
2904
4421
|
obj.field
|
|
2905
4422
|
]);
|
|
2906
|
-
const
|
|
4423
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
2907
4424
|
space,
|
|
2908
4425
|
channel: `automerge.awareness.${obj.id}`,
|
|
2909
4426
|
info: {
|
|
@@ -2913,19 +4430,22 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2913
4430
|
},
|
|
2914
4431
|
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2915
4432
|
});
|
|
4433
|
+
const extensions = [
|
|
4434
|
+
//
|
|
4435
|
+
modelState.init(() => model),
|
|
4436
|
+
automerge({
|
|
4437
|
+
handle: doc.handle,
|
|
4438
|
+
path: doc.path
|
|
4439
|
+
})
|
|
4440
|
+
];
|
|
4441
|
+
if (awarenessProvider2) {
|
|
4442
|
+
extensions.push(awareness(awarenessProvider2));
|
|
4443
|
+
}
|
|
2916
4444
|
const model = {
|
|
2917
4445
|
id: obj.id,
|
|
2918
4446
|
content: doc,
|
|
2919
4447
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
2920
|
-
extension:
|
|
2921
|
-
modelState.init(() => model),
|
|
2922
|
-
automerge3({
|
|
2923
|
-
handle: doc.handle,
|
|
2924
|
-
path: doc.path
|
|
2925
|
-
}),
|
|
2926
|
-
awarenessProvider && AwarenessProvider.of(awarenessProvider),
|
|
2927
|
-
awareness()
|
|
2928
|
-
].filter(isNotNullOrUndefined),
|
|
4448
|
+
extension: extensions,
|
|
2929
4449
|
peer: identity ? {
|
|
2930
4450
|
id: identity.identityKey.toHex(),
|
|
2931
4451
|
name: identity.profile?.displayName
|
|
@@ -2934,40 +4454,57 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2934
4454
|
return model;
|
|
2935
4455
|
};
|
|
2936
4456
|
export {
|
|
2937
|
-
AwarenessProvider,
|
|
2938
4457
|
BaseTextEditor,
|
|
2939
4458
|
Cursor,
|
|
2940
4459
|
Doc,
|
|
2941
4460
|
EditorModes,
|
|
4461
|
+
Inline,
|
|
4462
|
+
List,
|
|
2942
4463
|
MarkdownEditor,
|
|
2943
4464
|
RemoteSelectionsDecorator,
|
|
2944
4465
|
SpaceAwarenessProvider,
|
|
2945
4466
|
TextEditor,
|
|
2946
4467
|
TextKind,
|
|
4468
|
+
Toolbar,
|
|
2947
4469
|
YText,
|
|
2948
4470
|
YXmlFragment,
|
|
4471
|
+
addBlockquote,
|
|
4472
|
+
addCodeblock,
|
|
4473
|
+
addLink,
|
|
4474
|
+
addList,
|
|
4475
|
+
addStyle,
|
|
2949
4476
|
autocomplete,
|
|
2950
|
-
|
|
4477
|
+
automerge,
|
|
2951
4478
|
awareness,
|
|
2952
|
-
|
|
4479
|
+
awarenessProvider,
|
|
2953
4480
|
blast,
|
|
2954
4481
|
callbackWrapper,
|
|
2955
4482
|
code2 as code,
|
|
2956
4483
|
codeTheme,
|
|
2957
4484
|
comments,
|
|
4485
|
+
compareFormatting,
|
|
4486
|
+
createBasicBundle,
|
|
4487
|
+
createComment,
|
|
4488
|
+
createDataExtensions,
|
|
4489
|
+
createMarkdownExtensions,
|
|
4490
|
+
createThemeExtensions,
|
|
2958
4491
|
defaultMarkdownSlots,
|
|
2959
4492
|
defaultOptions,
|
|
2960
4493
|
defaultSlots,
|
|
2961
4494
|
defaultTextSlots,
|
|
2962
4495
|
defaultTheme,
|
|
4496
|
+
focusComment,
|
|
4497
|
+
formatting,
|
|
4498
|
+
getFormatting,
|
|
2963
4499
|
getToken,
|
|
2964
4500
|
heading2 as heading,
|
|
2965
4501
|
hr,
|
|
2966
4502
|
image,
|
|
4503
|
+
insertTable,
|
|
4504
|
+
keymap7 as keymap,
|
|
2967
4505
|
link,
|
|
2968
4506
|
listener,
|
|
2969
4507
|
logChanges,
|
|
2970
|
-
markdownBundle,
|
|
2971
4508
|
markdownHighlightStyle,
|
|
2972
4509
|
markdownTags,
|
|
2973
4510
|
markdownTagsExtensions,
|
|
@@ -2975,16 +4512,36 @@ export {
|
|
|
2975
4512
|
mention,
|
|
2976
4513
|
modelState,
|
|
2977
4514
|
outliner,
|
|
4515
|
+
removeBlockquote,
|
|
4516
|
+
removeCodeblock,
|
|
4517
|
+
removeLink,
|
|
4518
|
+
removeList,
|
|
4519
|
+
removeStyle,
|
|
4520
|
+
setBlockquote,
|
|
2978
4521
|
setComments,
|
|
2979
|
-
|
|
4522
|
+
setHeading,
|
|
2980
4523
|
setSelection,
|
|
4524
|
+
setStyle,
|
|
2981
4525
|
table,
|
|
2982
4526
|
tags2 as tags,
|
|
2983
4527
|
tasklist,
|
|
2984
4528
|
textTheme,
|
|
4529
|
+
toggleBlockquote,
|
|
4530
|
+
toggleCodeblock,
|
|
4531
|
+
toggleEmphasis,
|
|
4532
|
+
toggleInlineCode,
|
|
4533
|
+
toggleList,
|
|
4534
|
+
toggleStrikethrough,
|
|
4535
|
+
toggleStrong,
|
|
4536
|
+
toggleStyle,
|
|
2985
4537
|
typewriter,
|
|
4538
|
+
useActionHandler,
|
|
2986
4539
|
useComments,
|
|
4540
|
+
useEditorView,
|
|
4541
|
+
useFormattingState,
|
|
4542
|
+
useInMemoryTextModel,
|
|
2987
4543
|
useTextEditor,
|
|
2988
|
-
useTextModel
|
|
4544
|
+
useTextModel,
|
|
4545
|
+
useToolbarContext
|
|
2989
4546
|
};
|
|
2990
4547
|
//# sourceMappingURL=index.mjs.map
|