@dxos/react-ui-editor 0.3.11-main.c95bc86 → 0.3.11-main.cb8120f
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 +434 -210
- 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.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +9 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +14 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- 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/comments.d.ts +5 -1
- package/dist/types/src/extensions/comments.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 +11 -0
- package/dist/types/src/extensions/markdown/formatting.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 +1 -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/useTextModel.d.ts.map +1 -1
- package/package.json +36 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +8 -13
- package/src/components/TextEditor/TextEditor.tsx +3 -1
- package/src/components/Toolbar/Toolbar.stories.tsx +86 -0
- package/src/components/Toolbar/Toolbar.tsx +115 -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 +3 -3
- package/src/extensions/comments.ts +112 -64
- package/src/extensions/markdown/code.ts +24 -9
- package/src/extensions/markdown/formatting.ts +159 -0
- package/src/extensions/markdown/heading.ts +1 -1
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/markdown/link.ts +4 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useActionHandler.ts +45 -0
- package/src/hooks/useTextModel.ts +11 -8
- package/src/themes/default.ts +1 -1
|
@@ -15,6 +15,7 @@ import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeH
|
|
|
15
15
|
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
17
|
import { attentionSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
|
+
import { nonNullable as nonNullable2 } 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 t = [];
|
|
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
|
+
t.push({
|
|
132
|
+
fromA,
|
|
133
|
+
toA,
|
|
134
|
+
insert
|
|
135
|
+
});
|
|
128
136
|
});
|
|
129
137
|
}
|
|
138
|
+
t.reverse().forEach(({ fromA, toA, insert }) => {
|
|
139
|
+
A2.splice(doc, path.slice(), fromA, toA - fromA, 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({
|
|
@@ -640,8 +653,8 @@ var basicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true }
|
|
|
640
653
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
641
654
|
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
642
655
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
643
|
-
import { invariant
|
|
644
|
-
var
|
|
656
|
+
import { invariant } from "@dxos/invariant";
|
|
657
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
645
658
|
var defaultOptions = {
|
|
646
659
|
effect: 2,
|
|
647
660
|
maxParticles: 200,
|
|
@@ -767,8 +780,8 @@ var Blaster = class {
|
|
|
767
780
|
return this._node;
|
|
768
781
|
}
|
|
769
782
|
initialize() {
|
|
770
|
-
|
|
771
|
-
F:
|
|
783
|
+
invariant(!this._canvas && !this._ctx, void 0, {
|
|
784
|
+
F: __dxlog_file,
|
|
772
785
|
L: 138,
|
|
773
786
|
S: this,
|
|
774
787
|
A: [
|
|
@@ -804,8 +817,8 @@ var Blaster = class {
|
|
|
804
817
|
}
|
|
805
818
|
}
|
|
806
819
|
start() {
|
|
807
|
-
|
|
808
|
-
F:
|
|
820
|
+
invariant(this._canvas && this._ctx, void 0, {
|
|
821
|
+
F: __dxlog_file,
|
|
809
822
|
L: 177,
|
|
810
823
|
S: this,
|
|
811
824
|
A: [
|
|
@@ -948,12 +961,12 @@ var random = (min, max) => {
|
|
|
948
961
|
};
|
|
949
962
|
|
|
950
963
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
-
import {
|
|
964
|
+
import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
|
|
965
|
+
import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
966
|
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
967
|
import sortBy from "lodash.sortby";
|
|
954
968
|
import { useEffect } from "react";
|
|
955
969
|
import { debounce } from "@dxos/async";
|
|
956
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
970
|
import { nonNullable } from "@dxos/util";
|
|
958
971
|
|
|
959
972
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
@@ -1025,13 +1038,13 @@ var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue)
|
|
|
1025
1038
|
|
|
1026
1039
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1027
1040
|
import { log } from "@dxos/log";
|
|
1028
|
-
var
|
|
1041
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1029
1042
|
var callbackWrapper = (fn) => (...args) => {
|
|
1030
1043
|
try {
|
|
1031
1044
|
return fn(...args);
|
|
1032
1045
|
} catch (err) {
|
|
1033
1046
|
log.catch(err, void 0, {
|
|
1034
|
-
F:
|
|
1047
|
+
F: __dxlog_file2,
|
|
1035
1048
|
L: 18,
|
|
1036
1049
|
S: void 0,
|
|
1037
1050
|
C: (f, a) => f(...a)
|
|
@@ -1059,7 +1072,6 @@ var logChanges = (trs) => {
|
|
|
1059
1072
|
};
|
|
1060
1073
|
|
|
1061
1074
|
// 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
1075
|
var styles2 = EditorView5.baseTheme({
|
|
1064
1076
|
"& .cm-comment": {
|
|
1065
1077
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
@@ -1068,14 +1080,12 @@ var styles2 = EditorView5.baseTheme({
|
|
|
1068
1080
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1069
1081
|
}
|
|
1070
1082
|
});
|
|
1071
|
-
var
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
})
|
|
1078
|
-
};
|
|
1083
|
+
var commentMark = Decoration2.mark({
|
|
1084
|
+
class: "cm-comment"
|
|
1085
|
+
});
|
|
1086
|
+
var commentCurrentMark = Decoration2.mark({
|
|
1087
|
+
class: "cm-comment-current"
|
|
1088
|
+
});
|
|
1079
1089
|
var setFocus = (view, id, center = true) => {
|
|
1080
1090
|
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1081
1091
|
if (!comment?.comment.cursor) {
|
|
@@ -1138,7 +1148,7 @@ var commentsState = StateField2.define({
|
|
|
1138
1148
|
return value;
|
|
1139
1149
|
}
|
|
1140
1150
|
});
|
|
1141
|
-
var
|
|
1151
|
+
var commentsDecorations = EditorView5.decorations.compute([
|
|
1142
1152
|
commentsState
|
|
1143
1153
|
], (state) => {
|
|
1144
1154
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
@@ -1149,9 +1159,9 @@ var highlightDecorations = EditorView5.decorations.compute([
|
|
|
1149
1159
|
return void 0;
|
|
1150
1160
|
}
|
|
1151
1161
|
if (comment.comment.id === current) {
|
|
1152
|
-
return
|
|
1162
|
+
return commentCurrentMark.range(range.from, range.to);
|
|
1153
1163
|
} else {
|
|
1154
|
-
return
|
|
1164
|
+
return commentMark.range(range.from, range.to);
|
|
1155
1165
|
}
|
|
1156
1166
|
}).filter(nonNullable);
|
|
1157
1167
|
return Decoration2.set(decorations);
|
|
@@ -1180,84 +1190,124 @@ var trackPastedComments = (onUpdate) => {
|
|
|
1180
1190
|
cut: handleTrack,
|
|
1181
1191
|
copy: handleTrack
|
|
1182
1192
|
}),
|
|
1183
|
-
//
|
|
1184
|
-
|
|
1193
|
+
// Track deleted comments.
|
|
1194
|
+
invertedEffects2.of((tr) => {
|
|
1195
|
+
const { comments: comments2 } = tr.startState.field(commentsState);
|
|
1196
|
+
const effects = [];
|
|
1197
|
+
tr.changes.iterChangedRanges((fromA, toA) => {
|
|
1198
|
+
for (const { comment: { id }, range: { from, to } } of comments2) {
|
|
1199
|
+
if (from < to && from >= fromA && to <= toA) {
|
|
1200
|
+
effects.push(restoreCommentEffect.of({
|
|
1201
|
+
id,
|
|
1202
|
+
from,
|
|
1203
|
+
to
|
|
1204
|
+
}));
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
return effects;
|
|
1209
|
+
}),
|
|
1210
|
+
// Handle paste or the undo of comment deletion.
|
|
1211
|
+
EditorView5.updateListener.of((update2) => {
|
|
1212
|
+
const restore = [];
|
|
1213
|
+
for (let i = 0; i < update2.transactions.length; i++) {
|
|
1214
|
+
const tr = update2.transactions[i];
|
|
1215
|
+
for (let j = 0; j < restore.length; j++) {
|
|
1216
|
+
restore[j] = mapTrackedComment(restore[j], tr.changes);
|
|
1217
|
+
}
|
|
1218
|
+
for (const effect of tr.effects) {
|
|
1219
|
+
if (effect.is(restoreCommentEffect)) {
|
|
1220
|
+
restore.push(effect.value);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1185
1224
|
if (tracked) {
|
|
1186
|
-
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1225
|
+
const paste = update2.transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1187
1226
|
if (paste) {
|
|
1188
1227
|
let found = -1;
|
|
1189
1228
|
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1190
1229
|
if (text.eq(tracked.text)) {
|
|
1191
|
-
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1192
|
-
fromB = transactions[i].changes.mapPos(fromB);
|
|
1230
|
+
for (let i = update2.transactions.indexOf(paste) + 1; i < update2.transactions.length; i++) {
|
|
1231
|
+
fromB = update2.transactions[i].changes.mapPos(fromB);
|
|
1193
1232
|
}
|
|
1194
1233
|
found = fromB;
|
|
1195
1234
|
}
|
|
1196
1235
|
});
|
|
1197
1236
|
if (found > -1) {
|
|
1198
1237
|
for (const moved of tracked.comments) {
|
|
1199
|
-
|
|
1238
|
+
restore.push({
|
|
1239
|
+
id: moved.id,
|
|
1200
1240
|
from: found + moved.from,
|
|
1201
1241
|
to: found + moved.to
|
|
1202
|
-
};
|
|
1203
|
-
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1204
|
-
onUpdate(moved.id, cursor);
|
|
1242
|
+
});
|
|
1205
1243
|
}
|
|
1206
1244
|
}
|
|
1207
1245
|
tracked = null;
|
|
1208
1246
|
}
|
|
1209
1247
|
}
|
|
1248
|
+
for (const comment of restore) {
|
|
1249
|
+
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
1250
|
+
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
1251
|
+
if (!exists) {
|
|
1252
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
1253
|
+
onUpdate(comment.id, cursor);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1210
1256
|
})
|
|
1211
1257
|
];
|
|
1212
1258
|
};
|
|
1213
|
-
var
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1259
|
+
var mapTrackedComment = (comment, changes) => ({
|
|
1260
|
+
id: comment.id,
|
|
1261
|
+
from: changes.mapPos(comment.from, 1),
|
|
1262
|
+
to: changes.mapPos(comment.to, 1)
|
|
1263
|
+
});
|
|
1264
|
+
var restoreCommentEffect = StateEffect2.define({
|
|
1265
|
+
map: mapTrackedComment
|
|
1266
|
+
});
|
|
1267
|
+
var optionsFacet = Facet3.define({
|
|
1268
|
+
combine: (providers) => providers[0]
|
|
1269
|
+
});
|
|
1270
|
+
var createComment = (view) => {
|
|
1271
|
+
const options = view.state.facet(optionsFacet);
|
|
1272
|
+
const { from, to } = view.state.selection.main;
|
|
1273
|
+
if (from === to) {
|
|
1274
|
+
return false;
|
|
1275
|
+
}
|
|
1276
|
+
if (to === view.state.doc.length) {
|
|
1277
|
+
view.dispatch({
|
|
1278
|
+
changes: {
|
|
1279
|
+
from: to,
|
|
1280
|
+
insert: "\n"
|
|
1281
|
+
}
|
|
1225
1282
|
});
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1283
|
+
}
|
|
1284
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1285
|
+
from,
|
|
1286
|
+
to
|
|
1287
|
+
});
|
|
1288
|
+
if (cursor) {
|
|
1289
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1290
|
+
if (id) {
|
|
1231
1291
|
view.dispatch({
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1292
|
+
effects: setSelection.of({
|
|
1293
|
+
current: id
|
|
1294
|
+
}),
|
|
1295
|
+
selection: {
|
|
1296
|
+
anchor: from
|
|
1235
1297
|
}
|
|
1236
1298
|
});
|
|
1299
|
+
return true;
|
|
1237
1300
|
}
|
|
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
|
-
};
|
|
1301
|
+
}
|
|
1302
|
+
return false;
|
|
1303
|
+
};
|
|
1304
|
+
var comments = (options = {}) => {
|
|
1305
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1306
|
+
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1258
1307
|
return [
|
|
1308
|
+
optionsFacet.of(options),
|
|
1259
1309
|
commentsState,
|
|
1260
|
-
|
|
1310
|
+
commentsDecorations,
|
|
1261
1311
|
styles2,
|
|
1262
1312
|
//
|
|
1263
1313
|
// Keymap.
|
|
@@ -1265,7 +1315,7 @@ var comments = (options = {}) => {
|
|
|
1265
1315
|
options.onCreate ? keymap3.of([
|
|
1266
1316
|
{
|
|
1267
1317
|
key: shortcut,
|
|
1268
|
-
run: callbackWrapper(
|
|
1318
|
+
run: callbackWrapper(createComment)
|
|
1269
1319
|
}
|
|
1270
1320
|
]) : [],
|
|
1271
1321
|
//
|
|
@@ -1657,21 +1707,37 @@ var styles3 = EditorView8.baseTheme({
|
|
|
1657
1707
|
},
|
|
1658
1708
|
"& .cm-codeblock": {
|
|
1659
1709
|
display: "inline-block",
|
|
1660
|
-
width: "100%"
|
|
1710
|
+
width: "100%",
|
|
1711
|
+
position: "relative",
|
|
1712
|
+
"&::after": {
|
|
1713
|
+
content: '""',
|
|
1714
|
+
position: "absolute",
|
|
1715
|
+
inset: 0
|
|
1716
|
+
}
|
|
1661
1717
|
},
|
|
1662
|
-
"&light .cm-codeblock
|
|
1663
|
-
|
|
1718
|
+
"&light .cm-codeblock": {
|
|
1719
|
+
"&::after": {
|
|
1720
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
1721
|
+
mixBlendMode: "darken"
|
|
1722
|
+
}
|
|
1664
1723
|
},
|
|
1665
|
-
"&dark .cm-codeblock
|
|
1666
|
-
|
|
1724
|
+
"&dark .cm-codeblock": {
|
|
1725
|
+
"&::after": {
|
|
1726
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
1727
|
+
mixBlendMode: "lighten"
|
|
1728
|
+
}
|
|
1667
1729
|
},
|
|
1668
1730
|
"& .cm-codeblock-first": {
|
|
1669
|
-
|
|
1670
|
-
|
|
1731
|
+
"&::after": {
|
|
1732
|
+
borderTopLeftRadius: ".5rem",
|
|
1733
|
+
borderTopRightRadius: ".5rem"
|
|
1734
|
+
}
|
|
1671
1735
|
},
|
|
1672
1736
|
"& .cm-codeblock-last": {
|
|
1673
|
-
|
|
1674
|
-
|
|
1737
|
+
"&::after": {
|
|
1738
|
+
borderBottomLeftRadius: ".5rem",
|
|
1739
|
+
borderBottomRightRadius: ".5rem"
|
|
1740
|
+
}
|
|
1675
1741
|
}
|
|
1676
1742
|
});
|
|
1677
1743
|
var getLineRange = (lines, from, to) => {
|
|
@@ -1743,16 +1809,130 @@ var code2 = () => {
|
|
|
1743
1809
|
];
|
|
1744
1810
|
};
|
|
1745
1811
|
|
|
1746
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/
|
|
1812
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
1747
1813
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1748
1814
|
import { RangeSetBuilder as RangeSetBuilder2 } from "@codemirror/state";
|
|
1749
|
-
import { Decoration as Decoration4, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1815
|
+
import { Decoration as Decoration4, keymap as keymap5, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
1816
|
+
var setHeading = (level) => (view) => {
|
|
1817
|
+
const { selection: { ranges }, doc } = view.state;
|
|
1818
|
+
const changes = [];
|
|
1819
|
+
for (const range of ranges) {
|
|
1820
|
+
const { number } = doc.lineAt(range.anchor);
|
|
1821
|
+
const { from } = doc.line(number);
|
|
1822
|
+
const line = doc.sliceString(from, from + 7);
|
|
1823
|
+
const [_, marks, spaces] = line.match(/(#+)(\s+)/) ?? [];
|
|
1824
|
+
const current = marks?.length ?? 0;
|
|
1825
|
+
if (level !== current) {
|
|
1826
|
+
changes.push({
|
|
1827
|
+
from,
|
|
1828
|
+
to: from + current + (spaces?.length ?? 0),
|
|
1829
|
+
insert: "#".repeat(level) + (level > 0 ? " " : "")
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
if (changes.length) {
|
|
1834
|
+
view.dispatch({
|
|
1835
|
+
changes
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
return true;
|
|
1839
|
+
};
|
|
1840
|
+
var toggleStyle = (mark2) => (view) => {
|
|
1841
|
+
const { ranges } = view.state.selection;
|
|
1842
|
+
for (const range of ranges) {
|
|
1843
|
+
if (range.from === range.to) {
|
|
1844
|
+
return false;
|
|
1845
|
+
}
|
|
1846
|
+
view.dispatch({
|
|
1847
|
+
changes: [
|
|
1848
|
+
{
|
|
1849
|
+
from: range.from,
|
|
1850
|
+
insert: mark2
|
|
1851
|
+
},
|
|
1852
|
+
{
|
|
1853
|
+
from: range.to,
|
|
1854
|
+
insert: mark2
|
|
1855
|
+
}
|
|
1856
|
+
]
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
return true;
|
|
1860
|
+
};
|
|
1861
|
+
var toggleBold = toggleStyle("**");
|
|
1862
|
+
var toggleItalic = toggleStyle("_");
|
|
1863
|
+
var toggleStrikethrough = toggleStyle("~~");
|
|
1864
|
+
var toggleList = (view) => {
|
|
1865
|
+
};
|
|
1866
|
+
var formatting = (options = {}) => {
|
|
1867
|
+
return [
|
|
1868
|
+
keymap5.of([
|
|
1869
|
+
{
|
|
1870
|
+
key: "meta-b",
|
|
1871
|
+
run: toggleBold
|
|
1872
|
+
}
|
|
1873
|
+
]),
|
|
1874
|
+
styling()
|
|
1875
|
+
];
|
|
1876
|
+
};
|
|
1877
|
+
var styling = () => {
|
|
1878
|
+
const buildDecorations7 = (view) => {
|
|
1879
|
+
const builder = new RangeSetBuilder2();
|
|
1880
|
+
const { state } = view;
|
|
1881
|
+
const cursor = state.selection.main.head;
|
|
1882
|
+
const replace = (node, marks) => {
|
|
1883
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1884
|
+
for (const mark2 of marks) {
|
|
1885
|
+
builder.add(mark2.from, mark2.to, Decoration4.replace({}));
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1890
|
+
syntaxTree2(state).iterate({
|
|
1891
|
+
enter: (node) => {
|
|
1892
|
+
switch (node.name) {
|
|
1893
|
+
case "Emphasis":
|
|
1894
|
+
case "StrongEmphasis": {
|
|
1895
|
+
const marks = node.node.getChildren("EmphasisMark");
|
|
1896
|
+
replace(node, marks);
|
|
1897
|
+
break;
|
|
1898
|
+
}
|
|
1899
|
+
case "Strikethrough": {
|
|
1900
|
+
const marks = node.node.getChildren("StrikethroughMark");
|
|
1901
|
+
replace(node, marks);
|
|
1902
|
+
break;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
},
|
|
1906
|
+
from,
|
|
1907
|
+
to
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
return builder.finish();
|
|
1911
|
+
};
|
|
1912
|
+
return [
|
|
1913
|
+
ViewPlugin4.fromClass(class {
|
|
1914
|
+
constructor(view) {
|
|
1915
|
+
this.decorations = buildDecorations7(view);
|
|
1916
|
+
}
|
|
1917
|
+
update(update2) {
|
|
1918
|
+
this.decorations = buildDecorations7(update2.view);
|
|
1919
|
+
}
|
|
1920
|
+
}, {
|
|
1921
|
+
decorations: (value) => value.decorations
|
|
1922
|
+
})
|
|
1923
|
+
];
|
|
1924
|
+
};
|
|
1925
|
+
|
|
1926
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1927
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1928
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1929
|
+
import { Decoration as Decoration5, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
1750
1930
|
var buildDecorations2 = (view) => {
|
|
1751
|
-
const builder = new
|
|
1931
|
+
const builder = new RangeSetBuilder3();
|
|
1752
1932
|
const { state } = view;
|
|
1753
1933
|
const cursor = state.selection.main.head;
|
|
1754
1934
|
for (const { from, to } of view.visibleRanges) {
|
|
1755
|
-
|
|
1935
|
+
syntaxTree3(state).iterate({
|
|
1756
1936
|
enter: (node) => {
|
|
1757
1937
|
switch (node.name) {
|
|
1758
1938
|
case "ATXHeading1":
|
|
@@ -1763,8 +1943,8 @@ var buildDecorations2 = (view) => {
|
|
|
1763
1943
|
case "ATXHeading6": {
|
|
1764
1944
|
const mark2 = node.node.getChild("HeaderMark");
|
|
1765
1945
|
if (mark2) {
|
|
1766
|
-
if (view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1767
|
-
builder.add(mark2.from, mark2.to + 1,
|
|
1946
|
+
if (!view.hasFocus || view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1947
|
+
builder.add(mark2.from, mark2.to + 1, Decoration5.replace({}));
|
|
1768
1948
|
}
|
|
1769
1949
|
}
|
|
1770
1950
|
}
|
|
@@ -1778,7 +1958,7 @@ var buildDecorations2 = (view) => {
|
|
|
1778
1958
|
};
|
|
1779
1959
|
var heading2 = () => {
|
|
1780
1960
|
return [
|
|
1781
|
-
|
|
1961
|
+
ViewPlugin5.fromClass(class {
|
|
1782
1962
|
constructor(view) {
|
|
1783
1963
|
this.decorations = buildDecorations2(view);
|
|
1784
1964
|
}
|
|
@@ -1792,9 +1972,9 @@ var heading2 = () => {
|
|
|
1792
1972
|
};
|
|
1793
1973
|
|
|
1794
1974
|
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
1795
|
-
import { syntaxTree as
|
|
1796
|
-
import { RangeSetBuilder as
|
|
1797
|
-
import { Decoration as
|
|
1975
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
1976
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
1977
|
+
import { Decoration as Decoration6, EditorView as EditorView9, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1798
1978
|
var styles4 = EditorView9.baseTheme({
|
|
1799
1979
|
"& .cm-hr": {
|
|
1800
1980
|
// Note that block-level decorations should not have vertical margins,
|
|
@@ -1808,15 +1988,15 @@ var HorizontalRuleWidget = class extends WidgetType3 {
|
|
|
1808
1988
|
return el;
|
|
1809
1989
|
}
|
|
1810
1990
|
};
|
|
1811
|
-
var decoration =
|
|
1991
|
+
var decoration = Decoration6.replace({
|
|
1812
1992
|
widget: new HorizontalRuleWidget()
|
|
1813
1993
|
});
|
|
1814
1994
|
var buildDecorations3 = (view) => {
|
|
1815
|
-
const builder = new
|
|
1995
|
+
const builder = new RangeSetBuilder4();
|
|
1816
1996
|
const { state } = view;
|
|
1817
1997
|
const cursor = state.selection.main.head;
|
|
1818
1998
|
for (const { from, to } of view.visibleRanges) {
|
|
1819
|
-
|
|
1999
|
+
syntaxTree4(state).iterate({
|
|
1820
2000
|
enter: (node) => {
|
|
1821
2001
|
if (node.name === "HorizontalRule") {
|
|
1822
2002
|
if (cursor <= node.from || cursor >= node.to) {
|
|
@@ -1832,7 +2012,7 @@ var buildDecorations3 = (view) => {
|
|
|
1832
2012
|
};
|
|
1833
2013
|
var hr = () => {
|
|
1834
2014
|
return [
|
|
1835
|
-
|
|
2015
|
+
ViewPlugin6.fromClass(class {
|
|
1836
2016
|
constructor(view) {
|
|
1837
2017
|
this.decorations = buildDecorations3(view);
|
|
1838
2018
|
}
|
|
@@ -1847,13 +2027,13 @@ var hr = () => {
|
|
|
1847
2027
|
};
|
|
1848
2028
|
|
|
1849
2029
|
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1850
|
-
import { syntaxTree as
|
|
2030
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
1851
2031
|
import { StateField as StateField3 } from "@codemirror/state";
|
|
1852
|
-
import { Decoration as
|
|
2032
|
+
import { Decoration as Decoration7, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1853
2033
|
var image = (options = {}) => {
|
|
1854
2034
|
return StateField3.define({
|
|
1855
2035
|
create: (state) => {
|
|
1856
|
-
return
|
|
2036
|
+
return Decoration7.set(buildDecorations4(0, state.doc.length, state));
|
|
1857
2037
|
},
|
|
1858
2038
|
update: (value, tr) => {
|
|
1859
2039
|
if (!tr.docChanged && !tr.selection) {
|
|
@@ -1882,14 +2062,14 @@ var image = (options = {}) => {
|
|
|
1882
2062
|
var buildDecorations4 = (from, to, state) => {
|
|
1883
2063
|
const decorations = [];
|
|
1884
2064
|
const cursor = state.selection.main.head;
|
|
1885
|
-
|
|
2065
|
+
syntaxTree5(state).iterate({
|
|
1886
2066
|
enter: (node) => {
|
|
1887
2067
|
if (node.name === "Image") {
|
|
1888
2068
|
const urlNode = node.node.getChild("URL");
|
|
1889
2069
|
if (urlNode) {
|
|
1890
2070
|
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1891
2071
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1892
|
-
decorations.push(
|
|
2072
|
+
decorations.push(Decoration7.replace({
|
|
1893
2073
|
block: true,
|
|
1894
2074
|
widget: new ImageWidget(url)
|
|
1895
2075
|
}).range(hide ? node.from : node.to, node.to));
|
|
@@ -1919,13 +2099,13 @@ var ImageWidget = class extends WidgetType4 {
|
|
|
1919
2099
|
};
|
|
1920
2100
|
|
|
1921
2101
|
// 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
|
|
2102
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2103
|
+
import { RangeSetBuilder as RangeSetBuilder5 } from "@codemirror/state";
|
|
2104
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration8, ViewPlugin as ViewPlugin7, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1925
2105
|
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1926
2106
|
var link = (options = {}) => {
|
|
1927
2107
|
const extensions = [
|
|
1928
|
-
|
|
2108
|
+
ViewPlugin7.fromClass(class {
|
|
1929
2109
|
constructor(view) {
|
|
1930
2110
|
this.decorations = buildDecorations5(view, options);
|
|
1931
2111
|
}
|
|
@@ -1944,7 +2124,7 @@ var link = (options = {}) => {
|
|
|
1944
2124
|
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1945
2125
|
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1946
2126
|
hoverTooltip2((view, pos, side) => {
|
|
1947
|
-
const syntax =
|
|
2127
|
+
const syntax = syntaxTree6(view.state).resolveInner(pos, side);
|
|
1948
2128
|
let link2 = null;
|
|
1949
2129
|
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1950
2130
|
link2 = node.name === "Link" ? node : null;
|
|
@@ -2021,27 +2201,27 @@ var LinkText = class extends WidgetType5 {
|
|
|
2021
2201
|
}
|
|
2022
2202
|
};
|
|
2023
2203
|
var buildDecorations5 = (view, options) => {
|
|
2024
|
-
const builder = new
|
|
2204
|
+
const builder = new RangeSetBuilder5();
|
|
2025
2205
|
const { state } = view;
|
|
2026
2206
|
const cursor = state.selection.main.head;
|
|
2027
2207
|
for (const { from, to } of view.visibleRanges) {
|
|
2028
|
-
|
|
2208
|
+
syntaxTree6(state).iterate({
|
|
2029
2209
|
enter: (node) => {
|
|
2030
2210
|
if (node.name === "Link") {
|
|
2031
|
-
const
|
|
2032
|
-
const text =
|
|
2211
|
+
const marks = node.node.getChildren("LinkMark");
|
|
2212
|
+
const text = marks.length >= 2 ? state.sliceDoc(marks[0].to, marks[1].from) : "";
|
|
2033
2213
|
const urlNode = node.node.getChild("URL");
|
|
2034
2214
|
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2035
2215
|
if (!url) {
|
|
2036
2216
|
return false;
|
|
2037
2217
|
}
|
|
2038
2218
|
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2039
|
-
builder.add(node.from, node.to,
|
|
2219
|
+
builder.add(node.from, node.to, Decoration8.replace({
|
|
2040
2220
|
widget: new LinkText(text, options.link ? url : void 0)
|
|
2041
2221
|
}));
|
|
2042
2222
|
}
|
|
2043
2223
|
if (options.onRender) {
|
|
2044
|
-
builder.add(node.to, node.to,
|
|
2224
|
+
builder.add(node.to, node.to, Decoration8.replace({
|
|
2045
2225
|
widget: new LinkButton(url, options.onRender)
|
|
2046
2226
|
}));
|
|
2047
2227
|
}
|
|
@@ -2056,9 +2236,9 @@ var buildDecorations5 = (view, options) => {
|
|
|
2056
2236
|
};
|
|
2057
2237
|
|
|
2058
2238
|
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2059
|
-
import { syntaxTree as
|
|
2060
|
-
import { RangeSetBuilder as
|
|
2061
|
-
import { Decoration as
|
|
2239
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2240
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField4 } from "@codemirror/state";
|
|
2241
|
+
import { Decoration as Decoration9, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
2062
2242
|
var table = (options = {}) => {
|
|
2063
2243
|
return StateField4.define({
|
|
2064
2244
|
create: (state) => update(state, options),
|
|
@@ -2067,7 +2247,7 @@ var table = (options = {}) => {
|
|
|
2067
2247
|
});
|
|
2068
2248
|
};
|
|
2069
2249
|
var update = (state, options) => {
|
|
2070
|
-
const builder = new
|
|
2250
|
+
const builder = new RangeSetBuilder6();
|
|
2071
2251
|
const cursor = state.selection.main.head;
|
|
2072
2252
|
const tables = [];
|
|
2073
2253
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2075,7 +2255,7 @@ var update = (state, options) => {
|
|
|
2075
2255
|
const table2 = getTable();
|
|
2076
2256
|
return table2.rows?.[table2.rows.length - 1];
|
|
2077
2257
|
};
|
|
2078
|
-
|
|
2258
|
+
syntaxTree7(state).iterate({
|
|
2079
2259
|
enter: (node) => {
|
|
2080
2260
|
switch (node.name) {
|
|
2081
2261
|
case "Table": {
|
|
@@ -2107,10 +2287,10 @@ var update = (state, options) => {
|
|
|
2107
2287
|
});
|
|
2108
2288
|
tables.forEach((table2) => {
|
|
2109
2289
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2110
|
-
hide && builder.add(table2.from, table2.to,
|
|
2290
|
+
hide && builder.add(table2.from, table2.to, Decoration9.replace({
|
|
2111
2291
|
widget: new TableWidget(table2)
|
|
2112
2292
|
}));
|
|
2113
|
-
builder.add(table2.from, table2.to,
|
|
2293
|
+
builder.add(table2.from, table2.to, Decoration9.mark({
|
|
2114
2294
|
class: "cm-table"
|
|
2115
2295
|
}));
|
|
2116
2296
|
});
|
|
@@ -2154,9 +2334,9 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2154
2334
|
};
|
|
2155
2335
|
|
|
2156
2336
|
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2157
|
-
import { syntaxTree as
|
|
2158
|
-
import { RangeSetBuilder as
|
|
2159
|
-
import { EditorView as EditorView12, Decoration as
|
|
2337
|
+
import { syntaxTree as syntaxTree8 } from "@codemirror/language";
|
|
2338
|
+
import { RangeSetBuilder as RangeSetBuilder7 } from "@codemirror/state";
|
|
2339
|
+
import { EditorView as EditorView12, Decoration as Decoration10, WidgetType as WidgetType7, ViewPlugin as ViewPlugin8 } from "@codemirror/view";
|
|
2160
2340
|
var styles5 = EditorView12.baseTheme({
|
|
2161
2341
|
"& .cm-task": {
|
|
2162
2342
|
color: getToken("extend.colors.blue.500")
|
|
@@ -2203,23 +2383,23 @@ var CheckboxWidget = class extends WidgetType7 {
|
|
|
2203
2383
|
return false;
|
|
2204
2384
|
}
|
|
2205
2385
|
};
|
|
2206
|
-
var checkedDecoration =
|
|
2386
|
+
var checkedDecoration = Decoration10.replace({
|
|
2207
2387
|
widget: new CheckboxWidget(true)
|
|
2208
2388
|
});
|
|
2209
|
-
var uncheckedDecoration =
|
|
2389
|
+
var uncheckedDecoration = Decoration10.replace({
|
|
2210
2390
|
widget: new CheckboxWidget(false)
|
|
2211
2391
|
});
|
|
2212
2392
|
var buildDecorations6 = (view) => {
|
|
2213
|
-
const builder = new
|
|
2393
|
+
const builder = new RangeSetBuilder7();
|
|
2214
2394
|
const { state } = view;
|
|
2215
2395
|
const cursor = state.selection.main.head;
|
|
2216
2396
|
for (const { from, to } of view.visibleRanges) {
|
|
2217
|
-
|
|
2397
|
+
syntaxTree8(state).iterate({
|
|
2218
2398
|
enter: (node) => {
|
|
2219
2399
|
if (node.name === "TaskMarker") {
|
|
2220
2400
|
if (cursor < node.from || cursor > node.to) {
|
|
2221
2401
|
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2222
|
-
builder.add(node.from - 2, node.from - 1,
|
|
2402
|
+
builder.add(node.from - 2, node.from - 1, Decoration10.mark({
|
|
2223
2403
|
class: "cm-task"
|
|
2224
2404
|
}));
|
|
2225
2405
|
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
@@ -2234,7 +2414,7 @@ var buildDecorations6 = (view) => {
|
|
|
2234
2414
|
};
|
|
2235
2415
|
var tasklist = (options = {}) => {
|
|
2236
2416
|
return [
|
|
2237
|
-
|
|
2417
|
+
ViewPlugin8.fromClass(class {
|
|
2238
2418
|
constructor(view) {
|
|
2239
2419
|
this.decorations = buildDecorations6(view);
|
|
2240
2420
|
}
|
|
@@ -2285,7 +2465,7 @@ var outliner = (options = {}) => {
|
|
|
2285
2465
|
};
|
|
2286
2466
|
|
|
2287
2467
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2288
|
-
import { keymap as
|
|
2468
|
+
import { keymap as keymap6 } from "@codemirror/view";
|
|
2289
2469
|
var defaultItems = [
|
|
2290
2470
|
"hello world!",
|
|
2291
2471
|
"this is a test.",
|
|
@@ -2295,7 +2475,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2295
2475
|
let t;
|
|
2296
2476
|
let idx = 0;
|
|
2297
2477
|
return [
|
|
2298
|
-
|
|
2478
|
+
keymap6.of([
|
|
2299
2479
|
{
|
|
2300
2480
|
// Reset.
|
|
2301
2481
|
key: "alt-meta-'",
|
|
@@ -2407,7 +2587,7 @@ var defaultTheme = {
|
|
|
2407
2587
|
paddingInline: 0
|
|
2408
2588
|
},
|
|
2409
2589
|
".cm-activeLine": {
|
|
2410
|
-
background: "
|
|
2590
|
+
background: "transparent"
|
|
2411
2591
|
},
|
|
2412
2592
|
//
|
|
2413
2593
|
// Selection
|
|
@@ -2578,7 +2758,7 @@ var codeTheme = {
|
|
|
2578
2758
|
};
|
|
2579
2759
|
|
|
2580
2760
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2581
|
-
var
|
|
2761
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2582
2762
|
var EditorModes = [
|
|
2583
2763
|
"default",
|
|
2584
2764
|
"vim"
|
|
@@ -2612,8 +2792,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2612
2792
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2613
2793
|
EditorView13.exceptionSink.of((err) => {
|
|
2614
2794
|
log2.catch(err, void 0, {
|
|
2615
|
-
F:
|
|
2616
|
-
L:
|
|
2795
|
+
F: __dxlog_file3,
|
|
2796
|
+
L: 124,
|
|
2617
2797
|
S: void 0,
|
|
2618
2798
|
C: (f, a) => f(...a)
|
|
2619
2799
|
});
|
|
@@ -2630,6 +2810,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2630
2810
|
class: slots.content?.className ?? ""
|
|
2631
2811
|
}),
|
|
2632
2812
|
// State.
|
|
2813
|
+
EditorView13.editable.of(!readonly),
|
|
2633
2814
|
EditorState2.readOnly.of(!!readonly),
|
|
2634
2815
|
// Storage and replication.
|
|
2635
2816
|
// NOTE: This must come before user extensions.
|
|
@@ -2638,7 +2819,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
2638
2819
|
editorMode === "vim" && vim(),
|
|
2639
2820
|
// Custom.
|
|
2640
2821
|
...extensions
|
|
2641
|
-
].filter(
|
|
2822
|
+
].filter(nonNullable2)
|
|
2642
2823
|
});
|
|
2643
2824
|
const newView = new EditorView13({
|
|
2644
2825
|
state,
|
|
@@ -2750,9 +2931,9 @@ var defaultMarkdownSlots = {
|
|
|
2750
2931
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2751
2932
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2752
2933
|
import { Context as Context2 } from "@dxos/context";
|
|
2753
|
-
import { invariant as
|
|
2934
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
2754
2935
|
import { log as log3 } from "@dxos/log";
|
|
2755
|
-
var
|
|
2936
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2756
2937
|
var DEBOUNCE_INTERVAL = 100;
|
|
2757
2938
|
var SpaceAwarenessProvider = class {
|
|
2758
2939
|
constructor(params) {
|
|
@@ -2792,7 +2973,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2792
2973
|
log3.debug("failed to query awareness", {
|
|
2793
2974
|
err
|
|
2794
2975
|
}, {
|
|
2795
|
-
F:
|
|
2976
|
+
F: __dxlog_file4,
|
|
2796
2977
|
L: 89,
|
|
2797
2978
|
S: this,
|
|
2798
2979
|
C: (f, a) => f(...a)
|
|
@@ -2808,8 +2989,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2808
2989
|
return Array.from(this._remoteStates.values());
|
|
2809
2990
|
}
|
|
2810
2991
|
update(position) {
|
|
2811
|
-
|
|
2812
|
-
F:
|
|
2992
|
+
invariant2(this._postTask, void 0, {
|
|
2993
|
+
F: __dxlog_file4,
|
|
2813
2994
|
L: 104,
|
|
2814
2995
|
S: this,
|
|
2815
2996
|
A: [
|
|
@@ -2825,8 +3006,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2825
3006
|
this._postTask.schedule();
|
|
2826
3007
|
}
|
|
2827
3008
|
_handleQueryMessage() {
|
|
2828
|
-
|
|
2829
|
-
F:
|
|
3009
|
+
invariant2(this._postTask, void 0, {
|
|
3010
|
+
F: __dxlog_file4,
|
|
2830
3011
|
L: 115,
|
|
2831
3012
|
S: this,
|
|
2832
3013
|
A: [
|
|
@@ -2837,8 +3018,8 @@ var SpaceAwarenessProvider = class {
|
|
|
2837
3018
|
this._postTask.schedule();
|
|
2838
3019
|
}
|
|
2839
3020
|
_handlePostMessage(message) {
|
|
2840
|
-
|
|
2841
|
-
F:
|
|
3021
|
+
invariant2(message.kind === "post", void 0, {
|
|
3022
|
+
F: __dxlog_file4,
|
|
2842
3023
|
L: 120,
|
|
2843
3024
|
S: this,
|
|
2844
3025
|
A: [
|
|
@@ -2858,6 +3039,38 @@ var modelState = StateField5.define({
|
|
|
2858
3039
|
update: (model) => model
|
|
2859
3040
|
});
|
|
2860
3041
|
|
|
3042
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
3043
|
+
var useActionHandler = (view) => {
|
|
3044
|
+
return (action) => {
|
|
3045
|
+
if (!view) {
|
|
3046
|
+
return;
|
|
3047
|
+
}
|
|
3048
|
+
switch (action.type) {
|
|
3049
|
+
case "heading":
|
|
3050
|
+
setHeading(parseInt(action.data))(view);
|
|
3051
|
+
break;
|
|
3052
|
+
case "bold":
|
|
3053
|
+
toggleBold(view);
|
|
3054
|
+
break;
|
|
3055
|
+
case "italic":
|
|
3056
|
+
toggleItalic(view);
|
|
3057
|
+
break;
|
|
3058
|
+
case "strikethrough":
|
|
3059
|
+
toggleStrikethrough(view);
|
|
3060
|
+
break;
|
|
3061
|
+
case "list":
|
|
3062
|
+
toggleList(view);
|
|
3063
|
+
break;
|
|
3064
|
+
case "comment":
|
|
3065
|
+
createComment(view);
|
|
3066
|
+
break;
|
|
3067
|
+
}
|
|
3068
|
+
setTimeout(() => {
|
|
3069
|
+
view.focus();
|
|
3070
|
+
});
|
|
3071
|
+
};
|
|
3072
|
+
};
|
|
3073
|
+
|
|
2861
3074
|
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
2862
3075
|
import { useState as useState2 } from "react";
|
|
2863
3076
|
var useTextEditor = () => {
|
|
@@ -2875,10 +3088,9 @@ import get4 from "lodash.get";
|
|
|
2875
3088
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2876
3089
|
import { generateName } from "@dxos/display-name";
|
|
2877
3090
|
import { getRawDoc } from "@dxos/echo-schema";
|
|
2878
|
-
import { invariant as
|
|
3091
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
2879
3092
|
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";
|
|
3093
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2882
3094
|
var useTextModel = (props) => {
|
|
2883
3095
|
const { identity, space, text } = props;
|
|
2884
3096
|
const [model, setModel] = useState3();
|
|
@@ -2890,9 +3102,9 @@ var useTextModel = (props) => {
|
|
|
2890
3102
|
return model;
|
|
2891
3103
|
};
|
|
2892
3104
|
var createModel = ({ space, identity, text }) => {
|
|
2893
|
-
|
|
2894
|
-
F:
|
|
2895
|
-
L:
|
|
3105
|
+
invariant3(isAutomergeObject(text), void 0, {
|
|
3106
|
+
F: __dxlog_file5,
|
|
3107
|
+
L: 34,
|
|
2896
3108
|
S: void 0,
|
|
2897
3109
|
A: [
|
|
2898
3110
|
"isAutomergeObject(text)",
|
|
@@ -2903,7 +3115,7 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2903
3115
|
const doc = getRawDoc(obj, [
|
|
2904
3116
|
obj.field
|
|
2905
3117
|
]);
|
|
2906
|
-
const
|
|
3118
|
+
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
2907
3119
|
space,
|
|
2908
3120
|
channel: `automerge.awareness.${obj.id}`,
|
|
2909
3121
|
info: {
|
|
@@ -2913,19 +3125,22 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2913
3125
|
},
|
|
2914
3126
|
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
2915
3127
|
});
|
|
3128
|
+
const extensions = [
|
|
3129
|
+
//
|
|
3130
|
+
modelState.init(() => model),
|
|
3131
|
+
automerge({
|
|
3132
|
+
handle: doc.handle,
|
|
3133
|
+
path: doc.path
|
|
3134
|
+
})
|
|
3135
|
+
];
|
|
3136
|
+
if (awarenessProvider2) {
|
|
3137
|
+
extensions.push(awareness(awarenessProvider2));
|
|
3138
|
+
}
|
|
2916
3139
|
const model = {
|
|
2917
3140
|
id: obj.id,
|
|
2918
3141
|
content: doc,
|
|
2919
3142
|
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),
|
|
3143
|
+
extension: extensions,
|
|
2929
3144
|
peer: identity ? {
|
|
2930
3145
|
id: identity.identityKey.toHex(),
|
|
2931
3146
|
name: identity.profile?.displayName
|
|
@@ -2934,7 +3149,6 @@ var createModel = ({ space, identity, text }) => {
|
|
|
2934
3149
|
return model;
|
|
2935
3150
|
};
|
|
2936
3151
|
export {
|
|
2937
|
-
AwarenessProvider,
|
|
2938
3152
|
BaseTextEditor,
|
|
2939
3153
|
Cursor,
|
|
2940
3154
|
Doc,
|
|
@@ -2947,19 +3161,22 @@ export {
|
|
|
2947
3161
|
YText,
|
|
2948
3162
|
YXmlFragment,
|
|
2949
3163
|
autocomplete,
|
|
2950
|
-
|
|
3164
|
+
automerge,
|
|
2951
3165
|
awareness,
|
|
3166
|
+
awarenessProvider,
|
|
2952
3167
|
basicBundle,
|
|
2953
3168
|
blast,
|
|
2954
3169
|
callbackWrapper,
|
|
2955
3170
|
code2 as code,
|
|
2956
3171
|
codeTheme,
|
|
2957
3172
|
comments,
|
|
3173
|
+
createComment,
|
|
2958
3174
|
defaultMarkdownSlots,
|
|
2959
3175
|
defaultOptions,
|
|
2960
3176
|
defaultSlots,
|
|
2961
3177
|
defaultTextSlots,
|
|
2962
3178
|
defaultTheme,
|
|
3179
|
+
formatting,
|
|
2963
3180
|
getToken,
|
|
2964
3181
|
heading2 as heading,
|
|
2965
3182
|
hr,
|
|
@@ -2977,12 +3194,19 @@ export {
|
|
|
2977
3194
|
outliner,
|
|
2978
3195
|
setComments,
|
|
2979
3196
|
setFocus,
|
|
3197
|
+
setHeading,
|
|
2980
3198
|
setSelection,
|
|
2981
3199
|
table,
|
|
2982
3200
|
tags2 as tags,
|
|
2983
3201
|
tasklist,
|
|
2984
3202
|
textTheme,
|
|
3203
|
+
toggleBold,
|
|
3204
|
+
toggleItalic,
|
|
3205
|
+
toggleList,
|
|
3206
|
+
toggleStrikethrough,
|
|
3207
|
+
toggleStyle,
|
|
2985
3208
|
typewriter,
|
|
3209
|
+
useActionHandler,
|
|
2986
3210
|
useComments,
|
|
2987
3211
|
useTextEditor,
|
|
2988
3212
|
useTextModel
|