@dxos/react-ui-editor 0.3.11-main.4eab977 → 0.3.11-main.4faaf44
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 +1134 -1241
- 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 +16 -13
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/index.d.ts +0 -1
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/awareness.d.ts +1 -1
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +32 -19
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -7
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +7 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +25 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +2 -32
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +2 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +34 -36
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +82 -82
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +122 -93
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/extensions/autocomplete.ts +6 -3
- package/src/extensions/automerge/automerge.ts +40 -46
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/index.ts +0 -1
- package/src/extensions/automerge/semaphore.ts +23 -20
- package/src/extensions/automerge/update-automerge.ts +2 -2
- package/src/extensions/awareness.ts +40 -46
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/comments.ts +246 -238
- package/src/extensions/cursor.ts +50 -0
- package/src/extensions/index.ts +2 -7
- package/src/extensions/markdown/bundle.ts +20 -30
- package/src/extensions/markdown/code.ts +127 -0
- package/src/extensions/markdown/heading.ts +59 -0
- package/src/extensions/markdown/highlight.ts +9 -23
- package/src/extensions/markdown/hr.ts +71 -0
- package/src/extensions/{image.ts → markdown/image.ts} +2 -2
- package/src/extensions/markdown/index.ts +7 -0
- package/src/extensions/{link.ts → markdown/link.ts} +8 -9
- package/src/extensions/{table.ts → markdown/table.ts} +2 -2
- package/src/extensions/markdown/tasklist.ts +110 -0
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +3 -2
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +48 -60
- package/src/index.ts +1 -0
- package/src/styles/markdown.ts +9 -12
- package/src/themes/default.ts +15 -50
- package/src/util.ts +41 -0
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -27
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts +0 -5
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/code.ts +0 -98
- package/src/extensions/hr.ts +0 -73
- package/src/extensions/tasklist.ts +0 -119
- package/src/extensions/yjs/cursor.ts +0 -21
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/yjs.ts +0 -178
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- package/src/util/util.ts +0 -18
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
|
@@ -7,14 +7,14 @@ import { tags as tags2 } from "@lezer/highlight";
|
|
|
7
7
|
|
|
8
8
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
9
9
|
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
10
|
-
import { EditorView as
|
|
10
|
+
import { EditorView as EditorView13 } from "@codemirror/view";
|
|
11
11
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
12
12
|
import { vim } from "@replit/codemirror-vim";
|
|
13
13
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
14
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
15
|
-
import {
|
|
14
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState } from "react";
|
|
15
|
+
import { log as log2 } from "@dxos/log";
|
|
16
16
|
import { useThemeContext } from "@dxos/react-ui";
|
|
17
|
-
import {
|
|
17
|
+
import { attentionSurface, mx as mx3 } from "@dxos/react-ui-theme";
|
|
18
18
|
|
|
19
19
|
// packages/ui/react-ui-editor/src/extensions/autocomplete.ts
|
|
20
20
|
import { autocompletion, completionKeymap } from "@codemirror/autocomplete";
|
|
@@ -29,9 +29,11 @@ var autocomplete = ({ onSearch }) => {
|
|
|
29
29
|
// https://codemirror.net/examples/autocompletion
|
|
30
30
|
// https://codemirror.net/docs/ref/#autocomplete.autocompletion
|
|
31
31
|
autocompletion({
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
32
|
+
activateOnTyping: true,
|
|
33
|
+
// closeOnBlur: false,
|
|
34
|
+
// defaultKeymap: false,
|
|
35
|
+
// TODO(burdon): Styles/fragments.
|
|
36
|
+
tooltipClass: () => "shadow rounded"
|
|
35
37
|
}),
|
|
36
38
|
// TODO(burdon): Option to create new page?
|
|
37
39
|
// TODO(burdon): Optional decoration via addToOptions
|
|
@@ -51,9 +53,10 @@ var autocomplete = ({ onSearch }) => {
|
|
|
51
53
|
};
|
|
52
54
|
|
|
53
55
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
54
|
-
import {
|
|
55
|
-
import { ViewPlugin } from "@codemirror/view";
|
|
56
|
+
import { StateField } from "@codemirror/state";
|
|
57
|
+
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
56
58
|
import { next as A } from "@dxos/automerge/automerge";
|
|
59
|
+
import { invariant } from "@dxos/invariant";
|
|
57
60
|
|
|
58
61
|
// packages/ui/react-ui-editor/src/extensions/automerge/cursor.ts
|
|
59
62
|
import get from "lodash.get";
|
|
@@ -94,12 +97,12 @@ var cursorConverter = (handle, path) => ({
|
|
|
94
97
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
95
98
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
96
99
|
var effectType = StateEffect.define({});
|
|
100
|
+
var reconcileAnnotationType = Annotation.define();
|
|
101
|
+
var getPath = (state, field) => state.field(field).path;
|
|
102
|
+
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
97
103
|
var updateHeads = (newHeads) => effectType.of({
|
|
98
104
|
newHeads
|
|
99
105
|
});
|
|
100
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
101
|
-
var getPath = (state, field) => state.field(field).path;
|
|
102
|
-
var reconcileAnnotationType = Annotation.define();
|
|
103
106
|
var isReconcileTx = (tr) => !!tr.annotation(reconcileAnnotationType);
|
|
104
107
|
|
|
105
108
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
@@ -237,85 +240,96 @@ var charPath = (textPath, candidatePath) => {
|
|
|
237
240
|
|
|
238
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
|
|
239
242
|
var PatchSemaphore = class {
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
// prettier-ignore
|
|
244
|
+
constructor(_handle, _state) {
|
|
245
|
+
this._handle = _handle;
|
|
246
|
+
this._state = _state;
|
|
242
247
|
this._inReconcile = false;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
changes: inverted,
|
|
259
|
-
annotations: reconcileAnnotationType.of(true)
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
|
|
263
|
-
if (newHeads === null || newHeads === void 0) {
|
|
264
|
-
newHeads = automerge2.getHeads(handle.docSync());
|
|
265
|
-
}
|
|
266
|
-
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(handle.docSync(), oldHeads, newHeads);
|
|
267
|
-
updateCodeMirror(view, selection, path, diff);
|
|
248
|
+
}
|
|
249
|
+
// NOTE: Cannot destruct view.state.
|
|
250
|
+
reconcile(view) {
|
|
251
|
+
if (this._inReconcile) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this._inReconcile = true;
|
|
255
|
+
const path = getPath(view.state, this._state);
|
|
256
|
+
const oldHeads = getLastHeads(view.state, this._state);
|
|
257
|
+
let selection = view.state.selection;
|
|
258
|
+
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
|
|
259
|
+
const toInvert = transactions.slice().reverse();
|
|
260
|
+
for (const tx of toInvert) {
|
|
261
|
+
const inverted = tx.changes.invert(tx.startState.doc);
|
|
262
|
+
selection = selection.map(inverted);
|
|
268
263
|
view.dispatch({
|
|
269
|
-
|
|
270
|
-
annotations: reconcileAnnotationType.of(
|
|
264
|
+
changes: inverted,
|
|
265
|
+
annotations: reconcileAnnotationType.of(true)
|
|
271
266
|
});
|
|
272
|
-
|
|
273
|
-
|
|
267
|
+
}
|
|
268
|
+
let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
269
|
+
if (newHeads === null || newHeads === void 0) {
|
|
270
|
+
newHeads = automerge2.getHeads(this._handle.docSync());
|
|
271
|
+
}
|
|
272
|
+
const diff = automerge2.equals(oldHeads, newHeads) ? [] : automerge2.diff(this._handle.docSync(), oldHeads, newHeads);
|
|
273
|
+
updateCodeMirror(view, selection, path, diff);
|
|
274
|
+
view.dispatch({
|
|
275
|
+
effects: updateHeads(newHeads),
|
|
276
|
+
annotations: reconcileAnnotationType.of({})
|
|
277
|
+
});
|
|
278
|
+
this._inReconcile = false;
|
|
274
279
|
}
|
|
275
280
|
};
|
|
276
281
|
|
|
277
|
-
// packages/ui/react-ui-editor/src/
|
|
282
|
+
// packages/ui/react-ui-editor/src/extensions/cursor.ts
|
|
278
283
|
import { Facet } from "@codemirror/state";
|
|
279
|
-
var
|
|
284
|
+
var defaultCursorConverter = {
|
|
280
285
|
toCursor: (position) => position.toString(),
|
|
281
286
|
fromCursor: (cursor) => parseInt(cursor)
|
|
282
287
|
};
|
|
283
|
-
var
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
// packages/ui/react-ui-editor/src/util/util.ts
|
|
288
|
-
import { log } from "@dxos/log";
|
|
289
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util/util.ts";
|
|
290
|
-
var callbackWrapper = (fn) => (...args) => {
|
|
291
|
-
try {
|
|
292
|
-
return fn(...args);
|
|
293
|
-
} catch (error) {
|
|
294
|
-
log.catch(error, void 0, {
|
|
295
|
-
F: __dxlog_file,
|
|
296
|
-
L: 16,
|
|
297
|
-
S: void 0,
|
|
298
|
-
C: (f, a) => f(...a)
|
|
288
|
+
var Cursor = class _Cursor {
|
|
289
|
+
static {
|
|
290
|
+
this.converter = Facet.define({
|
|
291
|
+
combine: (providers) => providers[0] ?? defaultCursorConverter
|
|
299
292
|
});
|
|
300
293
|
}
|
|
294
|
+
static {
|
|
295
|
+
this.getCursorFromRange = (state, range) => {
|
|
296
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
297
|
+
const from = cursorConverter2.toCursor(range.from);
|
|
298
|
+
const to = cursorConverter2.toCursor(range.to, -1);
|
|
299
|
+
return [
|
|
300
|
+
from,
|
|
301
|
+
to
|
|
302
|
+
].join(":");
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
static {
|
|
306
|
+
this.getRangeFromCursor = (state, cursor) => {
|
|
307
|
+
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
308
|
+
const parts = cursor.split(":");
|
|
309
|
+
const from = cursorConverter2.fromCursor(parts[0]);
|
|
310
|
+
const to = cursorConverter2.fromCursor(parts[1]);
|
|
311
|
+
return from !== void 0 && to !== void 0 ? {
|
|
312
|
+
from,
|
|
313
|
+
to
|
|
314
|
+
} : void 0;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
301
317
|
};
|
|
302
318
|
|
|
303
319
|
// packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
|
|
304
|
-
var
|
|
305
|
-
combine: (values) => values.at(-1)
|
|
306
|
-
});
|
|
320
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts";
|
|
307
321
|
var automerge3 = ({ handle, path }) => {
|
|
308
|
-
const
|
|
322
|
+
const state = StateField.define({
|
|
309
323
|
create: () => ({
|
|
324
|
+
path: path.slice(),
|
|
310
325
|
lastHeads: A.getHeads(handle.docSync()),
|
|
311
|
-
unreconciledTransactions: []
|
|
312
|
-
path: path.slice()
|
|
326
|
+
unreconciledTransactions: []
|
|
313
327
|
}),
|
|
314
328
|
update: (value, tr) => {
|
|
315
329
|
const result = {
|
|
330
|
+
path: path.slice(),
|
|
316
331
|
lastHeads: value.lastHeads,
|
|
317
|
-
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
318
|
-
path: path.slice()
|
|
332
|
+
unreconciledTransactions: value.unreconciledTransactions.slice()
|
|
319
333
|
};
|
|
320
334
|
let clearUnreconciled = false;
|
|
321
335
|
for (const effect of tr.effects) {
|
|
@@ -334,39 +348,44 @@ var automerge3 = ({ handle, path }) => {
|
|
|
334
348
|
return result;
|
|
335
349
|
}
|
|
336
350
|
});
|
|
337
|
-
const semaphore = new PatchSemaphore(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
const semaphore = new PatchSemaphore(handle, state);
|
|
352
|
+
return [
|
|
353
|
+
Cursor.converter.of(cursorConverter(handle, path)),
|
|
354
|
+
// Reconcile external updates.
|
|
355
|
+
ViewPlugin.fromClass(class {
|
|
356
|
+
constructor(_view) {
|
|
357
|
+
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
|
+
]
|
|
350
366
|
});
|
|
367
|
+
handle.addListener("change", this._handleChange.bind(this));
|
|
351
368
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
destroy() {
|
|
370
|
+
handle.removeListener("change", this._handleChange.bind(this));
|
|
371
|
+
}
|
|
372
|
+
_handleChange() {
|
|
373
|
+
semaphore.reconcile(this._view);
|
|
374
|
+
}
|
|
375
|
+
}),
|
|
376
|
+
// Reconcile local updates.
|
|
377
|
+
EditorView.updateListener.of(({ view, changes }) => {
|
|
378
|
+
if (!changes.empty) {
|
|
379
|
+
semaphore.reconcile(view);
|
|
380
|
+
}
|
|
381
|
+
}),
|
|
382
|
+
state
|
|
383
|
+
];
|
|
365
384
|
};
|
|
366
385
|
|
|
367
386
|
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
368
|
-
import { Annotation as Annotation2, Facet as
|
|
369
|
-
import { Decoration, EditorView, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
387
|
+
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
388
|
+
import { Decoration, EditorView as EditorView2, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
370
389
|
import { Event } from "@dxos/async";
|
|
371
390
|
import { Context } from "@dxos/context";
|
|
372
391
|
var dummyProvider = {
|
|
@@ -375,11 +394,11 @@ var dummyProvider = {
|
|
|
375
394
|
},
|
|
376
395
|
close: () => {
|
|
377
396
|
},
|
|
397
|
+
getRemoteStates: () => [],
|
|
378
398
|
update: () => {
|
|
379
|
-
}
|
|
380
|
-
getRemoteStates: () => []
|
|
399
|
+
}
|
|
381
400
|
};
|
|
382
|
-
var AwarenessProvider =
|
|
401
|
+
var AwarenessProvider = Facet2.define({
|
|
383
402
|
combine: (providers) => providers[0] ?? dummyProvider
|
|
384
403
|
});
|
|
385
404
|
var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
@@ -398,7 +417,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
398
417
|
this._ctx = new Context();
|
|
399
418
|
this._lastAnchor = void 0;
|
|
400
419
|
this._lastHead = void 0;
|
|
401
|
-
this._cursorConverter = view.state.facet(
|
|
420
|
+
this._cursorConverter = view.state.facet(Cursor.converter);
|
|
402
421
|
this._provider = view.state.facet(AwarenessProvider);
|
|
403
422
|
this._provider.open();
|
|
404
423
|
this._provider.remoteStateChange.on(this._ctx, () => {
|
|
@@ -453,7 +472,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
453
472
|
attributes: {
|
|
454
473
|
style: `background-color: ${lightColor}`
|
|
455
474
|
},
|
|
456
|
-
class: "cm-
|
|
475
|
+
class: "cm-collab-selection"
|
|
457
476
|
})
|
|
458
477
|
});
|
|
459
478
|
} else {
|
|
@@ -464,7 +483,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
464
483
|
attributes: {
|
|
465
484
|
style: `background-color: ${color}`
|
|
466
485
|
},
|
|
467
|
-
class: "cm-
|
|
486
|
+
class: "cm-collab-selection"
|
|
468
487
|
})
|
|
469
488
|
});
|
|
470
489
|
decorations.push({
|
|
@@ -474,7 +493,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
474
493
|
attributes: {
|
|
475
494
|
style: `background-color: ${color}`
|
|
476
495
|
},
|
|
477
|
-
class: "cm-
|
|
496
|
+
class: "cm-collab-selection"
|
|
478
497
|
})
|
|
479
498
|
});
|
|
480
499
|
for (let i = startLine.number + 1; i < endLine.number; i++) {
|
|
@@ -485,7 +504,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
485
504
|
value: Decoration.line({
|
|
486
505
|
attributes: {
|
|
487
506
|
style: `background-color: ${color}`,
|
|
488
|
-
class: "cm-
|
|
507
|
+
class: "cm-collab-selectionLine"
|
|
489
508
|
}
|
|
490
509
|
})
|
|
491
510
|
});
|
|
@@ -505,23 +524,21 @@ var RemoteSelectionsDecorator = class {
|
|
|
505
524
|
}
|
|
506
525
|
};
|
|
507
526
|
var RemoteCaretWidget = class extends WidgetType {
|
|
508
|
-
constructor(
|
|
527
|
+
constructor(_name, _color) {
|
|
509
528
|
super();
|
|
510
|
-
this.
|
|
511
|
-
this.
|
|
512
|
-
this.name = name;
|
|
513
|
-
this.color = color;
|
|
529
|
+
this._name = _name;
|
|
530
|
+
this._color = _color;
|
|
514
531
|
}
|
|
515
532
|
toDOM() {
|
|
516
533
|
const span = document.createElement("span");
|
|
517
|
-
span.className = "cm-
|
|
518
|
-
span.style.backgroundColor = this.
|
|
519
|
-
span.style.borderColor = this.
|
|
534
|
+
span.className = "cm-collab-selectionCaret";
|
|
535
|
+
span.style.backgroundColor = this._color;
|
|
536
|
+
span.style.borderColor = this._color;
|
|
520
537
|
const dot = document.createElement("div");
|
|
521
|
-
dot.className = "cm-
|
|
538
|
+
dot.className = "cm-collab-selectionCaretDot";
|
|
522
539
|
const info = document.createElement("div");
|
|
523
|
-
info.className = "cm-
|
|
524
|
-
info.innerText = this.
|
|
540
|
+
info.className = "cm-collab-selectionInfo";
|
|
541
|
+
info.innerText = this._name;
|
|
525
542
|
span.appendChild(document.createTextNode("\u2060"));
|
|
526
543
|
span.appendChild(dot);
|
|
527
544
|
span.appendChild(document.createTextNode("\u2060"));
|
|
@@ -529,15 +546,12 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
529
546
|
span.appendChild(document.createTextNode("\u2060"));
|
|
530
547
|
return span;
|
|
531
548
|
}
|
|
532
|
-
eq(widget) {
|
|
533
|
-
return widget.color === this.color;
|
|
534
|
-
}
|
|
535
|
-
compare(widget) {
|
|
536
|
-
return widget.color === this.color;
|
|
537
|
-
}
|
|
538
549
|
updateDOM() {
|
|
539
550
|
return false;
|
|
540
551
|
}
|
|
552
|
+
eq(widget) {
|
|
553
|
+
return widget._color === this._color;
|
|
554
|
+
}
|
|
541
555
|
get estimatedHeight() {
|
|
542
556
|
return -1;
|
|
543
557
|
}
|
|
@@ -545,58 +559,60 @@ var RemoteCaretWidget = class extends WidgetType {
|
|
|
545
559
|
return true;
|
|
546
560
|
}
|
|
547
561
|
};
|
|
548
|
-
var styles =
|
|
549
|
-
".cm-
|
|
550
|
-
".cm-
|
|
562
|
+
var styles = EditorView2.baseTheme({
|
|
563
|
+
".cm-collab-selection": {},
|
|
564
|
+
".cm-collab-selectionLine": {
|
|
551
565
|
padding: 0,
|
|
552
566
|
margin: "0px 2px 0px 4px"
|
|
553
567
|
},
|
|
554
|
-
".cm-
|
|
568
|
+
".cm-collab-selectionCaret": {
|
|
555
569
|
position: "relative",
|
|
556
570
|
borderLeft: "1px solid black",
|
|
557
571
|
borderRight: "1px solid black",
|
|
558
572
|
marginLeft: "-1px",
|
|
559
573
|
marginRight: "-1px",
|
|
560
574
|
boxSizing: "border-box",
|
|
561
|
-
display: "inline"
|
|
575
|
+
display: "inline",
|
|
576
|
+
cursor: "pointer"
|
|
562
577
|
},
|
|
563
|
-
".cm-
|
|
578
|
+
".cm-collab-selectionCaretDot": {
|
|
564
579
|
borderRadius: "50%",
|
|
565
580
|
position: "absolute",
|
|
566
|
-
width: ".
|
|
567
|
-
height: ".
|
|
568
|
-
top: "-.
|
|
569
|
-
left: "-.
|
|
581
|
+
width: ".5em",
|
|
582
|
+
height: ".5em",
|
|
583
|
+
top: "-.25em",
|
|
584
|
+
left: "-.25em",
|
|
570
585
|
backgroundColor: "inherit",
|
|
571
586
|
transition: "transform .3s ease-in-out",
|
|
572
587
|
boxSizing: "border-box"
|
|
573
588
|
},
|
|
574
|
-
".cm-
|
|
575
|
-
|
|
576
|
-
|
|
589
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot": {
|
|
590
|
+
transform: "scale(0)",
|
|
591
|
+
transformOrigin: "center"
|
|
577
592
|
},
|
|
578
|
-
".cm-
|
|
593
|
+
".cm-collab-selectionInfo": {
|
|
579
594
|
position: "absolute",
|
|
580
|
-
|
|
581
|
-
|
|
595
|
+
transform: "translate(-50%, 0)",
|
|
596
|
+
top: "-20px",
|
|
597
|
+
left: 0,
|
|
582
598
|
fontSize: ".75em",
|
|
583
|
-
fontFamily: "serif",
|
|
599
|
+
fontFamily: "sans-serif",
|
|
584
600
|
fontStyle: "normal",
|
|
585
601
|
fontWeight: "normal",
|
|
586
602
|
lineHeight: "normal",
|
|
587
603
|
userSelect: "none",
|
|
588
604
|
color: "white",
|
|
589
|
-
|
|
590
|
-
paddingRight: "2px",
|
|
605
|
+
padding: "2px",
|
|
591
606
|
zIndex: 101,
|
|
592
607
|
transition: "opacity .3s ease-in-out",
|
|
593
608
|
backgroundColor: "inherit",
|
|
594
|
-
|
|
609
|
+
borderRadius: "2px",
|
|
610
|
+
// These should be separate.
|
|
595
611
|
opacity: 0,
|
|
596
612
|
transitionDelay: "0s",
|
|
597
613
|
whiteSpace: "nowrap"
|
|
598
614
|
},
|
|
599
|
-
".cm-
|
|
615
|
+
".cm-collab-selectionCaret:hover > .cm-collab-selectionInfo": {
|
|
600
616
|
opacity: 1,
|
|
601
617
|
transitionDelay: "0s"
|
|
602
618
|
}
|
|
@@ -604,25 +620,27 @@ var styles = EditorView.baseTheme({
|
|
|
604
620
|
|
|
605
621
|
// packages/ui/react-ui-editor/src/extensions/basic.ts
|
|
606
622
|
import { closeBrackets } from "@codemirror/autocomplete";
|
|
623
|
+
import { history } from "@codemirror/commands";
|
|
607
624
|
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
608
625
|
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
609
|
-
import { drawSelection, EditorView as
|
|
610
|
-
var basicBundle = ({
|
|
611
|
-
|
|
612
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
626
|
+
import { drawSelection, EditorView as EditorView3, highlightActiveLine, placeholder } from "@codemirror/view";
|
|
627
|
+
var basicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true }) => [
|
|
628
|
+
lineWrapping ? EditorView3.lineWrapping : [],
|
|
613
629
|
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
614
630
|
bracketMatching(),
|
|
615
631
|
closeBrackets(),
|
|
616
632
|
drawSelection(),
|
|
617
|
-
|
|
618
|
-
|
|
633
|
+
highlightActiveLine(),
|
|
634
|
+
history(),
|
|
635
|
+
_placeholder ? placeholder(_placeholder) : [],
|
|
636
|
+
// https://github.com/codemirror/theme-one-dark
|
|
619
637
|
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
|
|
620
|
-
]
|
|
638
|
+
];
|
|
621
639
|
|
|
622
640
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
623
|
-
import { EditorView as
|
|
641
|
+
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
624
642
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
625
|
-
import { invariant } from "@dxos/invariant";
|
|
643
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
626
644
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
627
645
|
var defaultOptions = {
|
|
628
646
|
effect: 2,
|
|
@@ -656,10 +674,10 @@ var blast = (options = defaultOptions) => {
|
|
|
656
674
|
const getPoint = (view, pos) => {
|
|
657
675
|
const { left: x = 0, top: y = 0 } = view.coordsForChar(pos) ?? {};
|
|
658
676
|
const element = document.elementFromPoint(x, y);
|
|
659
|
-
const { offsetLeft: left = 0, offsetTop:
|
|
677
|
+
const { offsetLeft: left = 0, offsetTop: top2 = 0 } = view.scrollDOM.parentElement ?? {};
|
|
660
678
|
const point = {
|
|
661
679
|
x: x - left,
|
|
662
|
-
y: y -
|
|
680
|
+
y: y - top2
|
|
663
681
|
};
|
|
664
682
|
return {
|
|
665
683
|
element,
|
|
@@ -668,7 +686,7 @@ var blast = (options = defaultOptions) => {
|
|
|
668
686
|
};
|
|
669
687
|
return [
|
|
670
688
|
// Cursor moved.
|
|
671
|
-
|
|
689
|
+
EditorView4.updateListener.of((update2) => {
|
|
672
690
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
673
691
|
if (blaster) {
|
|
674
692
|
blaster.destroy();
|
|
@@ -749,7 +767,7 @@ var Blaster = class {
|
|
|
749
767
|
return this._node;
|
|
750
768
|
}
|
|
751
769
|
initialize() {
|
|
752
|
-
|
|
770
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
753
771
|
F: __dxlog_file2,
|
|
754
772
|
L: 138,
|
|
755
773
|
S: this,
|
|
@@ -786,7 +804,7 @@ var Blaster = class {
|
|
|
786
804
|
}
|
|
787
805
|
}
|
|
788
806
|
start() {
|
|
789
|
-
|
|
807
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
790
808
|
F: __dxlog_file2,
|
|
791
809
|
L: 177,
|
|
792
810
|
S: this,
|
|
@@ -929,9 +947,14 @@ var random = (min, max) => {
|
|
|
929
947
|
return min + ~~(Math.random() * (max - min + 1));
|
|
930
948
|
};
|
|
931
949
|
|
|
932
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
933
|
-
import {
|
|
934
|
-
import {
|
|
950
|
+
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
951
|
+
import { StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
952
|
+
import { hoverTooltip, keymap as keymap3, Decoration as Decoration2, EditorView as EditorView5 } from "@codemirror/view";
|
|
953
|
+
import sortBy from "lodash.sortby";
|
|
954
|
+
import { useEffect } from "react";
|
|
955
|
+
import { debounce } from "@dxos/async";
|
|
956
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
957
|
+
import { nonNullable } from "@dxos/util";
|
|
935
958
|
|
|
936
959
|
// packages/ui/react-ui-editor/src/styles/cursors.ts
|
|
937
960
|
import * as random2 from "lib0/random";
|
|
@@ -974,34 +997,15 @@ var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
|
|
|
974
997
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
975
998
|
import { mx } from "@dxos/react-ui-theme";
|
|
976
999
|
var headings = {
|
|
977
|
-
1:
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
987
|
-
"-ml-[7px]"
|
|
988
|
-
],
|
|
989
|
-
4: [
|
|
990
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
991
|
-
"-ml-[6px]"
|
|
992
|
-
],
|
|
993
|
-
5: [
|
|
994
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
995
|
-
"-ml-[5px]"
|
|
996
|
-
],
|
|
997
|
-
6: [
|
|
998
|
-
"mbs-4 mbe-2 font-medium text-inherit no-underline",
|
|
999
|
-
"-ml-[4px]"
|
|
1000
|
-
]
|
|
1001
|
-
};
|
|
1002
|
-
var heading = (level, readonly) => {
|
|
1003
|
-
const [style, offset] = headings[level];
|
|
1004
|
-
return mx(style, readonly && offset);
|
|
1000
|
+
1: "mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl",
|
|
1001
|
+
2: "mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl",
|
|
1002
|
+
3: "mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl",
|
|
1003
|
+
4: "mbs-4 mbe-2 font-medium text-inherit no-underline text-xl",
|
|
1004
|
+
5: "mbs-4 mbe-2 font-medium text-inherit no-underline text-lg",
|
|
1005
|
+
6: "mbs-4 mbe-2 font-medium text-inherit no-underline"
|
|
1006
|
+
};
|
|
1007
|
+
var heading = (level) => {
|
|
1008
|
+
return headings[level];
|
|
1005
1009
|
};
|
|
1006
1010
|
var light = "text-neutral-200 dark:text-neutral-800";
|
|
1007
1011
|
var mark = mx("!font-normal !no-underline !text-inherit opacity-40", light);
|
|
@@ -1019,154 +1023,112 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
|
1019
1023
|
var tokens = tailwindConfig({}).theme;
|
|
1020
1024
|
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1021
1025
|
|
|
1022
|
-
// packages/ui/react-ui-editor/src/
|
|
1023
|
-
|
|
1024
|
-
var
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
display: "block",
|
|
1036
|
-
paddingInline: "4px !important"
|
|
1037
|
-
},
|
|
1038
|
-
'& [aria-readonly="true"] .cm-codeblock-first': {
|
|
1039
|
-
paddingTop: "4px !important",
|
|
1040
|
-
borderTopLeftRadius: "4px",
|
|
1041
|
-
borderTopRightRadius: "4px"
|
|
1042
|
-
},
|
|
1043
|
-
'& [aria-readonly="true"] .cm-codeblock-last': {
|
|
1044
|
-
paddingBottom: "4px !important",
|
|
1045
|
-
borderBottomLeftRadius: "4px",
|
|
1046
|
-
borderBottomRightRadius: "4px"
|
|
1026
|
+
// packages/ui/react-ui-editor/src/util.ts
|
|
1027
|
+
import { log } from "@dxos/log";
|
|
1028
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1029
|
+
var callbackWrapper = (fn) => (...args) => {
|
|
1030
|
+
try {
|
|
1031
|
+
return fn(...args);
|
|
1032
|
+
} catch (err) {
|
|
1033
|
+
log.catch(err, void 0, {
|
|
1034
|
+
F: __dxlog_file3,
|
|
1035
|
+
L: 18,
|
|
1036
|
+
S: void 0,
|
|
1037
|
+
C: (f, a) => f(...a)
|
|
1038
|
+
});
|
|
1047
1039
|
}
|
|
1048
|
-
});
|
|
1049
|
-
var getLineRange = (lines, from, to) => {
|
|
1050
|
-
const start = lines.findIndex((line) => line.from >= from);
|
|
1051
|
-
const end = lines.findIndex((line) => line.to >= to);
|
|
1052
|
-
return [
|
|
1053
|
-
start,
|
|
1054
|
-
end
|
|
1055
|
-
];
|
|
1056
1040
|
};
|
|
1057
|
-
var
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const text = view.state.doc.sliceString(0);
|
|
1062
|
-
const matches = text.matchAll(CODE_REGEX);
|
|
1063
|
-
const blocks = view.viewportLineBlocks;
|
|
1064
|
-
for (const match of matches) {
|
|
1065
|
-
const range = getLineRange(blocks, match.index, match.index + match[0].length);
|
|
1066
|
-
for (let i = range[0]; i <= range[1]; i++) {
|
|
1067
|
-
const block = blocks[i];
|
|
1068
|
-
decorations.push(Decoration2.line({
|
|
1069
|
-
class: mx2("cm-codeblock", i === range[0] && "cm-codeblock-first", i === range[1] && "cm-codeblock-last")
|
|
1070
|
-
}).range(block.from));
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1041
|
+
var logChanges = (trs) => {
|
|
1042
|
+
const changes = trs.flatMap((tr) => {
|
|
1043
|
+
if (tr.changes.empty) {
|
|
1044
|
+
return void 0;
|
|
1073
1045
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
decorations: (value) => value.decorations
|
|
1088
|
-
}),
|
|
1089
|
-
styles2
|
|
1090
|
-
];
|
|
1046
|
+
const changes2 = [];
|
|
1047
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => changes2.push(JSON.stringify({
|
|
1048
|
+
fromA,
|
|
1049
|
+
toA,
|
|
1050
|
+
fromB,
|
|
1051
|
+
toB,
|
|
1052
|
+
inserted: inserted.toString()
|
|
1053
|
+
})));
|
|
1054
|
+
return changes2;
|
|
1055
|
+
}).filter(Boolean);
|
|
1056
|
+
if (changes.length) {
|
|
1057
|
+
console.log("changes", changes);
|
|
1058
|
+
}
|
|
1091
1059
|
};
|
|
1092
1060
|
|
|
1093
1061
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
import sortBy from "lodash.sortby";
|
|
1097
|
-
import { debounce } from "@dxos/async";
|
|
1098
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1099
|
-
import { log as log2 } from "@dxos/log";
|
|
1100
|
-
import { nonNullable } from "@dxos/util";
|
|
1101
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1102
|
-
var styles3 = EditorView5.baseTheme({
|
|
1103
|
-
"& .cm-bookmark": {
|
|
1104
|
-
cursor: "pointer",
|
|
1105
|
-
margin: "4px",
|
|
1106
|
-
padding: "4px",
|
|
1107
|
-
backgroundColor: "yellow"
|
|
1108
|
-
},
|
|
1109
|
-
"& .cm-bookmark-selected": {
|
|
1110
|
-
backgroundColor: "orange"
|
|
1111
|
-
},
|
|
1062
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1063
|
+
var styles2 = EditorView5.baseTheme({
|
|
1112
1064
|
"& .cm-comment": {
|
|
1113
1065
|
backgroundColor: getToken("extend.colors.yellow.50")
|
|
1114
1066
|
},
|
|
1115
|
-
"& .cm-comment-
|
|
1067
|
+
"& .cm-comment-current": {
|
|
1116
1068
|
backgroundColor: getToken("extend.colors.yellow.100")
|
|
1117
1069
|
}
|
|
1118
1070
|
});
|
|
1119
1071
|
var marks = {
|
|
1120
|
-
highlight:
|
|
1072
|
+
highlight: Decoration2.mark({
|
|
1121
1073
|
class: "cm-comment"
|
|
1122
1074
|
}),
|
|
1123
|
-
highlightActive:
|
|
1124
|
-
class: "cm-comment-
|
|
1075
|
+
highlightActive: Decoration2.mark({
|
|
1076
|
+
class: "cm-comment-current"
|
|
1125
1077
|
})
|
|
1126
1078
|
};
|
|
1127
|
-
var setFocus = (view,
|
|
1128
|
-
const
|
|
1129
|
-
if (!
|
|
1079
|
+
var setFocus = (view, id, center = true) => {
|
|
1080
|
+
const comment = view.state.field(commentsState).comments.find((range2) => range2.comment.id === id);
|
|
1081
|
+
if (!comment?.comment.cursor) {
|
|
1130
1082
|
return;
|
|
1131
1083
|
}
|
|
1132
|
-
view.
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1084
|
+
const range = Cursor.getRangeFromCursor(view.state, comment.comment.cursor);
|
|
1085
|
+
if (range) {
|
|
1086
|
+
view.dispatch({
|
|
1087
|
+
selection: {
|
|
1088
|
+
anchor: range.from
|
|
1089
|
+
},
|
|
1090
|
+
effects: [
|
|
1091
|
+
//
|
|
1092
|
+
EditorView5.scrollIntoView(range.from, center ? {
|
|
1093
|
+
y: "center"
|
|
1094
|
+
} : void 0),
|
|
1095
|
+
setSelection.of({
|
|
1096
|
+
current: id
|
|
1097
|
+
})
|
|
1098
|
+
]
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1141
1101
|
};
|
|
1142
|
-
var
|
|
1102
|
+
var setComments = StateEffect2.define();
|
|
1143
1103
|
var setSelection = StateEffect2.define();
|
|
1144
1104
|
var setCommentState = StateEffect2.define();
|
|
1145
|
-
var
|
|
1105
|
+
var commentsState = StateField2.define({
|
|
1146
1106
|
create: () => ({
|
|
1147
|
-
|
|
1107
|
+
comments: [],
|
|
1108
|
+
selection: {}
|
|
1148
1109
|
}),
|
|
1149
1110
|
update: (value, tr) => {
|
|
1150
|
-
const cursorConverter3 = tr.state.facet(CursorConverter);
|
|
1151
1111
|
for (const effect of tr.effects) {
|
|
1152
1112
|
if (effect.is(setSelection)) {
|
|
1153
1113
|
return {
|
|
1154
1114
|
...value,
|
|
1155
|
-
|
|
1115
|
+
selection: effect.value
|
|
1156
1116
|
};
|
|
1157
1117
|
}
|
|
1158
|
-
if (effect.is(
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1118
|
+
if (effect.is(setComments)) {
|
|
1119
|
+
const comments2 = effect.value.map((comment) => {
|
|
1120
|
+
if (!comment.cursor) {
|
|
1121
|
+
return void 0;
|
|
1122
|
+
}
|
|
1123
|
+
const range = Cursor.getRangeFromCursor(tr.state, comment.cursor);
|
|
1162
1124
|
return range && {
|
|
1163
|
-
|
|
1164
|
-
|
|
1125
|
+
comment,
|
|
1126
|
+
range
|
|
1165
1127
|
};
|
|
1166
1128
|
}).filter(nonNullable);
|
|
1167
1129
|
return {
|
|
1168
1130
|
...value,
|
|
1169
|
-
|
|
1131
|
+
comments: comments2
|
|
1170
1132
|
};
|
|
1171
1133
|
}
|
|
1172
1134
|
if (effect.is(setCommentState)) {
|
|
@@ -1177,141 +1139,132 @@ var commentsStateField = StateField2.define({
|
|
|
1177
1139
|
}
|
|
1178
1140
|
});
|
|
1179
1141
|
var highlightDecorations = EditorView5.decorations.compute([
|
|
1180
|
-
|
|
1142
|
+
commentsState
|
|
1181
1143
|
], (state) => {
|
|
1182
|
-
const {
|
|
1183
|
-
const decorations = sortBy(
|
|
1184
|
-
|
|
1144
|
+
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
1145
|
+
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1146
|
+
const range = comment.range;
|
|
1147
|
+
if (!range || range.from === range.to) {
|
|
1148
|
+
console.warn("Invalid range:", range);
|
|
1185
1149
|
return void 0;
|
|
1186
1150
|
}
|
|
1187
|
-
|
|
1188
|
-
from: selection.from,
|
|
1189
|
-
to: selection.to
|
|
1190
|
-
};
|
|
1191
|
-
if (selection.id === active) {
|
|
1151
|
+
if (comment.comment.id === current) {
|
|
1192
1152
|
return marks.highlightActive.range(range.from, range.to);
|
|
1193
1153
|
} else {
|
|
1194
1154
|
return marks.highlight.range(range.from, range.to);
|
|
1195
1155
|
}
|
|
1196
|
-
}).filter(nonNullable)
|
|
1197
|
-
return
|
|
1156
|
+
}).filter(nonNullable);
|
|
1157
|
+
return Decoration2.set(decorations);
|
|
1198
1158
|
});
|
|
1199
|
-
var
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
1217
|
-
}
|
|
1218
|
-
toDOM() {
|
|
1219
|
-
const span = document.createElement("span");
|
|
1220
|
-
span.className = "cm-bookmark";
|
|
1221
|
-
span.textContent = "\u203B";
|
|
1222
|
-
if (this._handleClick) {
|
|
1223
|
-
span.onclick = () => this._handleClick();
|
|
1159
|
+
var trackPastedComments = (onUpdate) => {
|
|
1160
|
+
let tracked = null;
|
|
1161
|
+
const handleTrack = (event, view) => {
|
|
1162
|
+
const comments2 = view.state.field(commentsState);
|
|
1163
|
+
const { main } = view.state.selection;
|
|
1164
|
+
const selectedRanges = comments2.comments.filter(({ range }) => range.from >= main.from && range.to <= main.to && range.from < range.to);
|
|
1165
|
+
if (!selectedRanges.length) {
|
|
1166
|
+
tracked = null;
|
|
1167
|
+
} else {
|
|
1168
|
+
tracked = {
|
|
1169
|
+
text: view.state.doc.slice(main.from, main.to),
|
|
1170
|
+
comments: selectedRanges.map(({ comment, range }) => ({
|
|
1171
|
+
id: comment.id,
|
|
1172
|
+
from: range.from - main.from,
|
|
1173
|
+
to: range.to - main.from
|
|
1174
|
+
}))
|
|
1175
|
+
};
|
|
1224
1176
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1177
|
+
};
|
|
1178
|
+
return [
|
|
1179
|
+
EditorView5.domEventHandlers({
|
|
1180
|
+
cut: handleTrack,
|
|
1181
|
+
copy: handleTrack
|
|
1182
|
+
}),
|
|
1183
|
+
// Handle paste.
|
|
1184
|
+
EditorView5.updateListener.of(({ view, state, transactions }) => {
|
|
1185
|
+
if (tracked) {
|
|
1186
|
+
const paste = transactions.find((tr) => tr.isUserEvent("input.paste"));
|
|
1187
|
+
if (paste) {
|
|
1188
|
+
let found = -1;
|
|
1189
|
+
paste.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
1190
|
+
if (text.eq(tracked.text)) {
|
|
1191
|
+
for (let i = transactions.indexOf(paste) + 1; i < transactions.length; i++) {
|
|
1192
|
+
fromB = transactions[i].changes.mapPos(fromB);
|
|
1193
|
+
}
|
|
1194
|
+
found = fromB;
|
|
1195
|
+
}
|
|
1196
|
+
});
|
|
1197
|
+
if (found > -1) {
|
|
1198
|
+
for (const moved of tracked.comments) {
|
|
1199
|
+
const range = {
|
|
1200
|
+
from: found + moved.from,
|
|
1201
|
+
to: found + moved.to
|
|
1202
|
+
};
|
|
1203
|
+
const cursor = Cursor.getCursorFromRange(state, range);
|
|
1204
|
+
onUpdate(moved.id, cursor);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
tracked = null;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
})
|
|
1211
|
+
];
|
|
1227
1212
|
};
|
|
1228
1213
|
var comments = (options = {}) => {
|
|
1214
|
+
const { key: shortcut = "meta-'" } = options;
|
|
1229
1215
|
const handleSelect = debounce((state) => options.onSelect?.(state), 200);
|
|
1230
1216
|
const createCommentThread = (view) => {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
L: 224,
|
|
1217
|
+
invariant3(options.onCreate, void 0, {
|
|
1218
|
+
F: __dxlog_file4,
|
|
1219
|
+
L: 259,
|
|
1235
1220
|
S: void 0,
|
|
1236
1221
|
A: [
|
|
1237
1222
|
"options.onCreate",
|
|
1238
1223
|
""
|
|
1239
1224
|
]
|
|
1240
1225
|
});
|
|
1241
|
-
const {
|
|
1226
|
+
const { from, to } = view.state.selection.main;
|
|
1242
1227
|
if (from === to) {
|
|
1243
1228
|
return false;
|
|
1244
1229
|
}
|
|
1245
|
-
|
|
1230
|
+
if (to === view.state.doc.length) {
|
|
1231
|
+
view.dispatch({
|
|
1232
|
+
changes: {
|
|
1233
|
+
from: to,
|
|
1234
|
+
insert: "\n"
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
1246
1239
|
from,
|
|
1247
1240
|
to
|
|
1248
1241
|
});
|
|
1249
|
-
if (
|
|
1250
|
-
const id =
|
|
1242
|
+
if (cursor) {
|
|
1243
|
+
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
1251
1244
|
if (id) {
|
|
1252
1245
|
view.dispatch({
|
|
1253
1246
|
effects: setSelection.of({
|
|
1254
|
-
|
|
1247
|
+
current: id
|
|
1255
1248
|
}),
|
|
1256
1249
|
selection: {
|
|
1257
1250
|
anchor: from
|
|
1258
1251
|
}
|
|
1259
1252
|
});
|
|
1260
|
-
if (options.footnote) {
|
|
1261
|
-
const tag = `[^${id}]`;
|
|
1262
|
-
view.dispatch({
|
|
1263
|
-
changes: {
|
|
1264
|
-
from: head,
|
|
1265
|
-
insert: tag
|
|
1266
|
-
},
|
|
1267
|
-
selection: {
|
|
1268
|
-
anchor: head + tag.length
|
|
1269
|
-
}
|
|
1270
|
-
});
|
|
1271
|
-
}
|
|
1272
1253
|
return true;
|
|
1273
1254
|
}
|
|
1274
1255
|
}
|
|
1275
1256
|
return false;
|
|
1276
1257
|
};
|
|
1277
|
-
const bookmarksViewPlugin = ViewPlugin4.fromClass(class BookmarkViewPlugin {
|
|
1278
|
-
static {
|
|
1279
|
-
// Match markdown footnotes (option).
|
|
1280
|
-
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
1281
|
-
this.bookmarkMatcher = new MatchDecorator({
|
|
1282
|
-
regexp: /\[\^(\w+)\]/g,
|
|
1283
|
-
decoration: (match, view, pos) => {
|
|
1284
|
-
const id = match[1];
|
|
1285
|
-
return Decoration3.replace({
|
|
1286
|
-
id,
|
|
1287
|
-
widget: new BookmarkWidget(pos, id)
|
|
1288
|
-
});
|
|
1289
|
-
}
|
|
1290
|
-
});
|
|
1291
|
-
}
|
|
1292
|
-
constructor(view) {
|
|
1293
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
1294
|
-
}
|
|
1295
|
-
update(update2) {
|
|
1296
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update2, this.bookmarks);
|
|
1297
|
-
}
|
|
1298
|
-
}, {
|
|
1299
|
-
decorations: (instance) => instance.bookmarks,
|
|
1300
|
-
provide: (plugin) => EditorView5.atomicRanges.of((view) => {
|
|
1301
|
-
return view.plugin(plugin)?.bookmarks || Decoration3.none;
|
|
1302
|
-
})
|
|
1303
|
-
});
|
|
1304
1258
|
return [
|
|
1305
|
-
|
|
1306
|
-
commentsStateField,
|
|
1259
|
+
commentsState,
|
|
1307
1260
|
highlightDecorations,
|
|
1308
|
-
|
|
1261
|
+
styles2,
|
|
1309
1262
|
//
|
|
1310
1263
|
// Keymap.
|
|
1311
1264
|
//
|
|
1312
1265
|
options.onCreate ? keymap3.of([
|
|
1313
1266
|
{
|
|
1314
|
-
key:
|
|
1267
|
+
key: shortcut,
|
|
1315
1268
|
run: callbackWrapper(createCommentThread)
|
|
1316
1269
|
}
|
|
1317
1270
|
]) : [],
|
|
@@ -1328,7 +1281,7 @@ var comments = (options = {}) => {
|
|
|
1328
1281
|
above: true,
|
|
1329
1282
|
create: () => {
|
|
1330
1283
|
const el = document.createElement("div");
|
|
1331
|
-
options.onHover
|
|
1284
|
+
options.onHover(el, shortcut);
|
|
1332
1285
|
return {
|
|
1333
1286
|
dom: el,
|
|
1334
1287
|
offset: {
|
|
@@ -1341,381 +1294,115 @@ var comments = (options = {}) => {
|
|
|
1341
1294
|
}
|
|
1342
1295
|
return null;
|
|
1343
1296
|
}, {
|
|
1344
|
-
|
|
1297
|
+
// TODO(burdon): Hide on change triggered immediately?
|
|
1298
|
+
// hideOnChange: true,
|
|
1345
1299
|
hoverTime: 1e3
|
|
1346
1300
|
}) : [],
|
|
1347
1301
|
//
|
|
1348
|
-
//
|
|
1349
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
1302
|
+
// Track deleted ranges and update ranges for decorations.
|
|
1350
1303
|
//
|
|
1351
1304
|
EditorView5.updateListener.of(({ view, state, changes }) => {
|
|
1352
|
-
|
|
1353
|
-
{
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
if (
|
|
1359
|
-
|
|
1360
|
-
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1361
|
-
log2.info("deleted comment", {
|
|
1362
|
-
thread: range.id
|
|
1363
|
-
}, {
|
|
1364
|
-
F: __dxlog_file3,
|
|
1365
|
-
L: 358,
|
|
1366
|
-
S: void 0,
|
|
1367
|
-
C: (f, a) => f(...a)
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
if (from <= range.to) {
|
|
1372
|
-
const newRange = getRangeFromCursor(cursorConverter3, range.cursor);
|
|
1373
|
-
Object.assign(range, newRange);
|
|
1374
|
-
mod = true;
|
|
1305
|
+
let mod = false;
|
|
1306
|
+
const { comments: comments2, ...value } = state.field(commentsState);
|
|
1307
|
+
changes.iterChanges((from, to, from2, to2) => {
|
|
1308
|
+
comments2.forEach(({ comment, range }) => {
|
|
1309
|
+
if (from2 === to2) {
|
|
1310
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1311
|
+
if (!newRange || newRange.to - newRange.from === 0) {
|
|
1312
|
+
options.onDelete?.(comment.id);
|
|
1375
1313
|
}
|
|
1376
|
-
}
|
|
1314
|
+
}
|
|
1315
|
+
if (from <= range.to) {
|
|
1316
|
+
const newRange = Cursor.getRangeFromCursor(view.state, comment.cursor);
|
|
1317
|
+
Object.assign(range, newRange);
|
|
1318
|
+
mod = true;
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
});
|
|
1322
|
+
if (mod) {
|
|
1323
|
+
view.dispatch({
|
|
1324
|
+
effects: setCommentState.of({
|
|
1325
|
+
comments: comments2,
|
|
1326
|
+
...value
|
|
1327
|
+
})
|
|
1377
1328
|
});
|
|
1378
|
-
if (mod) {
|
|
1379
|
-
view.dispatch({
|
|
1380
|
-
effects: setCommentState.of({
|
|
1381
|
-
active,
|
|
1382
|
-
ranges
|
|
1383
|
-
})
|
|
1384
|
-
});
|
|
1385
|
-
}
|
|
1386
1329
|
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1330
|
+
}),
|
|
1331
|
+
//
|
|
1332
|
+
// Track selection/proximity.
|
|
1333
|
+
//
|
|
1334
|
+
EditorView5.updateListener.of(({ view, state }) => {
|
|
1335
|
+
let min = Infinity;
|
|
1336
|
+
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
1337
|
+
const { head } = state.selection.main;
|
|
1338
|
+
const selection = {};
|
|
1339
|
+
comments2.forEach(({ comment, range }) => {
|
|
1340
|
+
if (head >= range.from && head <= range.to) {
|
|
1341
|
+
selection.current = comment.id;
|
|
1342
|
+
selection.closest = void 0;
|
|
1343
|
+
}
|
|
1344
|
+
if (!selection.current) {
|
|
1345
|
+
const d = Math.min(Math.abs(head - range.from), Math.abs(head - range.to));
|
|
1400
1346
|
if (d < min) {
|
|
1401
|
-
|
|
1347
|
+
selection.closest = comment.id;
|
|
1402
1348
|
min = d;
|
|
1403
1349
|
}
|
|
1404
|
-
});
|
|
1405
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
1406
|
-
view.dispatch({
|
|
1407
|
-
effects: setSelection.of(selected)
|
|
1408
|
-
});
|
|
1409
|
-
handleSelect({
|
|
1410
|
-
...selected,
|
|
1411
|
-
ranges: ranges.map((range) => ({
|
|
1412
|
-
...range,
|
|
1413
|
-
location: view.coordsAtPos(range.from)
|
|
1414
|
-
}))
|
|
1415
|
-
});
|
|
1416
1350
|
}
|
|
1351
|
+
});
|
|
1352
|
+
if (selection.current !== current || selection.closest !== closest) {
|
|
1353
|
+
view.dispatch({
|
|
1354
|
+
effects: setSelection.of(selection)
|
|
1355
|
+
});
|
|
1356
|
+
handleSelect({
|
|
1357
|
+
selection,
|
|
1358
|
+
comments: comments2.map(({ comment, range }) => ({
|
|
1359
|
+
comment,
|
|
1360
|
+
range,
|
|
1361
|
+
location: view.coordsAtPos(range.from)
|
|
1362
|
+
}))
|
|
1363
|
+
});
|
|
1417
1364
|
}
|
|
1418
|
-
})
|
|
1365
|
+
}),
|
|
1366
|
+
options.onUpdate ? trackPastedComments(options.onUpdate) : []
|
|
1419
1367
|
];
|
|
1420
1368
|
};
|
|
1421
|
-
var
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
const to = cursorConverter3.fromCursor(parts[1]);
|
|
1433
|
-
return from !== void 0 && to !== void 0 ? {
|
|
1434
|
-
from,
|
|
1435
|
-
to
|
|
1436
|
-
} : void 0;
|
|
1369
|
+
var useComments = (view, comments2 = []) => {
|
|
1370
|
+
useEffect(() => {
|
|
1371
|
+
if (view) {
|
|
1372
|
+
view.dispatch({
|
|
1373
|
+
effects: setComments.of(comments2)
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}, [
|
|
1377
|
+
view,
|
|
1378
|
+
comments2
|
|
1379
|
+
]);
|
|
1437
1380
|
};
|
|
1438
1381
|
|
|
1439
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1440
|
-
import {
|
|
1441
|
-
var
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
this._pos = _pos;
|
|
1452
|
-
}
|
|
1453
|
-
eq(other) {
|
|
1454
|
-
return this._pos === other._pos;
|
|
1455
|
-
}
|
|
1456
|
-
toDOM(view) {
|
|
1457
|
-
const el = document.createElement("div");
|
|
1458
|
-
el.className = "cm-hr";
|
|
1459
|
-
return el;
|
|
1460
|
-
}
|
|
1461
|
-
};
|
|
1462
|
-
var placeholderMatcher = new MatchDecorator2({
|
|
1463
|
-
regexp: /^---$/g,
|
|
1464
|
-
decoration: (match, view, pos) => Decoration4.replace({
|
|
1465
|
-
widget: new HorizontalRuleWidget(pos)
|
|
1466
|
-
})
|
|
1467
|
-
});
|
|
1468
|
-
var hr = () => [
|
|
1469
|
-
styles4,
|
|
1470
|
-
ViewPlugin5.fromClass(class {
|
|
1471
|
-
constructor(view) {
|
|
1472
|
-
this.rules = placeholderMatcher.createDeco(view);
|
|
1473
|
-
}
|
|
1474
|
-
update(update2) {
|
|
1475
|
-
this.rules = placeholderMatcher.updateDeco(update2, this.rules);
|
|
1476
|
-
}
|
|
1477
|
-
}, {
|
|
1478
|
-
decorations: (instance) => instance.rules,
|
|
1479
|
-
// TODO(burdon): Is this really atomic (cursor can move into ---).
|
|
1480
|
-
provide: (plugin) => EditorView6.atomicRanges.of((view) => {
|
|
1481
|
-
return view.plugin(plugin)?.rules || Decoration4.none;
|
|
1482
|
-
})
|
|
1483
|
-
})
|
|
1484
|
-
];
|
|
1485
|
-
|
|
1486
|
-
// packages/ui/react-ui-editor/src/extensions/image.ts
|
|
1487
|
-
import { syntaxTree } from "@codemirror/language";
|
|
1488
|
-
import { StateField as StateField3 } from "@codemirror/state";
|
|
1489
|
-
import { Decoration as Decoration5, EditorView as EditorView7, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1490
|
-
var image = (options = {}) => {
|
|
1491
|
-
return StateField3.define({
|
|
1492
|
-
create: (state) => {
|
|
1493
|
-
return Decoration5.set(buildDecorations(0, state.doc.length, state));
|
|
1494
|
-
},
|
|
1495
|
-
update: (value, tr) => {
|
|
1496
|
-
if (!tr.docChanged && !tr.selection) {
|
|
1497
|
-
return value;
|
|
1498
|
-
}
|
|
1499
|
-
const cursor = tr.state.selection.main.head;
|
|
1500
|
-
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1501
|
-
let from = Math.min(cursor, oldCursor);
|
|
1502
|
-
let to = Math.max(cursor, oldCursor);
|
|
1503
|
-
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1504
|
-
from = Math.min(from, fromB);
|
|
1505
|
-
to = Math.max(to, toB);
|
|
1506
|
-
});
|
|
1507
|
-
from = tr.state.doc.lineAt(from).from;
|
|
1508
|
-
to = tr.state.doc.lineAt(to).to;
|
|
1509
|
-
return value.map(tr.changes).update({
|
|
1510
|
-
filterFrom: from,
|
|
1511
|
-
filterTo: to,
|
|
1512
|
-
filter: () => false,
|
|
1513
|
-
add: buildDecorations(from, to, tr.state)
|
|
1514
|
-
});
|
|
1515
|
-
},
|
|
1516
|
-
provide: (field) => EditorView7.decorations.from(field)
|
|
1517
|
-
});
|
|
1518
|
-
};
|
|
1519
|
-
var buildDecorations = (from, to, state) => {
|
|
1520
|
-
const decorations = [];
|
|
1521
|
-
const cursor = state.selection.main.head;
|
|
1522
|
-
syntaxTree(state).iterate({
|
|
1523
|
-
enter: (node) => {
|
|
1524
|
-
if (node.name === "Image") {
|
|
1525
|
-
const urlNode = node.node.getChild("URL");
|
|
1526
|
-
if (urlNode) {
|
|
1527
|
-
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1528
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1529
|
-
decorations.push(Decoration5.replace({
|
|
1530
|
-
block: true,
|
|
1531
|
-
widget: new ImageWidget(url)
|
|
1532
|
-
}).range(hide ? node.from : node.to, node.to));
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
},
|
|
1536
|
-
from,
|
|
1537
|
-
to
|
|
1538
|
-
});
|
|
1539
|
-
return decorations;
|
|
1540
|
-
};
|
|
1541
|
-
var ImageWidget = class extends WidgetType4 {
|
|
1542
|
-
constructor(_url) {
|
|
1543
|
-
super();
|
|
1544
|
-
this._url = _url;
|
|
1545
|
-
}
|
|
1546
|
-
eq(other) {
|
|
1547
|
-
return this._url === other._url;
|
|
1548
|
-
}
|
|
1549
|
-
toDOM(view) {
|
|
1550
|
-
const img = document.createElement("img");
|
|
1551
|
-
img.setAttribute("src", this._url);
|
|
1552
|
-
img.setAttribute("class", "cm-image");
|
|
1553
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1554
|
-
return img;
|
|
1555
|
-
}
|
|
1556
|
-
};
|
|
1557
|
-
|
|
1558
|
-
// packages/ui/react-ui-editor/src/extensions/link.ts
|
|
1559
|
-
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
1560
|
-
import { RangeSetBuilder } from "@codemirror/state";
|
|
1561
|
-
import { Decoration as Decoration6, WidgetType as WidgetType5, hoverTooltip as hoverTooltip2, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
1562
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1563
|
-
var link = (options = {}) => {
|
|
1564
|
-
const extensions = [
|
|
1565
|
-
ViewPlugin6.fromClass(class {
|
|
1566
|
-
constructor(view) {
|
|
1567
|
-
this.decorations = buildDecorations2(view, options);
|
|
1568
|
-
}
|
|
1569
|
-
update(update2) {
|
|
1570
|
-
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1571
|
-
this.decorations = buildDecorations2(update2.view, options);
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
}, {
|
|
1575
|
-
decorations: (v) => v.decorations
|
|
1576
|
-
})
|
|
1577
|
-
];
|
|
1578
|
-
if (options.onHover) {
|
|
1579
|
-
extensions.push(
|
|
1580
|
-
// https://codemirror.net/examples/tooltip
|
|
1581
|
-
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1582
|
-
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1583
|
-
hoverTooltip2((view, pos, side) => {
|
|
1584
|
-
const syntax = syntaxTree2(view.state).resolveInner(pos, side);
|
|
1585
|
-
let link2 = null;
|
|
1586
|
-
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1587
|
-
link2 = node.name === "Link" ? node : null;
|
|
1588
|
-
}
|
|
1589
|
-
const url = link2 && link2.getChild("URL");
|
|
1590
|
-
if (!url || !link2) {
|
|
1591
|
-
return null;
|
|
1592
|
-
}
|
|
1593
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1594
|
-
return {
|
|
1595
|
-
pos: link2.from,
|
|
1596
|
-
end: link2.to,
|
|
1597
|
-
above: true,
|
|
1598
|
-
create: () => {
|
|
1599
|
-
const el = document.createElement("div");
|
|
1600
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1601
|
-
options.onHover(el, urlText);
|
|
1602
|
-
return {
|
|
1603
|
-
dom: el,
|
|
1604
|
-
offset: {
|
|
1605
|
-
x: 0,
|
|
1606
|
-
y: 4
|
|
1607
|
-
}
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1610
|
-
};
|
|
1611
|
-
})
|
|
1612
|
-
);
|
|
1613
|
-
}
|
|
1614
|
-
return extensions;
|
|
1615
|
-
};
|
|
1616
|
-
var LinkButton = class extends WidgetType5 {
|
|
1617
|
-
constructor(_url, _onAttach) {
|
|
1618
|
-
super();
|
|
1619
|
-
this._url = _url;
|
|
1620
|
-
this._onAttach = _onAttach;
|
|
1621
|
-
}
|
|
1622
|
-
eq(other) {
|
|
1623
|
-
return this._url === other._url;
|
|
1624
|
-
}
|
|
1625
|
-
toDOM(view) {
|
|
1626
|
-
const el = document.createElement("span");
|
|
1627
|
-
this._onAttach(el, this._url);
|
|
1628
|
-
return el;
|
|
1629
|
-
}
|
|
1630
|
-
};
|
|
1631
|
-
var LinkText = class extends WidgetType5 {
|
|
1632
|
-
constructor(_text, _url) {
|
|
1633
|
-
super();
|
|
1634
|
-
this._text = _text;
|
|
1635
|
-
this._url = _url;
|
|
1636
|
-
}
|
|
1637
|
-
eq(other) {
|
|
1638
|
-
return this._url === other._url;
|
|
1639
|
-
}
|
|
1640
|
-
toDOM(view) {
|
|
1641
|
-
const link2 = document.createElement("a");
|
|
1642
|
-
link2.setAttribute("class", "cm-link");
|
|
1643
|
-
link2.textContent = this._text;
|
|
1644
|
-
if (this._url) {
|
|
1645
|
-
link2.setAttribute("rel", "noreferrer");
|
|
1646
|
-
link2.setAttribute("target", "_blank");
|
|
1647
|
-
link2.href = this._url;
|
|
1648
|
-
} else {
|
|
1649
|
-
link2.onclick = () => {
|
|
1650
|
-
view.dispatch({
|
|
1651
|
-
selection: {
|
|
1652
|
-
anchor: view.posAtDOM(link2)
|
|
1653
|
-
}
|
|
1654
|
-
});
|
|
1655
|
-
};
|
|
1656
|
-
}
|
|
1657
|
-
return link2;
|
|
1658
|
-
}
|
|
1659
|
-
};
|
|
1660
|
-
var buildDecorations2 = (view, options) => {
|
|
1661
|
-
const builder = new RangeSetBuilder();
|
|
1662
|
-
const { state } = view;
|
|
1663
|
-
const cursor = state.selection.main.head;
|
|
1664
|
-
for (const { from, to } of view.visibleRanges) {
|
|
1665
|
-
syntaxTree2(state).iterate({
|
|
1666
|
-
enter: (node) => {
|
|
1667
|
-
if (node.name === "Link") {
|
|
1668
|
-
const marks2 = node.node.getChildren("LinkMark");
|
|
1669
|
-
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
1670
|
-
const urlNode = node.node.getChild("URL");
|
|
1671
|
-
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
1672
|
-
if (!url) {
|
|
1673
|
-
return false;
|
|
1674
|
-
}
|
|
1675
|
-
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1676
|
-
builder.add(node.from, node.to, Decoration6.replace({
|
|
1677
|
-
widget: new LinkText(text, options.link ? url : void 0)
|
|
1678
|
-
}));
|
|
1679
|
-
}
|
|
1680
|
-
if (options.onRender) {
|
|
1681
|
-
builder.add(node.to, node.to, Decoration6.replace({
|
|
1682
|
-
widget: new LinkButton(url, options.onRender)
|
|
1683
|
-
}));
|
|
1684
|
-
}
|
|
1685
|
-
return false;
|
|
1686
|
-
}
|
|
1687
|
-
},
|
|
1688
|
-
from,
|
|
1689
|
-
to
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
return builder.finish();
|
|
1693
|
-
};
|
|
1694
|
-
|
|
1695
|
-
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1696
|
-
import { EditorView as EditorView8 } from "@codemirror/view";
|
|
1697
|
-
var listener = ({ onFocus, onChange }) => {
|
|
1698
|
-
const extensions = [];
|
|
1699
|
-
onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
|
|
1700
|
-
onFocus(focused);
|
|
1701
|
-
return null;
|
|
1702
|
-
}));
|
|
1703
|
-
onChange && extensions.push(EditorView8.updateListener.of((update2) => {
|
|
1704
|
-
onChange(update2.state.doc.toString());
|
|
1705
|
-
}));
|
|
1706
|
-
return extensions;
|
|
1382
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
1383
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
1384
|
+
var listener = ({ onFocus, onChange }) => {
|
|
1385
|
+
const extensions = [];
|
|
1386
|
+
onFocus && extensions.push(EditorView6.focusChangeEffect.of((_, focused) => {
|
|
1387
|
+
onFocus(focused);
|
|
1388
|
+
return null;
|
|
1389
|
+
}));
|
|
1390
|
+
onChange && extensions.push(EditorView6.updateListener.of((update2) => {
|
|
1391
|
+
onChange(update2.state.doc.toString());
|
|
1392
|
+
}));
|
|
1393
|
+
return extensions;
|
|
1707
1394
|
};
|
|
1708
1395
|
|
|
1709
1396
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1710
1397
|
import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1711
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1398
|
+
import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1712
1399
|
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
1713
1400
|
import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
1714
1401
|
import { languages } from "@codemirror/language-data";
|
|
1715
1402
|
import { searchKeymap } from "@codemirror/search";
|
|
1716
1403
|
import { EditorState } from "@codemirror/state";
|
|
1717
1404
|
import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
|
|
1718
|
-
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as
|
|
1405
|
+
import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView7, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
|
|
1719
1406
|
|
|
1720
1407
|
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
1721
1408
|
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
@@ -1728,7 +1415,6 @@ var markdownTags = {
|
|
|
1728
1415
|
CodeText: Tag.define(),
|
|
1729
1416
|
EmphasisMark: Tag.define(),
|
|
1730
1417
|
HeaderMark: Tag.define(),
|
|
1731
|
-
// HorizontalRule: Tag.define(),
|
|
1732
1418
|
InlineCode: Tag.define(),
|
|
1733
1419
|
LinkLabel: Tag.define(),
|
|
1734
1420
|
LinkReference: Tag.define(),
|
|
@@ -1813,7 +1499,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1813
1499
|
markdownTags.QuoteMark,
|
|
1814
1500
|
markdownTags.EmphasisMark
|
|
1815
1501
|
],
|
|
1816
|
-
class:
|
|
1502
|
+
class: mark
|
|
1817
1503
|
},
|
|
1818
1504
|
// E.g., code block language (after ```).
|
|
1819
1505
|
{
|
|
@@ -1821,7 +1507,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1821
1507
|
tags.function(tags.variableName),
|
|
1822
1508
|
tags.labelName
|
|
1823
1509
|
],
|
|
1824
|
-
class:
|
|
1510
|
+
class: codeMark
|
|
1825
1511
|
},
|
|
1826
1512
|
{
|
|
1827
1513
|
tag: [
|
|
@@ -1832,27 +1518,27 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1832
1518
|
// Headings.
|
|
1833
1519
|
{
|
|
1834
1520
|
tag: tags.heading1,
|
|
1835
|
-
class: heading(1
|
|
1521
|
+
class: heading(1)
|
|
1836
1522
|
},
|
|
1837
1523
|
{
|
|
1838
1524
|
tag: tags.heading2,
|
|
1839
|
-
class: heading(2
|
|
1525
|
+
class: heading(2)
|
|
1840
1526
|
},
|
|
1841
1527
|
{
|
|
1842
1528
|
tag: tags.heading3,
|
|
1843
|
-
class: heading(3
|
|
1529
|
+
class: heading(3)
|
|
1844
1530
|
},
|
|
1845
1531
|
{
|
|
1846
1532
|
tag: tags.heading4,
|
|
1847
|
-
class: heading(4
|
|
1533
|
+
class: heading(4)
|
|
1848
1534
|
},
|
|
1849
1535
|
{
|
|
1850
1536
|
tag: tags.heading5,
|
|
1851
|
-
class: heading(5
|
|
1537
|
+
class: heading(5)
|
|
1852
1538
|
},
|
|
1853
1539
|
{
|
|
1854
1540
|
tag: tags.heading6,
|
|
1855
|
-
class: heading(6
|
|
1541
|
+
class: heading(6)
|
|
1856
1542
|
},
|
|
1857
1543
|
// Emphasis.
|
|
1858
1544
|
{
|
|
@@ -1878,7 +1564,7 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1878
1564
|
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
1879
1565
|
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
1880
1566
|
// the code, but all other CSS properties will be inherited.
|
|
1881
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font.
|
|
1567
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
1882
1568
|
{
|
|
1883
1569
|
tag: [
|
|
1884
1570
|
markdownTags.CodeText,
|
|
@@ -1892,12 +1578,6 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1892
1578
|
],
|
|
1893
1579
|
class: blockquote
|
|
1894
1580
|
},
|
|
1895
|
-
// TODO(burdon): Replace with extension.
|
|
1896
|
-
// {
|
|
1897
|
-
// tag: [markdownTags.HorizontalRule],
|
|
1898
|
-
// class: mx(horizontalRule, readonly && '-indent-[100rem]'),
|
|
1899
|
-
// },
|
|
1900
|
-
// TODO(burdon): Only if being edited.
|
|
1901
1581
|
{
|
|
1902
1582
|
tag: [
|
|
1903
1583
|
markdownTags.TableCell
|
|
@@ -1913,21 +1593,21 @@ var markdownHighlightStyle = (readonly) => {
|
|
|
1913
1593
|
};
|
|
1914
1594
|
|
|
1915
1595
|
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
1916
|
-
var markdownBundle = ({
|
|
1596
|
+
var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
|
|
1917
1597
|
return [
|
|
1918
1598
|
EditorState.allowMultipleSelections.of(true),
|
|
1919
1599
|
EditorState.tabSize.of(2),
|
|
1920
|
-
|
|
1921
|
-
|
|
1600
|
+
EditorView7.lineWrapping,
|
|
1601
|
+
// https://github.com/codemirror/basic-setup
|
|
1922
1602
|
bracketMatching2(),
|
|
1923
1603
|
closeBrackets2(),
|
|
1924
1604
|
crosshairCursor(),
|
|
1925
1605
|
dropCursor(),
|
|
1926
1606
|
drawSelection2(),
|
|
1927
|
-
|
|
1928
|
-
|
|
1607
|
+
highlightActiveLine2(),
|
|
1608
|
+
history2(),
|
|
1929
1609
|
indentOnInput(),
|
|
1930
|
-
_placeholder
|
|
1610
|
+
_placeholder ? placeholder2(_placeholder) : [],
|
|
1931
1611
|
// Main extension.
|
|
1932
1612
|
// https://github.com/codemirror/lang-markdown
|
|
1933
1613
|
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
@@ -1949,58 +1629,445 @@ var markdownBundle = ({ readonly, themeMode, placeholder: _placeholder }) => {
|
|
|
1949
1629
|
// https://github.com/codemirror/theme-one-dark
|
|
1950
1630
|
themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
|
|
1951
1631
|
// Custom styles.
|
|
1952
|
-
syntaxHighlighting2(markdownHighlightStyle(
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1632
|
+
syntaxHighlighting2(markdownHighlightStyle()),
|
|
1633
|
+
keymap4.of([
|
|
1634
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
1635
|
+
indentWithTab,
|
|
1636
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
1637
|
+
...closeBracketsKeymap,
|
|
1638
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
1639
|
+
...historyKeymap,
|
|
1640
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
1641
|
+
...searchKeymap,
|
|
1642
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
1643
|
+
...standardKeymap
|
|
1644
|
+
])
|
|
1645
|
+
];
|
|
1646
|
+
};
|
|
1967
1647
|
|
|
1968
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1969
|
-
import {
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1648
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/code.ts
|
|
1649
|
+
import { syntaxTree } from "@codemirror/language";
|
|
1650
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
1651
|
+
import { ViewPlugin as ViewPlugin3, EditorView as EditorView8, Decoration as Decoration3, WidgetType as WidgetType2 } from "@codemirror/view";
|
|
1652
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1653
|
+
var styles3 = EditorView8.baseTheme({
|
|
1654
|
+
"& .cm-code": {
|
|
1655
|
+
paddingInline: "1rem !important",
|
|
1656
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1657
|
+
},
|
|
1658
|
+
"& .cm-codeblock": {
|
|
1659
|
+
display: "inline-block",
|
|
1660
|
+
width: "100%"
|
|
1661
|
+
},
|
|
1662
|
+
"&light .cm-codeblock, &light .cm-codeblock.cm-activeLine": {
|
|
1663
|
+
background: getToken("extend.colors.neutral.25")
|
|
1664
|
+
},
|
|
1665
|
+
"&dark .cm-codeblock, &dark .cm-codeblock.cm-activeLine": {
|
|
1666
|
+
background: getToken("extend.colors.neutral.850")
|
|
1667
|
+
},
|
|
1668
|
+
"& .cm-codeblock-first": {
|
|
1669
|
+
borderTopLeftRadius: ".5rem",
|
|
1670
|
+
borderTopRightRadius: ".5rem"
|
|
1671
|
+
},
|
|
1672
|
+
"& .cm-codeblock-last": {
|
|
1673
|
+
borderBottomLeftRadius: ".5rem",
|
|
1674
|
+
borderBottomRightRadius: ".5rem"
|
|
1675
|
+
}
|
|
1676
|
+
});
|
|
1677
|
+
var getLineRange = (lines, from, to) => {
|
|
1678
|
+
const start = lines.findIndex((line) => line.from >= from);
|
|
1679
|
+
const end = lines.findIndex((line) => line.to >= to);
|
|
1680
|
+
return [
|
|
1681
|
+
start,
|
|
1682
|
+
end
|
|
1683
|
+
];
|
|
1684
|
+
};
|
|
1685
|
+
var LineWidget = class extends WidgetType2 {
|
|
1686
|
+
constructor(_className) {
|
|
1687
|
+
super();
|
|
1688
|
+
this._className = _className;
|
|
1689
|
+
}
|
|
1690
|
+
toDOM() {
|
|
1691
|
+
const el = document.createElement("span");
|
|
1692
|
+
el.innerHTML = " ";
|
|
1693
|
+
el.className = mx2("cm-code cm-codeblock", this._className);
|
|
1694
|
+
return el;
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
var top = new LineWidget("cm-codeblock-first");
|
|
1698
|
+
var bottom = new LineWidget("cm-codeblock-last");
|
|
1699
|
+
var buildDecorations = (view) => {
|
|
1700
|
+
const builder = new RangeSetBuilder();
|
|
1701
|
+
const { state } = view;
|
|
1702
|
+
const blocks = view.viewportLineBlocks;
|
|
1703
|
+
const cursor = state.selection.main.head;
|
|
1704
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1705
|
+
syntaxTree(state).iterate({
|
|
1706
|
+
enter: (node) => {
|
|
1707
|
+
if (node.name === "FencedCode") {
|
|
1708
|
+
const edit = !view.state.readOnly && cursor >= node.from && cursor <= node.to;
|
|
1709
|
+
const range = getLineRange(blocks, node.from, node.to);
|
|
1710
|
+
for (let i = range[0]; i <= range[1]; i++) {
|
|
1711
|
+
const block = blocks[i];
|
|
1712
|
+
if (!edit && (i === range[0] || i === range[1])) {
|
|
1713
|
+
builder.add(block.from, block.to, Decoration3.replace({
|
|
1714
|
+
widget: i === range[0] ? top : bottom
|
|
1715
|
+
}));
|
|
1716
|
+
} else {
|
|
1717
|
+
builder.add(block.from, block.from, Decoration3.line({
|
|
1718
|
+
class: mx2("cm-code cm-codeblock")
|
|
1719
|
+
}));
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
},
|
|
1724
|
+
from,
|
|
1725
|
+
to
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
return builder.finish();
|
|
1729
|
+
};
|
|
1730
|
+
var code2 = () => {
|
|
1731
|
+
return [
|
|
1732
|
+
ViewPlugin3.fromClass(class {
|
|
1733
|
+
constructor(view) {
|
|
1734
|
+
this.decorations = buildDecorations(view);
|
|
1735
|
+
}
|
|
1736
|
+
update(update2) {
|
|
1737
|
+
this.decorations = buildDecorations(update2.view);
|
|
1738
|
+
}
|
|
1739
|
+
}, {
|
|
1740
|
+
decorations: (value) => value.decorations
|
|
1741
|
+
}),
|
|
1742
|
+
styles3
|
|
1743
|
+
];
|
|
1744
|
+
};
|
|
1745
|
+
|
|
1746
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/heading.ts
|
|
1747
|
+
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
|
+
var buildDecorations2 = (view) => {
|
|
1751
|
+
const builder = new RangeSetBuilder2();
|
|
1752
|
+
const { state } = view;
|
|
1753
|
+
const cursor = state.selection.main.head;
|
|
1754
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1755
|
+
syntaxTree2(state).iterate({
|
|
1756
|
+
enter: (node) => {
|
|
1757
|
+
switch (node.name) {
|
|
1758
|
+
case "ATXHeading1":
|
|
1759
|
+
case "ATXHeading2":
|
|
1760
|
+
case "ATXHeading3":
|
|
1761
|
+
case "ATXHeading4":
|
|
1762
|
+
case "ATXHeading5":
|
|
1763
|
+
case "ATXHeading6": {
|
|
1764
|
+
const mark2 = node.node.getChild("HeaderMark");
|
|
1765
|
+
if (mark2) {
|
|
1766
|
+
if (view.state.readOnly || cursor < node.from || cursor > node.to) {
|
|
1767
|
+
builder.add(mark2.from, mark2.to + 1, Decoration4.replace({}));
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
},
|
|
1773
|
+
from,
|
|
1774
|
+
to
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1777
|
+
return builder.finish();
|
|
1778
|
+
};
|
|
1779
|
+
var heading2 = () => {
|
|
1780
|
+
return [
|
|
1781
|
+
ViewPlugin4.fromClass(class {
|
|
1782
|
+
constructor(view) {
|
|
1783
|
+
this.decorations = buildDecorations2(view);
|
|
1784
|
+
}
|
|
1785
|
+
update(update2) {
|
|
1786
|
+
this.decorations = buildDecorations2(update2.view);
|
|
1787
|
+
}
|
|
1788
|
+
}, {
|
|
1789
|
+
decorations: (value) => value.decorations
|
|
1790
|
+
})
|
|
1791
|
+
];
|
|
1792
|
+
};
|
|
1793
|
+
|
|
1794
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/hr.ts
|
|
1795
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
1796
|
+
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
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")}`
|
|
1802
|
+
}
|
|
1803
|
+
});
|
|
1804
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
1805
|
+
toDOM() {
|
|
1806
|
+
const el = document.createElement("div");
|
|
1807
|
+
el.className = "cm-hr";
|
|
1808
|
+
return el;
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
1811
|
+
var decoration = Decoration5.replace({
|
|
1812
|
+
widget: new HorizontalRuleWidget()
|
|
1813
|
+
});
|
|
1814
|
+
var buildDecorations3 = (view) => {
|
|
1815
|
+
const builder = new RangeSetBuilder3();
|
|
1816
|
+
const { state } = view;
|
|
1817
|
+
const cursor = state.selection.main.head;
|
|
1818
|
+
for (const { from, to } of view.visibleRanges) {
|
|
1819
|
+
syntaxTree3(state).iterate({
|
|
1820
|
+
enter: (node) => {
|
|
1821
|
+
if (node.name === "HorizontalRule") {
|
|
1822
|
+
if (cursor <= node.from || cursor >= node.to) {
|
|
1823
|
+
builder.add(node.from, node.to, decoration);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
},
|
|
1827
|
+
from,
|
|
1828
|
+
to
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
return builder.finish();
|
|
1832
|
+
};
|
|
1833
|
+
var hr = () => {
|
|
1834
|
+
return [
|
|
1835
|
+
ViewPlugin5.fromClass(class {
|
|
1836
|
+
constructor(view) {
|
|
1837
|
+
this.decorations = buildDecorations3(view);
|
|
1838
|
+
}
|
|
1839
|
+
update(update2) {
|
|
1840
|
+
this.decorations = buildDecorations3(update2.view);
|
|
1841
|
+
}
|
|
1842
|
+
}, {
|
|
1843
|
+
decorations: (value) => value.decorations
|
|
1844
|
+
}),
|
|
1845
|
+
styles4
|
|
1846
|
+
];
|
|
1847
|
+
};
|
|
1848
|
+
|
|
1849
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
1850
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
1851
|
+
import { StateField as StateField3 } from "@codemirror/state";
|
|
1852
|
+
import { Decoration as Decoration6, EditorView as EditorView10, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
1853
|
+
var image = (options = {}) => {
|
|
1854
|
+
return StateField3.define({
|
|
1855
|
+
create: (state) => {
|
|
1856
|
+
return Decoration6.set(buildDecorations4(0, state.doc.length, state));
|
|
1857
|
+
},
|
|
1858
|
+
update: (value, tr) => {
|
|
1859
|
+
if (!tr.docChanged && !tr.selection) {
|
|
1860
|
+
return value;
|
|
1861
|
+
}
|
|
1862
|
+
const cursor = tr.state.selection.main.head;
|
|
1863
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
1864
|
+
let from = Math.min(cursor, oldCursor);
|
|
1865
|
+
let to = Math.max(cursor, oldCursor);
|
|
1866
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
1867
|
+
from = Math.min(from, fromB);
|
|
1868
|
+
to = Math.max(to, toB);
|
|
1869
|
+
});
|
|
1870
|
+
from = tr.state.doc.lineAt(from).from;
|
|
1871
|
+
to = tr.state.doc.lineAt(to).to;
|
|
1872
|
+
return value.map(tr.changes).update({
|
|
1873
|
+
filterFrom: from,
|
|
1874
|
+
filterTo: to,
|
|
1875
|
+
filter: () => false,
|
|
1876
|
+
add: buildDecorations4(from, to, tr.state)
|
|
1877
|
+
});
|
|
1878
|
+
},
|
|
1879
|
+
provide: (field) => EditorView10.decorations.from(field)
|
|
1880
|
+
});
|
|
1881
|
+
};
|
|
1882
|
+
var buildDecorations4 = (from, to, state) => {
|
|
1883
|
+
const decorations = [];
|
|
1884
|
+
const cursor = state.selection.main.head;
|
|
1885
|
+
syntaxTree4(state).iterate({
|
|
1886
|
+
enter: (node) => {
|
|
1887
|
+
if (node.name === "Image") {
|
|
1888
|
+
const urlNode = node.node.getChild("URL");
|
|
1889
|
+
if (urlNode) {
|
|
1890
|
+
const hide = state.readOnly || cursor < node.from || cursor > node.to;
|
|
1891
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
1892
|
+
decorations.push(Decoration6.replace({
|
|
1893
|
+
block: true,
|
|
1894
|
+
widget: new ImageWidget(url)
|
|
1895
|
+
}).range(hide ? node.from : node.to, node.to));
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
},
|
|
1899
|
+
from,
|
|
1900
|
+
to
|
|
1901
|
+
});
|
|
1902
|
+
return decorations;
|
|
1903
|
+
};
|
|
1904
|
+
var ImageWidget = class extends WidgetType4 {
|
|
1905
|
+
constructor(_url) {
|
|
1906
|
+
super();
|
|
1907
|
+
this._url = _url;
|
|
1908
|
+
}
|
|
1909
|
+
eq(other) {
|
|
1910
|
+
return this._url === other._url;
|
|
1911
|
+
}
|
|
1912
|
+
toDOM(view) {
|
|
1913
|
+
const img = document.createElement("img");
|
|
1914
|
+
img.setAttribute("src", this._url);
|
|
1915
|
+
img.setAttribute("class", "cm-image");
|
|
1916
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
1917
|
+
return img;
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
|
|
1921
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
1922
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
1923
|
+
import { RangeSetBuilder as RangeSetBuilder4 } from "@codemirror/state";
|
|
1924
|
+
import { hoverTooltip as hoverTooltip2, Decoration as Decoration7, ViewPlugin as ViewPlugin6, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
1925
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
1926
|
+
var link = (options = {}) => {
|
|
1927
|
+
const extensions = [
|
|
1928
|
+
ViewPlugin6.fromClass(class {
|
|
1929
|
+
constructor(view) {
|
|
1930
|
+
this.decorations = buildDecorations5(view, options);
|
|
1931
|
+
}
|
|
1932
|
+
update(update2) {
|
|
1933
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
1934
|
+
this.decorations = buildDecorations5(update2.view, options);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}, {
|
|
1938
|
+
decorations: (value) => value.decorations
|
|
1939
|
+
})
|
|
1940
|
+
];
|
|
1941
|
+
if (options.onHover) {
|
|
1942
|
+
extensions.push(
|
|
1943
|
+
// https://codemirror.net/examples/tooltip
|
|
1944
|
+
// https://codemirror.net/docs/ref/#view.hoverTooltip
|
|
1945
|
+
// https://github.com/codemirror/view/blob/main/src/tooltip.ts
|
|
1946
|
+
hoverTooltip2((view, pos, side) => {
|
|
1947
|
+
const syntax = syntaxTree5(view.state).resolveInner(pos, side);
|
|
1948
|
+
let link2 = null;
|
|
1949
|
+
for (let i = 0, node = syntax; !link2 && node && i < 5; node = node.parent, i++) {
|
|
1950
|
+
link2 = node.name === "Link" ? node : null;
|
|
1951
|
+
}
|
|
1952
|
+
const url = link2 && link2.getChild("URL");
|
|
1953
|
+
if (!url || !link2) {
|
|
1954
|
+
return null;
|
|
1955
|
+
}
|
|
1956
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
1957
|
+
return {
|
|
1958
|
+
pos: link2.from,
|
|
1959
|
+
end: link2.to,
|
|
1960
|
+
above: true,
|
|
1961
|
+
create: () => {
|
|
1962
|
+
const el = document.createElement("div");
|
|
1963
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
1964
|
+
options.onHover(el, urlText);
|
|
1965
|
+
return {
|
|
1966
|
+
dom: el,
|
|
1967
|
+
offset: {
|
|
1968
|
+
x: 0,
|
|
1969
|
+
y: 4
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
};
|
|
1974
|
+
})
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1977
|
+
return extensions;
|
|
1978
|
+
};
|
|
1979
|
+
var LinkButton = class extends WidgetType5 {
|
|
1980
|
+
constructor(_url, _onAttach) {
|
|
1981
|
+
super();
|
|
1982
|
+
this._url = _url;
|
|
1983
|
+
this._onAttach = _onAttach;
|
|
1984
|
+
}
|
|
1985
|
+
eq(other) {
|
|
1986
|
+
return this._url === other._url;
|
|
1987
|
+
}
|
|
1988
|
+
toDOM(view) {
|
|
1989
|
+
const el = document.createElement("span");
|
|
1990
|
+
this._onAttach(el, this._url);
|
|
1991
|
+
return el;
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
var LinkText = class extends WidgetType5 {
|
|
1995
|
+
constructor(_text, _url) {
|
|
1996
|
+
super();
|
|
1997
|
+
this._text = _text;
|
|
1998
|
+
this._url = _url;
|
|
1999
|
+
}
|
|
2000
|
+
eq(other) {
|
|
2001
|
+
return this._url === other._url;
|
|
2002
|
+
}
|
|
2003
|
+
toDOM(view) {
|
|
2004
|
+
const link2 = document.createElement("a");
|
|
2005
|
+
link2.setAttribute("class", "cm-link");
|
|
2006
|
+
link2.textContent = this._text;
|
|
2007
|
+
if (this._url) {
|
|
2008
|
+
link2.setAttribute("rel", "noreferrer");
|
|
2009
|
+
link2.setAttribute("target", "_blank");
|
|
2010
|
+
link2.href = this._url;
|
|
2011
|
+
} else {
|
|
2012
|
+
link2.onclick = () => {
|
|
2013
|
+
view.dispatch({
|
|
2014
|
+
selection: {
|
|
2015
|
+
anchor: view.posAtDOM(link2)
|
|
2016
|
+
}
|
|
2017
|
+
});
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
return link2;
|
|
2021
|
+
}
|
|
2022
|
+
};
|
|
2023
|
+
var buildDecorations5 = (view, options) => {
|
|
2024
|
+
const builder = new RangeSetBuilder4();
|
|
2025
|
+
const { state } = view;
|
|
2026
|
+
const cursor = state.selection.main.head;
|
|
2027
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2028
|
+
syntaxTree5(state).iterate({
|
|
2029
|
+
enter: (node) => {
|
|
2030
|
+
if (node.name === "Link") {
|
|
2031
|
+
const marks2 = node.node.getChildren("LinkMark");
|
|
2032
|
+
const text = marks2.length >= 2 ? state.sliceDoc(marks2[0].to, marks2[1].from) : "";
|
|
2033
|
+
const urlNode = node.node.getChild("URL");
|
|
2034
|
+
const url = urlNode ? state.sliceDoc(urlNode.from, urlNode.to) : "";
|
|
2035
|
+
if (!url) {
|
|
2036
|
+
return false;
|
|
2037
|
+
}
|
|
2038
|
+
if (!view.hasFocus || state.readOnly || cursor < node.from || cursor > node.to) {
|
|
2039
|
+
builder.add(node.from, node.to, Decoration7.replace({
|
|
2040
|
+
widget: new LinkText(text, options.link ? url : void 0)
|
|
2041
|
+
}));
|
|
2042
|
+
}
|
|
2043
|
+
if (options.onRender) {
|
|
2044
|
+
builder.add(node.to, node.to, Decoration7.replace({
|
|
2045
|
+
widget: new LinkButton(url, options.onRender)
|
|
2046
|
+
}));
|
|
2047
|
+
}
|
|
2048
|
+
return false;
|
|
1978
2049
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
};
|
|
1986
|
-
}
|
|
1987
|
-
]
|
|
1988
|
-
});
|
|
2050
|
+
},
|
|
2051
|
+
from,
|
|
2052
|
+
to
|
|
2053
|
+
});
|
|
2054
|
+
}
|
|
2055
|
+
return builder.finish();
|
|
1989
2056
|
};
|
|
1990
2057
|
|
|
1991
|
-
// packages/ui/react-ui-editor/src/extensions/table.ts
|
|
1992
|
-
import { syntaxTree as
|
|
1993
|
-
import { RangeSetBuilder as
|
|
1994
|
-
import { Decoration as
|
|
2058
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
2059
|
+
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
2060
|
+
import { RangeSetBuilder as RangeSetBuilder5, StateField as StateField4 } from "@codemirror/state";
|
|
2061
|
+
import { Decoration as Decoration8, EditorView as EditorView11, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
1995
2062
|
var table = (options = {}) => {
|
|
1996
2063
|
return StateField4.define({
|
|
1997
2064
|
create: (state) => update(state, options),
|
|
1998
2065
|
update: (_, tr) => update(tr.state, options),
|
|
1999
|
-
provide: (field) =>
|
|
2066
|
+
provide: (field) => EditorView11.decorations.from(field)
|
|
2000
2067
|
});
|
|
2001
2068
|
};
|
|
2002
2069
|
var update = (state, options) => {
|
|
2003
|
-
const builder = new
|
|
2070
|
+
const builder = new RangeSetBuilder5();
|
|
2004
2071
|
const cursor = state.selection.main.head;
|
|
2005
2072
|
const tables = [];
|
|
2006
2073
|
const getTable = () => tables[tables.length - 1];
|
|
@@ -2008,7 +2075,7 @@ var update = (state, options) => {
|
|
|
2008
2075
|
const table2 = getTable();
|
|
2009
2076
|
return table2.rows?.[table2.rows.length - 1];
|
|
2010
2077
|
};
|
|
2011
|
-
|
|
2078
|
+
syntaxTree6(state).iterate({
|
|
2012
2079
|
enter: (node) => {
|
|
2013
2080
|
switch (node.name) {
|
|
2014
2081
|
case "Table": {
|
|
@@ -2040,10 +2107,10 @@ var update = (state, options) => {
|
|
|
2040
2107
|
});
|
|
2041
2108
|
tables.forEach((table2) => {
|
|
2042
2109
|
const hide = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
2043
|
-
hide && builder.add(table2.from, table2.to,
|
|
2110
|
+
hide && builder.add(table2.from, table2.to, Decoration8.replace({
|
|
2044
2111
|
widget: new TableWidget(table2)
|
|
2045
2112
|
}));
|
|
2046
|
-
builder.add(table2.from, table2.to,
|
|
2113
|
+
builder.add(table2.from, table2.to, Decoration8.mark({
|
|
2047
2114
|
class: "cm-table"
|
|
2048
2115
|
}));
|
|
2049
2116
|
});
|
|
@@ -2086,90 +2153,137 @@ var TableWidget = class extends WidgetType6 {
|
|
|
2086
2153
|
}
|
|
2087
2154
|
};
|
|
2088
2155
|
|
|
2089
|
-
// packages/ui/react-ui-editor/src/extensions/tasklist.ts
|
|
2090
|
-
import {
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2156
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/tasklist.ts
|
|
2157
|
+
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
2158
|
+
import { RangeSetBuilder as RangeSetBuilder6 } from "@codemirror/state";
|
|
2159
|
+
import { EditorView as EditorView12, Decoration as Decoration9, WidgetType as WidgetType7, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
2160
|
+
var styles5 = EditorView12.baseTheme({
|
|
2161
|
+
"& .cm-task": {
|
|
2162
|
+
color: getToken("extend.colors.blue.500")
|
|
2163
|
+
},
|
|
2164
|
+
"& .cm-task-checkbox": {
|
|
2165
|
+
marginLeft: "4px",
|
|
2166
|
+
marginRight: "4px"
|
|
2095
2167
|
}
|
|
2096
2168
|
});
|
|
2097
2169
|
var CheckboxWidget = class extends WidgetType7 {
|
|
2098
|
-
constructor(_checked
|
|
2170
|
+
constructor(_checked) {
|
|
2099
2171
|
super();
|
|
2100
2172
|
this._checked = _checked;
|
|
2101
|
-
this._indent = _indent;
|
|
2102
|
-
this._onCheck = _onCheck;
|
|
2103
2173
|
}
|
|
2104
2174
|
eq(other) {
|
|
2105
|
-
return this._checked === other._checked
|
|
2175
|
+
return this._checked === other._checked;
|
|
2106
2176
|
}
|
|
2107
2177
|
toDOM(view) {
|
|
2108
|
-
const
|
|
2109
|
-
|
|
2110
|
-
wrap.setAttribute("aria-hidden", "true");
|
|
2111
|
-
wrap.style.setProperty("margin-left", this._indent * 24 + "px");
|
|
2112
|
-
const input = wrap.appendChild(document.createElement("input"));
|
|
2178
|
+
const input = document.createElement("input");
|
|
2179
|
+
input.className = "cm-task-checkbox";
|
|
2113
2180
|
input.type = "checkbox";
|
|
2114
2181
|
input.checked = this._checked;
|
|
2115
|
-
if (
|
|
2182
|
+
if (view.state.readOnly) {
|
|
2116
2183
|
input.setAttribute("disabled", "true");
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2184
|
+
} else {
|
|
2185
|
+
input.onmousedown = (event) => {
|
|
2186
|
+
const pos = view.posAtDOM(input);
|
|
2187
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2188
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2189
|
+
view.dispatch({
|
|
2190
|
+
changes: {
|
|
2191
|
+
from: pos + 1,
|
|
2192
|
+
to: pos + 2,
|
|
2193
|
+
insert: this._checked ? " " : "x"
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2196
|
+
event.preventDefault();
|
|
2197
|
+
}
|
|
2122
2198
|
};
|
|
2123
2199
|
}
|
|
2124
|
-
return
|
|
2200
|
+
return input;
|
|
2125
2201
|
}
|
|
2126
2202
|
ignoreEvent() {
|
|
2127
2203
|
return false;
|
|
2128
2204
|
}
|
|
2129
2205
|
};
|
|
2206
|
+
var checkedDecoration = Decoration9.replace({
|
|
2207
|
+
widget: new CheckboxWidget(true)
|
|
2208
|
+
});
|
|
2209
|
+
var uncheckedDecoration = Decoration9.replace({
|
|
2210
|
+
widget: new CheckboxWidget(false)
|
|
2211
|
+
});
|
|
2212
|
+
var buildDecorations6 = (view) => {
|
|
2213
|
+
const builder = new RangeSetBuilder6();
|
|
2214
|
+
const { state } = view;
|
|
2215
|
+
const cursor = state.selection.main.head;
|
|
2216
|
+
for (const { from, to } of view.visibleRanges) {
|
|
2217
|
+
syntaxTree7(state).iterate({
|
|
2218
|
+
enter: (node) => {
|
|
2219
|
+
if (node.name === "TaskMarker") {
|
|
2220
|
+
if (cursor < node.from || cursor > node.to) {
|
|
2221
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2222
|
+
builder.add(node.from - 2, node.from - 1, Decoration9.mark({
|
|
2223
|
+
class: "cm-task"
|
|
2224
|
+
}));
|
|
2225
|
+
builder.add(node.from, node.to, checked ? checkedDecoration : uncheckedDecoration);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
},
|
|
2229
|
+
from,
|
|
2230
|
+
to
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
return builder.finish();
|
|
2234
|
+
};
|
|
2130
2235
|
var tasklist = (options = {}) => {
|
|
2131
|
-
const taskMatcher = new MatchDecorator3({
|
|
2132
|
-
regexp: /^(\s*)- \[([ xX])\]\s/g,
|
|
2133
|
-
decoration: (match, view, pos) => {
|
|
2134
|
-
const indent = Math.floor(match[1].length / 2);
|
|
2135
|
-
const checked = match[2] === "x" || match[2] === "X";
|
|
2136
|
-
return Decoration8.replace({
|
|
2137
|
-
widget: new CheckboxWidget(checked, indent, view.state.readOnly ? void 0 : (checked2) => {
|
|
2138
|
-
const idx = pos + match[0].indexOf("[") + 1;
|
|
2139
|
-
view.dispatch({
|
|
2140
|
-
changes: {
|
|
2141
|
-
from: idx,
|
|
2142
|
-
to: idx + 1,
|
|
2143
|
-
insert: checked2 ? "x" : " "
|
|
2144
|
-
},
|
|
2145
|
-
// TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
|
|
2146
|
-
selection: {
|
|
2147
|
-
anchor: idx + 3
|
|
2148
|
-
}
|
|
2149
|
-
});
|
|
2150
|
-
})
|
|
2151
|
-
});
|
|
2152
|
-
}
|
|
2153
|
-
});
|
|
2154
|
-
const tasks = ViewPlugin7.fromClass(class {
|
|
2155
|
-
constructor(view) {
|
|
2156
|
-
this.tasks = taskMatcher.createDeco(view);
|
|
2157
|
-
}
|
|
2158
|
-
update(update2) {
|
|
2159
|
-
this.tasks = taskMatcher.updateDeco(update2, this.tasks);
|
|
2160
|
-
}
|
|
2161
|
-
}, {
|
|
2162
|
-
decorations: (value) => value.tasks,
|
|
2163
|
-
provide: (plugin) => EditorView11.atomicRanges.of((view) => {
|
|
2164
|
-
return view.plugin(plugin)?.tasks || Decoration8.none;
|
|
2165
|
-
})
|
|
2166
|
-
});
|
|
2167
2236
|
return [
|
|
2168
|
-
|
|
2237
|
+
ViewPlugin7.fromClass(class {
|
|
2238
|
+
constructor(view) {
|
|
2239
|
+
this.decorations = buildDecorations6(view);
|
|
2240
|
+
}
|
|
2241
|
+
update(update2) {
|
|
2242
|
+
if (update2.docChanged || update2.viewportChanged || update2.selectionSet) {
|
|
2243
|
+
this.decorations = buildDecorations6(update2.view);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}, {
|
|
2247
|
+
decorations: (value) => value.decorations
|
|
2248
|
+
}),
|
|
2169
2249
|
styles5
|
|
2170
2250
|
];
|
|
2171
2251
|
};
|
|
2172
2252
|
|
|
2253
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
2254
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
2255
|
+
var mention = ({ onSearch }) => {
|
|
2256
|
+
return autocompletion2({
|
|
2257
|
+
// TODO(burdon): Not working.
|
|
2258
|
+
activateOnTyping: true,
|
|
2259
|
+
// activateOnTypingDelay: 100,
|
|
2260
|
+
// selectOnOpen: true,
|
|
2261
|
+
closeOnBlur: false,
|
|
2262
|
+
// defaultKeymap: false,
|
|
2263
|
+
icons: false,
|
|
2264
|
+
override: [
|
|
2265
|
+
(context) => {
|
|
2266
|
+
console.log(context);
|
|
2267
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
2268
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
2269
|
+
return null;
|
|
2270
|
+
}
|
|
2271
|
+
return {
|
|
2272
|
+
from: match.from,
|
|
2273
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
2274
|
+
label: `@${value}`
|
|
2275
|
+
}))
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
]
|
|
2279
|
+
});
|
|
2280
|
+
};
|
|
2281
|
+
|
|
2282
|
+
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
2283
|
+
var outliner = (options = {}) => {
|
|
2284
|
+
return [];
|
|
2285
|
+
};
|
|
2286
|
+
|
|
2173
2287
|
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
2174
2288
|
import { keymap as keymap5 } from "@codemirror/view";
|
|
2175
2289
|
var defaultItems = [
|
|
@@ -2227,27 +2341,6 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
|
2227
2341
|
];
|
|
2228
2342
|
};
|
|
2229
2343
|
|
|
2230
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2231
|
-
import { yCollab } from "y-codemirror.next";
|
|
2232
|
-
|
|
2233
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/cursor.ts
|
|
2234
|
-
import * as Y from "yjs";
|
|
2235
|
-
import { arrayToString, stringToArray } from "@dxos/util";
|
|
2236
|
-
var cursorConverter2 = (text) => ({
|
|
2237
|
-
toCursor: (index, assoc) => {
|
|
2238
|
-
return arrayToString(Y.encodeRelativePosition(Y.createRelativePositionFromTypeIndex(text, index, assoc)));
|
|
2239
|
-
},
|
|
2240
|
-
fromCursor: (cursor) => {
|
|
2241
|
-
return Y.createAbsolutePositionFromRelativePosition(Y.decodeRelativePosition(stringToArray(cursor)), text.doc)?.index ?? 0;
|
|
2242
|
-
}
|
|
2243
|
-
});
|
|
2244
|
-
|
|
2245
|
-
// packages/ui/react-ui-editor/src/extensions/yjs/yjs.ts
|
|
2246
|
-
var yjs = (content, awareness2) => [
|
|
2247
|
-
CursorConverter.of(cursorConverter2(content)),
|
|
2248
|
-
yCollab(content, awareness2)
|
|
2249
|
-
];
|
|
2250
|
-
|
|
2251
2344
|
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
2252
2345
|
import get3 from "lodash.get";
|
|
2253
2346
|
var defaultTheme = {
|
|
@@ -2341,33 +2434,6 @@ var defaultTheme = {
|
|
|
2341
2434
|
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2342
2435
|
},
|
|
2343
2436
|
//
|
|
2344
|
-
// collaboration
|
|
2345
|
-
// TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
|
|
2346
|
-
//
|
|
2347
|
-
"&light .cm-ySelection, &light .cm-yLineSelection": {
|
|
2348
|
-
mixBlendMode: "multiply"
|
|
2349
|
-
},
|
|
2350
|
-
"&dark .cm-ySelection, &dark .cm-yLineSelection": {
|
|
2351
|
-
mixBlendMode: "screen"
|
|
2352
|
-
},
|
|
2353
|
-
".cm-ySelectionInfo": {
|
|
2354
|
-
padding: "2px 4px",
|
|
2355
|
-
marginBlockStart: "-4px"
|
|
2356
|
-
},
|
|
2357
|
-
".cm-ySelection, & .cm-selectionMatch": {
|
|
2358
|
-
paddingBlockStart: ".15em",
|
|
2359
|
-
paddingBlockEnd: ".15em"
|
|
2360
|
-
},
|
|
2361
|
-
".cm-ySelectionCaret": {
|
|
2362
|
-
display: "inline-block",
|
|
2363
|
-
insetBlockStart: ".1em",
|
|
2364
|
-
blockSize: "1.4em",
|
|
2365
|
-
verticalAlign: "top"
|
|
2366
|
-
},
|
|
2367
|
-
".cm-yLineSelection": {
|
|
2368
|
-
margin: 0
|
|
2369
|
-
},
|
|
2370
|
-
//
|
|
2371
2437
|
// link
|
|
2372
2438
|
//
|
|
2373
2439
|
".cm-link": {
|
|
@@ -2404,13 +2470,6 @@ var defaultTheme = {
|
|
|
2404
2470
|
textDecoration: "none"
|
|
2405
2471
|
},
|
|
2406
2472
|
//
|
|
2407
|
-
// widgets
|
|
2408
|
-
//
|
|
2409
|
-
".cm-widgetBuffer": {
|
|
2410
|
-
display: "none",
|
|
2411
|
-
height: 0
|
|
2412
|
-
},
|
|
2413
|
-
//
|
|
2414
2473
|
// table
|
|
2415
2474
|
//
|
|
2416
2475
|
".cm-table *": {
|
|
@@ -2441,27 +2500,17 @@ var defaultTheme = {
|
|
|
2441
2500
|
},
|
|
2442
2501
|
//
|
|
2443
2502
|
// font size
|
|
2444
|
-
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2503
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2504
|
+
// but it's far more verbose than it needs to be.
|
|
2445
2505
|
//
|
|
2446
|
-
...Object.keys(
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = {
|
|
2455
|
-
height
|
|
2456
|
-
};
|
|
2457
|
-
acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = {
|
|
2458
|
-
height
|
|
2459
|
-
};
|
|
2460
|
-
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = {
|
|
2461
|
-
height
|
|
2462
|
-
};
|
|
2463
|
-
return acc;
|
|
2464
|
-
}, {}),
|
|
2506
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2507
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2508
|
+
//
|
|
2509
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2510
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2511
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2512
|
+
// return acc;
|
|
2513
|
+
// }, {}),
|
|
2465
2514
|
/**
|
|
2466
2515
|
* Panels
|
|
2467
2516
|
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
@@ -2512,7 +2561,9 @@ var textTheme = {
|
|
|
2512
2561
|
}
|
|
2513
2562
|
};
|
|
2514
2563
|
var markdownTheme = {
|
|
2515
|
-
|
|
2564
|
+
".cm-scroller": {
|
|
2565
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2566
|
+
},
|
|
2516
2567
|
".cm-placeholder": {
|
|
2517
2568
|
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2518
2569
|
}
|
|
@@ -2527,95 +2578,89 @@ var codeTheme = {
|
|
|
2527
2578
|
};
|
|
2528
2579
|
|
|
2529
2580
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
2581
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
2530
2582
|
var EditorModes = [
|
|
2531
2583
|
"default",
|
|
2532
2584
|
"vim"
|
|
2533
2585
|
];
|
|
2534
|
-
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly,
|
|
2535
|
-
const { themeMode } = useThemeContext();
|
|
2586
|
+
var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
|
|
2536
2587
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
2537
2588
|
tabBehavior: "limited"
|
|
2538
2589
|
});
|
|
2539
|
-
const
|
|
2540
|
-
const
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
state,
|
|
2590
|
+
const { themeMode } = useThemeContext();
|
|
2591
|
+
const rootRef = useRef(null);
|
|
2592
|
+
const [view, setView] = useState(null);
|
|
2593
|
+
useImperativeHandle(forwardedRef, () => view, [
|
|
2544
2594
|
view
|
|
2545
|
-
}), [
|
|
2546
|
-
view,
|
|
2547
|
-
state,
|
|
2548
|
-
root
|
|
2549
|
-
]);
|
|
2550
|
-
const { awareness: awareness2, peer } = model;
|
|
2551
|
-
useEffect(() => {
|
|
2552
|
-
if (awareness2 && peer) {
|
|
2553
|
-
awareness2.setLocalStateField("user", {
|
|
2554
|
-
name: peer.name ?? generateName(peer.id),
|
|
2555
|
-
color: getColorForValue({
|
|
2556
|
-
value: peer.id,
|
|
2557
|
-
type: "color"
|
|
2558
|
-
}),
|
|
2559
|
-
colorLight: getColorForValue({
|
|
2560
|
-
value: peer.id,
|
|
2561
|
-
themeMode,
|
|
2562
|
-
type: "highlight"
|
|
2563
|
-
})
|
|
2564
|
-
});
|
|
2565
|
-
}
|
|
2566
|
-
}, [
|
|
2567
|
-
awareness2,
|
|
2568
|
-
peer,
|
|
2569
|
-
themeMode
|
|
2570
2595
|
]);
|
|
2571
|
-
|
|
2572
|
-
if (
|
|
2573
|
-
view
|
|
2574
|
-
effects: setCommentRange.of({
|
|
2575
|
-
model,
|
|
2576
|
-
comments: comments2
|
|
2577
|
-
})
|
|
2578
|
-
});
|
|
2596
|
+
useEffect2(() => {
|
|
2597
|
+
if (autoFocus) {
|
|
2598
|
+
view?.focus();
|
|
2579
2599
|
}
|
|
2580
2600
|
}, [
|
|
2581
2601
|
view,
|
|
2582
|
-
|
|
2602
|
+
autoFocus
|
|
2583
2603
|
]);
|
|
2584
|
-
|
|
2585
|
-
if (!
|
|
2604
|
+
useEffect2(() => {
|
|
2605
|
+
if (!model || !rootRef.current) {
|
|
2586
2606
|
return;
|
|
2587
2607
|
}
|
|
2588
|
-
const
|
|
2608
|
+
const state = EditorState2.create({
|
|
2589
2609
|
doc: model.text(),
|
|
2610
|
+
selection,
|
|
2590
2611
|
extensions: [
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2612
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
2613
|
+
EditorView13.exceptionSink.of((err) => {
|
|
2614
|
+
log2.catch(err, void 0, {
|
|
2615
|
+
F: __dxlog_file5,
|
|
2616
|
+
L: 123,
|
|
2617
|
+
S: void 0,
|
|
2618
|
+
C: (f, a) => f(...a)
|
|
2619
|
+
});
|
|
2620
|
+
}),
|
|
2594
2621
|
// Theme.
|
|
2595
|
-
// TODO(burdon): Make
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2622
|
+
// TODO(burdon): Make configurable.
|
|
2623
|
+
EditorView13.baseTheme(defaultTheme),
|
|
2624
|
+
EditorView13.theme(theme ?? {}),
|
|
2625
|
+
EditorView13.darkTheme.of(themeMode === "dark"),
|
|
2626
|
+
EditorView13.editorAttributes.of({
|
|
2627
|
+
class: slots.editor?.className ?? ""
|
|
2628
|
+
}),
|
|
2629
|
+
EditorView13.contentAttributes.of({
|
|
2630
|
+
class: slots.content?.className ?? ""
|
|
2631
|
+
}),
|
|
2632
|
+
// State.
|
|
2633
|
+
EditorState2.readOnly.of(!!readonly),
|
|
2599
2634
|
// Storage and replication.
|
|
2635
|
+
// NOTE: This must come before user extensions.
|
|
2600
2636
|
model.extension,
|
|
2637
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
2638
|
+
editorMode === "vim" && vim(),
|
|
2601
2639
|
// Custom.
|
|
2602
2640
|
...extensions
|
|
2603
2641
|
].filter(Boolean)
|
|
2604
2642
|
});
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2643
|
+
const newView = new EditorView13({
|
|
2644
|
+
state,
|
|
2645
|
+
parent: rootRef.current,
|
|
2646
|
+
scrollTo,
|
|
2647
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
2648
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
2649
|
+
dispatchTransactions: (trs, view2) => {
|
|
2650
|
+
if (debug) {
|
|
2651
|
+
logChanges(trs);
|
|
2652
|
+
}
|
|
2653
|
+
view2.update(trs);
|
|
2654
|
+
}
|
|
2612
2655
|
});
|
|
2656
|
+
view?.destroy();
|
|
2657
|
+
setView(newView);
|
|
2613
2658
|
return () => {
|
|
2614
|
-
|
|
2615
|
-
|
|
2659
|
+
newView?.destroy();
|
|
2660
|
+
setView(null);
|
|
2616
2661
|
};
|
|
2617
2662
|
}, [
|
|
2618
|
-
|
|
2663
|
+
rootRef,
|
|
2619
2664
|
model,
|
|
2620
2665
|
readonly,
|
|
2621
2666
|
editorMode,
|
|
@@ -2625,11 +2670,13 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2625
2670
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
2626
2671
|
switch (key) {
|
|
2627
2672
|
case "Enter": {
|
|
2628
|
-
view?.
|
|
2673
|
+
view?.focus();
|
|
2629
2674
|
break;
|
|
2630
2675
|
}
|
|
2631
2676
|
case "Escape": {
|
|
2632
|
-
editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)
|
|
2677
|
+
if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
2678
|
+
rootRef.current?.focus();
|
|
2679
|
+
}
|
|
2633
2680
|
break;
|
|
2634
2681
|
}
|
|
2635
2682
|
}
|
|
@@ -2639,83 +2686,78 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, comments: co
|
|
|
2639
2686
|
]);
|
|
2640
2687
|
return /* @__PURE__ */ React.createElement("div", {
|
|
2641
2688
|
key: model.id,
|
|
2642
|
-
|
|
2689
|
+
role: "none",
|
|
2643
2690
|
tabIndex: 0,
|
|
2644
|
-
|
|
2691
|
+
onKeyUp: handleKeyUp,
|
|
2692
|
+
...slots.root,
|
|
2645
2693
|
...editorMode !== "vim" && tabsterDOMAttribute,
|
|
2646
|
-
|
|
2694
|
+
ref: rootRef
|
|
2647
2695
|
});
|
|
2648
2696
|
});
|
|
2649
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2697
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2650
2698
|
const { themeMode } = useThemeContext();
|
|
2651
|
-
const
|
|
2699
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
|
|
2652
2700
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2653
2701
|
ref: forwardedRef,
|
|
2654
2702
|
readonly,
|
|
2655
2703
|
extensions: [
|
|
2656
2704
|
basicBundle({
|
|
2657
|
-
readonly,
|
|
2658
2705
|
themeMode,
|
|
2659
|
-
placeholder:
|
|
2706
|
+
placeholder: placeholder3,
|
|
2707
|
+
lineWrapping
|
|
2660
2708
|
}),
|
|
2661
2709
|
...extensions
|
|
2662
2710
|
],
|
|
2663
|
-
|
|
2711
|
+
theme,
|
|
2712
|
+
slots: updatedSlots,
|
|
2664
2713
|
...props
|
|
2665
2714
|
});
|
|
2666
2715
|
});
|
|
2667
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly,
|
|
2716
|
+
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
2668
2717
|
const { themeMode } = useThemeContext();
|
|
2669
|
-
const
|
|
2718
|
+
const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
|
|
2670
2719
|
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
2671
2720
|
ref: forwardedRef,
|
|
2672
2721
|
readonly,
|
|
2673
2722
|
extensions: [
|
|
2674
2723
|
markdownBundle({
|
|
2675
|
-
readonly,
|
|
2676
2724
|
themeMode,
|
|
2677
|
-
placeholder:
|
|
2725
|
+
placeholder: placeholder3
|
|
2678
2726
|
}),
|
|
2679
2727
|
...extensions
|
|
2680
2728
|
],
|
|
2681
|
-
|
|
2729
|
+
theme,
|
|
2730
|
+
slots: updatedSlots,
|
|
2682
2731
|
...props
|
|
2683
2732
|
});
|
|
2684
2733
|
});
|
|
2685
2734
|
var defaultSlots = {
|
|
2686
2735
|
root: {
|
|
2687
|
-
|
|
2736
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
2737
|
+
className: mx3("flex flex-col grow overflow-y-auto", attentionSurface)
|
|
2738
|
+
},
|
|
2739
|
+
editor: {
|
|
2740
|
+
className: "h-full p-2"
|
|
2688
2741
|
}
|
|
2689
2742
|
};
|
|
2690
2743
|
var defaultTextSlots = {
|
|
2691
|
-
...defaultSlots
|
|
2692
|
-
editor: {
|
|
2693
|
-
theme: textTheme
|
|
2694
|
-
}
|
|
2744
|
+
...defaultSlots
|
|
2695
2745
|
};
|
|
2696
2746
|
var defaultMarkdownSlots = {
|
|
2697
|
-
...defaultSlots
|
|
2698
|
-
editor: {
|
|
2699
|
-
theme: markdownTheme
|
|
2700
|
-
}
|
|
2747
|
+
...defaultSlots
|
|
2701
2748
|
};
|
|
2702
2749
|
|
|
2703
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
2704
|
-
import get4 from "lodash.get";
|
|
2705
|
-
import { getRawDoc } from "@dxos/echo-schema";
|
|
2706
|
-
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2707
|
-
|
|
2708
2750
|
// packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
|
|
2709
2751
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
2710
2752
|
import { Context as Context2 } from "@dxos/context";
|
|
2711
|
-
import { invariant as
|
|
2753
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
2712
2754
|
import { log as log3 } from "@dxos/log";
|
|
2713
|
-
var
|
|
2755
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
|
|
2714
2756
|
var DEBOUNCE_INTERVAL = 100;
|
|
2715
2757
|
var SpaceAwarenessProvider = class {
|
|
2716
2758
|
constructor(params) {
|
|
2717
|
-
this.remoteStateChange = new Event2();
|
|
2718
2759
|
this._remoteStates = /* @__PURE__ */ new Map();
|
|
2760
|
+
this.remoteStateChange = new Event2();
|
|
2719
2761
|
this._space = params.space;
|
|
2720
2762
|
this._channel = params.channel;
|
|
2721
2763
|
this._peerId = params.peerId;
|
|
@@ -2732,7 +2774,7 @@ var SpaceAwarenessProvider = class {
|
|
|
2732
2774
|
await sleep(DEBOUNCE_INTERVAL);
|
|
2733
2775
|
}
|
|
2734
2776
|
});
|
|
2735
|
-
|
|
2777
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
2736
2778
|
switch (message.payload.kind) {
|
|
2737
2779
|
case "query": {
|
|
2738
2780
|
this._handleQueryMessage();
|
|
@@ -2743,16 +2785,15 @@ var SpaceAwarenessProvider = class {
|
|
|
2743
2785
|
break;
|
|
2744
2786
|
}
|
|
2745
2787
|
}
|
|
2746
|
-
});
|
|
2747
|
-
this._ctx.onDispose(unsubscribe);
|
|
2788
|
+
}));
|
|
2748
2789
|
void this._space.postMessage(this._channel, {
|
|
2749
2790
|
kind: "query"
|
|
2750
2791
|
}).catch((err) => {
|
|
2751
2792
|
log3.debug("failed to query awareness", {
|
|
2752
2793
|
err
|
|
2753
2794
|
}, {
|
|
2754
|
-
F:
|
|
2755
|
-
L:
|
|
2795
|
+
F: __dxlog_file6,
|
|
2796
|
+
L: 89,
|
|
2756
2797
|
S: this,
|
|
2757
2798
|
C: (f, a) => f(...a)
|
|
2758
2799
|
});
|
|
@@ -2763,10 +2804,13 @@ var SpaceAwarenessProvider = class {
|
|
|
2763
2804
|
this._ctx = void 0;
|
|
2764
2805
|
this._postTask = void 0;
|
|
2765
2806
|
}
|
|
2807
|
+
getRemoteStates() {
|
|
2808
|
+
return Array.from(this._remoteStates.values());
|
|
2809
|
+
}
|
|
2766
2810
|
update(position) {
|
|
2767
|
-
|
|
2768
|
-
F:
|
|
2769
|
-
L:
|
|
2811
|
+
invariant4(this._postTask, void 0, {
|
|
2812
|
+
F: __dxlog_file6,
|
|
2813
|
+
L: 104,
|
|
2770
2814
|
S: this,
|
|
2771
2815
|
A: [
|
|
2772
2816
|
"this._postTask",
|
|
@@ -2780,13 +2824,10 @@ var SpaceAwarenessProvider = class {
|
|
|
2780
2824
|
};
|
|
2781
2825
|
this._postTask.schedule();
|
|
2782
2826
|
}
|
|
2783
|
-
getRemoteStates() {
|
|
2784
|
-
return Array.from(this._remoteStates.values());
|
|
2785
|
-
}
|
|
2786
2827
|
_handleQueryMessage() {
|
|
2787
|
-
|
|
2788
|
-
F:
|
|
2789
|
-
L:
|
|
2828
|
+
invariant4(this._postTask, void 0, {
|
|
2829
|
+
F: __dxlog_file6,
|
|
2830
|
+
L: 115,
|
|
2790
2831
|
S: this,
|
|
2791
2832
|
A: [
|
|
2792
2833
|
"this._postTask",
|
|
@@ -2796,9 +2837,9 @@ var SpaceAwarenessProvider = class {
|
|
|
2796
2837
|
this._postTask.schedule();
|
|
2797
2838
|
}
|
|
2798
2839
|
_handlePostMessage(message) {
|
|
2799
|
-
|
|
2800
|
-
F:
|
|
2801
|
-
L:
|
|
2840
|
+
invariant4(message.kind === "post", void 0, {
|
|
2841
|
+
F: __dxlog_file6,
|
|
2842
|
+
L: 120,
|
|
2802
2843
|
S: this,
|
|
2803
2844
|
A: [
|
|
2804
2845
|
"message.kind === 'post'",
|
|
@@ -2810,201 +2851,54 @@ var SpaceAwarenessProvider = class {
|
|
|
2810
2851
|
}
|
|
2811
2852
|
};
|
|
2812
2853
|
|
|
2813
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2854
|
+
// packages/ui/react-ui-editor/src/hooks/defs.ts
|
|
2814
2855
|
import { StateField as StateField5 } from "@codemirror/state";
|
|
2815
|
-
|
|
2816
|
-
|
|
2856
|
+
var modelState = StateField5.define({
|
|
2857
|
+
create: () => void 0,
|
|
2858
|
+
update: (model) => model
|
|
2859
|
+
});
|
|
2817
2860
|
|
|
2818
|
-
// packages/ui/react-ui-editor/src/hooks/
|
|
2819
|
-
import
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
import { log as log4 } from "@dxos/log";
|
|
2826
|
-
import { arrayToString as arrayToString2, stringToArray as stringToArray2 } from "@dxos/util";
|
|
2827
|
-
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/yjs.ts";
|
|
2828
|
-
var createYjsModel = ({ identity, space, text }) => {
|
|
2829
|
-
invariant4(text?.doc && text?.content, void 0, {
|
|
2830
|
-
F: __dxlog_file5,
|
|
2831
|
-
L: 23,
|
|
2832
|
-
S: void 0,
|
|
2833
|
-
A: [
|
|
2834
|
-
"text?.doc && text?.content",
|
|
2835
|
-
""
|
|
2836
|
-
]
|
|
2837
|
-
});
|
|
2838
|
-
const provider = space ? new YAwarenessProvider({
|
|
2839
|
-
space,
|
|
2840
|
-
doc: text.doc,
|
|
2841
|
-
channel: `yjs.awareness.${text.id}`
|
|
2842
|
-
}) : void 0;
|
|
2843
|
-
const model = {
|
|
2844
|
-
id: text.doc.guid,
|
|
2845
|
-
content: text.content,
|
|
2846
|
-
text: () => text.content.toString(),
|
|
2847
|
-
// https://github.com/yjs/yjs?tab=readme-ov-file#relative-positions
|
|
2848
|
-
// TODO(dmaretskyi): Refactor as cursor-converter.
|
|
2849
|
-
getCursorFromRange: (range) => {
|
|
2850
|
-
const from = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.from));
|
|
2851
|
-
const to = Y2.encodeRelativePosition(Y2.createRelativePositionFromTypeIndex(text.content, range.to, -1));
|
|
2852
|
-
return [
|
|
2853
|
-
arrayToString2(from),
|
|
2854
|
-
arrayToString2(to)
|
|
2855
|
-
].join(":");
|
|
2856
|
-
},
|
|
2857
|
-
getRangeFromCursor: (cursor) => {
|
|
2858
|
-
invariant4(text.doc, void 0, {
|
|
2859
|
-
F: __dxlog_file5,
|
|
2860
|
-
L: 40,
|
|
2861
|
-
S: void 0,
|
|
2862
|
-
A: [
|
|
2863
|
-
"text.doc",
|
|
2864
|
-
""
|
|
2865
|
-
]
|
|
2866
|
-
});
|
|
2867
|
-
const parts = cursor.split(":");
|
|
2868
|
-
const from = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[0])), text.doc);
|
|
2869
|
-
const to = Y2.createAbsolutePositionFromRelativePosition(Y2.decodeRelativePosition(stringToArray2(parts[1])), text.doc);
|
|
2870
|
-
return from && to ? {
|
|
2871
|
-
from: from.index,
|
|
2872
|
-
to: to.index
|
|
2873
|
-
} : void 0;
|
|
2861
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
2862
|
+
import { useState as useState2 } from "react";
|
|
2863
|
+
var useTextEditor = () => {
|
|
2864
|
+
const [view, setView] = useState2(null);
|
|
2865
|
+
return [
|
|
2866
|
+
(ref) => {
|
|
2867
|
+
setView(ref);
|
|
2874
2868
|
},
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
yjs(text.content, provider?.awareness)
|
|
2878
|
-
],
|
|
2879
|
-
awareness: provider?.awareness,
|
|
2880
|
-
peer: identity ? {
|
|
2881
|
-
id: identity.identityKey.toHex(),
|
|
2882
|
-
name: identity.profile?.displayName
|
|
2883
|
-
} : void 0
|
|
2884
|
-
};
|
|
2885
|
-
return model;
|
|
2886
|
-
};
|
|
2887
|
-
var messageAwareness = 1;
|
|
2888
|
-
var messageQueryAwareness = 3;
|
|
2889
|
-
var YAwarenessProvider = class extends Observable {
|
|
2890
|
-
constructor({ space, doc, channel, awareness: awareness2 }) {
|
|
2891
|
-
super();
|
|
2892
|
-
this._space = space;
|
|
2893
|
-
this._awareness = awareness2 ?? new YP.Awareness(doc);
|
|
2894
|
-
this._channel = channel;
|
|
2895
|
-
this._clientId = doc.clientID;
|
|
2896
|
-
this._awareness.on("update", this._handleAwarenessUpdate.bind(this));
|
|
2897
|
-
this._space.listen(this._channel, this._handleSpaceMessage.bind(this));
|
|
2898
|
-
if (typeof window !== "undefined") {
|
|
2899
|
-
window.addEventListener("beforeunload", this._handleBeforeUnload.bind(this));
|
|
2900
|
-
} else if (typeof process !== "undefined") {
|
|
2901
|
-
process.on("exit", this._handleBeforeUnload.bind(this));
|
|
2902
|
-
}
|
|
2903
|
-
const encoderAwarenessQuery = encoding.createEncoder();
|
|
2904
|
-
encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
|
|
2905
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessQuery));
|
|
2906
|
-
const encoderAwarenessState = encoding.createEncoder();
|
|
2907
|
-
encoding.writeVarUint(encoderAwarenessState, messageAwareness);
|
|
2908
|
-
encoding.writeVarUint8Array(encoderAwarenessState, YP.encodeAwarenessUpdate(this.awareness, [
|
|
2909
|
-
this._clientId
|
|
2910
|
-
]));
|
|
2911
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwarenessState));
|
|
2912
|
-
}
|
|
2913
|
-
get awareness() {
|
|
2914
|
-
return this._awareness;
|
|
2915
|
-
}
|
|
2916
|
-
_handleAwarenessUpdate({ added, updated, removed }, origin) {
|
|
2917
|
-
log4("awareness update", {
|
|
2918
|
-
added,
|
|
2919
|
-
updated,
|
|
2920
|
-
removed,
|
|
2921
|
-
origin
|
|
2922
|
-
}, {
|
|
2923
|
-
F: __dxlog_file5,
|
|
2924
|
-
L: 122,
|
|
2925
|
-
S: this,
|
|
2926
|
-
C: (f, a) => f(...a)
|
|
2927
|
-
});
|
|
2928
|
-
const changedClients = added.concat(updated).concat(removed);
|
|
2929
|
-
const encoderAwareness = encoding.createEncoder();
|
|
2930
|
-
encoding.writeVarUint(encoderAwareness, messageAwareness);
|
|
2931
|
-
encoding.writeVarUint8Array(encoderAwareness, YP.encodeAwarenessUpdate(this._awareness, changedClients));
|
|
2932
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoderAwareness));
|
|
2933
|
-
}
|
|
2934
|
-
_handleSpaceMessage({ payload }) {
|
|
2935
|
-
log4("space message", payload, {
|
|
2936
|
-
F: __dxlog_file5,
|
|
2937
|
-
L: 131,
|
|
2938
|
-
S: this,
|
|
2939
|
-
C: (f, a) => f(...a)
|
|
2940
|
-
});
|
|
2941
|
-
const data = new Uint8Array(Array.from(Object.values(payload)));
|
|
2942
|
-
const encoder = this._readMessage(data);
|
|
2943
|
-
if (encoder) {
|
|
2944
|
-
void this._space.postMessage(this._channel, encoding.toUint8Array(encoder));
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
|
-
_readMessage(message) {
|
|
2948
|
-
const decoder = decoding.createDecoder(message);
|
|
2949
|
-
const encoder = encoding.createEncoder();
|
|
2950
|
-
const messageType = decoding.readVarUint(decoder);
|
|
2951
|
-
let sendReply = false;
|
|
2952
|
-
switch (messageType) {
|
|
2953
|
-
case messageAwareness: {
|
|
2954
|
-
YP.applyAwarenessUpdate(this._awareness, decoding.readVarUint8Array(decoder), this);
|
|
2955
|
-
break;
|
|
2956
|
-
}
|
|
2957
|
-
case messageQueryAwareness: {
|
|
2958
|
-
encoding.writeVarUint(encoder, messageAwareness);
|
|
2959
|
-
encoding.writeVarUint8Array(encoder, YP.encodeAwarenessUpdate(this._awareness, Array.from(this._awareness.getStates().keys())));
|
|
2960
|
-
sendReply = true;
|
|
2961
|
-
break;
|
|
2962
|
-
}
|
|
2963
|
-
default: {
|
|
2964
|
-
console.error("Invalid message:", messageType);
|
|
2965
|
-
return encoder;
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
2968
|
-
if (!sendReply) {
|
|
2969
|
-
return null;
|
|
2970
|
-
}
|
|
2971
|
-
return encoder;
|
|
2972
|
-
}
|
|
2973
|
-
_handleBeforeUnload() {
|
|
2974
|
-
YP.removeAwarenessStates(this._awareness, [
|
|
2975
|
-
this._clientId
|
|
2976
|
-
], "window unload");
|
|
2977
|
-
}
|
|
2869
|
+
view
|
|
2870
|
+
];
|
|
2978
2871
|
};
|
|
2979
2872
|
|
|
2980
2873
|
// packages/ui/react-ui-editor/src/hooks/useTextModel.ts
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
}
|
|
2874
|
+
import get4 from "lodash.get";
|
|
2875
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
2876
|
+
import { generateName } from "@dxos/display-name";
|
|
2877
|
+
import { getRawDoc } from "@dxos/echo-schema";
|
|
2878
|
+
import { invariant as invariant5 } from "@dxos/invariant";
|
|
2879
|
+
import { isAutomergeObject } from "@dxos/react-client/echo";
|
|
2880
|
+
import { isNotNullOrUndefined } from "@dxos/util";
|
|
2881
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
|
|
2985
2882
|
var useTextModel = (props) => {
|
|
2986
2883
|
const { identity, space, text } = props;
|
|
2987
|
-
const [model, setModel] =
|
|
2988
|
-
|
|
2884
|
+
const [model, setModel] = useState3();
|
|
2885
|
+
useEffect3(() => setModel(createModel(props)), [
|
|
2989
2886
|
identity,
|
|
2990
2887
|
space,
|
|
2991
2888
|
text
|
|
2992
2889
|
]);
|
|
2993
2890
|
return model;
|
|
2994
2891
|
};
|
|
2995
|
-
var createModel = (
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
};
|
|
3005
|
-
|
|
3006
|
-
// packages/ui/react-ui-editor/src/hooks/automerge.ts
|
|
3007
|
-
var createAutomergeModel = ({ space, identity, text }) => {
|
|
2892
|
+
var createModel = ({ space, identity, text }) => {
|
|
2893
|
+
invariant5(isAutomergeObject(text), void 0, {
|
|
2894
|
+
F: __dxlog_file7,
|
|
2895
|
+
L: 35,
|
|
2896
|
+
S: void 0,
|
|
2897
|
+
A: [
|
|
2898
|
+
"isAutomergeObject(text)",
|
|
2899
|
+
""
|
|
2900
|
+
]
|
|
2901
|
+
});
|
|
3008
2902
|
const obj = text;
|
|
3009
2903
|
const doc = getRawDoc(obj, [
|
|
3010
2904
|
obj.field
|
|
@@ -3013,7 +2907,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3013
2907
|
space,
|
|
3014
2908
|
channel: `automerge.awareness.${obj.id}`,
|
|
3015
2909
|
info: {
|
|
3016
|
-
displayName: identity
|
|
2910
|
+
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
3017
2911
|
color: cursorColor.color,
|
|
3018
2912
|
lightColor: cursorColor.light
|
|
3019
2913
|
},
|
|
@@ -3023,7 +2917,6 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3023
2917
|
id: obj.id,
|
|
3024
2918
|
content: doc,
|
|
3025
2919
|
text: () => get4(doc.handle.docSync(), doc.path),
|
|
3026
|
-
// TODO(burdon): https://automerge.org/automerge/api-docs/js/functions/next.getCursor.html
|
|
3027
2920
|
extension: [
|
|
3028
2921
|
modelState.init(() => model),
|
|
3029
2922
|
automerge3({
|
|
@@ -3043,7 +2936,7 @@ var createAutomergeModel = ({ space, identity, text }) => {
|
|
|
3043
2936
|
export {
|
|
3044
2937
|
AwarenessProvider,
|
|
3045
2938
|
BaseTextEditor,
|
|
3046
|
-
|
|
2939
|
+
Cursor,
|
|
3047
2940
|
Doc,
|
|
3048
2941
|
EditorModes,
|
|
3049
2942
|
MarkdownEditor,
|
|
@@ -3051,7 +2944,6 @@ export {
|
|
|
3051
2944
|
SpaceAwarenessProvider,
|
|
3052
2945
|
TextEditor,
|
|
3053
2946
|
TextKind,
|
|
3054
|
-
YAwarenessProvider,
|
|
3055
2947
|
YText,
|
|
3056
2948
|
YXmlFragment,
|
|
3057
2949
|
autocomplete,
|
|
@@ -3063,19 +2955,18 @@ export {
|
|
|
3063
2955
|
code2 as code,
|
|
3064
2956
|
codeTheme,
|
|
3065
2957
|
comments,
|
|
3066
|
-
createAutomergeModel,
|
|
3067
|
-
createYjsModel,
|
|
3068
|
-
cursorConverter,
|
|
3069
2958
|
defaultMarkdownSlots,
|
|
3070
2959
|
defaultOptions,
|
|
3071
2960
|
defaultSlots,
|
|
3072
2961
|
defaultTextSlots,
|
|
3073
2962
|
defaultTheme,
|
|
3074
2963
|
getToken,
|
|
2964
|
+
heading2 as heading,
|
|
3075
2965
|
hr,
|
|
3076
2966
|
image,
|
|
3077
2967
|
link,
|
|
3078
2968
|
listener,
|
|
2969
|
+
logChanges,
|
|
3079
2970
|
markdownBundle,
|
|
3080
2971
|
markdownHighlightStyle,
|
|
3081
2972
|
markdownTags,
|
|
@@ -3083,7 +2974,8 @@ export {
|
|
|
3083
2974
|
markdownTheme,
|
|
3084
2975
|
mention,
|
|
3085
2976
|
modelState,
|
|
3086
|
-
|
|
2977
|
+
outliner,
|
|
2978
|
+
setComments,
|
|
3087
2979
|
setFocus,
|
|
3088
2980
|
setSelection,
|
|
3089
2981
|
table,
|
|
@@ -3091,7 +2983,8 @@ export {
|
|
|
3091
2983
|
tasklist,
|
|
3092
2984
|
textTheme,
|
|
3093
2985
|
typewriter,
|
|
3094
|
-
|
|
3095
|
-
|
|
2986
|
+
useComments,
|
|
2987
|
+
useTextEditor,
|
|
2988
|
+
useTextModel
|
|
3096
2989
|
};
|
|
3097
2990
|
//# sourceMappingURL=index.mjs.map
|