@dxos/react-ui-editor 0.4.8-main.05fda5d → 0.4.8-main.06fa7e4
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 +1938 -1920
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +18 -34
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +80 -5
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +12 -11
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +4 -2
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +2 -1
- package/dist/types/src/extensions/automerge/automerge.stories.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 +1 -15
- 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/sync.d.ts +2 -1
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/{hooks → extensions/awareness}/awareness-provider.d.ts +1 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/index.d.ts +3 -0
- package/dist/types/src/extensions/awareness/index.d.ts.map +1 -0
- package/dist/types/src/extensions/comments.d.ts +2 -2
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/cursor.d.ts +1 -1
- package/dist/types/src/extensions/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts +7 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/doc.d.ts +3 -0
- package/dist/types/src/extensions/doc.d.ts.map +1 -0
- package/dist/types/src/extensions/factories.d.ts +53 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +4 -2
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts +9 -0
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts +5 -4
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +8 -5
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts +6 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/table.d.ts +2 -2
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/dist/types/src/extensions/modes.d.ts +2 -1
- package/dist/types/src/extensions/modes.d.ts.map +1 -1
- package/dist/types/src/extensions/state.d.ts +20 -0
- package/dist/types/src/extensions/state.d.ts.map +1 -0
- package/dist/types/src/extensions/types.d.ts +9 -0
- package/dist/types/src/extensions/types.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +1 -4
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +9 -0
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +3 -44
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextEditor.stories.d.ts +7 -0
- package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts +0 -3
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +26 -27
- package/src/components/TextEditor/TextEditor.stories.tsx +532 -23
- package/src/components/TextEditor/TextEditor.tsx +45 -156
- package/src/components/Toolbar/Toolbar.stories.tsx +54 -55
- package/src/components/Toolbar/Toolbar.tsx +102 -60
- package/src/extensions/automerge/automerge.stories.tsx +16 -17
- package/src/extensions/automerge/automerge.ts +6 -5
- package/src/extensions/automerge/cursor.ts +1 -1
- package/src/extensions/automerge/defs.ts +1 -22
- package/src/extensions/automerge/index.ts +0 -1
- package/src/extensions/automerge/sync.ts +2 -9
- package/src/extensions/automerge/update-automerge.ts +2 -1
- package/src/{hooks → extensions/awareness}/awareness-provider.ts +1 -1
- package/src/extensions/{awareness.ts → awareness/awareness.ts} +1 -1
- package/src/extensions/awareness/index.ts +6 -0
- package/src/extensions/command/state.ts +3 -3
- package/src/extensions/comments.ts +9 -5
- package/src/extensions/cursor.ts +1 -1
- package/src/extensions/dnd.ts +31 -9
- package/src/extensions/doc.ts +14 -0
- package/src/extensions/factories.ts +193 -0
- package/src/extensions/index.ts +4 -2
- package/src/extensions/markdown/action.ts +112 -0
- package/src/extensions/markdown/bundle.ts +17 -37
- package/src/extensions/markdown/decorate.ts +2 -4
- package/src/extensions/markdown/formatting.test.ts +13 -13
- package/src/extensions/markdown/formatting.ts +110 -97
- package/src/extensions/markdown/image.ts +7 -0
- package/src/extensions/markdown/index.ts +1 -0
- package/src/extensions/markdown/table.ts +11 -3
- package/src/extensions/modes.ts +11 -2
- package/src/extensions/state.ts +90 -0
- package/src/extensions/types.ts +16 -0
- package/src/hooks/index.ts +1 -5
- package/src/hooks/useActionHandler.ts +4 -85
- package/src/hooks/useDocAccessor.ts +27 -0
- package/src/hooks/useTextEditor.stories.tsx +40 -35
- package/src/hooks/useTextEditor.ts +14 -120
- package/src/index.ts +1 -1
- package/src/themes/default.ts +25 -36
- package/src/translations.ts +1 -0
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +0 -103
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/awareness.d.ts.map +0 -1
- package/dist/types/src/extensions/cursor-line-margin.d.ts +0 -8
- package/dist/types/src/extensions/cursor-line-margin.d.ts.map +0 -1
- package/dist/types/src/extensions/outliner.d.ts +0 -4
- package/dist/types/src/extensions/outliner.d.ts.map +0 -1
- package/dist/types/src/hooks/awareness-provider.d.ts.map +0 -1
- package/dist/types/src/hooks/defs.d.ts +0 -20
- package/dist/types/src/hooks/defs.d.ts.map +0 -1
- package/dist/types/src/hooks/useEditorView.d.ts +0 -20
- package/dist/types/src/hooks/useEditorView.d.ts.map +0 -1
- package/dist/types/src/hooks/useTextModel.d.ts +0 -33
- package/dist/types/src/hooks/useTextModel.d.ts.map +0 -1
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +0 -524
- package/src/extensions/cursor-line-margin.ts +0 -95
- package/src/extensions/outliner.ts +0 -12
- package/src/hooks/defs.ts +0 -30
- package/src/hooks/useEditorView.ts +0 -32
- package/src/hooks/useTextModel.ts +0 -121
- /package/dist/types/src/extensions/{awareness.d.ts → awareness/awareness.d.ts} +0 -0
|
@@ -15,6 +15,7 @@ var translations_default = [
|
|
|
15
15
|
"blockquote label": "Block quote",
|
|
16
16
|
"codeblock label": "Code block",
|
|
17
17
|
"comment label": "Create comment",
|
|
18
|
+
"image label": "Insert image",
|
|
18
19
|
"heading label": "Heading level",
|
|
19
20
|
"table label": "Create table"
|
|
20
21
|
}
|
|
@@ -23,21 +24,17 @@ var translations_default = [
|
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
// packages/ui/react-ui-editor/src/index.ts
|
|
26
|
-
import { keymap as
|
|
27
|
+
import { keymap as keymap11 } from "@codemirror/view";
|
|
27
28
|
import { tags as tags2 } from "@lezer/highlight";
|
|
28
29
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
29
30
|
import { Doc, YText, YXmlFragment } from "@dxos/text-model";
|
|
30
31
|
|
|
31
32
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
32
|
-
import { EditorState as
|
|
33
|
-
import { EditorView as
|
|
33
|
+
import { EditorState as EditorState2 } from "@codemirror/state";
|
|
34
|
+
import { EditorView as EditorView16 } from "@codemirror/view";
|
|
34
35
|
import { useFocusableGroup } from "@fluentui/react-tabster";
|
|
35
|
-
import
|
|
36
|
-
import
|
|
37
|
-
import { DocAccessor } from "@dxos/echo-schema";
|
|
38
|
-
import { log as log9 } from "@dxos/log";
|
|
39
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
40
|
-
import { focusRing } from "@dxos/react-ui-theme";
|
|
36
|
+
import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
|
|
37
|
+
import { log as log7 } from "@dxos/log";
|
|
41
38
|
import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
|
|
42
39
|
|
|
43
40
|
// packages/ui/react-ui-editor/src/extensions/annotations.ts
|
|
@@ -60,8 +57,8 @@ var Cursor = class _Cursor {
|
|
|
60
57
|
});
|
|
61
58
|
}
|
|
62
59
|
static {
|
|
63
|
-
this.getCursorFromRange = (
|
|
64
|
-
const cursorConverter2 =
|
|
60
|
+
this.getCursorFromRange = (state2, range) => {
|
|
61
|
+
const cursorConverter2 = state2.facet(_Cursor.converter);
|
|
65
62
|
const from = cursorConverter2.toCursor(range.from);
|
|
66
63
|
const to = cursorConverter2.toCursor(range.to, -1);
|
|
67
64
|
return [
|
|
@@ -71,8 +68,8 @@ var Cursor = class _Cursor {
|
|
|
71
68
|
};
|
|
72
69
|
}
|
|
73
70
|
static {
|
|
74
|
-
this.getRangeFromCursor = (
|
|
75
|
-
const cursorConverter2 =
|
|
71
|
+
this.getRangeFromCursor = (state2, cursor) => {
|
|
72
|
+
const cursorConverter2 = state2.facet(_Cursor.converter);
|
|
76
73
|
const parts = cursor.split(":");
|
|
77
74
|
const from = cursorConverter2.fromCursor(parts[0]);
|
|
78
75
|
const to = cursorConverter2.fromCursor(parts[1]);
|
|
@@ -89,15 +86,15 @@ var annotationMark = Decoration.mark({
|
|
|
89
86
|
class: "cm-annotation"
|
|
90
87
|
});
|
|
91
88
|
var annotations = (options = {}) => {
|
|
92
|
-
const match = (
|
|
89
|
+
const match = (state2) => {
|
|
93
90
|
const annotations2 = [];
|
|
94
|
-
const text =
|
|
91
|
+
const text = state2.doc.toString();
|
|
95
92
|
if (options.match) {
|
|
96
93
|
const matches = text.matchAll(options.match);
|
|
97
94
|
for (const match2 of matches) {
|
|
98
95
|
const from = match2.index;
|
|
99
96
|
const to = from + match2[0].length;
|
|
100
|
-
const cursor = Cursor.getCursorFromRange(
|
|
97
|
+
const cursor = Cursor.getCursorFromRange(state2, {
|
|
101
98
|
from,
|
|
102
99
|
to
|
|
103
100
|
});
|
|
@@ -109,8 +106,8 @@ var annotations = (options = {}) => {
|
|
|
109
106
|
return annotations2;
|
|
110
107
|
};
|
|
111
108
|
const annotationsState = StateField.define({
|
|
112
|
-
create: (
|
|
113
|
-
return match(
|
|
109
|
+
create: (state2) => {
|
|
110
|
+
return match(state2);
|
|
114
111
|
},
|
|
115
112
|
update: (value, tr) => {
|
|
116
113
|
if (!tr.changes.empty) {
|
|
@@ -123,10 +120,10 @@ var annotations = (options = {}) => {
|
|
|
123
120
|
annotationsState,
|
|
124
121
|
EditorView.decorations.compute([
|
|
125
122
|
annotationsState
|
|
126
|
-
], (
|
|
127
|
-
const annotations2 =
|
|
128
|
-
const decorations = annotations2.map((
|
|
129
|
-
const range = Cursor.getRangeFromCursor(
|
|
123
|
+
], (state2) => {
|
|
124
|
+
const annotations2 = state2.field(annotationsState);
|
|
125
|
+
const decorations = annotations2.map((annotation) => {
|
|
126
|
+
const range = Cursor.getRangeFromCursor(state2, annotation.cursor);
|
|
130
127
|
return range && annotationMark.range(range.from, range.to);
|
|
131
128
|
}).filter(isNotFalsy);
|
|
132
129
|
return Decoration.set(decorations);
|
|
@@ -243,9 +240,8 @@ var cursorConverter = ({ handle, path }) => ({
|
|
|
243
240
|
|
|
244
241
|
// packages/ui/react-ui-editor/src/extensions/automerge/defs.ts
|
|
245
242
|
import { Annotation, StateEffect } from "@codemirror/state";
|
|
246
|
-
|
|
247
|
-
var
|
|
248
|
-
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
243
|
+
var getPath = (state2, field) => state2.field(field).path;
|
|
244
|
+
var getLastHeads = (state2, field) => state2.field(field).lastHeads;
|
|
249
245
|
var updateHeadsEffect = StateEffect.define({});
|
|
250
246
|
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
251
247
|
newHeads
|
|
@@ -260,8 +256,8 @@ import { next as A3 } from "@dxos/automerge/automerge";
|
|
|
260
256
|
|
|
261
257
|
// packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
|
|
262
258
|
import { next as A2 } from "@dxos/automerge/automerge";
|
|
263
|
-
var updateAutomerge = (field, handle, transactions,
|
|
264
|
-
const { lastHeads, path } =
|
|
259
|
+
var updateAutomerge = (field, handle, transactions, state2) => {
|
|
260
|
+
const { lastHeads, path } = state2.field(field);
|
|
265
261
|
let hasChanges = false;
|
|
266
262
|
for (const tr of transactions) {
|
|
267
263
|
tr.changes.iterChanges(() => {
|
|
@@ -308,7 +304,7 @@ var updateCodeMirror = (view, selection, target, patches) => {
|
|
|
308
304
|
annotations: reconcileAnnotation.of(false)
|
|
309
305
|
});
|
|
310
306
|
};
|
|
311
|
-
var handlePatch = (patch, target,
|
|
307
|
+
var handlePatch = (patch, target, state2) => {
|
|
312
308
|
if (patch.action === "insert") {
|
|
313
309
|
return handleInsert(target, patch);
|
|
314
310
|
} else if (patch.action === "splice") {
|
|
@@ -316,7 +312,7 @@ var handlePatch = (patch, target, state) => {
|
|
|
316
312
|
} else if (patch.action === "del") {
|
|
317
313
|
return handleDel(target, patch);
|
|
318
314
|
} else if (patch.action === "put") {
|
|
319
|
-
return handlePut(target, patch,
|
|
315
|
+
return handlePut(target, patch, state2);
|
|
320
316
|
} else {
|
|
321
317
|
return null;
|
|
322
318
|
}
|
|
@@ -360,7 +356,7 @@ var handleDel = (target, patch) => {
|
|
|
360
356
|
}
|
|
361
357
|
];
|
|
362
358
|
};
|
|
363
|
-
var handlePut = (target, patch,
|
|
359
|
+
var handlePut = (target, patch, state2) => {
|
|
364
360
|
const index = charPath(target, [
|
|
365
361
|
...patch.path,
|
|
366
362
|
0
|
|
@@ -368,7 +364,7 @@ var handlePut = (target, patch, state) => {
|
|
|
368
364
|
if (index == null) {
|
|
369
365
|
return [];
|
|
370
366
|
}
|
|
371
|
-
const length =
|
|
367
|
+
const length = state2.doc.length;
|
|
372
368
|
if (typeof patch.value !== "string") {
|
|
373
369
|
return [];
|
|
374
370
|
}
|
|
@@ -479,13 +475,13 @@ var automerge = (accessor) => {
|
|
|
479
475
|
ViewPlugin.fromClass(class {
|
|
480
476
|
constructor(_view) {
|
|
481
477
|
this._view = _view;
|
|
482
|
-
|
|
478
|
+
this._handleChange = () => {
|
|
479
|
+
syncer.reconcile(this._view, false);
|
|
480
|
+
};
|
|
481
|
+
accessor.handle.addListener("change", this._handleChange);
|
|
483
482
|
}
|
|
484
483
|
destroy() {
|
|
485
|
-
accessor.handle.removeListener("change", this._handleChange
|
|
486
|
-
}
|
|
487
|
-
_handleChange() {
|
|
488
|
-
syncer.reconcile(this._view, false);
|
|
484
|
+
accessor.handle.removeListener("change", this._handleChange);
|
|
489
485
|
}
|
|
490
486
|
}),
|
|
491
487
|
// Reconcile local updates.
|
|
@@ -497,7 +493,7 @@ var automerge = (accessor) => {
|
|
|
497
493
|
];
|
|
498
494
|
};
|
|
499
495
|
|
|
500
|
-
// packages/ui/react-ui-editor/src/extensions/awareness.ts
|
|
496
|
+
// packages/ui/react-ui-editor/src/extensions/awareness/awareness.ts
|
|
501
497
|
import { Annotation as Annotation2, Facet as Facet2, RangeSet } from "@codemirror/state";
|
|
502
498
|
import { Decoration as Decoration2, EditorView as EditorView3, ViewPlugin as ViewPlugin2, WidgetType } from "@codemirror/view";
|
|
503
499
|
import { Event } from "@dxos/async";
|
|
@@ -566,9 +562,9 @@ var RemoteSelectionsDecorator = class {
|
|
|
566
562
|
_updateRemoteSelections(update2) {
|
|
567
563
|
const decorations = [];
|
|
568
564
|
const awarenessStates = this._provider.getRemoteStates();
|
|
569
|
-
for (const
|
|
570
|
-
const anchor =
|
|
571
|
-
const head =
|
|
565
|
+
for (const state2 of awarenessStates) {
|
|
566
|
+
const anchor = state2.position?.anchor ? this._cursorConverter.fromCursor(state2.position.anchor) : null;
|
|
567
|
+
const head = state2.position?.head ? this._cursorConverter.fromCursor(state2.position.head) : null;
|
|
572
568
|
if (anchor == null || head == null) {
|
|
573
569
|
continue;
|
|
574
570
|
}
|
|
@@ -576,8 +572,8 @@ var RemoteSelectionsDecorator = class {
|
|
|
576
572
|
const end = Math.min(Math.max(anchor, head), update2.view.state.doc.length);
|
|
577
573
|
const startLine = update2.view.state.doc.lineAt(start);
|
|
578
574
|
const endLine = update2.view.state.doc.lineAt(end);
|
|
579
|
-
const color =
|
|
580
|
-
const lightColor =
|
|
575
|
+
const color = state2.info.color ?? "#30bced";
|
|
576
|
+
const lightColor = state2.info.lightColor ?? color + "33";
|
|
581
577
|
if (startLine.number === endLine.number) {
|
|
582
578
|
decorations.push({
|
|
583
579
|
from: start,
|
|
@@ -630,7 +626,7 @@ var RemoteSelectionsDecorator = class {
|
|
|
630
626
|
value: Decoration2.widget({
|
|
631
627
|
side: head - anchor > 0 ? -1 : 1,
|
|
632
628
|
block: false,
|
|
633
|
-
widget: new RemoteCaretWidget(
|
|
629
|
+
widget: new RemoteCaretWidget(state2.info.displayName ?? "Anonymous", color)
|
|
634
630
|
})
|
|
635
631
|
});
|
|
636
632
|
}
|
|
@@ -732,11 +728,115 @@ var styles2 = EditorView3.baseTheme({
|
|
|
732
728
|
}
|
|
733
729
|
});
|
|
734
730
|
|
|
731
|
+
// packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts
|
|
732
|
+
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
733
|
+
import { Context as Context2 } from "@dxos/context";
|
|
734
|
+
import { invariant } from "@dxos/invariant";
|
|
735
|
+
import { log as log2 } from "@dxos/log";
|
|
736
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/awareness/awareness-provider.ts";
|
|
737
|
+
var DEBOUNCE_INTERVAL = 100;
|
|
738
|
+
var SpaceAwarenessProvider = class {
|
|
739
|
+
constructor(params) {
|
|
740
|
+
this._remoteStates = /* @__PURE__ */ new Map();
|
|
741
|
+
this.remoteStateChange = new Event2();
|
|
742
|
+
this._space = params.space;
|
|
743
|
+
this._channel = params.channel;
|
|
744
|
+
this._peerId = params.peerId;
|
|
745
|
+
this._info = params.info;
|
|
746
|
+
}
|
|
747
|
+
open() {
|
|
748
|
+
this._ctx = new Context2();
|
|
749
|
+
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
750
|
+
if (this._localState) {
|
|
751
|
+
await this._space.postMessage(this._channel, {
|
|
752
|
+
kind: "post",
|
|
753
|
+
state: this._localState
|
|
754
|
+
});
|
|
755
|
+
await sleep(DEBOUNCE_INTERVAL);
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
759
|
+
switch (message.payload.kind) {
|
|
760
|
+
case "query": {
|
|
761
|
+
this._handleQueryMessage();
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
case "post": {
|
|
765
|
+
this._handlePostMessage(message.payload);
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}));
|
|
770
|
+
void this._space.postMessage(this._channel, {
|
|
771
|
+
kind: "query"
|
|
772
|
+
}).catch((err) => {
|
|
773
|
+
log2.debug("failed to query awareness", {
|
|
774
|
+
err
|
|
775
|
+
}, {
|
|
776
|
+
F: __dxlog_file2,
|
|
777
|
+
L: 89,
|
|
778
|
+
S: this,
|
|
779
|
+
C: (f, a) => f(...a)
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
close() {
|
|
784
|
+
void this._ctx?.dispose();
|
|
785
|
+
this._ctx = void 0;
|
|
786
|
+
this._postTask = void 0;
|
|
787
|
+
}
|
|
788
|
+
getRemoteStates() {
|
|
789
|
+
return Array.from(this._remoteStates.values());
|
|
790
|
+
}
|
|
791
|
+
update(position) {
|
|
792
|
+
invariant(this._postTask, void 0, {
|
|
793
|
+
F: __dxlog_file2,
|
|
794
|
+
L: 104,
|
|
795
|
+
S: this,
|
|
796
|
+
A: [
|
|
797
|
+
"this._postTask",
|
|
798
|
+
""
|
|
799
|
+
]
|
|
800
|
+
});
|
|
801
|
+
this._localState = {
|
|
802
|
+
peerId: this._peerId,
|
|
803
|
+
position,
|
|
804
|
+
info: this._info
|
|
805
|
+
};
|
|
806
|
+
this._postTask.schedule();
|
|
807
|
+
}
|
|
808
|
+
_handleQueryMessage() {
|
|
809
|
+
invariant(this._postTask, void 0, {
|
|
810
|
+
F: __dxlog_file2,
|
|
811
|
+
L: 115,
|
|
812
|
+
S: this,
|
|
813
|
+
A: [
|
|
814
|
+
"this._postTask",
|
|
815
|
+
""
|
|
816
|
+
]
|
|
817
|
+
});
|
|
818
|
+
this._postTask.schedule();
|
|
819
|
+
}
|
|
820
|
+
_handlePostMessage(message) {
|
|
821
|
+
invariant(message.kind === "post", void 0, {
|
|
822
|
+
F: __dxlog_file2,
|
|
823
|
+
L: 120,
|
|
824
|
+
S: this,
|
|
825
|
+
A: [
|
|
826
|
+
"message.kind === 'post'",
|
|
827
|
+
""
|
|
828
|
+
]
|
|
829
|
+
});
|
|
830
|
+
this._remoteStates.set(message.state.peerId, message.state);
|
|
831
|
+
this.remoteStateChange.emit();
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
|
|
735
835
|
// packages/ui/react-ui-editor/src/extensions/blast.ts
|
|
736
836
|
import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
|
|
737
837
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
738
|
-
import { invariant } from "@dxos/invariant";
|
|
739
|
-
var
|
|
838
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
839
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
|
|
740
840
|
var defaultOptions = {
|
|
741
841
|
effect: 2,
|
|
742
842
|
maxParticles: 200,
|
|
@@ -862,8 +962,8 @@ var Blaster = class {
|
|
|
862
962
|
return this._node;
|
|
863
963
|
}
|
|
864
964
|
initialize() {
|
|
865
|
-
|
|
866
|
-
F:
|
|
965
|
+
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
966
|
+
F: __dxlog_file3,
|
|
867
967
|
L: 141,
|
|
868
968
|
S: this,
|
|
869
969
|
A: [
|
|
@@ -899,8 +999,8 @@ var Blaster = class {
|
|
|
899
999
|
}
|
|
900
1000
|
}
|
|
901
1001
|
start() {
|
|
902
|
-
|
|
903
|
-
F:
|
|
1002
|
+
invariant2(this._canvas && this._ctx, void 0, {
|
|
1003
|
+
F: __dxlog_file3,
|
|
904
1004
|
L: 180,
|
|
905
1005
|
S: this,
|
|
906
1006
|
A: [
|
|
@@ -1057,7 +1157,7 @@ var commandConfig = Facet3.define({
|
|
|
1057
1157
|
});
|
|
1058
1158
|
var commandState = StateField3.define({
|
|
1059
1159
|
create: () => ({}),
|
|
1060
|
-
update: (
|
|
1160
|
+
update: (state2, tr) => {
|
|
1061
1161
|
for (const effect of tr.effects) {
|
|
1062
1162
|
if (effect.is(closeEffect)) {
|
|
1063
1163
|
return {};
|
|
@@ -1096,7 +1196,7 @@ var commandState = StateField3.define({
|
|
|
1096
1196
|
}
|
|
1097
1197
|
});
|
|
1098
1198
|
}
|
|
1099
|
-
|
|
1199
|
+
requestAnimationFrame(() => view2.focus());
|
|
1100
1200
|
});
|
|
1101
1201
|
}
|
|
1102
1202
|
};
|
|
@@ -1108,10 +1208,10 @@ var commandState = StateField3.define({
|
|
|
1108
1208
|
};
|
|
1109
1209
|
}
|
|
1110
1210
|
}
|
|
1111
|
-
return
|
|
1211
|
+
return state2;
|
|
1112
1212
|
},
|
|
1113
|
-
provide: (
|
|
1114
|
-
showTooltip.from(
|
|
1213
|
+
provide: (field) => [
|
|
1214
|
+
showTooltip.from(field, (value) => value.tooltip ?? null)
|
|
1115
1215
|
]
|
|
1116
1216
|
});
|
|
1117
1217
|
var openEffect = StateEffect2.define();
|
|
@@ -1266,7 +1366,7 @@ import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView
|
|
|
1266
1366
|
import sortBy from "lodash.sortby";
|
|
1267
1367
|
import { useEffect } from "react";
|
|
1268
1368
|
import { debounce } from "@dxos/async";
|
|
1269
|
-
import { log as
|
|
1369
|
+
import { log as log4 } from "@dxos/log";
|
|
1270
1370
|
import { nonNullable } from "@dxos/util";
|
|
1271
1371
|
|
|
1272
1372
|
// packages/ui/react-ui-editor/src/styles/markdown.ts
|
|
@@ -1293,10 +1393,10 @@ var inlineUrl = mx(code, "px-1");
|
|
|
1293
1393
|
var blockquote = mx("pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30", light);
|
|
1294
1394
|
|
|
1295
1395
|
// packages/ui/react-ui-editor/src/styles/tokens.ts
|
|
1296
|
-
import
|
|
1396
|
+
import get2 from "lodash.get";
|
|
1297
1397
|
import { tailwindConfig } from "@dxos/react-ui-theme";
|
|
1298
1398
|
var tokens = tailwindConfig({}).theme;
|
|
1299
|
-
var getToken = (path, defaultValue = void 0) =>
|
|
1399
|
+
var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
|
|
1300
1400
|
|
|
1301
1401
|
// packages/ui/react-ui-editor/src/styles/layout.ts
|
|
1302
1402
|
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
@@ -1304,14 +1404,14 @@ var editorFillLayoutRoot = "bs-full relative";
|
|
|
1304
1404
|
var editorFillLayoutEditor = "!absolute inset-0";
|
|
1305
1405
|
|
|
1306
1406
|
// packages/ui/react-ui-editor/src/util.ts
|
|
1307
|
-
import { log as
|
|
1308
|
-
var
|
|
1407
|
+
import { log as log3 } from "@dxos/log";
|
|
1408
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
|
|
1309
1409
|
var callbackWrapper = (fn) => (...args) => {
|
|
1310
1410
|
try {
|
|
1311
1411
|
return fn(...args);
|
|
1312
1412
|
} catch (err) {
|
|
1313
|
-
|
|
1314
|
-
F:
|
|
1413
|
+
log3.catch(err, void 0, {
|
|
1414
|
+
F: __dxlog_file4,
|
|
1315
1415
|
L: 18,
|
|
1316
1416
|
S: void 0,
|
|
1317
1417
|
C: (f, a) => f(...a)
|
|
@@ -1334,10 +1434,10 @@ var logChanges = (trs) => {
|
|
|
1334
1434
|
return changes2;
|
|
1335
1435
|
}).filter(Boolean);
|
|
1336
1436
|
if (changes.length) {
|
|
1337
|
-
|
|
1437
|
+
log3.info("changes", {
|
|
1338
1438
|
changes
|
|
1339
1439
|
}, {
|
|
1340
|
-
F:
|
|
1440
|
+
F: __dxlog_file4,
|
|
1341
1441
|
L: 39,
|
|
1342
1442
|
S: void 0,
|
|
1343
1443
|
C: (f, a) => f(...a)
|
|
@@ -1346,7 +1446,7 @@ var logChanges = (trs) => {
|
|
|
1346
1446
|
};
|
|
1347
1447
|
|
|
1348
1448
|
// packages/ui/react-ui-editor/src/extensions/comments.ts
|
|
1349
|
-
var
|
|
1449
|
+
var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
|
|
1350
1450
|
var documentId = Facet4.define({
|
|
1351
1451
|
combine: (values) => values[0]
|
|
1352
1452
|
});
|
|
@@ -1354,8 +1454,8 @@ var setComments = StateEffect3.define();
|
|
|
1354
1454
|
var setSelection = StateEffect3.define();
|
|
1355
1455
|
var setCommentState = StateEffect3.define();
|
|
1356
1456
|
var commentsState = StateField4.define({
|
|
1357
|
-
create: (
|
|
1358
|
-
id:
|
|
1457
|
+
create: (state2) => ({
|
|
1458
|
+
id: state2.facet(documentId),
|
|
1359
1459
|
comments: [],
|
|
1360
1460
|
selection: {}
|
|
1361
1461
|
}),
|
|
@@ -1427,13 +1527,13 @@ var commentCurrentMark = Decoration4.mark({
|
|
|
1427
1527
|
});
|
|
1428
1528
|
var commentsDecorations = EditorView7.decorations.compute([
|
|
1429
1529
|
commentsState
|
|
1430
|
-
], (
|
|
1431
|
-
const { selection: { current }, comments: comments2 } =
|
|
1530
|
+
], (state2) => {
|
|
1531
|
+
const { selection: { current }, comments: comments2 } = state2.field(commentsState);
|
|
1432
1532
|
const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
1433
1533
|
const range = comment.range;
|
|
1434
1534
|
if (!range || range.from === range.to) {
|
|
1435
|
-
|
|
1436
|
-
F:
|
|
1535
|
+
log4.warn("Invalid range:", range, {
|
|
1536
|
+
F: __dxlog_file5,
|
|
1437
1537
|
L: 132,
|
|
1438
1538
|
S: void 0,
|
|
1439
1539
|
C: (f, a) => f(...a)
|
|
@@ -1592,7 +1692,7 @@ var optionsFacet = Facet4.define({
|
|
|
1592
1692
|
});
|
|
1593
1693
|
var comments = (options = {}) => {
|
|
1594
1694
|
const { key: shortcut = "meta-'" } = options;
|
|
1595
|
-
const handleSelect = debounce((
|
|
1695
|
+
const handleSelect = debounce((state2) => options.onSelect?.(state2), 200);
|
|
1596
1696
|
return [
|
|
1597
1697
|
optionsFacet.of(options),
|
|
1598
1698
|
documentId.of(options.id),
|
|
@@ -1641,9 +1741,9 @@ var comments = (options = {}) => {
|
|
|
1641
1741
|
//
|
|
1642
1742
|
// Track deleted ranges and update ranges for decorations.
|
|
1643
1743
|
//
|
|
1644
|
-
EditorView7.updateListener.of(({ view, state, changes }) => {
|
|
1744
|
+
EditorView7.updateListener.of(({ view, state: state2, changes }) => {
|
|
1645
1745
|
let mod = false;
|
|
1646
|
-
const { comments: comments2, ...value } =
|
|
1746
|
+
const { comments: comments2, ...value } = state2.field(commentsState);
|
|
1647
1747
|
changes.iterChanges((from, to, from2, to2) => {
|
|
1648
1748
|
comments2.forEach(({ comment, range }) => {
|
|
1649
1749
|
if (from2 === to2) {
|
|
@@ -1673,10 +1773,10 @@ var comments = (options = {}) => {
|
|
|
1673
1773
|
//
|
|
1674
1774
|
// Track selection/proximity.
|
|
1675
1775
|
//
|
|
1676
|
-
EditorView7.updateListener.of(({ view, state }) => {
|
|
1776
|
+
EditorView7.updateListener.of(({ view, state: state2 }) => {
|
|
1677
1777
|
let min = Infinity;
|
|
1678
|
-
const { selection: { current, closest }, comments: comments2 } =
|
|
1679
|
-
const { head } =
|
|
1778
|
+
const { selection: { current, closest }, comments: comments2 } = state2.field(commentsState);
|
|
1779
|
+
const { head } = state2.selection.main;
|
|
1680
1780
|
const selection = {};
|
|
1681
1781
|
comments2.forEach(({ comment, range }) => {
|
|
1682
1782
|
if (head >= range.from && head <= range.to) {
|
|
@@ -1697,7 +1797,7 @@ var comments = (options = {}) => {
|
|
|
1697
1797
|
});
|
|
1698
1798
|
handleSelect({
|
|
1699
1799
|
selection,
|
|
1700
|
-
id:
|
|
1800
|
+
id: state2.facet(documentId),
|
|
1701
1801
|
comments: comments2.map(({ comment, range }) => ({
|
|
1702
1802
|
comment,
|
|
1703
1803
|
range,
|
|
@@ -1732,15 +1832,17 @@ var focusComment = (view, id, center = true) => {
|
|
|
1732
1832
|
});
|
|
1733
1833
|
}
|
|
1734
1834
|
};
|
|
1735
|
-
var useComments = (view, id, comments2
|
|
1835
|
+
var useComments = (view, id, comments2) => {
|
|
1736
1836
|
useEffect(() => {
|
|
1737
1837
|
if (view) {
|
|
1738
|
-
view.
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1838
|
+
if (id === view.state.facet(documentId)) {
|
|
1839
|
+
view.dispatch({
|
|
1840
|
+
effects: setComments.of({
|
|
1841
|
+
id,
|
|
1842
|
+
comments: comments2 ?? []
|
|
1843
|
+
})
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1744
1846
|
}
|
|
1745
1847
|
}, [
|
|
1746
1848
|
id,
|
|
@@ -1749,623 +1851,442 @@ var useComments = (view, id, comments2 = []) => {
|
|
|
1749
1851
|
]);
|
|
1750
1852
|
};
|
|
1751
1853
|
|
|
1752
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1753
|
-
import { Facet as Facet5
|
|
1754
|
-
import {
|
|
1755
|
-
|
|
1756
|
-
var
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
|
|
1762
|
-
var cursorLineMargin = EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
|
|
1763
|
-
if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
|
|
1764
|
-
return;
|
|
1765
|
-
}
|
|
1766
|
-
const s = state;
|
|
1767
|
-
const { main } = s.selection;
|
|
1768
|
-
const cursorLineMargin2 = s.facet(cursorLineMarginFacet);
|
|
1769
|
-
const rect = view.dom.getBoundingClientRect();
|
|
1770
|
-
const viewportTop = rect.top - view.documentTop;
|
|
1771
|
-
const viewportBottom = rect.bottom - view.documentTop;
|
|
1772
|
-
const mainLine = lineAtPos(s, main.head);
|
|
1773
|
-
const _visTopLine = lineAtPos(s, view.lineBlockAtHeight(viewportTop).from);
|
|
1774
|
-
const botLineBlk = view.lineBlockAtHeight(viewportBottom);
|
|
1775
|
-
const visBotLineDoc = lineAtPos(s, Math.min(botLineBlk.to, s.doc.length));
|
|
1776
|
-
const visBotLine = botLineBlk.bottom >= viewportBottom ? visBotLineDoc : visBotLineDoc + Math.floor((viewportBottom - botLineBlk.bottom) / view.defaultLineHeight);
|
|
1777
|
-
const needsScrollTop = false;
|
|
1778
|
-
const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
|
|
1779
|
-
if (needsScrollTop && needsScrollBot) {
|
|
1780
|
-
log4.warn("is cursorScrollMargin too large for the editor size?", void 0, {
|
|
1781
|
-
F: __dxlog_file5,
|
|
1782
|
-
L: 66,
|
|
1854
|
+
// packages/ui/react-ui-editor/src/extensions/doc.ts
|
|
1855
|
+
import { Facet as Facet5 } from "@codemirror/state";
|
|
1856
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1857
|
+
var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/doc.ts";
|
|
1858
|
+
var documentId2 = Facet5.define({
|
|
1859
|
+
combine: (providers) => {
|
|
1860
|
+
invariant3(providers.length <= 1, void 0, {
|
|
1861
|
+
F: __dxlog_file6,
|
|
1862
|
+
L: 11,
|
|
1783
1863
|
S: void 0,
|
|
1784
|
-
|
|
1864
|
+
A: [
|
|
1865
|
+
"providers.length <= 1",
|
|
1866
|
+
""
|
|
1867
|
+
]
|
|
1785
1868
|
});
|
|
1786
|
-
return;
|
|
1787
|
-
}
|
|
1788
|
-
if (!needsScrollTop && !needsScrollBot) {
|
|
1789
|
-
return;
|
|
1790
|
-
}
|
|
1791
|
-
if (selectionSet) {
|
|
1792
|
-
const { head } = startState.selection.main;
|
|
1793
|
-
const oldMainLine = lineAtPos(startState, head);
|
|
1794
|
-
if (needsScrollTop && oldMainLine < mainLine) {
|
|
1795
|
-
return;
|
|
1796
|
-
}
|
|
1797
|
-
if (needsScrollBot && oldMainLine > mainLine) {
|
|
1798
|
-
return;
|
|
1799
|
-
}
|
|
1869
|
+
return providers[0];
|
|
1800
1870
|
}
|
|
1801
|
-
view.dispatch({
|
|
1802
|
-
annotations: Transaction.userEvent.of(annotation),
|
|
1803
|
-
effects: EditorView8.scrollIntoView(s.selection.main.head, {
|
|
1804
|
-
y: needsScrollTop ? "start" : "end",
|
|
1805
|
-
yMargin: view.defaultLineHeight * cursorLineMargin2
|
|
1806
|
-
})
|
|
1807
|
-
});
|
|
1808
1871
|
});
|
|
1809
1872
|
|
|
1810
1873
|
// packages/ui/react-ui-editor/src/extensions/dnd.ts
|
|
1811
|
-
import { EditorView as
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1874
|
+
import { dropCursor, EditorView as EditorView8 } from "@codemirror/view";
|
|
1875
|
+
var styles4 = EditorView8.baseTheme({
|
|
1876
|
+
".cm-dropCursor": {
|
|
1877
|
+
borderLeft: `2px solid ${getToken("extend.colors.primary.500")}`,
|
|
1878
|
+
color: getToken("extend.colors.primary.500"),
|
|
1879
|
+
padding: "0 4px"
|
|
1880
|
+
},
|
|
1881
|
+
".cm-dropCursor:after": {
|
|
1882
|
+
content: '"\u2190"'
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
var dropFile = (options = {}) => {
|
|
1886
|
+
return [
|
|
1887
|
+
styles4,
|
|
1888
|
+
dropCursor(),
|
|
1889
|
+
EditorView8.domEventHandlers({
|
|
1890
|
+
drop: (event, view) => {
|
|
1891
|
+
event.preventDefault();
|
|
1892
|
+
const files = event.dataTransfer?.files;
|
|
1893
|
+
const pos = view.posAtCoords(event);
|
|
1894
|
+
if (files?.length && pos !== null) {
|
|
1895
|
+
view.dispatch({
|
|
1896
|
+
selection: {
|
|
1897
|
+
anchor: pos
|
|
1898
|
+
}
|
|
1899
|
+
});
|
|
1900
|
+
options.onDrop?.(view, {
|
|
1901
|
+
files
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
})
|
|
1906
|
+
];
|
|
1841
1907
|
};
|
|
1842
1908
|
|
|
1843
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
1909
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
1844
1910
|
import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
|
|
1845
|
-
import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1846
|
-
import {
|
|
1847
|
-
import { bracketMatching, defaultHighlightStyle, indentOnInput, syntaxHighlighting } from "@codemirror/language";
|
|
1848
|
-
import { languages } from "@codemirror/language-data";
|
|
1911
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
|
|
1912
|
+
import { bracketMatching } from "@codemirror/language";
|
|
1849
1913
|
import { searchKeymap } from "@codemirror/search";
|
|
1850
1914
|
import { EditorState } from "@codemirror/state";
|
|
1851
|
-
import {
|
|
1852
|
-
import
|
|
1853
|
-
import {
|
|
1915
|
+
import { EditorView as EditorView9, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap5, lineNumbers, placeholder, scrollPastEnd } from "@codemirror/view";
|
|
1916
|
+
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
1917
|
+
import { generateName } from "@dxos/display-name";
|
|
1918
|
+
import { log as log5 } from "@dxos/log";
|
|
1919
|
+
import { hueTokens } from "@dxos/react-ui-theme";
|
|
1920
|
+
import { hexToHue, isNotFalsy as isNotFalsy2 } from "@dxos/util";
|
|
1854
1921
|
|
|
1855
|
-
// packages/ui/react-ui-editor/src/
|
|
1856
|
-
import
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
//
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
Table,
|
|
1885
|
-
{
|
|
1886
|
-
props: [
|
|
1887
|
-
styleTags(markdownTags)
|
|
1888
|
-
]
|
|
1889
|
-
}
|
|
1890
|
-
];
|
|
1891
|
-
var markdownHighlightStyle = (readonly) => {
|
|
1892
|
-
return HighlightStyle.define([
|
|
1893
|
-
{
|
|
1894
|
-
tag: [
|
|
1895
|
-
tags.keyword,
|
|
1896
|
-
tags.name,
|
|
1897
|
-
tags.deleted,
|
|
1898
|
-
tags.character,
|
|
1899
|
-
tags.propertyName,
|
|
1900
|
-
tags.macroName,
|
|
1901
|
-
tags.color,
|
|
1902
|
-
tags.constant(tags.name),
|
|
1903
|
-
tags.standard(tags.name),
|
|
1904
|
-
tags.definition(tags.name),
|
|
1905
|
-
tags.separator,
|
|
1906
|
-
tags.typeName,
|
|
1907
|
-
tags.className,
|
|
1908
|
-
tags.number,
|
|
1909
|
-
tags.changed,
|
|
1910
|
-
tags.annotation,
|
|
1911
|
-
tags.modifier,
|
|
1912
|
-
tags.self,
|
|
1913
|
-
tags.namespace,
|
|
1914
|
-
tags.operator,
|
|
1915
|
-
tags.operatorKeyword,
|
|
1916
|
-
tags.escape,
|
|
1917
|
-
tags.regexp,
|
|
1918
|
-
tags.special(tags.string),
|
|
1919
|
-
tags.meta,
|
|
1920
|
-
tags.comment,
|
|
1921
|
-
tags.atom,
|
|
1922
|
-
tags.bool,
|
|
1923
|
-
tags.special(tags.variableName),
|
|
1924
|
-
tags.processingInstruction,
|
|
1925
|
-
tags.string,
|
|
1926
|
-
tags.inserted,
|
|
1927
|
-
tags.invalid
|
|
1928
|
-
],
|
|
1929
|
-
color: "inherit !important"
|
|
1930
|
-
},
|
|
1931
|
-
// Markdown marks.
|
|
1932
|
-
{
|
|
1933
|
-
tag: [
|
|
1934
|
-
tags.meta,
|
|
1935
|
-
tags.processingInstruction,
|
|
1936
|
-
markdownTags.LinkLabel,
|
|
1937
|
-
markdownTags.LinkReference,
|
|
1938
|
-
markdownTags.ListMark
|
|
1939
|
-
],
|
|
1940
|
-
class: mark
|
|
1941
|
-
},
|
|
1942
|
-
// Markdown marks.
|
|
1943
|
-
{
|
|
1944
|
-
tag: [
|
|
1945
|
-
markdownTags.CodeMark,
|
|
1946
|
-
markdownTags.HeaderMark,
|
|
1947
|
-
markdownTags.QuoteMark,
|
|
1948
|
-
markdownTags.EmphasisMark
|
|
1949
|
-
],
|
|
1950
|
-
class: mark
|
|
1951
|
-
},
|
|
1952
|
-
// E.g., code block language (after ```).
|
|
1953
|
-
{
|
|
1954
|
-
tag: [
|
|
1955
|
-
tags.function(tags.variableName),
|
|
1956
|
-
tags.labelName
|
|
1957
|
-
],
|
|
1958
|
-
class: codeMark
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
tag: [
|
|
1962
|
-
tags.monospace
|
|
1963
|
-
],
|
|
1964
|
-
class: "font-mono"
|
|
1965
|
-
},
|
|
1966
|
-
// Headings.
|
|
1967
|
-
{
|
|
1968
|
-
tag: tags.heading1,
|
|
1969
|
-
class: heading(1)
|
|
1970
|
-
},
|
|
1971
|
-
{
|
|
1972
|
-
tag: tags.heading2,
|
|
1973
|
-
class: heading(2)
|
|
1974
|
-
},
|
|
1975
|
-
{
|
|
1976
|
-
tag: tags.heading3,
|
|
1977
|
-
class: heading(3)
|
|
1978
|
-
},
|
|
1979
|
-
{
|
|
1980
|
-
tag: tags.heading4,
|
|
1981
|
-
class: heading(4)
|
|
1982
|
-
},
|
|
1983
|
-
{
|
|
1984
|
-
tag: tags.heading5,
|
|
1985
|
-
class: heading(5)
|
|
1986
|
-
},
|
|
1987
|
-
{
|
|
1988
|
-
tag: tags.heading6,
|
|
1989
|
-
class: heading(6)
|
|
1990
|
-
},
|
|
1991
|
-
// Emphasis.
|
|
1992
|
-
{
|
|
1993
|
-
tag: tags.emphasis,
|
|
1994
|
-
class: italic
|
|
1995
|
-
},
|
|
1996
|
-
{
|
|
1997
|
-
tag: tags.strong,
|
|
1998
|
-
class: bold
|
|
1999
|
-
},
|
|
2000
|
-
{
|
|
2001
|
-
tag: tags.strikethrough,
|
|
2002
|
-
class: strikethrough
|
|
2003
|
-
},
|
|
2004
|
-
// Naked URLs.
|
|
2005
|
-
{
|
|
2006
|
-
tag: [
|
|
2007
|
-
markdownTags.URL
|
|
2008
|
-
],
|
|
2009
|
-
class: inlineUrl
|
|
2010
|
-
},
|
|
2011
|
-
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
2012
|
-
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
2013
|
-
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
2014
|
-
// the code, but all other CSS properties will be inherited.
|
|
2015
|
-
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
2016
|
-
{
|
|
2017
|
-
tag: [
|
|
2018
|
-
markdownTags.CodeText,
|
|
2019
|
-
markdownTags.InlineCode
|
|
2020
|
-
],
|
|
2021
|
-
class: code
|
|
2022
|
-
},
|
|
2023
|
-
{
|
|
2024
|
-
tag: [
|
|
2025
|
-
markdownTags.QuoteMark
|
|
2026
|
-
],
|
|
2027
|
-
class: blockquote
|
|
2028
|
-
},
|
|
2029
|
-
{
|
|
2030
|
-
tag: [
|
|
2031
|
-
markdownTags.TableCell
|
|
2032
|
-
],
|
|
2033
|
-
class: "font-mono"
|
|
2034
|
-
}
|
|
2035
|
-
], {
|
|
2036
|
-
scope: markdownLanguage2,
|
|
2037
|
-
all: {
|
|
2038
|
-
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
2039
|
-
}
|
|
2040
|
-
});
|
|
2041
|
-
};
|
|
2042
|
-
|
|
2043
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
2044
|
-
var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
|
|
2045
|
-
return [
|
|
2046
|
-
// TODO(burdon): Reconcile with createBasicExtensions.
|
|
2047
|
-
lineWrapping && EditorView11.lineWrapping,
|
|
2048
|
-
EditorState.allowMultipleSelections.of(true),
|
|
2049
|
-
EditorState.tabSize.of(2),
|
|
2050
|
-
bracketMatching(),
|
|
2051
|
-
closeBrackets(),
|
|
2052
|
-
dropCursor(),
|
|
2053
|
-
drawSelection(),
|
|
2054
|
-
history(),
|
|
2055
|
-
indentOnInput(),
|
|
2056
|
-
_placeholder && placeholder(_placeholder),
|
|
2057
|
-
// Main extension.
|
|
2058
|
-
// https://github.com/codemirror/lang-markdown
|
|
2059
|
-
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
2060
|
-
markdown({
|
|
2061
|
-
// GRM by default (vs strict CommonMark):
|
|
2062
|
-
// Table, TaskList, Strikethrough, and Autolink.
|
|
2063
|
-
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
2064
|
-
// https://github.github.com/gfm
|
|
2065
|
-
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
2066
|
-
base: markdownLanguage3,
|
|
2067
|
-
// Languages for syntax highlighting fenced code blocks.
|
|
2068
|
-
codeLanguages: languages,
|
|
2069
|
-
// Parser extensions.
|
|
2070
|
-
extensions: [
|
|
2071
|
-
// GFM provided by default.
|
|
2072
|
-
markdownTagsExtensions
|
|
2073
|
-
]
|
|
2074
|
-
}),
|
|
2075
|
-
// https://github.com/codemirror/theme-one-dark
|
|
2076
|
-
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
2077
|
-
// Custom styles.
|
|
2078
|
-
syntaxHighlighting(markdownHighlightStyle()),
|
|
2079
|
-
keymap5.of([
|
|
2080
|
-
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2081
|
-
indentWithTab,
|
|
2082
|
-
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2083
|
-
...closeBracketsKeymap,
|
|
2084
|
-
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2085
|
-
...historyKeymap,
|
|
2086
|
-
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2087
|
-
...searchKeymap,
|
|
2088
|
-
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2089
|
-
...standardKeymap
|
|
2090
|
-
])
|
|
2091
|
-
].filter(isNotFalsy2);
|
|
2092
|
-
};
|
|
2093
|
-
|
|
2094
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
2095
|
-
import { syntaxTree } from "@codemirror/language";
|
|
2096
|
-
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
2097
|
-
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
2098
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
2099
|
-
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
2100
|
-
toDOM() {
|
|
2101
|
-
const el = document.createElement("span");
|
|
2102
|
-
el.className = "cm-hr";
|
|
2103
|
-
return el;
|
|
2104
|
-
}
|
|
2105
|
-
};
|
|
2106
|
-
var LinkButton = class extends WidgetType3 {
|
|
2107
|
-
constructor(url, render) {
|
|
2108
|
-
super();
|
|
2109
|
-
this.url = url;
|
|
2110
|
-
this.render = render;
|
|
2111
|
-
}
|
|
2112
|
-
eq(other) {
|
|
2113
|
-
return this.url === other.url;
|
|
2114
|
-
}
|
|
2115
|
-
toDOM(view) {
|
|
2116
|
-
const el = document.createElement("span");
|
|
2117
|
-
this.render(el, this.url);
|
|
2118
|
-
return el;
|
|
2119
|
-
}
|
|
2120
|
-
};
|
|
2121
|
-
var CheckboxWidget = class extends WidgetType3 {
|
|
2122
|
-
constructor(_checked) {
|
|
2123
|
-
super();
|
|
2124
|
-
this._checked = _checked;
|
|
2125
|
-
}
|
|
2126
|
-
eq(other) {
|
|
2127
|
-
return this._checked === other._checked;
|
|
2128
|
-
}
|
|
2129
|
-
toDOM(view) {
|
|
2130
|
-
const input = document.createElement("input");
|
|
2131
|
-
input.className = "cm-task-checkbox";
|
|
2132
|
-
input.type = "checkbox";
|
|
2133
|
-
input.checked = this._checked;
|
|
2134
|
-
if (view.state.readOnly) {
|
|
2135
|
-
input.setAttribute("disabled", "true");
|
|
2136
|
-
} else {
|
|
2137
|
-
input.onmousedown = (event) => {
|
|
2138
|
-
const pos = view.posAtDOM(input);
|
|
2139
|
-
const text = view.state.sliceDoc(pos, pos + 3);
|
|
2140
|
-
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
2141
|
-
view.dispatch({
|
|
2142
|
-
changes: {
|
|
2143
|
-
from: pos + 1,
|
|
2144
|
-
to: pos + 2,
|
|
2145
|
-
insert: this._checked ? " " : "x"
|
|
2146
|
-
}
|
|
2147
|
-
});
|
|
2148
|
-
event.preventDefault();
|
|
2149
|
-
}
|
|
2150
|
-
};
|
|
2151
|
-
}
|
|
2152
|
-
return input;
|
|
2153
|
-
}
|
|
2154
|
-
ignoreEvent() {
|
|
2155
|
-
return false;
|
|
2156
|
-
}
|
|
2157
|
-
};
|
|
2158
|
-
var hide = Decoration5.replace({});
|
|
2159
|
-
var fencedCodeLine = Decoration5.line({
|
|
2160
|
-
class: mx2("cm-code cm-codeblock-line")
|
|
2161
|
-
});
|
|
2162
|
-
var fencedCodeLineFirst = Decoration5.line({
|
|
2163
|
-
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
|
2164
|
-
});
|
|
2165
|
-
var fencedCodeLineLast = Decoration5.line({
|
|
2166
|
-
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
2167
|
-
});
|
|
2168
|
-
var horizontalRule = Decoration5.replace({
|
|
2169
|
-
widget: new HorizontalRuleWidget()
|
|
2170
|
-
});
|
|
2171
|
-
var checkedTask = Decoration5.replace({
|
|
2172
|
-
widget: new CheckboxWidget(true)
|
|
2173
|
-
});
|
|
2174
|
-
var uncheckedTask = Decoration5.replace({
|
|
2175
|
-
widget: new CheckboxWidget(false)
|
|
2176
|
-
});
|
|
2177
|
-
var editingRange = (state, range, focus) => {
|
|
2178
|
-
const { readOnly, selection: { main: { head } } } = state;
|
|
2179
|
-
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
2180
|
-
};
|
|
2181
|
-
var MarksByParent = /* @__PURE__ */ new Set([
|
|
2182
|
-
"CodeMark",
|
|
2183
|
-
"EmphasisMark",
|
|
2184
|
-
"StrikethroughMark",
|
|
2185
|
-
"SubscriptMark",
|
|
2186
|
-
"SuperscriptMark"
|
|
2187
|
-
]);
|
|
2188
|
-
var buildDecorations = (view, options, focus) => {
|
|
2189
|
-
const deco = new RangeSetBuilder2();
|
|
2190
|
-
const atomicDeco = new RangeSetBuilder2();
|
|
2191
|
-
const { state } = view;
|
|
2192
|
-
for (const { from, to } of view.visibleRanges) {
|
|
2193
|
-
syntaxTree(state).iterate({
|
|
2194
|
-
from,
|
|
2195
|
-
to,
|
|
2196
|
-
enter: (node) => {
|
|
2197
|
-
if (node.name === "FencedCode") {
|
|
2198
|
-
const editing = editingRange(state, node, focus);
|
|
2199
|
-
for (const block of view.viewportLineBlocks) {
|
|
2200
|
-
if (block.to < node.from) {
|
|
2201
|
-
continue;
|
|
2202
|
-
}
|
|
2203
|
-
if (block.from > node.to) {
|
|
2204
|
-
break;
|
|
2205
|
-
}
|
|
2206
|
-
const first = block.from <= node.from;
|
|
2207
|
-
const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
|
|
2208
|
-
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
2209
|
-
if (!editing && (first || last)) {
|
|
2210
|
-
atomicDeco.add(block.from, block.to, hide);
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
return false;
|
|
2214
|
-
} else if (node.name === "Link") {
|
|
2215
|
-
const marks = node.node.getChildren("LinkMark");
|
|
2216
|
-
const urlNode = node.node.getChild("URL");
|
|
2217
|
-
const editing = editingRange(state, node, focus);
|
|
2218
|
-
if (urlNode && marks.length >= 2) {
|
|
2219
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
2220
|
-
if (!editing) {
|
|
2221
|
-
atomicDeco.add(node.from, marks[0].to, hide);
|
|
2222
|
-
}
|
|
2223
|
-
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
2224
|
-
tagName: "a",
|
|
2225
|
-
attributes: {
|
|
2226
|
-
class: "cm-link",
|
|
2227
|
-
href: url,
|
|
2228
|
-
rel: "noreferrer",
|
|
2229
|
-
target: "_blank"
|
|
2230
|
-
}
|
|
2231
|
-
}));
|
|
2232
|
-
if (!editing) {
|
|
2233
|
-
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
2234
|
-
widget: new LinkButton(url, options.renderLinkButton)
|
|
2235
|
-
}) : hide);
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
} else if (node.name === "HeaderMark") {
|
|
2239
|
-
const parent = node.node.parent;
|
|
2240
|
-
if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from), focus)) {
|
|
2241
|
-
const next = state.doc.sliceString(node.to, node.to + 1);
|
|
2242
|
-
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
2243
|
-
}
|
|
2244
|
-
} else if (node.name === "HorizontalRule") {
|
|
2245
|
-
if (!editingRange(state, node, focus)) {
|
|
2246
|
-
deco.add(node.from, node.to, horizontalRule);
|
|
2247
|
-
}
|
|
2248
|
-
} else if (node.name === "TaskMarker") {
|
|
2249
|
-
if (!editingRange(state, node, focus)) {
|
|
2250
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
2251
|
-
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
2252
|
-
class: "cm-task"
|
|
2253
|
-
}));
|
|
2254
|
-
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
2255
|
-
}
|
|
2256
|
-
} else if (MarksByParent.has(node.name)) {
|
|
2257
|
-
if (!editingRange(state, node.node.parent, focus)) {
|
|
2258
|
-
atomicDeco.add(node.from, node.to, hide);
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
});
|
|
2263
|
-
}
|
|
2264
|
-
return {
|
|
2265
|
-
deco: deco.finish(),
|
|
2266
|
-
atomicDeco: atomicDeco.finish()
|
|
2267
|
-
};
|
|
2268
|
-
};
|
|
2269
|
-
var forceUpdate = StateEffect4.define();
|
|
2270
|
-
var decorateMarkdown = (options = {}) => {
|
|
2271
|
-
return [
|
|
2272
|
-
ViewPlugin4.fromClass(class {
|
|
2273
|
-
constructor(view) {
|
|
2274
|
-
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
|
|
2275
|
-
}
|
|
2276
|
-
update(update2) {
|
|
2277
|
-
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
2278
|
-
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
2279
|
-
this.clearUpdate();
|
|
2280
|
-
} else if (update2.selectionSet) {
|
|
2281
|
-
this.scheduleUpdate(update2.view);
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
2285
|
-
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
2286
|
-
scheduleUpdate(view) {
|
|
2287
|
-
this.clearUpdate();
|
|
2288
|
-
this.pendingUpdate = setTimeout(() => {
|
|
2289
|
-
view.dispatch({
|
|
2290
|
-
effects: forceUpdate.of(null)
|
|
2291
|
-
});
|
|
2292
|
-
}, options.selectionChangeDelay);
|
|
2293
|
-
}
|
|
2294
|
-
clearUpdate() {
|
|
2295
|
-
if (this.pendingUpdate) {
|
|
2296
|
-
clearTimeout(this.pendingUpdate);
|
|
2297
|
-
this.pendingUpdate = void 0;
|
|
2298
|
-
}
|
|
2299
|
-
}
|
|
2300
|
-
destroy() {
|
|
2301
|
-
this.clearUpdate();
|
|
2302
|
-
}
|
|
2303
|
-
}, {
|
|
2304
|
-
provide: (plugin) => [
|
|
2305
|
-
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2306
|
-
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
2307
|
-
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
2308
|
-
]
|
|
2309
|
-
}),
|
|
2310
|
-
formattingStyles
|
|
2311
|
-
];
|
|
2312
|
-
};
|
|
2313
|
-
var formattingStyles = EditorView12.baseTheme({
|
|
2314
|
-
"& .cm-code": {
|
|
2315
|
-
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
1922
|
+
// packages/ui/react-ui-editor/src/themes/default.ts
|
|
1923
|
+
import get3 from "lodash.get";
|
|
1924
|
+
var defaultTheme = {
|
|
1925
|
+
//
|
|
1926
|
+
// Main layout:
|
|
1927
|
+
// https://codemirror.net/examples/styling
|
|
1928
|
+
//
|
|
1929
|
+
// <div class="cm-editor [cm-focused] [generated classes]">
|
|
1930
|
+
// <div class="cm-scroller">
|
|
1931
|
+
// <div class="cm-gutters">
|
|
1932
|
+
// <div class="cm-gutter [...]">
|
|
1933
|
+
// <div class="cm-gutterElement">...</div>
|
|
1934
|
+
// </div>
|
|
1935
|
+
// </div>
|
|
1936
|
+
// <div class="cm-content" role="textbox" contenteditable="true">
|
|
1937
|
+
// <div class="cm-line"></div>
|
|
1938
|
+
// </div>
|
|
1939
|
+
// <div class="cm-selectionLayer">
|
|
1940
|
+
// <div class="cm-selectionBackground"></div>
|
|
1941
|
+
// </div>
|
|
1942
|
+
// <div class="cm-cursorLayer">
|
|
1943
|
+
// <div class="cm-cursor"></div>
|
|
1944
|
+
// </div>
|
|
1945
|
+
// </div>
|
|
1946
|
+
// </div>
|
|
1947
|
+
//
|
|
1948
|
+
"&": {},
|
|
1949
|
+
"&.cm-focused": {
|
|
1950
|
+
outline: "none"
|
|
2316
1951
|
},
|
|
2317
|
-
|
|
2318
|
-
|
|
1952
|
+
// NOTE: See https://codemirror.net/docs/guide (DOM Structure).
|
|
1953
|
+
".cm-scroller": {
|
|
1954
|
+
// TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
|
|
1955
|
+
// Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
|
|
1956
|
+
overflowY: "auto",
|
|
1957
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
1958
|
+
lineHeight: 1.5
|
|
2319
1959
|
},
|
|
2320
|
-
"
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
"
|
|
2325
|
-
position: "absolute",
|
|
2326
|
-
inset: 0,
|
|
2327
|
-
content: '""'
|
|
2328
|
-
}
|
|
1960
|
+
".cm-content": {
|
|
1961
|
+
// TODO(burdon): Is it possible to remove the padding value from CM's default theme?
|
|
1962
|
+
// padding: 'unset',
|
|
1963
|
+
// NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
|
|
1964
|
+
fontSize: "16px"
|
|
2329
1965
|
},
|
|
2330
|
-
"& .cm-
|
|
2331
|
-
|
|
2332
|
-
|
|
1966
|
+
"&light .cm-content": {
|
|
1967
|
+
color: get3(tokens, "extend.semanticColors.base.fg.light", "black"),
|
|
1968
|
+
caretColor: "black"
|
|
2333
1969
|
},
|
|
2334
|
-
"& .cm-
|
|
2335
|
-
|
|
2336
|
-
|
|
1970
|
+
"&dark .cm-content": {
|
|
1971
|
+
color: get3(tokens, "extend.semanticColors.base.fg.dark", "white"),
|
|
1972
|
+
caretColor: "white"
|
|
2337
1973
|
},
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
1974
|
+
//
|
|
1975
|
+
// Cursor
|
|
1976
|
+
//
|
|
1977
|
+
"&light .cm-cursor, &light .cm-dropCursor": {
|
|
1978
|
+
borderLeft: "2px solid black"
|
|
1979
|
+
},
|
|
1980
|
+
"&dark .cm-cursor, &dark .cm-dropCursor": {
|
|
1981
|
+
borderLeft: "2px solid white"
|
|
1982
|
+
},
|
|
1983
|
+
"&light .cm-placeholder": {
|
|
1984
|
+
color: get3(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
|
|
1985
|
+
},
|
|
1986
|
+
"&dark .cm-placeholder": {
|
|
1987
|
+
color: get3(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
|
|
1988
|
+
},
|
|
1989
|
+
//
|
|
1990
|
+
// line
|
|
1991
|
+
//
|
|
1992
|
+
".cm-line": {
|
|
1993
|
+
paddingInline: 0
|
|
1994
|
+
},
|
|
1995
|
+
".cm-activeLine": {
|
|
1996
|
+
background: "transparent"
|
|
1997
|
+
},
|
|
1998
|
+
//
|
|
1999
|
+
// gutter
|
|
2000
|
+
//
|
|
2001
|
+
".cm-gutterElement": {
|
|
2002
|
+
width: "48px"
|
|
2003
|
+
},
|
|
2004
|
+
//
|
|
2005
|
+
// Selection
|
|
2006
|
+
//
|
|
2007
|
+
"&light .cm-selectionBackground": {
|
|
2008
|
+
background: get3(tokens, "extend.colors.primary.100")
|
|
2009
|
+
},
|
|
2010
|
+
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2011
|
+
background: get3(tokens, "extend.colors.primary.200")
|
|
2012
|
+
},
|
|
2013
|
+
"&dark .cm-selectionBackground": {
|
|
2014
|
+
background: get3(tokens, "extend.colors.primary.700")
|
|
2015
|
+
},
|
|
2016
|
+
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
2017
|
+
background: get3(tokens, "extend.colors.primary.600")
|
|
2018
|
+
},
|
|
2019
|
+
//
|
|
2020
|
+
// Search
|
|
2021
|
+
//
|
|
2022
|
+
"&light .cm-searchMatch": {
|
|
2023
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.100")
|
|
2024
|
+
},
|
|
2025
|
+
"&dark .cm-searchMatch": {
|
|
2026
|
+
backgroundColor: get3(tokens, "extend.colors.yellow.700")
|
|
2027
|
+
},
|
|
2028
|
+
//
|
|
2029
|
+
// link
|
|
2030
|
+
//
|
|
2031
|
+
".cm-link": {
|
|
2032
|
+
color: get3(tokens, "extend.colors.primary.500"),
|
|
2033
|
+
textDecorationLine: "underline",
|
|
2034
|
+
textDecorationThickness: "1px",
|
|
2035
|
+
textUnderlineOffset: "2px",
|
|
2036
|
+
borderRadius: ".125rem",
|
|
2037
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2038
|
+
},
|
|
2039
|
+
//
|
|
2040
|
+
// tooltip
|
|
2041
|
+
//
|
|
2042
|
+
".cm-tooltip": {
|
|
2043
|
+
border: "none",
|
|
2044
|
+
background: "unset"
|
|
2045
|
+
},
|
|
2046
|
+
".cm-tooltip-below": {},
|
|
2047
|
+
//
|
|
2048
|
+
// autocomplete
|
|
2049
|
+
//
|
|
2050
|
+
".cm-tooltip-autocomplete": {
|
|
2051
|
+
marginTop: "4px",
|
|
2052
|
+
marginLeft: "-3px"
|
|
2053
|
+
},
|
|
2054
|
+
".cm-tooltip-autocomplete ul li": {},
|
|
2055
|
+
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
2056
|
+
".cm-completionIcon": {
|
|
2057
|
+
display: "none"
|
|
2058
|
+
},
|
|
2059
|
+
".cm-completionLabel": {
|
|
2060
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2061
|
+
},
|
|
2062
|
+
".cm-completionMatchedText": {
|
|
2063
|
+
textDecoration: "none"
|
|
2064
|
+
},
|
|
2065
|
+
//
|
|
2066
|
+
// table
|
|
2067
|
+
//
|
|
2068
|
+
".cm-table *": {
|
|
2069
|
+
fontFamily: `${get3(tokens, "fontFamily.mono", []).join(",")} !important`,
|
|
2070
|
+
textDecoration: "none !important"
|
|
2071
|
+
},
|
|
2072
|
+
".cm-table-head": {
|
|
2073
|
+
padding: "2px 16px 2px 0px",
|
|
2074
|
+
borderBottom: `1px solid ${get3(tokens, "extend.colors.neutral.500")}`,
|
|
2075
|
+
fontWeight: 100,
|
|
2076
|
+
textAlign: "left",
|
|
2077
|
+
color: get3(tokens, "extend.colors.neutral.500")
|
|
2078
|
+
},
|
|
2079
|
+
".cm-table-cell": {
|
|
2080
|
+
padding: "2px 16px 2px 0px"
|
|
2081
|
+
},
|
|
2082
|
+
//
|
|
2083
|
+
// image
|
|
2084
|
+
//
|
|
2085
|
+
".cm-image": {
|
|
2086
|
+
display: "block",
|
|
2087
|
+
height: "0"
|
|
2088
|
+
},
|
|
2089
|
+
".cm-image.cm-loaded-image": {
|
|
2090
|
+
height: "auto",
|
|
2091
|
+
borderTop: "0.5rem solid transparent",
|
|
2092
|
+
borderBottom: "0.5rem solid transparent"
|
|
2093
|
+
},
|
|
2094
|
+
//
|
|
2095
|
+
// font size
|
|
2096
|
+
// TODO(thure): This appears to be the best or only way to set selection caret heights,
|
|
2097
|
+
// but it's far more verbose than it needs to be.
|
|
2098
|
+
//
|
|
2099
|
+
// ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
|
|
2100
|
+
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
2101
|
+
//
|
|
2102
|
+
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
2103
|
+
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
2104
|
+
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
2105
|
+
// return acc;
|
|
2106
|
+
// }, {}),
|
|
2107
|
+
/**
|
|
2108
|
+
* Panels
|
|
2109
|
+
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
2110
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
2111
|
+
*
|
|
2112
|
+
* Find/replace panel.
|
|
2113
|
+
* <div class="cm-announced">...</div>
|
|
2114
|
+
* <div class="cm-scroller">...</div>
|
|
2115
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
2116
|
+
* <div class="cm-search cm-panel">
|
|
2117
|
+
* <input class="cm-textfield" />
|
|
2118
|
+
* <button class="cm-button">...</button>
|
|
2119
|
+
* <label><input type="checkbox" />...</label>
|
|
2120
|
+
* </div>
|
|
2121
|
+
* </div
|
|
2122
|
+
*/
|
|
2123
|
+
".cm-panels": {},
|
|
2124
|
+
".cm-panel": {
|
|
2125
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(",")
|
|
2126
|
+
},
|
|
2127
|
+
".cm-panel input[type=checkbox]": {
|
|
2128
|
+
marginRight: "0.4rem !important"
|
|
2129
|
+
},
|
|
2130
|
+
"&light .cm-panel": {
|
|
2131
|
+
background: get3(tokens, "extend.colors.neutral.50")
|
|
2341
2132
|
},
|
|
2342
|
-
"&dark .cm-
|
|
2343
|
-
background:
|
|
2344
|
-
mixBlendMode: "lighten"
|
|
2133
|
+
"&dark .cm-panel": {
|
|
2134
|
+
background: get3(tokens, "extend.colors.neutral.850")
|
|
2345
2135
|
},
|
|
2346
|
-
"
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2136
|
+
".cm-button": {
|
|
2137
|
+
margin: "4px",
|
|
2138
|
+
fontFamily: get3(tokens, "fontFamily.body", []).join(","),
|
|
2139
|
+
backgroundImage: "none",
|
|
2140
|
+
border: "none",
|
|
2141
|
+
"&:active": {
|
|
2142
|
+
backgroundImage: "none"
|
|
2143
|
+
}
|
|
2352
2144
|
},
|
|
2353
|
-
"& .cm-
|
|
2354
|
-
|
|
2145
|
+
"&light .cm-button": {
|
|
2146
|
+
background: get3(tokens, "extend.colors.neutral.100"),
|
|
2147
|
+
"&:hover": {
|
|
2148
|
+
background: get3(tokens, "extend.colors.neutral.200")
|
|
2149
|
+
},
|
|
2150
|
+
"&:active": {
|
|
2151
|
+
background: get3(tokens, "extend.colors.neutral.300")
|
|
2152
|
+
}
|
|
2355
2153
|
},
|
|
2356
|
-
"& .cm-
|
|
2357
|
-
|
|
2358
|
-
|
|
2154
|
+
"&dark .cm-button": {
|
|
2155
|
+
background: get3(tokens, "extend.colors.neutral.800"),
|
|
2156
|
+
"&:hover": {
|
|
2157
|
+
background: get3(tokens, "extend.colors.neutral.700")
|
|
2158
|
+
},
|
|
2159
|
+
"&:active": {
|
|
2160
|
+
background: get3(tokens, "extend.colors.neutral.600")
|
|
2161
|
+
}
|
|
2359
2162
|
}
|
|
2360
|
-
}
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
// packages/ui/react-ui-editor/src/extensions/factories.ts
|
|
2166
|
+
var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/factories.ts";
|
|
2167
|
+
var defaultBasicOptions = {
|
|
2168
|
+
allowMultipleSelections: true,
|
|
2169
|
+
bracketMatching: true,
|
|
2170
|
+
closeBrackets: true,
|
|
2171
|
+
drawSelection: true,
|
|
2172
|
+
editable: true,
|
|
2173
|
+
history: true,
|
|
2174
|
+
keymap: "standard",
|
|
2175
|
+
lineWrapping: true,
|
|
2176
|
+
search: true
|
|
2177
|
+
};
|
|
2178
|
+
var keymaps = {
|
|
2179
|
+
// https://codemirror.net/docs/ref/#commands.standardKeymap
|
|
2180
|
+
standard: standardKeymap,
|
|
2181
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
2182
|
+
default: defaultKeymap
|
|
2183
|
+
};
|
|
2184
|
+
var createBasicExtensions = (_props) => {
|
|
2185
|
+
const props = defaultsDeep2({}, _props, defaultBasicOptions);
|
|
2186
|
+
return [
|
|
2187
|
+
// NOTE: Doesn't catch errors in keymap functions.
|
|
2188
|
+
EditorView9.exceptionSink.of((err) => {
|
|
2189
|
+
log5.catch(err, void 0, {
|
|
2190
|
+
F: __dxlog_file7,
|
|
2191
|
+
L: 91,
|
|
2192
|
+
S: void 0,
|
|
2193
|
+
C: (f, a) => f(...a)
|
|
2194
|
+
});
|
|
2195
|
+
}),
|
|
2196
|
+
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2197
|
+
props.bracketMatching && bracketMatching(),
|
|
2198
|
+
props.closeBrackets && closeBrackets(),
|
|
2199
|
+
props.dropCursor && dropCursor2(),
|
|
2200
|
+
props.drawSelection && drawSelection(),
|
|
2201
|
+
props.highlightActiveLine && highlightActiveLine(),
|
|
2202
|
+
props.history && history(),
|
|
2203
|
+
props.lineNumbers && lineNumbers(),
|
|
2204
|
+
props.lineWrapping && EditorView9.lineWrapping,
|
|
2205
|
+
props.placeholder && placeholder(props.placeholder),
|
|
2206
|
+
props.readonly && [
|
|
2207
|
+
EditorState.readOnly.of(true),
|
|
2208
|
+
EditorView9.editable.of(false)
|
|
2209
|
+
],
|
|
2210
|
+
props.scrollPastEnd && scrollPastEnd(),
|
|
2211
|
+
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
2212
|
+
// https://codemirror.net/docs/ref/#view.KeyBinding
|
|
2213
|
+
keymap5.of([
|
|
2214
|
+
...(props.keymap && keymaps[props.keymap]) ?? [],
|
|
2215
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
2216
|
+
...props.indentWithTab ? [
|
|
2217
|
+
indentWithTab
|
|
2218
|
+
] : [],
|
|
2219
|
+
// https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
|
|
2220
|
+
...props.closeBrackets ? closeBracketsKeymap : [],
|
|
2221
|
+
// https://codemirror.net/docs/ref/#commands.historyKeymap
|
|
2222
|
+
...props.history ? historyKeymap : [],
|
|
2223
|
+
// https://codemirror.net/docs/ref/#search.searchKeymap
|
|
2224
|
+
...props.search ? searchKeymap : []
|
|
2225
|
+
].filter(isNotFalsy2))
|
|
2226
|
+
].filter(isNotFalsy2);
|
|
2227
|
+
};
|
|
2228
|
+
var defaultThemeSlots = {
|
|
2229
|
+
editor: {
|
|
2230
|
+
className: "w-full bs-full"
|
|
2231
|
+
}
|
|
2232
|
+
};
|
|
2233
|
+
var createThemeExtensions = ({ theme, themeMode, slots: _slots } = {}) => {
|
|
2234
|
+
const slots = defaultsDeep2({}, _slots, defaultThemeSlots);
|
|
2235
|
+
return [
|
|
2236
|
+
EditorView9.baseTheme(defaultTheme),
|
|
2237
|
+
EditorView9.darkTheme.of(themeMode === "dark"),
|
|
2238
|
+
theme && EditorView9.theme(theme),
|
|
2239
|
+
slots.editor?.className && EditorView9.editorAttributes.of({
|
|
2240
|
+
class: slots.editor.className
|
|
2241
|
+
}),
|
|
2242
|
+
slots.content?.className && EditorView9.contentAttributes.of({
|
|
2243
|
+
class: slots.content.className
|
|
2244
|
+
})
|
|
2245
|
+
].filter(isNotFalsy2);
|
|
2246
|
+
};
|
|
2247
|
+
var createDataExtensions = ({ id, text, space, identity }) => {
|
|
2248
|
+
const extensions = [
|
|
2249
|
+
automerge(text)
|
|
2250
|
+
];
|
|
2251
|
+
if (space && identity) {
|
|
2252
|
+
const peerId = identity?.identityKey.toHex();
|
|
2253
|
+
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
2254
|
+
const awarenessProvider2 = new SpaceAwarenessProvider({
|
|
2255
|
+
space,
|
|
2256
|
+
channel: `awareness.${id}`,
|
|
2257
|
+
peerId: identity.identityKey.toHex(),
|
|
2258
|
+
info: {
|
|
2259
|
+
displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
2260
|
+
color: cursorDarkValue,
|
|
2261
|
+
lightColor: cursorLightValue
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
extensions.push(awareness(awarenessProvider2));
|
|
2265
|
+
}
|
|
2266
|
+
return extensions;
|
|
2267
|
+
};
|
|
2268
|
+
|
|
2269
|
+
// packages/ui/react-ui-editor/src/extensions/listener.ts
|
|
2270
|
+
import { EditorView as EditorView10 } from "@codemirror/view";
|
|
2271
|
+
var listener = ({ onFocus, onChange }) => {
|
|
2272
|
+
const extensions = [];
|
|
2273
|
+
onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
|
|
2274
|
+
onFocus(focusing);
|
|
2275
|
+
return null;
|
|
2276
|
+
}));
|
|
2277
|
+
onChange && extensions.push(EditorView10.updateListener.of((update2) => {
|
|
2278
|
+
onChange(update2.state.doc.toString());
|
|
2279
|
+
}));
|
|
2280
|
+
return extensions;
|
|
2281
|
+
};
|
|
2361
2282
|
|
|
2362
2283
|
// packages/ui/react-ui-editor/src/extensions/markdown/formatting.ts
|
|
2363
2284
|
import { snippet } from "@codemirror/autocomplete";
|
|
2364
|
-
import { syntaxTree
|
|
2285
|
+
import { syntaxTree } from "@codemirror/language";
|
|
2365
2286
|
import { EditorSelection } from "@codemirror/state";
|
|
2366
|
-
import { EditorView as
|
|
2367
|
-
import {
|
|
2368
|
-
var
|
|
2287
|
+
import { EditorView as EditorView11, keymap as keymap6 } from "@codemirror/view";
|
|
2288
|
+
import { useMemo, useState } from "react";
|
|
2289
|
+
var formattingEquals = (a, b) => a.blockType === b.blockType && a.strong === b.strong && a.emphasis === b.emphasis && a.strikethrough === b.strikethrough && a.code === b.code && a.link === b.link && a.listStyle === b.listStyle && a.blockQuote === b.blockQuote;
|
|
2369
2290
|
var Inline;
|
|
2370
2291
|
(function(Inline2) {
|
|
2371
2292
|
Inline2[Inline2["Strong"] = 0] = "Strong";
|
|
@@ -2379,13 +2300,13 @@ var List;
|
|
|
2379
2300
|
List2[List2["Bullet"] = 1] = "Bullet";
|
|
2380
2301
|
List2[List2["Task"] = 2] = "Task";
|
|
2381
2302
|
})(List || (List = {}));
|
|
2382
|
-
var setHeading = (level) => ({ state, dispatch }) => {
|
|
2383
|
-
const { selection: { ranges }, doc } =
|
|
2303
|
+
var setHeading = (level) => ({ state: state2, dispatch }) => {
|
|
2304
|
+
const { selection: { ranges }, doc } = state2;
|
|
2384
2305
|
const changes = [];
|
|
2385
2306
|
let prevBlock = -1;
|
|
2386
2307
|
for (const range of ranges) {
|
|
2387
2308
|
let sawBlock = false;
|
|
2388
|
-
|
|
2309
|
+
syntaxTree(state2).iterate({
|
|
2389
2310
|
from: range.from,
|
|
2390
2311
|
to: range.to,
|
|
2391
2312
|
enter: (node) => {
|
|
@@ -2438,7 +2359,7 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2438
2359
|
}
|
|
2439
2360
|
});
|
|
2440
2361
|
let line;
|
|
2441
|
-
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line =
|
|
2362
|
+
if (!sawBlock && range.empty && level > 0 && !/\S/.test((line = state2.doc.lineAt(range.from)).text)) {
|
|
2442
2363
|
changes.push({
|
|
2443
2364
|
from: line.from,
|
|
2444
2365
|
to: line.to,
|
|
@@ -2449,23 +2370,23 @@ var setHeading = (level) => ({ state, dispatch }) => {
|
|
|
2449
2370
|
if (!changes.length) {
|
|
2450
2371
|
return false;
|
|
2451
2372
|
}
|
|
2452
|
-
const changeSet =
|
|
2453
|
-
dispatch(
|
|
2373
|
+
const changeSet = state2.changes(changes);
|
|
2374
|
+
dispatch(state2.update({
|
|
2454
2375
|
changes: changeSet,
|
|
2455
|
-
selection:
|
|
2376
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2456
2377
|
userEvent: "format.setHeading",
|
|
2457
2378
|
scrollIntoView: true
|
|
2458
2379
|
}));
|
|
2459
2380
|
return true;
|
|
2460
2381
|
};
|
|
2461
|
-
var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
2382
|
+
var setStyle = (type, enable) => ({ state: state2, dispatch }) => {
|
|
2462
2383
|
const marker = inlineMarkerText(type);
|
|
2463
|
-
const changes =
|
|
2384
|
+
const changes = state2.changeByRange((range) => {
|
|
2464
2385
|
if (!enable && range.empty) {
|
|
2465
|
-
const after =
|
|
2386
|
+
const after = state2.doc.sliceString(range.head, range.head + 6);
|
|
2466
2387
|
const found = after.indexOf(marker);
|
|
2467
2388
|
if (found >= 0 && /^[*~`]*$/.test(after.slice(0, found))) {
|
|
2468
|
-
const before =
|
|
2389
|
+
const before = state2.doc.sliceString(range.head - 6, range.head);
|
|
2469
2390
|
if (before.slice(before.length - found - marker.length, before.length - found) === marker && [
|
|
2470
2391
|
...before.slice(before.length - found)
|
|
2471
2392
|
].reverse().join("") === after.slice(0, found)) {
|
|
@@ -2492,14 +2413,14 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2492
2413
|
let startCovered = false;
|
|
2493
2414
|
let endCovered = false;
|
|
2494
2415
|
let { from, to } = range;
|
|
2495
|
-
|
|
2416
|
+
syntaxTree(state2).iterate({
|
|
2496
2417
|
from,
|
|
2497
2418
|
to,
|
|
2498
2419
|
enter: (node) => {
|
|
2499
2420
|
const { name } = node;
|
|
2500
2421
|
if (Object.hasOwn(Textblocks, name) && Textblocks[name] !== "codeblock") {
|
|
2501
2422
|
blockStart = blockContentStart(node);
|
|
2502
|
-
blockEnd = blockContentEnd(node,
|
|
2423
|
+
blockEnd = blockContentEnd(node, state2.doc);
|
|
2503
2424
|
startCovered = endCovered = false;
|
|
2504
2425
|
} else if (name === "Link" || name === "Image" && enable) {
|
|
2505
2426
|
if (from < node.from && to > node.from && to <= node.to) {
|
|
@@ -2544,7 +2465,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2544
2465
|
});
|
|
2545
2466
|
if (markType !== type && closeStart >= to) {
|
|
2546
2467
|
changesAtEnd.push({
|
|
2547
|
-
from: skipSpaces(Math.min(to, blockEnd),
|
|
2468
|
+
from: skipSpaces(Math.min(to, blockEnd), state2.doc, 1, blockEnd),
|
|
2548
2469
|
insert: inlineMarkerText(markType)
|
|
2549
2470
|
});
|
|
2550
2471
|
}
|
|
@@ -2556,7 +2477,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2556
2477
|
});
|
|
2557
2478
|
if (markType !== type && openEnd <= from) {
|
|
2558
2479
|
changes2.push({
|
|
2559
|
-
from: skipSpaces(Math.max(from, blockStart),
|
|
2480
|
+
from: skipSpaces(Math.max(from, blockStart), state2.doc, -1, blockStart),
|
|
2560
2481
|
insert: inlineMarkerText(markType)
|
|
2561
2482
|
});
|
|
2562
2483
|
}
|
|
@@ -2586,7 +2507,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2586
2507
|
changes2.push(startCovered);
|
|
2587
2508
|
} else if (startCovered) {
|
|
2588
2509
|
changes2.push({
|
|
2589
|
-
from: skipSpaces(rangeStart,
|
|
2510
|
+
from: skipSpaces(rangeStart, state2.doc, -1, blockStart),
|
|
2590
2511
|
insert: marker
|
|
2591
2512
|
});
|
|
2592
2513
|
}
|
|
@@ -2594,7 +2515,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2594
2515
|
changes2.push(endCovered);
|
|
2595
2516
|
} else if (endCovered) {
|
|
2596
2517
|
changes2.push({
|
|
2597
|
-
from: skipSpaces(rangeEnd,
|
|
2518
|
+
from: skipSpaces(rangeEnd, state2.doc, 1, blockEnd),
|
|
2598
2519
|
insert: marker
|
|
2599
2520
|
});
|
|
2600
2521
|
}
|
|
@@ -2602,7 +2523,7 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2602
2523
|
}
|
|
2603
2524
|
}
|
|
2604
2525
|
});
|
|
2605
|
-
if (blockStart < 0 && range.empty && enable && !/\S/.test(
|
|
2526
|
+
if (blockStart < 0 && range.empty && enable && !/\S/.test(state2.doc.lineAt(range.from).text)) {
|
|
2606
2527
|
return {
|
|
2607
2528
|
changes: {
|
|
2608
2529
|
from: range.head,
|
|
@@ -2611,13 +2532,13 @@ var setStyle = (type, enable) => ({ state, dispatch }) => {
|
|
|
2611
2532
|
range: EditorSelection.cursor(range.head + marker.length)
|
|
2612
2533
|
};
|
|
2613
2534
|
}
|
|
2614
|
-
const changeSet =
|
|
2535
|
+
const changeSet = state2.changes(changes2.concat(changesAtEnd));
|
|
2615
2536
|
return {
|
|
2616
2537
|
changes: changeSet,
|
|
2617
2538
|
range: range.empty && !changeSet.empty ? EditorSelection.cursor(range.head + marker.length) : EditorSelection.range(changeSet.mapPos(range.from, 1), changeSet.mapPos(range.to, -1))
|
|
2618
2539
|
};
|
|
2619
2540
|
});
|
|
2620
|
-
dispatch(
|
|
2541
|
+
dispatch(state2.update(changes, {
|
|
2621
2542
|
userEvent: enable ? "format.style.add" : "format.style.remove",
|
|
2622
2543
|
scrollIntoView: true
|
|
2623
2544
|
}));
|
|
@@ -2691,8 +2612,8 @@ var insertTable = (view) => {
|
|
|
2691
2612
|
const { from } = doc.line(number);
|
|
2692
2613
|
snippets.table(view, null, from, from);
|
|
2693
2614
|
};
|
|
2694
|
-
var removeLinkInner = (from, to, changes,
|
|
2695
|
-
|
|
2615
|
+
var removeLinkInner = (from, to, changes, state2) => {
|
|
2616
|
+
syntaxTree(state2).iterate({
|
|
2696
2617
|
from,
|
|
2697
2618
|
to,
|
|
2698
2619
|
enter: (node) => {
|
|
@@ -2706,8 +2627,8 @@ var removeLinkInner = (from, to, changes, state) => {
|
|
|
2706
2627
|
});
|
|
2707
2628
|
} else if (name === "LinkTitle" || name === "URL") {
|
|
2708
2629
|
changes.push({
|
|
2709
|
-
from: skipSpaces(node2.from,
|
|
2710
|
-
to: skipSpaces(node2.to,
|
|
2630
|
+
from: skipSpaces(node2.from, state2.doc, -1),
|
|
2631
|
+
to: skipSpaces(node2.to, state2.doc, 1)
|
|
2711
2632
|
});
|
|
2712
2633
|
}
|
|
2713
2634
|
});
|
|
@@ -2716,32 +2637,32 @@ var removeLinkInner = (from, to, changes, state) => {
|
|
|
2716
2637
|
}
|
|
2717
2638
|
});
|
|
2718
2639
|
};
|
|
2719
|
-
var removeLink = ({ state, dispatch }) => {
|
|
2640
|
+
var removeLink = ({ state: state2, dispatch }) => {
|
|
2720
2641
|
const changes = [];
|
|
2721
|
-
for (const { from, to } of
|
|
2722
|
-
removeLinkInner(from, to, changes,
|
|
2642
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2643
|
+
removeLinkInner(from, to, changes, state2);
|
|
2723
2644
|
}
|
|
2724
2645
|
if (!changes) {
|
|
2725
2646
|
return false;
|
|
2726
2647
|
}
|
|
2727
|
-
dispatch(
|
|
2648
|
+
dispatch(state2.update({
|
|
2728
2649
|
changes,
|
|
2729
2650
|
userEvent: "format.link.remove",
|
|
2730
2651
|
scrollIntoView: true
|
|
2731
2652
|
}));
|
|
2732
2653
|
return true;
|
|
2733
2654
|
};
|
|
2734
|
-
var addLink = ({ state, dispatch }) => {
|
|
2735
|
-
const changes =
|
|
2655
|
+
var addLink = ({ url, image: image2 } = {}) => ({ state: state2, dispatch }) => {
|
|
2656
|
+
const changes = state2.changeByRange((range) => {
|
|
2736
2657
|
let { from, to } = range;
|
|
2737
2658
|
const cutStyles = [];
|
|
2738
2659
|
let okay = null;
|
|
2739
|
-
|
|
2660
|
+
syntaxTree(state2).iterate({
|
|
2740
2661
|
from,
|
|
2741
2662
|
to,
|
|
2742
2663
|
enter: (node) => {
|
|
2743
2664
|
if (Object.hasOwn(Textblocks, node.name)) {
|
|
2744
|
-
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node,
|
|
2665
|
+
okay = Textblocks[node.name] !== "codeblock" && from >= blockContentStart(node) && to <= blockContentEnd(node, state2.doc);
|
|
2745
2666
|
} else if (Object.hasOwn(InlineMarker, node.name)) {
|
|
2746
2667
|
const sNode = node.node;
|
|
2747
2668
|
if (node.from < from && node.to <= to) {
|
|
@@ -2761,7 +2682,7 @@ var addLink = ({ state, dispatch }) => {
|
|
|
2761
2682
|
}
|
|
2762
2683
|
});
|
|
2763
2684
|
if (okay === null) {
|
|
2764
|
-
const line =
|
|
2685
|
+
const line = state2.doc.lineAt(from);
|
|
2765
2686
|
okay = to <= line.to && !/\S/.test(line.text.slice(from - line.from));
|
|
2766
2687
|
}
|
|
2767
2688
|
if (!okay) {
|
|
@@ -2771,26 +2692,26 @@ var addLink = ({ state, dispatch }) => {
|
|
|
2771
2692
|
}
|
|
2772
2693
|
const changes2 = [];
|
|
2773
2694
|
const changesAfter = [];
|
|
2774
|
-
removeLinkInner(from, to, changesAfter,
|
|
2695
|
+
removeLinkInner(from, to, changesAfter, state2);
|
|
2775
2696
|
let cursorOffset = 1;
|
|
2776
2697
|
for (const style of cutStyles) {
|
|
2777
2698
|
const type = InlineMarker[style.name];
|
|
2778
2699
|
const mark2 = inlineMarkerText(type);
|
|
2779
2700
|
if (style.from < from) {
|
|
2780
2701
|
changes2.push({
|
|
2781
|
-
from: skipSpaces(from,
|
|
2702
|
+
from: skipSpaces(from, state2.doc, -1),
|
|
2782
2703
|
insert: mark2
|
|
2783
2704
|
});
|
|
2784
2705
|
changesAfter.push({
|
|
2785
|
-
from: skipSpaces(from,
|
|
2706
|
+
from: skipSpaces(from, state2.doc, 1, to),
|
|
2786
2707
|
insert: mark2
|
|
2787
2708
|
});
|
|
2788
2709
|
} else {
|
|
2789
2710
|
changes2.push({
|
|
2790
|
-
from: skipSpaces(to,
|
|
2711
|
+
from: skipSpaces(to, state2.doc, -1, from),
|
|
2791
2712
|
insert: mark2
|
|
2792
2713
|
});
|
|
2793
|
-
const after = skipSpaces(to,
|
|
2714
|
+
const after = skipSpaces(to, state2.doc, 1);
|
|
2794
2715
|
if (after === to) {
|
|
2795
2716
|
cursorOffset += mark2.length;
|
|
2796
2717
|
}
|
|
@@ -2802,34 +2723,34 @@ var addLink = ({ state, dispatch }) => {
|
|
|
2802
2723
|
}
|
|
2803
2724
|
changes2.push({
|
|
2804
2725
|
from,
|
|
2805
|
-
insert: "["
|
|
2726
|
+
insert: image2 ? "`
|
|
2809
2730
|
});
|
|
2810
|
-
const changeSet =
|
|
2731
|
+
const changeSet = state2.changes(changes2.concat(changesAfter));
|
|
2811
2732
|
return {
|
|
2812
2733
|
changes: changeSet,
|
|
2813
|
-
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset)
|
|
2734
|
+
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset - (url ? url.length + 2 : 0))
|
|
2814
2735
|
};
|
|
2815
2736
|
});
|
|
2816
2737
|
if (changes.changes.empty) {
|
|
2817
2738
|
return false;
|
|
2818
2739
|
}
|
|
2819
|
-
dispatch(
|
|
2740
|
+
dispatch(state2.update(changes, {
|
|
2820
2741
|
userEvent: "format.link.add",
|
|
2821
2742
|
scrollIntoView: true
|
|
2822
2743
|
}));
|
|
2823
2744
|
return true;
|
|
2824
2745
|
};
|
|
2825
|
-
var addList = (type) => ({ state, dispatch }) => {
|
|
2746
|
+
var addList = (type) => ({ state: state2, dispatch }) => {
|
|
2826
2747
|
let lastBlock = -1;
|
|
2827
2748
|
let counter = 1;
|
|
2828
2749
|
let first = true;
|
|
2829
2750
|
let parentColumn = null;
|
|
2830
2751
|
const blocks = [];
|
|
2831
|
-
for (const { from, to } of
|
|
2832
|
-
|
|
2752
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2753
|
+
syntaxTree(state2).iterate({
|
|
2833
2754
|
from,
|
|
2834
2755
|
to,
|
|
2835
2756
|
enter: (node) => {
|
|
@@ -2841,7 +2762,7 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2841
2762
|
}
|
|
2842
2763
|
if (before?.name === (type === 0 ? "OrderedList" : "BulletList")) {
|
|
2843
2764
|
const item = before.lastChild;
|
|
2844
|
-
const itemLine =
|
|
2765
|
+
const itemLine = state2.doc.lineAt(item.from);
|
|
2845
2766
|
const itemText = itemLine.text.slice(item.from - itemLine.from);
|
|
2846
2767
|
parentColumn = item.from - itemLine.from + /^\s*/.exec(itemText)[0].length;
|
|
2847
2768
|
if (type === 0) {
|
|
@@ -2876,10 +2797,10 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2876
2797
|
});
|
|
2877
2798
|
}
|
|
2878
2799
|
if (!blocks.length) {
|
|
2879
|
-
const { from, to } =
|
|
2800
|
+
const { from, to } = state2.doc.lineAt(state2.selection.main.anchor);
|
|
2880
2801
|
if (from === to) {
|
|
2881
2802
|
const insert = type === 1 ? "- " : type === 0 ? "1. " : "- [ ] ";
|
|
2882
|
-
dispatch(
|
|
2803
|
+
dispatch(state2.update({
|
|
2883
2804
|
changes: [
|
|
2884
2805
|
{
|
|
2885
2806
|
from,
|
|
@@ -2900,11 +2821,11 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2900
2821
|
for (let i = 0; i < blocks.length; i++) {
|
|
2901
2822
|
const { node, counter: counter2, parentColumn: parentColumn2 } = blocks[i];
|
|
2902
2823
|
const nodeFrom = node.name === "CodeBlock" ? node.from - 4 : node.from;
|
|
2903
|
-
let padding = nodeFrom > 0 && !/\s/.test(
|
|
2824
|
+
let padding = nodeFrom > 0 && !/\s/.test(state2.doc.sliceString(nodeFrom - 1, nodeFrom)) ? 1 : 0;
|
|
2904
2825
|
if (type === 0) {
|
|
2905
2826
|
padding += String(counter2).length;
|
|
2906
2827
|
}
|
|
2907
|
-
let line =
|
|
2828
|
+
let line = state2.doc.lineAt(nodeFrom);
|
|
2908
2829
|
const column = nodeFrom - line.from;
|
|
2909
2830
|
if (parentColumn2 !== null && parentColumn2 > column) {
|
|
2910
2831
|
padding = Math.max(padding, parentColumn2 - column);
|
|
@@ -2929,7 +2850,7 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2929
2850
|
insert: mark2
|
|
2930
2851
|
});
|
|
2931
2852
|
while (line.to < node.to) {
|
|
2932
|
-
line =
|
|
2853
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2933
2854
|
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2934
2855
|
changes.push({
|
|
2935
2856
|
from: line.from + Math.min(open, column),
|
|
@@ -2944,25 +2865,25 @@ var addList = (type) => ({ state, dispatch }) => {
|
|
|
2944
2865
|
next = next.nextSibling;
|
|
2945
2866
|
}
|
|
2946
2867
|
if (next?.name === "OrderedList") {
|
|
2947
|
-
renumberListItems(next.firstChild, last.counter + 1, changes,
|
|
2868
|
+
renumberListItems(next.firstChild, last.counter + 1, changes, state2.doc);
|
|
2948
2869
|
}
|
|
2949
2870
|
}
|
|
2950
|
-
const changeSet =
|
|
2951
|
-
dispatch(
|
|
2871
|
+
const changeSet = state2.changes(changes);
|
|
2872
|
+
dispatch(state2.update({
|
|
2952
2873
|
changes: changeSet,
|
|
2953
|
-
selection:
|
|
2874
|
+
selection: state2.selection.map(changeSet, 1),
|
|
2954
2875
|
userEvent: "format.list.add",
|
|
2955
2876
|
scrollIntoView: true
|
|
2956
2877
|
}));
|
|
2957
2878
|
return true;
|
|
2958
2879
|
};
|
|
2959
|
-
var removeList = (type) => ({ state, dispatch }) => {
|
|
2880
|
+
var removeList = (type) => ({ state: state2, dispatch }) => {
|
|
2960
2881
|
let lastBlock = -1;
|
|
2961
2882
|
const changes = [];
|
|
2962
2883
|
const stack = [];
|
|
2963
2884
|
const targetNodeType = type === 0 ? "OrderedList" : type === 1 ? "BulletList" : "TaskList";
|
|
2964
|
-
for (const { from, to } of
|
|
2965
|
-
|
|
2885
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
2886
|
+
syntaxTree(state2).iterate({
|
|
2966
2887
|
from,
|
|
2967
2888
|
to,
|
|
2968
2889
|
enter: (node) => {
|
|
@@ -2979,7 +2900,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
2979
2900
|
stack.pop();
|
|
2980
2901
|
} else if (name === "ListItem" && stack[stack.length - 1] === targetNodeType && node.from !== lastBlock) {
|
|
2981
2902
|
lastBlock = node.from;
|
|
2982
|
-
let line =
|
|
2903
|
+
let line = state2.doc.lineAt(node.from);
|
|
2983
2904
|
const mark2 = /^\s*(\d+[.)] |[-*+] (\[[ x]\] )?)/.exec(line.text.slice(node.from - line.from));
|
|
2984
2905
|
if (!mark2) {
|
|
2985
2906
|
return false;
|
|
@@ -2990,7 +2911,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
2990
2911
|
to: node.from + mark2[0].length
|
|
2991
2912
|
});
|
|
2992
2913
|
while (line.to < node.to) {
|
|
2993
|
-
line =
|
|
2914
|
+
line = state2.doc.lineAt(line.to + 1);
|
|
2994
2915
|
const open = /^[\s>]*/.exec(line.text)[0].length;
|
|
2995
2916
|
if (open > column) {
|
|
2996
2917
|
changes.push({
|
|
@@ -3000,7 +2921,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3000
2921
|
}
|
|
3001
2922
|
}
|
|
3002
2923
|
if (node.to >= to) {
|
|
3003
|
-
renumberListItems(node.node.nextSibling, 1, changes,
|
|
2924
|
+
renumberListItems(node.node.nextSibling, 1, changes, state2.doc);
|
|
3004
2925
|
}
|
|
3005
2926
|
return false;
|
|
3006
2927
|
}
|
|
@@ -3010,7 +2931,7 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3010
2931
|
if (!changes.length) {
|
|
3011
2932
|
return false;
|
|
3012
2933
|
}
|
|
3013
|
-
dispatch(
|
|
2934
|
+
dispatch(state2.update({
|
|
3014
2935
|
changes,
|
|
3015
2936
|
userEvent: "format.list.remove",
|
|
3016
2937
|
scrollIntoView: true
|
|
@@ -3018,8 +2939,8 @@ var removeList = (type) => ({ state, dispatch }) => {
|
|
|
3018
2939
|
return true;
|
|
3019
2940
|
};
|
|
3020
2941
|
var toggleList = (type) => (target) => {
|
|
3021
|
-
const
|
|
3022
|
-
const active =
|
|
2942
|
+
const formatting = getFormatting(target.state);
|
|
2943
|
+
const active = formatting.listStyle === (type === 1 ? "bullet" : type === 0 ? "ordered" : "task");
|
|
3023
2944
|
return (active ? removeList(type) : addList(type))(target);
|
|
3024
2945
|
};
|
|
3025
2946
|
var renumberListItems = (item, counter, changes, doc) => {
|
|
@@ -3040,12 +2961,12 @@ var renumberListItems = (item, counter, changes, doc) => {
|
|
|
3040
2961
|
}
|
|
3041
2962
|
}
|
|
3042
2963
|
};
|
|
3043
|
-
var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
2964
|
+
var setBlockquote = (enable) => ({ state: state2, dispatch }) => {
|
|
3044
2965
|
const lines = [];
|
|
3045
2966
|
let lastBlock = -1;
|
|
3046
|
-
for (const { from, to } of
|
|
2967
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3047
2968
|
const sawBlock = false;
|
|
3048
|
-
|
|
2969
|
+
syntaxTree(state2).iterate({
|
|
3049
2970
|
from,
|
|
3050
2971
|
to,
|
|
3051
2972
|
enter: (node) => {
|
|
@@ -3054,9 +2975,9 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3054
2975
|
return false;
|
|
3055
2976
|
}
|
|
3056
2977
|
lastBlock = node.from;
|
|
3057
|
-
let line2 =
|
|
2978
|
+
let line2 = state2.doc.lineAt(node.from);
|
|
3058
2979
|
if (line2.number > 1) {
|
|
3059
|
-
const prevLine =
|
|
2980
|
+
const prevLine = state2.doc.line(line2.number - 1);
|
|
3060
2981
|
if (/^[>\s]*$/.test(prevLine.text)) {
|
|
3061
2982
|
if (!enable || lines.length && lines[lines.length - 1].number === prevLine.number - 1) {
|
|
3062
2983
|
lines.push(prevLine);
|
|
@@ -3068,10 +2989,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3068
2989
|
if (line2.to >= node.to) {
|
|
3069
2990
|
break;
|
|
3070
2991
|
}
|
|
3071
|
-
line2 =
|
|
2992
|
+
line2 = state2.doc.line(line2.number + 1);
|
|
3072
2993
|
}
|
|
3073
|
-
if (!enable && line2.number <
|
|
3074
|
-
const nextLine =
|
|
2994
|
+
if (!enable && line2.number < state2.doc.lines) {
|
|
2995
|
+
const nextLine = state2.doc.line(line2.number + 1);
|
|
3075
2996
|
if (/^[>\s]*$/.test(nextLine.text)) {
|
|
3076
2997
|
lines.push(nextLine);
|
|
3077
2998
|
}
|
|
@@ -3081,7 +3002,7 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3081
3002
|
}
|
|
3082
3003
|
});
|
|
3083
3004
|
let line;
|
|
3084
|
-
if (!sawBlock && enable && from === to && !/\S/.test((line =
|
|
3005
|
+
if (!sawBlock && enable && from === to && !/\S/.test((line = state2.doc.lineAt(from)).text)) {
|
|
3085
3006
|
lines.push(line);
|
|
3086
3007
|
}
|
|
3087
3008
|
}
|
|
@@ -3105,10 +3026,10 @@ var setBlockquote = (enable) => ({ state, dispatch }) => {
|
|
|
3105
3026
|
if (!changes.length) {
|
|
3106
3027
|
return false;
|
|
3107
3028
|
}
|
|
3108
|
-
const changeSet =
|
|
3109
|
-
dispatch(
|
|
3029
|
+
const changeSet = state2.changes(changes);
|
|
3030
|
+
dispatch(state2.update({
|
|
3110
3031
|
changes: changeSet,
|
|
3111
|
-
selection:
|
|
3032
|
+
selection: state2.selection.map(changeSet, 1),
|
|
3112
3033
|
userEvent: enable ? "format.blockquote.add" : "format.blockquote.remove",
|
|
3113
3034
|
scrollIntoView: true
|
|
3114
3035
|
}));
|
|
@@ -3120,11 +3041,11 @@ var toggleBlockquote = (target) => {
|
|
|
3120
3041
|
return (getFormatting(target.state).blockQuote ? removeBlockquote : addBlockquote)(target);
|
|
3121
3042
|
};
|
|
3122
3043
|
var addCodeblock = (target) => {
|
|
3123
|
-
const { state, dispatch } = target;
|
|
3124
|
-
const { selection } =
|
|
3044
|
+
const { state: state2, dispatch } = target;
|
|
3045
|
+
const { selection } = state2;
|
|
3125
3046
|
if (selection.ranges.length === 1 && selection.main.empty) {
|
|
3126
3047
|
const { head } = selection.main;
|
|
3127
|
-
const line =
|
|
3048
|
+
const line = state2.doc.lineAt(head);
|
|
3128
3049
|
if (!/\S/.test(line.text) && head === line.from) {
|
|
3129
3050
|
snippets.codeblock(target, null, line.from, line.to);
|
|
3130
3051
|
return true;
|
|
@@ -3134,7 +3055,7 @@ var addCodeblock = (target) => {
|
|
|
3134
3055
|
for (const { from, to } of selection.ranges) {
|
|
3135
3056
|
let blockFrom = from;
|
|
3136
3057
|
let blockTo = to;
|
|
3137
|
-
|
|
3058
|
+
syntaxTree(state2).iterate({
|
|
3138
3059
|
from,
|
|
3139
3060
|
to,
|
|
3140
3061
|
enter: (node) => {
|
|
@@ -3143,8 +3064,8 @@ var addCodeblock = (target) => {
|
|
|
3143
3064
|
blockFrom = node.from;
|
|
3144
3065
|
blockTo = node.to;
|
|
3145
3066
|
} else {
|
|
3146
|
-
blockFrom = Math.min(blockFrom,
|
|
3147
|
-
blockTo = Math.max(blockTo,
|
|
3067
|
+
blockFrom = Math.min(blockFrom, state2.doc.lineAt(node.from).from);
|
|
3068
|
+
blockTo = Math.max(blockTo, state2.doc.lineAt(node.to).to);
|
|
3148
3069
|
}
|
|
3149
3070
|
}
|
|
3150
3071
|
}
|
|
@@ -3162,7 +3083,7 @@ var addCodeblock = (target) => {
|
|
|
3162
3083
|
return false;
|
|
3163
3084
|
}
|
|
3164
3085
|
const changes = ranges.map(({ from, to }) => {
|
|
3165
|
-
const column = from -
|
|
3086
|
+
const column = from - state2.doc.lineAt(from).from;
|
|
3166
3087
|
return [
|
|
3167
3088
|
{
|
|
3168
3089
|
from,
|
|
@@ -3174,30 +3095,30 @@ var addCodeblock = (target) => {
|
|
|
3174
3095
|
}
|
|
3175
3096
|
];
|
|
3176
3097
|
});
|
|
3177
|
-
dispatch(
|
|
3098
|
+
dispatch(state2.update({
|
|
3178
3099
|
changes,
|
|
3179
3100
|
userEvent: "format.codeblock.add",
|
|
3180
3101
|
scrollIntoView: true
|
|
3181
3102
|
}));
|
|
3182
3103
|
return true;
|
|
3183
3104
|
};
|
|
3184
|
-
var removeCodeblock = ({ state, dispatch }) => {
|
|
3105
|
+
var removeCodeblock = ({ state: state2, dispatch }) => {
|
|
3185
3106
|
const changes = [];
|
|
3186
3107
|
let lastBlock = -1;
|
|
3187
|
-
for (const { from, to } of
|
|
3188
|
-
|
|
3108
|
+
for (const { from, to } of state2.selection.ranges) {
|
|
3109
|
+
syntaxTree(state2).iterate({
|
|
3189
3110
|
from,
|
|
3190
3111
|
to,
|
|
3191
3112
|
enter: (node) => {
|
|
3192
3113
|
if (Textblocks[node.name] === "codeblock" && lastBlock !== node.from) {
|
|
3193
3114
|
lastBlock = node.from;
|
|
3194
|
-
const firstLine =
|
|
3115
|
+
const firstLine = state2.doc.lineAt(node.from);
|
|
3195
3116
|
if (node.name === "FencedCode") {
|
|
3196
3117
|
changes.push({
|
|
3197
3118
|
from: node.from,
|
|
3198
3119
|
to: firstLine.to + 1 + node.from - firstLine.from
|
|
3199
3120
|
});
|
|
3200
|
-
const lastLine =
|
|
3121
|
+
const lastLine = state2.doc.lineAt(node.to);
|
|
3201
3122
|
if (/^([\s>]|[-*+] |\d+[).])*`+$/.test(lastLine.text)) {
|
|
3202
3123
|
changes.push({
|
|
3203
3124
|
from: lastLine.from - (lastLine.number === firstLine.number + 1 ? 0 : 1),
|
|
@@ -3206,7 +3127,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3206
3127
|
}
|
|
3207
3128
|
} else {
|
|
3208
3129
|
const column = node.from - firstLine.from;
|
|
3209
|
-
for (let line = firstLine; ; line =
|
|
3130
|
+
for (let line = firstLine; ; line = state2.doc.line(line.number + 1)) {
|
|
3210
3131
|
changes.push({
|
|
3211
3132
|
from: line.from + column - 4,
|
|
3212
3133
|
to: line.from + column
|
|
@@ -3223,7 +3144,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3223
3144
|
if (!changes.length) {
|
|
3224
3145
|
return false;
|
|
3225
3146
|
}
|
|
3226
|
-
dispatch(
|
|
3147
|
+
dispatch(state2.update({
|
|
3227
3148
|
changes,
|
|
3228
3149
|
userEvent: "format.codeblock.remove",
|
|
3229
3150
|
scrollIntoView: true
|
|
@@ -3233,7 +3154,7 @@ var removeCodeblock = ({ state, dispatch }) => {
|
|
|
3233
3154
|
var toggleCodeblock = (target) => {
|
|
3234
3155
|
return (getFormatting(target.state).blockType === "codeblock" ? removeCodeblock : addCodeblock)(target);
|
|
3235
3156
|
};
|
|
3236
|
-
var
|
|
3157
|
+
var formattingKeymap = (options = {}) => {
|
|
3237
3158
|
return [
|
|
3238
3159
|
keymap6.of([
|
|
3239
3160
|
{
|
|
@@ -3282,7 +3203,7 @@ var Textblocks = {
|
|
|
3282
3203
|
TableCell: "tablecell",
|
|
3283
3204
|
Task: "paragraph"
|
|
3284
3205
|
};
|
|
3285
|
-
var getFormatting = (
|
|
3206
|
+
var getFormatting = (state2) => {
|
|
3286
3207
|
let blockType = null;
|
|
3287
3208
|
const inline = [
|
|
3288
3209
|
null,
|
|
@@ -3308,7 +3229,7 @@ var getFormatting = (state) => {
|
|
|
3308
3229
|
continue;
|
|
3309
3230
|
} else if (currentBlock.active[i]) {
|
|
3310
3231
|
inline[i] = true;
|
|
3311
|
-
} else if (/\S/.test(
|
|
3232
|
+
} else if (/\S/.test(state2.doc.sliceString(currentBlock.pos, upto))) {
|
|
3312
3233
|
inline[i] = false;
|
|
3313
3234
|
}
|
|
3314
3235
|
}
|
|
@@ -3319,12 +3240,12 @@ var getFormatting = (state) => {
|
|
|
3319
3240
|
currentBlock.pos = Math.min(upto, currentBlock.end);
|
|
3320
3241
|
}
|
|
3321
3242
|
};
|
|
3322
|
-
const { selection } =
|
|
3243
|
+
const { selection } = state2;
|
|
3323
3244
|
for (const range of selection.ranges) {
|
|
3324
3245
|
if (range.empty && inline.some((v) => v === null)) {
|
|
3325
3246
|
const contextSize = Math.min(range.head, 6);
|
|
3326
|
-
const contextBefore =
|
|
3327
|
-
let contextAfter =
|
|
3247
|
+
const contextBefore = state2.doc.sliceString(range.head - contextSize, range.head);
|
|
3248
|
+
let contextAfter = state2.doc.sliceString(range.head, range.head + contextSize);
|
|
3328
3249
|
for (let i = 0; i < contextSize; i++) {
|
|
3329
3250
|
const ch = contextAfter[i];
|
|
3330
3251
|
if (ch !== contextBefore[contextBefore.length - 1 - i] || !/[~`*]/.test(ch)) {
|
|
@@ -3343,7 +3264,7 @@ var getFormatting = (state) => {
|
|
|
3343
3264
|
}
|
|
3344
3265
|
}
|
|
3345
3266
|
}
|
|
3346
|
-
|
|
3267
|
+
syntaxTree(state2).iterate({
|
|
3347
3268
|
from: range.from,
|
|
3348
3269
|
to: range.to,
|
|
3349
3270
|
enter: (node) => {
|
|
@@ -3417,7 +3338,7 @@ var getFormatting = (state) => {
|
|
|
3417
3338
|
}
|
|
3418
3339
|
});
|
|
3419
3340
|
}
|
|
3420
|
-
const { from, to } =
|
|
3341
|
+
const { from, to } = state2.doc.lineAt(selection.main.anchor);
|
|
3421
3342
|
const blankLine = from === to;
|
|
3422
3343
|
return {
|
|
3423
3344
|
blankLine,
|
|
@@ -3431,1030 +3352,1032 @@ var getFormatting = (state) => {
|
|
|
3431
3352
|
listStyle: listStyle || null
|
|
3432
3353
|
};
|
|
3433
3354
|
};
|
|
3434
|
-
var useFormattingState = () => {
|
|
3435
|
-
const [
|
|
3436
|
-
const observer = useMemo(() =>
|
|
3437
|
-
if (update2.docChanged || update2.selectionSet) {
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
}
|
|
3443
|
-
}), []);
|
|
3444
|
-
return [
|
|
3445
|
-
state,
|
|
3446
|
-
observer
|
|
3447
|
-
];
|
|
3448
|
-
};
|
|
3449
|
-
|
|
3450
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3451
|
-
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3452
|
-
import { StateField as StateField5 } from "@codemirror/state";
|
|
3453
|
-
import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3454
|
-
var image = (options = {}) => {
|
|
3455
|
-
return StateField5.define({
|
|
3456
|
-
create: (state) => {
|
|
3457
|
-
return Decoration6.set(buildDecorations2(0, state.doc.length, state));
|
|
3458
|
-
},
|
|
3459
|
-
update: (value, tr) => {
|
|
3460
|
-
if (!tr.docChanged && !tr.selection) {
|
|
3461
|
-
return value;
|
|
3462
|
-
}
|
|
3463
|
-
const cursor = tr.state.selection.main.head;
|
|
3464
|
-
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
3465
|
-
let from = Math.min(cursor, oldCursor);
|
|
3466
|
-
let to = Math.max(cursor, oldCursor);
|
|
3467
|
-
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
3468
|
-
from = Math.min(from, fromB);
|
|
3469
|
-
to = Math.max(to, toB);
|
|
3470
|
-
});
|
|
3471
|
-
from = tr.state.doc.lineAt(from).from;
|
|
3472
|
-
to = tr.state.doc.lineAt(to).to;
|
|
3473
|
-
return value.map(tr.changes).update({
|
|
3474
|
-
filterFrom: from,
|
|
3475
|
-
filterTo: to,
|
|
3476
|
-
filter: () => false,
|
|
3477
|
-
add: buildDecorations2(from, to, tr.state)
|
|
3478
|
-
});
|
|
3479
|
-
},
|
|
3480
|
-
provide: (field) => EditorView14.decorations.from(field)
|
|
3481
|
-
});
|
|
3482
|
-
};
|
|
3483
|
-
var preloaded = /* @__PURE__ */ new Set();
|
|
3484
|
-
var preloadImage = (url) => {
|
|
3485
|
-
if (!preloaded.has(url)) {
|
|
3486
|
-
const img = document.createElement("img");
|
|
3487
|
-
img.src = url;
|
|
3488
|
-
preloaded.add(url);
|
|
3489
|
-
}
|
|
3490
|
-
};
|
|
3491
|
-
var buildDecorations2 = (from, to, state) => {
|
|
3492
|
-
const decorations = [];
|
|
3493
|
-
const cursor = state.selection.main.head;
|
|
3494
|
-
syntaxTree3(state).iterate({
|
|
3495
|
-
enter: (node) => {
|
|
3496
|
-
if (node.name === "Image") {
|
|
3497
|
-
const urlNode = node.node.getChild("URL");
|
|
3498
|
-
if (urlNode) {
|
|
3499
|
-
const hide2 = state.readOnly || cursor < node.from || cursor > node.to;
|
|
3500
|
-
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
3501
|
-
preloadImage(url);
|
|
3502
|
-
decorations.push(Decoration6.replace({
|
|
3503
|
-
block: true,
|
|
3504
|
-
widget: new ImageWidget(url)
|
|
3505
|
-
}).range(hide2 ? node.from : node.to, node.to));
|
|
3506
|
-
}
|
|
3507
|
-
}
|
|
3508
|
-
},
|
|
3509
|
-
from,
|
|
3510
|
-
to
|
|
3511
|
-
});
|
|
3512
|
-
return decorations;
|
|
3513
|
-
};
|
|
3514
|
-
var ImageWidget = class extends WidgetType4 {
|
|
3515
|
-
constructor(_url) {
|
|
3516
|
-
super();
|
|
3517
|
-
this._url = _url;
|
|
3518
|
-
}
|
|
3519
|
-
eq(other) {
|
|
3520
|
-
return this._url === other._url;
|
|
3521
|
-
}
|
|
3522
|
-
toDOM(view) {
|
|
3523
|
-
const img = document.createElement("img");
|
|
3524
|
-
img.setAttribute("src", this._url);
|
|
3525
|
-
img.setAttribute("class", "cm-image");
|
|
3526
|
-
img.onload = () => img.classList.add("cm-loaded-image");
|
|
3527
|
-
return img;
|
|
3528
|
-
}
|
|
3529
|
-
};
|
|
3530
|
-
|
|
3531
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
3532
|
-
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
3533
|
-
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
3534
|
-
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
3535
|
-
var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
3536
|
-
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
3537
|
-
let link = null;
|
|
3538
|
-
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
|
3539
|
-
link = node.name === "Link" ? node : null;
|
|
3540
|
-
}
|
|
3541
|
-
const url = link && link.getChild("URL");
|
|
3542
|
-
if (!url || !link) {
|
|
3543
|
-
return null;
|
|
3544
|
-
}
|
|
3545
|
-
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
3546
|
-
return {
|
|
3547
|
-
pos: link.from,
|
|
3548
|
-
end: link.to,
|
|
3549
|
-
above: true,
|
|
3550
|
-
create: () => {
|
|
3551
|
-
const el = document.createElement("div");
|
|
3552
|
-
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
3553
|
-
render(el, urlText);
|
|
3554
|
-
return {
|
|
3555
|
-
dom: el,
|
|
3556
|
-
offset: {
|
|
3557
|
-
x: 0,
|
|
3558
|
-
y: 4
|
|
3559
|
-
}
|
|
3560
|
-
};
|
|
3561
|
-
}
|
|
3562
|
-
};
|
|
3563
|
-
});
|
|
3564
|
-
|
|
3565
|
-
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
3566
|
-
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
3567
|
-
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
3568
|
-
import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
3569
|
-
var table = (options = {}) => {
|
|
3570
|
-
return StateField6.define({
|
|
3571
|
-
create: (state) => update(state, options),
|
|
3572
|
-
update: (_, tr) => update(tr.state, options),
|
|
3573
|
-
provide: (field) => EditorView15.decorations.from(field)
|
|
3574
|
-
});
|
|
3575
|
-
};
|
|
3576
|
-
var update = (state, options) => {
|
|
3577
|
-
const builder = new RangeSetBuilder3();
|
|
3578
|
-
const cursor = state.selection.main.head;
|
|
3579
|
-
const tables = [];
|
|
3580
|
-
const getTable = () => tables[tables.length - 1];
|
|
3581
|
-
const getRow = () => {
|
|
3582
|
-
const table2 = getTable();
|
|
3583
|
-
return table2.rows?.[table2.rows.length - 1];
|
|
3584
|
-
};
|
|
3585
|
-
syntaxTree5(state).iterate({
|
|
3586
|
-
enter: (node) => {
|
|
3587
|
-
switch (node.name) {
|
|
3588
|
-
case "Table": {
|
|
3589
|
-
tables.push({
|
|
3590
|
-
from: node.from,
|
|
3591
|
-
to: node.to
|
|
3592
|
-
});
|
|
3593
|
-
break;
|
|
3594
|
-
}
|
|
3595
|
-
case "TableHeader": {
|
|
3596
|
-
getTable().header = [];
|
|
3597
|
-
break;
|
|
3598
|
-
}
|
|
3599
|
-
case "TableRow": {
|
|
3600
|
-
(getTable().rows ??= []).push([]);
|
|
3601
|
-
break;
|
|
3602
|
-
}
|
|
3603
|
-
case "TableCell": {
|
|
3604
|
-
const row = getRow();
|
|
3605
|
-
if (row) {
|
|
3606
|
-
row.push(state.sliceDoc(node.from, node.to));
|
|
3607
|
-
} else {
|
|
3608
|
-
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
3609
|
-
}
|
|
3610
|
-
break;
|
|
3355
|
+
var useFormattingState = () => {
|
|
3356
|
+
const [state2, setState] = useState();
|
|
3357
|
+
const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
|
|
3358
|
+
if (update2.docChanged || update2.selectionSet) {
|
|
3359
|
+
setState((prevState) => {
|
|
3360
|
+
const newState = getFormatting(update2.state);
|
|
3361
|
+
if (!prevState || !formattingEquals(prevState, newState)) {
|
|
3362
|
+
return newState;
|
|
3611
3363
|
}
|
|
3612
|
-
|
|
3364
|
+
return prevState;
|
|
3365
|
+
});
|
|
3613
3366
|
}
|
|
3614
|
-
})
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
class: "cm-table"
|
|
3622
|
-
}));
|
|
3623
|
-
});
|
|
3624
|
-
return builder.finish();
|
|
3367
|
+
}), [
|
|
3368
|
+
setState
|
|
3369
|
+
]);
|
|
3370
|
+
return [
|
|
3371
|
+
state2,
|
|
3372
|
+
observer
|
|
3373
|
+
];
|
|
3625
3374
|
};
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3375
|
+
|
|
3376
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/action.ts
|
|
3377
|
+
var processAction = (view, action) => {
|
|
3378
|
+
let inlineType, listType;
|
|
3379
|
+
switch (action.type) {
|
|
3380
|
+
case "heading":
|
|
3381
|
+
setHeading(parseInt(action.data))(view);
|
|
3382
|
+
break;
|
|
3383
|
+
case "strong":
|
|
3384
|
+
case "emphasis":
|
|
3385
|
+
case "strikethrough":
|
|
3386
|
+
case "code":
|
|
3387
|
+
inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
|
|
3388
|
+
(typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
|
|
3389
|
+
break;
|
|
3390
|
+
case "list-ordered":
|
|
3391
|
+
case "list-bullet":
|
|
3392
|
+
case "list-task":
|
|
3393
|
+
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3394
|
+
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3395
|
+
break;
|
|
3396
|
+
case "blockquote":
|
|
3397
|
+
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3398
|
+
break;
|
|
3399
|
+
case "codeblock":
|
|
3400
|
+
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3401
|
+
break;
|
|
3402
|
+
case "table":
|
|
3403
|
+
insertTable(view);
|
|
3404
|
+
break;
|
|
3405
|
+
case "link":
|
|
3406
|
+
(action.data === false ? removeLink : addLink())(view);
|
|
3407
|
+
break;
|
|
3408
|
+
case "image":
|
|
3409
|
+
addLink({
|
|
3410
|
+
url: action.data,
|
|
3411
|
+
image: true
|
|
3412
|
+
})(view);
|
|
3413
|
+
break;
|
|
3414
|
+
case "comment":
|
|
3415
|
+
createComment(view);
|
|
3416
|
+
break;
|
|
3633
3417
|
}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
const header = table2.appendChild(document.createElement("thead"));
|
|
3638
|
-
const tr = header.appendChild(document.createElement("tr"));
|
|
3639
|
-
this._table.header?.forEach((cell) => {
|
|
3640
|
-
const th = document.createElement("th");
|
|
3641
|
-
th.setAttribute("class", "cm-table-head");
|
|
3642
|
-
tr.appendChild(th).textContent = cell;
|
|
3643
|
-
});
|
|
3644
|
-
}
|
|
3645
|
-
{
|
|
3646
|
-
const body = table2.appendChild(document.createElement("tbody"));
|
|
3647
|
-
this._table.rows?.forEach((row) => {
|
|
3648
|
-
const tr = body.appendChild(document.createElement("tr"));
|
|
3649
|
-
row.forEach((cell) => {
|
|
3650
|
-
const td = document.createElement("td");
|
|
3651
|
-
td.setAttribute("class", "cm-table-cell");
|
|
3652
|
-
tr.appendChild(td).textContent = cell;
|
|
3653
|
-
});
|
|
3654
|
-
});
|
|
3418
|
+
requestAnimationFrame(() => {
|
|
3419
|
+
if (!view.hasFocus) {
|
|
3420
|
+
view.focus();
|
|
3655
3421
|
}
|
|
3656
|
-
|
|
3657
|
-
}
|
|
3658
|
-
ignoreEvent(e) {
|
|
3659
|
-
return !/^mouse/.test(e.type);
|
|
3660
|
-
}
|
|
3422
|
+
});
|
|
3661
3423
|
};
|
|
3662
3424
|
|
|
3663
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
3664
|
-
import {
|
|
3665
|
-
import {
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3425
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3426
|
+
import { completionKeymap as completionKeymap2 } from "@codemirror/autocomplete";
|
|
3427
|
+
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
3428
|
+
import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
|
|
3429
|
+
import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3430
|
+
import { languages } from "@codemirror/language-data";
|
|
3431
|
+
import { lintKeymap } from "@codemirror/lint";
|
|
3432
|
+
import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
|
|
3433
|
+
import { keymap as keymap7 } from "@codemirror/view";
|
|
3434
|
+
|
|
3435
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
|
|
3436
|
+
import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
3437
|
+
import { HighlightStyle } from "@codemirror/language";
|
|
3438
|
+
import { tags, styleTags, Tag } from "@lezer/highlight";
|
|
3439
|
+
import { Table } from "@lezer/markdown";
|
|
3440
|
+
var markdownTags = {
|
|
3441
|
+
Blockquote: Tag.define(),
|
|
3442
|
+
CodeMark: Tag.define(),
|
|
3443
|
+
CodeText: Tag.define(),
|
|
3444
|
+
EmphasisMark: Tag.define(),
|
|
3445
|
+
HeaderMark: Tag.define(),
|
|
3446
|
+
InlineCode: Tag.define(),
|
|
3447
|
+
LinkLabel: Tag.define(),
|
|
3448
|
+
LinkReference: Tag.define(),
|
|
3449
|
+
ListMark: Tag.define(),
|
|
3450
|
+
QuoteMark: Tag.define(),
|
|
3451
|
+
URL: Tag.define(),
|
|
3452
|
+
// Custom.
|
|
3453
|
+
TableCell: Tag.define()
|
|
3454
|
+
};
|
|
3455
|
+
Table.defineNodes?.forEach((node) => {
|
|
3456
|
+
switch (node?.name) {
|
|
3457
|
+
case "TableCell": {
|
|
3458
|
+
node.style = markdownTags.TableCell;
|
|
3459
|
+
break;
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3462
|
+
});
|
|
3463
|
+
var markdownTagsExtensions = [
|
|
3464
|
+
Table,
|
|
3465
|
+
{
|
|
3466
|
+
props: [
|
|
3467
|
+
styleTags(markdownTags)
|
|
3697
3468
|
]
|
|
3469
|
+
}
|
|
3470
|
+
];
|
|
3471
|
+
var markdownHighlightStyle = (readonly) => {
|
|
3472
|
+
return HighlightStyle.define([
|
|
3473
|
+
{
|
|
3474
|
+
tag: [
|
|
3475
|
+
tags.keyword,
|
|
3476
|
+
tags.name,
|
|
3477
|
+
tags.deleted,
|
|
3478
|
+
tags.character,
|
|
3479
|
+
tags.propertyName,
|
|
3480
|
+
tags.macroName,
|
|
3481
|
+
tags.color,
|
|
3482
|
+
tags.constant(tags.name),
|
|
3483
|
+
tags.standard(tags.name),
|
|
3484
|
+
tags.definition(tags.name),
|
|
3485
|
+
tags.separator,
|
|
3486
|
+
tags.typeName,
|
|
3487
|
+
tags.className,
|
|
3488
|
+
tags.number,
|
|
3489
|
+
tags.changed,
|
|
3490
|
+
tags.annotation,
|
|
3491
|
+
tags.modifier,
|
|
3492
|
+
tags.self,
|
|
3493
|
+
tags.namespace,
|
|
3494
|
+
tags.operator,
|
|
3495
|
+
tags.operatorKeyword,
|
|
3496
|
+
tags.escape,
|
|
3497
|
+
tags.regexp,
|
|
3498
|
+
tags.special(tags.string),
|
|
3499
|
+
tags.meta,
|
|
3500
|
+
tags.comment,
|
|
3501
|
+
tags.atom,
|
|
3502
|
+
tags.bool,
|
|
3503
|
+
tags.special(tags.variableName),
|
|
3504
|
+
tags.processingInstruction,
|
|
3505
|
+
tags.string,
|
|
3506
|
+
tags.inserted,
|
|
3507
|
+
tags.invalid
|
|
3508
|
+
],
|
|
3509
|
+
color: "inherit !important"
|
|
3510
|
+
},
|
|
3511
|
+
// Markdown marks.
|
|
3512
|
+
{
|
|
3513
|
+
tag: [
|
|
3514
|
+
tags.meta,
|
|
3515
|
+
tags.processingInstruction,
|
|
3516
|
+
markdownTags.LinkLabel,
|
|
3517
|
+
markdownTags.LinkReference,
|
|
3518
|
+
markdownTags.ListMark
|
|
3519
|
+
],
|
|
3520
|
+
class: mark
|
|
3521
|
+
},
|
|
3522
|
+
// Markdown marks.
|
|
3523
|
+
{
|
|
3524
|
+
tag: [
|
|
3525
|
+
markdownTags.CodeMark,
|
|
3526
|
+
markdownTags.HeaderMark,
|
|
3527
|
+
markdownTags.QuoteMark,
|
|
3528
|
+
markdownTags.EmphasisMark
|
|
3529
|
+
],
|
|
3530
|
+
class: mark
|
|
3531
|
+
},
|
|
3532
|
+
// E.g., code block language (after ```).
|
|
3533
|
+
{
|
|
3534
|
+
tag: [
|
|
3535
|
+
tags.function(tags.variableName),
|
|
3536
|
+
tags.labelName
|
|
3537
|
+
],
|
|
3538
|
+
class: codeMark
|
|
3539
|
+
},
|
|
3540
|
+
{
|
|
3541
|
+
tag: [
|
|
3542
|
+
tags.monospace
|
|
3543
|
+
],
|
|
3544
|
+
class: "font-mono"
|
|
3545
|
+
},
|
|
3546
|
+
// Headings.
|
|
3547
|
+
{
|
|
3548
|
+
tag: tags.heading1,
|
|
3549
|
+
class: heading(1)
|
|
3550
|
+
},
|
|
3551
|
+
{
|
|
3552
|
+
tag: tags.heading2,
|
|
3553
|
+
class: heading(2)
|
|
3554
|
+
},
|
|
3555
|
+
{
|
|
3556
|
+
tag: tags.heading3,
|
|
3557
|
+
class: heading(3)
|
|
3558
|
+
},
|
|
3559
|
+
{
|
|
3560
|
+
tag: tags.heading4,
|
|
3561
|
+
class: heading(4)
|
|
3562
|
+
},
|
|
3563
|
+
{
|
|
3564
|
+
tag: tags.heading5,
|
|
3565
|
+
class: heading(5)
|
|
3566
|
+
},
|
|
3567
|
+
{
|
|
3568
|
+
tag: tags.heading6,
|
|
3569
|
+
class: heading(6)
|
|
3570
|
+
},
|
|
3571
|
+
// Emphasis.
|
|
3572
|
+
{
|
|
3573
|
+
tag: tags.emphasis,
|
|
3574
|
+
class: italic
|
|
3575
|
+
},
|
|
3576
|
+
{
|
|
3577
|
+
tag: tags.strong,
|
|
3578
|
+
class: bold
|
|
3579
|
+
},
|
|
3580
|
+
{
|
|
3581
|
+
tag: tags.strikethrough,
|
|
3582
|
+
class: strikethrough
|
|
3583
|
+
},
|
|
3584
|
+
// Naked URLs.
|
|
3585
|
+
{
|
|
3586
|
+
tag: [
|
|
3587
|
+
markdownTags.URL
|
|
3588
|
+
],
|
|
3589
|
+
class: inlineUrl
|
|
3590
|
+
},
|
|
3591
|
+
// NOTE: The `markdown` extension configures extensions for `lezer` to parse markdown tokens (incl. below).
|
|
3592
|
+
// However, since `codeLanguages` is also defined, the `lezer` will not parse fenced code blocks,
|
|
3593
|
+
// when a language is specified. In this case, the syntax highlighting extensions will colorize
|
|
3594
|
+
// the code, but all other CSS properties will be inherited.
|
|
3595
|
+
// IMPORTANT: Therefore, the fenced code block will use the base editor font unless changed by an extension.
|
|
3596
|
+
{
|
|
3597
|
+
tag: [
|
|
3598
|
+
markdownTags.CodeText,
|
|
3599
|
+
markdownTags.InlineCode
|
|
3600
|
+
],
|
|
3601
|
+
class: code
|
|
3602
|
+
},
|
|
3603
|
+
{
|
|
3604
|
+
tag: [
|
|
3605
|
+
markdownTags.QuoteMark
|
|
3606
|
+
],
|
|
3607
|
+
class: blockquote
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
tag: [
|
|
3611
|
+
markdownTags.TableCell
|
|
3612
|
+
],
|
|
3613
|
+
class: "font-mono"
|
|
3614
|
+
}
|
|
3615
|
+
], {
|
|
3616
|
+
scope: markdownLanguage2,
|
|
3617
|
+
all: {
|
|
3618
|
+
fontFamily: getToken("fontFamily.body", []).join(",")
|
|
3619
|
+
}
|
|
3698
3620
|
});
|
|
3699
3621
|
};
|
|
3700
3622
|
|
|
3701
|
-
// packages/ui/react-ui-editor/src/extensions/
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3623
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
|
|
3624
|
+
var createMarkdownExtensions = ({ themeMode } = {}) => {
|
|
3625
|
+
return [
|
|
3626
|
+
// Main extension.
|
|
3627
|
+
// https://github.com/codemirror/lang-markdown
|
|
3628
|
+
// https://codemirror.net/5/mode/markdown/index.html (demo).
|
|
3629
|
+
markdown({
|
|
3630
|
+
// GRM by default (vs strict CommonMark):
|
|
3631
|
+
// Table, TaskList, Strikethrough, and Autolink.
|
|
3632
|
+
// NOTE: This extends the parser; it doesn't affect rendering.
|
|
3633
|
+
// https://github.github.com/gfm
|
|
3634
|
+
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
3635
|
+
base: markdownLanguage3,
|
|
3636
|
+
// Languages for syntax highlighting fenced code blocks.
|
|
3637
|
+
codeLanguages: languages,
|
|
3638
|
+
// Parser extensions.
|
|
3639
|
+
extensions: [
|
|
3640
|
+
// GFM provided by default.
|
|
3641
|
+
markdownTagsExtensions
|
|
3642
|
+
]
|
|
3715
3643
|
}),
|
|
3644
|
+
// https://github.com/codemirror/theme-one-dark
|
|
3645
|
+
themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
3646
|
+
// Custom styles.
|
|
3647
|
+
syntaxHighlighting(markdownHighlightStyle()),
|
|
3716
3648
|
keymap7.of([
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
return true;
|
|
3724
|
-
}
|
|
3725
|
-
}
|
|
3726
|
-
])
|
|
3727
|
-
]
|
|
3728
|
-
};
|
|
3729
|
-
|
|
3730
|
-
// packages/ui/react-ui-editor/src/extensions/outliner.ts
|
|
3731
|
-
var outliner = (options = {}) => {
|
|
3732
|
-
return [];
|
|
3733
|
-
};
|
|
3734
|
-
|
|
3735
|
-
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
3736
|
-
import { keymap as keymap8 } from "@codemirror/view";
|
|
3737
|
-
var defaultItems = [
|
|
3738
|
-
"hello world!",
|
|
3739
|
-
"this is a test.",
|
|
3740
|
-
"this is [DXOS](https://dxos.org)"
|
|
3741
|
-
];
|
|
3742
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
3743
|
-
let t;
|
|
3744
|
-
let idx = 0;
|
|
3745
|
-
return [
|
|
3746
|
-
keymap8.of([
|
|
3747
|
-
{
|
|
3748
|
-
// Reset.
|
|
3749
|
-
key: "alt-meta-'",
|
|
3750
|
-
run: (view) => {
|
|
3751
|
-
clearTimeout(t);
|
|
3752
|
-
idx = 0;
|
|
3753
|
-
return true;
|
|
3754
|
-
}
|
|
3755
|
-
},
|
|
3756
|
-
{
|
|
3757
|
-
// Next prompt.
|
|
3758
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
|
3759
|
-
key: "shift-meta-'",
|
|
3760
|
-
run: (view) => {
|
|
3761
|
-
clearTimeout(t);
|
|
3762
|
-
const text = items[idx++];
|
|
3763
|
-
if (idx === items?.length) {
|
|
3764
|
-
idx = 0;
|
|
3765
|
-
}
|
|
3766
|
-
let i = 0;
|
|
3767
|
-
const insert = (d = 0) => {
|
|
3768
|
-
t = setTimeout(() => {
|
|
3769
|
-
const pos = view.state.selection.main.head;
|
|
3770
|
-
view.dispatch({
|
|
3771
|
-
changes: {
|
|
3772
|
-
from: pos,
|
|
3773
|
-
insert: text[i++]
|
|
3774
|
-
},
|
|
3775
|
-
selection: {
|
|
3776
|
-
anchor: pos + 1
|
|
3777
|
-
}
|
|
3778
|
-
});
|
|
3779
|
-
if (i < text.length) {
|
|
3780
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
3781
|
-
}
|
|
3782
|
-
}, d);
|
|
3783
|
-
};
|
|
3784
|
-
insert();
|
|
3785
|
-
return true;
|
|
3786
|
-
}
|
|
3787
|
-
}
|
|
3649
|
+
// https://codemirror.net/docs/ref/#commands.indentWithTab
|
|
3650
|
+
indentWithTab2,
|
|
3651
|
+
// https://codemirror.net/docs/ref/#commands.defaultKeymap
|
|
3652
|
+
...defaultKeymap2,
|
|
3653
|
+
...completionKeymap2,
|
|
3654
|
+
...lintKeymap
|
|
3788
3655
|
])
|
|
3789
3656
|
];
|
|
3790
3657
|
};
|
|
3791
3658
|
|
|
3792
|
-
// packages/ui/react-ui-editor/src/
|
|
3793
|
-
import {
|
|
3794
|
-
import {
|
|
3795
|
-
import {
|
|
3796
|
-
import {
|
|
3797
|
-
var
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
this.remoteStateChange = new Event2();
|
|
3803
|
-
this._space = params.space;
|
|
3804
|
-
this._channel = params.channel;
|
|
3805
|
-
this._peerId = params.peerId;
|
|
3806
|
-
this._info = params.info;
|
|
3659
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
|
|
3660
|
+
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3661
|
+
import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
|
|
3662
|
+
import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
|
|
3663
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
3664
|
+
var HorizontalRuleWidget = class extends WidgetType3 {
|
|
3665
|
+
toDOM() {
|
|
3666
|
+
const el = document.createElement("span");
|
|
3667
|
+
el.className = "cm-hr";
|
|
3668
|
+
return el;
|
|
3807
3669
|
}
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
state: this._localState
|
|
3815
|
-
});
|
|
3816
|
-
await sleep(DEBOUNCE_INTERVAL);
|
|
3817
|
-
}
|
|
3818
|
-
});
|
|
3819
|
-
this._ctx.onDispose(this._space.listen(this._channel, (message) => {
|
|
3820
|
-
switch (message.payload.kind) {
|
|
3821
|
-
case "query": {
|
|
3822
|
-
this._handleQueryMessage();
|
|
3823
|
-
break;
|
|
3824
|
-
}
|
|
3825
|
-
case "post": {
|
|
3826
|
-
this._handlePostMessage(message.payload);
|
|
3827
|
-
break;
|
|
3828
|
-
}
|
|
3829
|
-
}
|
|
3830
|
-
}));
|
|
3831
|
-
void this._space.postMessage(this._channel, {
|
|
3832
|
-
kind: "query"
|
|
3833
|
-
}).catch((err) => {
|
|
3834
|
-
log7.debug("failed to query awareness", {
|
|
3835
|
-
err
|
|
3836
|
-
}, {
|
|
3837
|
-
F: __dxlog_file8,
|
|
3838
|
-
L: 89,
|
|
3839
|
-
S: this,
|
|
3840
|
-
C: (f, a) => f(...a)
|
|
3841
|
-
});
|
|
3842
|
-
});
|
|
3670
|
+
};
|
|
3671
|
+
var LinkButton = class extends WidgetType3 {
|
|
3672
|
+
constructor(url, render) {
|
|
3673
|
+
super();
|
|
3674
|
+
this.url = url;
|
|
3675
|
+
this.render = render;
|
|
3843
3676
|
}
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
this._ctx = void 0;
|
|
3847
|
-
this._postTask = void 0;
|
|
3677
|
+
eq(other) {
|
|
3678
|
+
return this.url === other.url;
|
|
3848
3679
|
}
|
|
3849
|
-
|
|
3850
|
-
|
|
3680
|
+
toDOM(view) {
|
|
3681
|
+
const el = document.createElement("span");
|
|
3682
|
+
this.render(el, this.url);
|
|
3683
|
+
return el;
|
|
3851
3684
|
}
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
A: [
|
|
3858
|
-
"this._postTask",
|
|
3859
|
-
""
|
|
3860
|
-
]
|
|
3861
|
-
});
|
|
3862
|
-
this._localState = {
|
|
3863
|
-
peerId: this._peerId,
|
|
3864
|
-
position,
|
|
3865
|
-
info: this._info
|
|
3866
|
-
};
|
|
3867
|
-
this._postTask.schedule();
|
|
3685
|
+
};
|
|
3686
|
+
var CheckboxWidget = class extends WidgetType3 {
|
|
3687
|
+
constructor(_checked) {
|
|
3688
|
+
super();
|
|
3689
|
+
this._checked = _checked;
|
|
3868
3690
|
}
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3691
|
+
eq(other) {
|
|
3692
|
+
return this._checked === other._checked;
|
|
3693
|
+
}
|
|
3694
|
+
toDOM(view) {
|
|
3695
|
+
const input = document.createElement("input");
|
|
3696
|
+
input.className = "cm-task-checkbox ch-checkbox ch-focus-ring -mbs-0.5";
|
|
3697
|
+
input.type = "checkbox";
|
|
3698
|
+
input.checked = this._checked;
|
|
3699
|
+
if (view.state.readOnly) {
|
|
3700
|
+
input.setAttribute("disabled", "true");
|
|
3701
|
+
} else {
|
|
3702
|
+
input.onmousedown = (event) => {
|
|
3703
|
+
const pos = view.posAtDOM(input);
|
|
3704
|
+
const text = view.state.sliceDoc(pos, pos + 3);
|
|
3705
|
+
if (text === (this._checked ? "[x]" : "[ ]")) {
|
|
3706
|
+
view.dispatch({
|
|
3707
|
+
changes: {
|
|
3708
|
+
from: pos + 1,
|
|
3709
|
+
to: pos + 2,
|
|
3710
|
+
insert: this._checked ? " " : "x"
|
|
3711
|
+
}
|
|
3712
|
+
});
|
|
3713
|
+
event.preventDefault();
|
|
3714
|
+
}
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
return input;
|
|
3880
3718
|
}
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
F: __dxlog_file8,
|
|
3884
|
-
L: 120,
|
|
3885
|
-
S: this,
|
|
3886
|
-
A: [
|
|
3887
|
-
"message.kind === 'post'",
|
|
3888
|
-
""
|
|
3889
|
-
]
|
|
3890
|
-
});
|
|
3891
|
-
this._remoteStates.set(message.state.peerId, message.state);
|
|
3892
|
-
this.remoteStateChange.emit();
|
|
3719
|
+
ignoreEvent() {
|
|
3720
|
+
return false;
|
|
3893
3721
|
}
|
|
3894
3722
|
};
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
|
|
3918
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
|
|
3919
|
-
break;
|
|
3920
|
-
case "blockquote":
|
|
3921
|
-
(action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
|
|
3922
|
-
break;
|
|
3923
|
-
case "codeblock":
|
|
3924
|
-
(action.data === false ? removeCodeblock : addCodeblock)(view);
|
|
3925
|
-
break;
|
|
3926
|
-
case "table":
|
|
3927
|
-
insertTable(view);
|
|
3928
|
-
break;
|
|
3929
|
-
case "link":
|
|
3930
|
-
(action.data === false ? removeLink : addLink)(view);
|
|
3931
|
-
break;
|
|
3932
|
-
case "comment":
|
|
3933
|
-
createComment(view);
|
|
3934
|
-
break;
|
|
3935
|
-
}
|
|
3936
|
-
setTimeout(() => {
|
|
3937
|
-
if (!view.hasFocus) {
|
|
3938
|
-
view.focus();
|
|
3939
|
-
}
|
|
3940
|
-
});
|
|
3941
|
-
};
|
|
3942
|
-
};
|
|
3943
|
-
|
|
3944
|
-
// packages/ui/react-ui-editor/src/hooks/useEditorView.ts
|
|
3945
|
-
import { useRef, useState as useState2 } from "react";
|
|
3946
|
-
var useEditorView = (id) => {
|
|
3947
|
-
const editorRef = useRef(null);
|
|
3948
|
-
const [prev, setPrev] = useState2([
|
|
3949
|
-
null,
|
|
3950
|
-
""
|
|
3951
|
-
]);
|
|
3952
|
-
if (prev[0] !== editorRef.current) {
|
|
3953
|
-
setPrev([
|
|
3954
|
-
editorRef.current,
|
|
3955
|
-
id
|
|
3956
|
-
]);
|
|
3957
|
-
}
|
|
3958
|
-
return [
|
|
3959
|
-
editorRef,
|
|
3960
|
-
prev[1] !== id
|
|
3961
|
-
];
|
|
3723
|
+
var hide = Decoration5.replace({});
|
|
3724
|
+
var fencedCodeLine = Decoration5.line({
|
|
3725
|
+
class: mx2("cm-code cm-codeblock-line")
|
|
3726
|
+
});
|
|
3727
|
+
var fencedCodeLineFirst = Decoration5.line({
|
|
3728
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
|
|
3729
|
+
});
|
|
3730
|
+
var fencedCodeLineLast = Decoration5.line({
|
|
3731
|
+
class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
|
|
3732
|
+
});
|
|
3733
|
+
var horizontalRule = Decoration5.replace({
|
|
3734
|
+
widget: new HorizontalRuleWidget()
|
|
3735
|
+
});
|
|
3736
|
+
var checkedTask = Decoration5.replace({
|
|
3737
|
+
widget: new CheckboxWidget(true)
|
|
3738
|
+
});
|
|
3739
|
+
var uncheckedTask = Decoration5.replace({
|
|
3740
|
+
widget: new CheckboxWidget(false)
|
|
3741
|
+
});
|
|
3742
|
+
var editingRange = (state2, range, focus) => {
|
|
3743
|
+
const { readOnly, selection: { main: { head } } } = state2;
|
|
3744
|
+
return focus && !readOnly && head >= range.from && head <= range.to;
|
|
3962
3745
|
};
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
},
|
|
4099
|
-
".cm-tooltip-below": {},
|
|
4100
|
-
//
|
|
4101
|
-
// autocomplete
|
|
4102
|
-
//
|
|
4103
|
-
".cm-tooltip-autocomplete": {
|
|
4104
|
-
marginTop: "4px",
|
|
4105
|
-
marginLeft: "-3px"
|
|
4106
|
-
},
|
|
4107
|
-
".cm-tooltip-autocomplete ul li": {},
|
|
4108
|
-
".cm-tooltip-autocomplete ul li[aria-selected]": {},
|
|
4109
|
-
".cm-completionIcon": {
|
|
4110
|
-
display: "none"
|
|
4111
|
-
},
|
|
4112
|
-
".cm-completionLabel": {
|
|
4113
|
-
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
3746
|
+
var MarksByParent = /* @__PURE__ */ new Set([
|
|
3747
|
+
"CodeMark",
|
|
3748
|
+
"EmphasisMark",
|
|
3749
|
+
"StrikethroughMark",
|
|
3750
|
+
"SubscriptMark",
|
|
3751
|
+
"SuperscriptMark"
|
|
3752
|
+
]);
|
|
3753
|
+
var buildDecorations = (view, options, focus) => {
|
|
3754
|
+
const deco = new RangeSetBuilder2();
|
|
3755
|
+
const atomicDeco = new RangeSetBuilder2();
|
|
3756
|
+
const { state: state2 } = view;
|
|
3757
|
+
for (const { from, to } of view.visibleRanges) {
|
|
3758
|
+
syntaxTree2(state2).iterate({
|
|
3759
|
+
from,
|
|
3760
|
+
to,
|
|
3761
|
+
enter: (node) => {
|
|
3762
|
+
if (node.name === "FencedCode") {
|
|
3763
|
+
const editing = editingRange(state2, node, focus);
|
|
3764
|
+
for (const block of view.viewportLineBlocks) {
|
|
3765
|
+
if (block.to < node.from) {
|
|
3766
|
+
continue;
|
|
3767
|
+
}
|
|
3768
|
+
if (block.from > node.to) {
|
|
3769
|
+
break;
|
|
3770
|
+
}
|
|
3771
|
+
const first = block.from <= node.from;
|
|
3772
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state2.doc.sliceString(block.from, block.to));
|
|
3773
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
3774
|
+
if (!editing && (first || last)) {
|
|
3775
|
+
atomicDeco.add(block.from, block.to, hide);
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
return false;
|
|
3779
|
+
} else if (node.name === "Link") {
|
|
3780
|
+
const marks = node.node.getChildren("LinkMark");
|
|
3781
|
+
const urlNode = node.node.getChild("URL");
|
|
3782
|
+
const editing = editingRange(state2, node, focus);
|
|
3783
|
+
if (urlNode && marks.length >= 2) {
|
|
3784
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3785
|
+
if (!editing) {
|
|
3786
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
|
3787
|
+
}
|
|
3788
|
+
deco.add(marks[0].to, marks[1].from, Decoration5.mark({
|
|
3789
|
+
tagName: "a",
|
|
3790
|
+
attributes: {
|
|
3791
|
+
class: "cm-link",
|
|
3792
|
+
href: url,
|
|
3793
|
+
rel: "noreferrer",
|
|
3794
|
+
target: "_blank"
|
|
3795
|
+
}
|
|
3796
|
+
}));
|
|
3797
|
+
if (!editing) {
|
|
3798
|
+
atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
|
|
3799
|
+
widget: new LinkButton(url, options.renderLinkButton)
|
|
3800
|
+
}) : hide);
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
} else if (node.name === "HeaderMark") {
|
|
3804
|
+
const parent = node.node.parent;
|
|
3805
|
+
if (/^ATX/.test(parent.name) && !editingRange(state2, state2.doc.lineAt(node.from), focus)) {
|
|
3806
|
+
const next = state2.doc.sliceString(node.to, node.to + 1);
|
|
3807
|
+
atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
|
|
3808
|
+
}
|
|
3809
|
+
} else if (node.name === "HorizontalRule") {
|
|
3810
|
+
if (!editingRange(state2, node, focus)) {
|
|
3811
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
3812
|
+
}
|
|
3813
|
+
} else if (node.name === "TaskMarker") {
|
|
3814
|
+
if (!editingRange(state2, node, focus)) {
|
|
3815
|
+
const checked = state2.doc.sliceString(node.from + 1, node.to - 1) === "x";
|
|
3816
|
+
atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
|
|
3817
|
+
class: "cm-task"
|
|
3818
|
+
}));
|
|
3819
|
+
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
3820
|
+
}
|
|
3821
|
+
} else if (MarksByParent.has(node.name)) {
|
|
3822
|
+
if (!editingRange(state2, node.node.parent, focus)) {
|
|
3823
|
+
atomicDeco.add(node.from, node.to, hide);
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3829
|
+
return {
|
|
3830
|
+
deco: deco.finish(),
|
|
3831
|
+
atomicDeco: atomicDeco.finish()
|
|
3832
|
+
};
|
|
3833
|
+
};
|
|
3834
|
+
var forceUpdate = StateEffect4.define();
|
|
3835
|
+
var decorateMarkdown = (options = {}) => {
|
|
3836
|
+
return [
|
|
3837
|
+
ViewPlugin4.fromClass(class {
|
|
3838
|
+
constructor(view) {
|
|
3839
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
|
|
3840
|
+
}
|
|
3841
|
+
update(update2) {
|
|
3842
|
+
if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
|
|
3843
|
+
({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
|
|
3844
|
+
this.clearUpdate();
|
|
3845
|
+
} else if (update2.selectionSet) {
|
|
3846
|
+
this.scheduleUpdate(update2.view);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
3850
|
+
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
3851
|
+
scheduleUpdate(view) {
|
|
3852
|
+
this.clearUpdate();
|
|
3853
|
+
this.pendingUpdate = setTimeout(() => {
|
|
3854
|
+
view.dispatch({
|
|
3855
|
+
effects: forceUpdate.of(null)
|
|
3856
|
+
});
|
|
3857
|
+
}, options.selectionChangeDelay);
|
|
3858
|
+
}
|
|
3859
|
+
clearUpdate() {
|
|
3860
|
+
if (this.pendingUpdate) {
|
|
3861
|
+
clearTimeout(this.pendingUpdate);
|
|
3862
|
+
this.pendingUpdate = void 0;
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
destroy() {
|
|
3866
|
+
this.clearUpdate();
|
|
3867
|
+
}
|
|
3868
|
+
}, {
|
|
3869
|
+
provide: (plugin) => [
|
|
3870
|
+
EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3871
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
|
|
3872
|
+
EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
|
|
3873
|
+
]
|
|
3874
|
+
}),
|
|
3875
|
+
formattingStyles
|
|
3876
|
+
];
|
|
3877
|
+
};
|
|
3878
|
+
var formattingStyles = EditorView12.baseTheme({
|
|
3879
|
+
"& .cm-code": {
|
|
3880
|
+
fontFamily: getToken("fontFamily.mono", []).join(",")
|
|
4114
3881
|
},
|
|
4115
|
-
".cm-
|
|
4116
|
-
|
|
3882
|
+
"& .cm-codeblock-line": {
|
|
3883
|
+
paddingInline: "1rem !important"
|
|
4117
3884
|
},
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
3885
|
+
"& .cm-codeblock-end": {
|
|
3886
|
+
display: "inline-block",
|
|
3887
|
+
width: "100%",
|
|
3888
|
+
position: "relative",
|
|
3889
|
+
"&::after": {
|
|
3890
|
+
position: "absolute",
|
|
3891
|
+
inset: 0,
|
|
3892
|
+
content: '""'
|
|
3893
|
+
}
|
|
4124
3894
|
},
|
|
4125
|
-
".cm-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
fontWeight: 100,
|
|
4129
|
-
textAlign: "left",
|
|
4130
|
-
color: get4(tokens, "extend.colors.neutral.500")
|
|
3895
|
+
"& .cm-codeblock-first": {
|
|
3896
|
+
borderTopLeftRadius: ".5rem",
|
|
3897
|
+
borderTopRightRadius: ".5rem"
|
|
4131
3898
|
},
|
|
4132
|
-
".cm-
|
|
4133
|
-
|
|
3899
|
+
"& .cm-codeblock-last": {
|
|
3900
|
+
borderBottomLeftRadius: ".5rem",
|
|
3901
|
+
borderBottomRightRadius: ".5rem"
|
|
4134
3902
|
},
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
".cm-image": {
|
|
4139
|
-
display: "block",
|
|
4140
|
-
height: "0"
|
|
3903
|
+
"&light .cm-codeblock-line, &light .cm-activeLine.cm-codeblock-line": {
|
|
3904
|
+
background: getToken("extend.semanticColors.input.light"),
|
|
3905
|
+
mixBlendMode: "darken"
|
|
4141
3906
|
},
|
|
4142
|
-
".cm-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
borderBottom: "0.5rem solid transparent"
|
|
3907
|
+
"&dark .cm-codeblock-line, &dark .cm-activeLine.cm-codeblock-line": {
|
|
3908
|
+
background: getToken("extend.semanticColors.input.dark"),
|
|
3909
|
+
mixBlendMode: "lighten"
|
|
4146
3910
|
},
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
// const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
|
|
4154
|
-
//
|
|
4155
|
-
// acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
|
|
4156
|
-
// acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
|
|
4157
|
-
// acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
4158
|
-
// return acc;
|
|
4159
|
-
// }, {}),
|
|
4160
|
-
/**
|
|
4161
|
-
* Panels
|
|
4162
|
-
* TODO(burdon): Needs styling attention (esp. dark mode).
|
|
4163
|
-
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
4164
|
-
*
|
|
4165
|
-
* Find/replace panel.
|
|
4166
|
-
* <div class="cm-announced">...</div>
|
|
4167
|
-
* <div class="cm-scroller">...</div>
|
|
4168
|
-
* <div class="cm-panels cm-panels-bottom">
|
|
4169
|
-
* <div class="cm-search cm-panel">
|
|
4170
|
-
* <input class="cm-textfield" />
|
|
4171
|
-
* <button class="cm-button">...</button>
|
|
4172
|
-
* <label><input type="checkbox" />...</label>
|
|
4173
|
-
* </div>
|
|
4174
|
-
* </div
|
|
4175
|
-
*/
|
|
4176
|
-
".cm-panels": {
|
|
4177
|
-
border: `1px solid ${get4(tokens, "extend.colors.neutral.200")}`
|
|
3911
|
+
"& .cm-hr": {
|
|
3912
|
+
display: "inline-block",
|
|
3913
|
+
width: "100%",
|
|
3914
|
+
height: "0",
|
|
3915
|
+
verticalAlign: "middle",
|
|
3916
|
+
borderTop: `1px solid ${getToken("extend.colors.neutral.200")}`
|
|
4178
3917
|
},
|
|
4179
|
-
".cm-
|
|
4180
|
-
|
|
4181
|
-
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
3918
|
+
"& .cm-task": {
|
|
3919
|
+
color: getToken("extend.colors.blue.500")
|
|
4182
3920
|
},
|
|
4183
|
-
".cm-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
3921
|
+
"& .cm-task-checkbox": {
|
|
3922
|
+
marginLeft: "4px",
|
|
3923
|
+
marginRight: "4px"
|
|
3924
|
+
}
|
|
3925
|
+
});
|
|
3926
|
+
|
|
3927
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/image.ts
|
|
3928
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
3929
|
+
import { StateField as StateField5 } from "@codemirror/state";
|
|
3930
|
+
import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3931
|
+
var image = (options = {}) => {
|
|
3932
|
+
return StateField5.define({
|
|
3933
|
+
create: (state2) => {
|
|
3934
|
+
return Decoration6.set(buildDecorations2(0, state2.doc.length, state2));
|
|
4191
3935
|
},
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
3936
|
+
update: (value, tr) => {
|
|
3937
|
+
if (!tr.docChanged && !tr.selection) {
|
|
3938
|
+
return value;
|
|
3939
|
+
}
|
|
3940
|
+
const cursor = tr.state.selection.main.head;
|
|
3941
|
+
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
3942
|
+
let from = Math.min(cursor, oldCursor);
|
|
3943
|
+
let to = Math.max(cursor, oldCursor);
|
|
3944
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
3945
|
+
from = Math.min(from, fromB);
|
|
3946
|
+
to = Math.max(to, toB);
|
|
3947
|
+
});
|
|
3948
|
+
from = tr.state.doc.lineAt(from).from;
|
|
3949
|
+
to = tr.state.doc.lineAt(to).to;
|
|
3950
|
+
return value.map(tr.changes).update({
|
|
3951
|
+
filterFrom: from,
|
|
3952
|
+
filterTo: to,
|
|
3953
|
+
filter: () => false,
|
|
3954
|
+
add: buildDecorations2(from, to, tr.state)
|
|
3955
|
+
});
|
|
3956
|
+
},
|
|
3957
|
+
provide: (field) => EditorView13.decorations.from(field)
|
|
3958
|
+
});
|
|
3959
|
+
};
|
|
3960
|
+
var preloaded = /* @__PURE__ */ new Set();
|
|
3961
|
+
var preloadImage = (url) => {
|
|
3962
|
+
if (!preloaded.has(url)) {
|
|
3963
|
+
const img = document.createElement("img");
|
|
3964
|
+
img.src = url;
|
|
3965
|
+
preloaded.add(url);
|
|
3966
|
+
}
|
|
3967
|
+
};
|
|
3968
|
+
var buildDecorations2 = (from, to, state2) => {
|
|
3969
|
+
const decorations = [];
|
|
3970
|
+
const cursor = state2.selection.main.head;
|
|
3971
|
+
syntaxTree3(state2).iterate({
|
|
3972
|
+
enter: (node) => {
|
|
3973
|
+
if (node.name === "Image") {
|
|
3974
|
+
const urlNode = node.node.getChild("URL");
|
|
3975
|
+
if (urlNode) {
|
|
3976
|
+
const hide2 = state2.readOnly || cursor < node.from || cursor > node.to;
|
|
3977
|
+
const url = state2.sliceDoc(urlNode.from, urlNode.to);
|
|
3978
|
+
preloadImage(url);
|
|
3979
|
+
decorations.push(Decoration6.replace({
|
|
3980
|
+
block: true,
|
|
3981
|
+
widget: new ImageWidget(url)
|
|
3982
|
+
}).range(hide2 ? node.from : node.to, node.to));
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
},
|
|
3986
|
+
from,
|
|
3987
|
+
to
|
|
3988
|
+
});
|
|
3989
|
+
return decorations;
|
|
3990
|
+
};
|
|
3991
|
+
var ImageWidget = class extends WidgetType4 {
|
|
3992
|
+
constructor(_url) {
|
|
3993
|
+
super();
|
|
3994
|
+
this._url = _url;
|
|
3995
|
+
}
|
|
3996
|
+
eq(other) {
|
|
3997
|
+
return this._url === other._url;
|
|
3998
|
+
}
|
|
3999
|
+
toDOM(view) {
|
|
4000
|
+
const img = document.createElement("img");
|
|
4001
|
+
img.setAttribute("src", this._url);
|
|
4002
|
+
img.setAttribute("class", "cm-image");
|
|
4003
|
+
img.onload = () => img.classList.add("cm-loaded-image");
|
|
4004
|
+
return img;
|
|
4005
|
+
}
|
|
4006
|
+
};
|
|
4007
|
+
var imageUpload = (options = {}) => {
|
|
4008
|
+
};
|
|
4009
|
+
|
|
4010
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/link.ts
|
|
4011
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
4012
|
+
import { hoverTooltip as hoverTooltip2 } from "@codemirror/view";
|
|
4013
|
+
import { tooltipContent } from "@dxos/react-ui-theme";
|
|
4014
|
+
var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
|
|
4015
|
+
const syntax = syntaxTree4(view.state).resolveInner(pos, side);
|
|
4016
|
+
let link = null;
|
|
4017
|
+
for (let i = 0, node = syntax; !link && node && i < 5; node = node.parent, i++) {
|
|
4018
|
+
link = node.name === "Link" ? node : null;
|
|
4019
|
+
}
|
|
4020
|
+
const url = link && link.getChild("URL");
|
|
4021
|
+
if (!url || !link) {
|
|
4022
|
+
return null;
|
|
4023
|
+
}
|
|
4024
|
+
const urlText = view.state.sliceDoc(url.from, url.to);
|
|
4025
|
+
return {
|
|
4026
|
+
pos: link.from,
|
|
4027
|
+
end: link.to,
|
|
4028
|
+
above: true,
|
|
4029
|
+
create: () => {
|
|
4030
|
+
const el = document.createElement("div");
|
|
4031
|
+
el.className = tooltipContent({}, "pli-2 plb-1");
|
|
4032
|
+
render(el, urlText);
|
|
4033
|
+
return {
|
|
4034
|
+
dom: el,
|
|
4035
|
+
offset: {
|
|
4036
|
+
x: 0,
|
|
4037
|
+
y: 4
|
|
4038
|
+
}
|
|
4039
|
+
};
|
|
4195
4040
|
}
|
|
4196
|
-
}
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4041
|
+
};
|
|
4042
|
+
});
|
|
4043
|
+
|
|
4044
|
+
// packages/ui/react-ui-editor/src/extensions/markdown/table.ts
|
|
4045
|
+
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4046
|
+
import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
|
|
4047
|
+
import { Decoration as Decoration7, EditorView as EditorView14, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4048
|
+
var table = (options = {}) => {
|
|
4049
|
+
return StateField6.define({
|
|
4050
|
+
create: (state2) => update(state2, options),
|
|
4051
|
+
update: (_, tr) => update(tr.state, options),
|
|
4052
|
+
provide: (field) => EditorView14.decorations.from(field)
|
|
4053
|
+
});
|
|
4200
4054
|
};
|
|
4201
|
-
var
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4055
|
+
var update = (state2, options) => {
|
|
4056
|
+
const builder = new RangeSetBuilder3();
|
|
4057
|
+
const cursor = state2.selection.main.head;
|
|
4058
|
+
const tables = [];
|
|
4059
|
+
const getTable = () => tables[tables.length - 1];
|
|
4060
|
+
const getRow = () => {
|
|
4061
|
+
const table2 = getTable();
|
|
4062
|
+
return table2.rows?.[table2.rows.length - 1];
|
|
4063
|
+
};
|
|
4064
|
+
syntaxTree5(state2).iterate({
|
|
4065
|
+
enter: (node) => {
|
|
4066
|
+
switch (node.name) {
|
|
4067
|
+
case "Table": {
|
|
4068
|
+
tables.push({
|
|
4069
|
+
from: node.from,
|
|
4070
|
+
to: node.to
|
|
4071
|
+
});
|
|
4072
|
+
break;
|
|
4073
|
+
}
|
|
4074
|
+
case "TableHeader": {
|
|
4075
|
+
getTable().header = [];
|
|
4076
|
+
break;
|
|
4077
|
+
}
|
|
4078
|
+
case "TableRow": {
|
|
4079
|
+
(getTable().rows ??= []).push([]);
|
|
4080
|
+
break;
|
|
4081
|
+
}
|
|
4082
|
+
case "TableCell": {
|
|
4083
|
+
const row = getRow();
|
|
4084
|
+
if (row) {
|
|
4085
|
+
row.push(state2.sliceDoc(node.from, node.to));
|
|
4086
|
+
} else {
|
|
4087
|
+
getTable().header?.push(state2.sliceDoc(node.from, node.to));
|
|
4088
|
+
}
|
|
4089
|
+
break;
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
});
|
|
4094
|
+
tables.forEach((table2) => {
|
|
4095
|
+
const hide2 = state2.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4096
|
+
if (hide2) {
|
|
4097
|
+
builder.add(table2.from, table2.to, Decoration7.replace({
|
|
4098
|
+
widget: new TableWidget(table2)
|
|
4099
|
+
}));
|
|
4100
|
+
}
|
|
4101
|
+
builder.add(table2.from, table2.to, Decoration7.mark({
|
|
4102
|
+
class: "cm-table"
|
|
4103
|
+
}));
|
|
4104
|
+
});
|
|
4105
|
+
return builder.finish();
|
|
4208
4106
|
};
|
|
4209
|
-
var
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
".cm-placeholder": {
|
|
4214
|
-
fontFamily: get4(tokens, "fontFamily.body", []).join(",")
|
|
4107
|
+
var TableWidget = class extends WidgetType5 {
|
|
4108
|
+
constructor(_table) {
|
|
4109
|
+
super();
|
|
4110
|
+
this._table = _table;
|
|
4215
4111
|
}
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
".cm-scroller": {
|
|
4219
|
-
fontFamily: get4(tokens, "fontFamily.mono", []).join(",")
|
|
4220
|
-
},
|
|
4221
|
-
".cm-placeholder": {
|
|
4222
|
-
fontFamily: get4(tokens, "fontFamily.mono", []).join(",")
|
|
4112
|
+
eq(other) {
|
|
4113
|
+
return this._table.header?.join() === other._table.header?.join() && this._table.rows?.join() === other._table.rows?.join();
|
|
4223
4114
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
let view2;
|
|
4234
|
-
if (parentRef.current) {
|
|
4235
|
-
const state = EditorState2.create({
|
|
4236
|
-
doc,
|
|
4237
|
-
selection,
|
|
4238
|
-
extensions: [
|
|
4239
|
-
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4240
|
-
EditorView16.exceptionSink.of((err) => {
|
|
4241
|
-
log8.catch(err, void 0, {
|
|
4242
|
-
F: __dxlog_file9,
|
|
4243
|
-
L: 70,
|
|
4244
|
-
S: void 0,
|
|
4245
|
-
C: (f, a) => f(...a)
|
|
4246
|
-
});
|
|
4247
|
-
}),
|
|
4248
|
-
extensions,
|
|
4249
|
-
EditorView16.updateListener.of(() => {
|
|
4250
|
-
onUpdate.current?.();
|
|
4251
|
-
})
|
|
4252
|
-
].filter(isNotFalsy3)
|
|
4115
|
+
toDOM(view) {
|
|
4116
|
+
const table2 = document.createElement("table");
|
|
4117
|
+
{
|
|
4118
|
+
const header = table2.appendChild(document.createElement("thead"));
|
|
4119
|
+
const tr = header.appendChild(document.createElement("tr"));
|
|
4120
|
+
this._table.header?.forEach((cell) => {
|
|
4121
|
+
const th = document.createElement("th");
|
|
4122
|
+
th.setAttribute("class", "cm-table-head");
|
|
4123
|
+
tr.appendChild(th).textContent = cell;
|
|
4253
4124
|
});
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
view3.update(trs);
|
|
4265
|
-
}
|
|
4125
|
+
}
|
|
4126
|
+
{
|
|
4127
|
+
const body = table2.appendChild(document.createElement("tbody"));
|
|
4128
|
+
this._table.rows?.forEach((row) => {
|
|
4129
|
+
const tr = body.appendChild(document.createElement("tr"));
|
|
4130
|
+
row.forEach((cell) => {
|
|
4131
|
+
const td = document.createElement("td");
|
|
4132
|
+
td.setAttribute("class", "cm-table-cell");
|
|
4133
|
+
tr.appendChild(td).textContent = cell;
|
|
4134
|
+
});
|
|
4266
4135
|
});
|
|
4267
|
-
setView(view2);
|
|
4268
4136
|
}
|
|
4269
|
-
return
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4137
|
+
return table2;
|
|
4138
|
+
}
|
|
4139
|
+
ignoreEvent(e) {
|
|
4140
|
+
return !/^mouse/.test(e.type);
|
|
4141
|
+
}
|
|
4142
|
+
};
|
|
4143
|
+
|
|
4144
|
+
// packages/ui/react-ui-editor/src/extensions/mention.ts
|
|
4145
|
+
import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
|
|
4146
|
+
import { log as log6 } from "@dxos/log";
|
|
4147
|
+
var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
|
|
4148
|
+
var mention = ({ onSearch }) => {
|
|
4149
|
+
return autocompletion2({
|
|
4150
|
+
// TODO(burdon): Not working.
|
|
4151
|
+
activateOnTyping: true,
|
|
4152
|
+
// activateOnTypingDelay: 100,
|
|
4153
|
+
// selectOnOpen: true,
|
|
4154
|
+
closeOnBlur: false,
|
|
4155
|
+
// defaultKeymap: false,
|
|
4156
|
+
icons: false,
|
|
4157
|
+
override: [
|
|
4158
|
+
(context) => {
|
|
4159
|
+
log6.info("completion context", {
|
|
4160
|
+
context
|
|
4161
|
+
}, {
|
|
4162
|
+
F: __dxlog_file8,
|
|
4163
|
+
L: 26,
|
|
4164
|
+
S: void 0,
|
|
4165
|
+
C: (f, a) => f(...a)
|
|
4166
|
+
});
|
|
4167
|
+
const match = context.matchBefore(/@(\w+)?/);
|
|
4168
|
+
if (!match || match.from === match.to && !context.explicit) {
|
|
4169
|
+
return null;
|
|
4170
|
+
}
|
|
4171
|
+
return {
|
|
4172
|
+
from: match.from,
|
|
4173
|
+
options: onSearch(match.text.slice(1).toLowerCase()).map((value) => ({
|
|
4174
|
+
label: `@${value}`
|
|
4175
|
+
}))
|
|
4176
|
+
};
|
|
4277
4177
|
}
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4178
|
+
]
|
|
4179
|
+
});
|
|
4180
|
+
};
|
|
4181
|
+
|
|
4182
|
+
// packages/ui/react-ui-editor/src/extensions/modes.ts
|
|
4183
|
+
import { Facet as Facet6 } from "@codemirror/state";
|
|
4184
|
+
import { keymap as keymap8 } from "@codemirror/view";
|
|
4185
|
+
import { vim } from "@replit/codemirror-vim";
|
|
4186
|
+
import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
|
|
4187
|
+
var focusEvent = "focus.container";
|
|
4188
|
+
var editorMode = Facet6.define({
|
|
4189
|
+
combine: (modes) => modes[0] ?? {}
|
|
4190
|
+
});
|
|
4191
|
+
var EditorModes = {
|
|
4192
|
+
default: [],
|
|
4193
|
+
vscode: [
|
|
4194
|
+
// https://github.com/replit/codemirror-vscode-keymap
|
|
4195
|
+
editorMode.of({
|
|
4196
|
+
type: "vscode"
|
|
4197
|
+
}),
|
|
4198
|
+
keymap8.of(vscodeKeymap)
|
|
4199
|
+
],
|
|
4200
|
+
vim: [
|
|
4201
|
+
// https://github.com/replit/codemirror-vim
|
|
4202
|
+
vim(),
|
|
4203
|
+
editorMode.of({
|
|
4204
|
+
type: "vim",
|
|
4205
|
+
noTabster: true
|
|
4206
|
+
}),
|
|
4207
|
+
keymap8.of([
|
|
4208
|
+
{
|
|
4209
|
+
key: "Alt-Escape",
|
|
4210
|
+
run: (view) => {
|
|
4281
4211
|
view.dispatch({
|
|
4282
|
-
|
|
4283
|
-
effects: scrollTo && [
|
|
4284
|
-
scrollTo
|
|
4285
|
-
],
|
|
4286
|
-
scrollIntoView: !scrollTo
|
|
4212
|
+
userEvent: focusEvent
|
|
4287
4213
|
});
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
if (autoFocus) {
|
|
4291
|
-
view.focus();
|
|
4214
|
+
return true;
|
|
4215
|
+
}
|
|
4292
4216
|
}
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
view,
|
|
4296
|
-
autoFocus,
|
|
4297
|
-
selection,
|
|
4298
|
-
scrollTo
|
|
4299
|
-
]);
|
|
4300
|
-
return {
|
|
4301
|
-
parentRef,
|
|
4302
|
-
view
|
|
4303
|
-
};
|
|
4304
|
-
};
|
|
4305
|
-
var defaults = {
|
|
4306
|
-
bracketMatching: true,
|
|
4307
|
-
closeBrackets: true,
|
|
4308
|
-
drawSelection: true,
|
|
4309
|
-
editable: true,
|
|
4310
|
-
history: true,
|
|
4311
|
-
lineWrapping: true
|
|
4217
|
+
])
|
|
4218
|
+
]
|
|
4312
4219
|
};
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4220
|
+
|
|
4221
|
+
// packages/ui/react-ui-editor/src/extensions/state.ts
|
|
4222
|
+
import { Transaction } from "@codemirror/state";
|
|
4223
|
+
import { EditorView as EditorView15, keymap as keymap9 } from "@codemirror/view";
|
|
4224
|
+
import { debounce as debounce2 } from "@dxos/async";
|
|
4225
|
+
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4226
|
+
import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
|
|
4227
|
+
var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/state.ts";
|
|
4228
|
+
var scrollAnnotation = "dxos.org/cm/scrolling";
|
|
4229
|
+
var keyPrefix = "dxos.org/react-ui-editor/state";
|
|
4230
|
+
var localStorageStateStoreAdapter = {
|
|
4231
|
+
setState: (id, state2) => {
|
|
4232
|
+
invariant4(id, void 0, {
|
|
4233
|
+
F: __dxlog_file9,
|
|
4234
|
+
L: 35,
|
|
4235
|
+
S: void 0,
|
|
4236
|
+
A: [
|
|
4237
|
+
"id",
|
|
4238
|
+
""
|
|
4239
|
+
]
|
|
4240
|
+
});
|
|
4241
|
+
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state2));
|
|
4242
|
+
},
|
|
4243
|
+
getState: (id) => {
|
|
4244
|
+
invariant4(id, void 0, {
|
|
4245
|
+
F: __dxlog_file9,
|
|
4246
|
+
L: 39,
|
|
4247
|
+
S: void 0,
|
|
4248
|
+
A: [
|
|
4249
|
+
"id",
|
|
4250
|
+
""
|
|
4251
|
+
]
|
|
4252
|
+
});
|
|
4253
|
+
const state2 = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
4254
|
+
return state2 ? JSON.parse(state2) : void 0;
|
|
4255
|
+
}
|
|
4343
4256
|
};
|
|
4344
|
-
var
|
|
4257
|
+
var state = ({ getState, setState } = {}) => {
|
|
4258
|
+
const setStateDebounced = debounce2(setState, 1e3);
|
|
4345
4259
|
return [
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4260
|
+
// TODO(burdon): Track scrolling (currently only updates when cursor moves).
|
|
4261
|
+
EditorView15.updateListener.of(({ view, changes, transactions }) => {
|
|
4262
|
+
const id = view.state.facet(documentId2);
|
|
4263
|
+
if (!id || transactions.some((tr) => tr.isUserEvent(scrollAnnotation))) {
|
|
4264
|
+
return;
|
|
4265
|
+
}
|
|
4266
|
+
if (setState) {
|
|
4267
|
+
const { top } = view.dom.getBoundingClientRect();
|
|
4268
|
+
const pos = view.posAtCoords({
|
|
4269
|
+
x: 0,
|
|
4270
|
+
y: top
|
|
4271
|
+
});
|
|
4272
|
+
if (pos !== null) {
|
|
4273
|
+
const { anchor, head } = view.state.selection.main;
|
|
4274
|
+
setStateDebounced(id, {
|
|
4275
|
+
scrollTo: {
|
|
4276
|
+
from: pos,
|
|
4277
|
+
yMargin: 0
|
|
4278
|
+
},
|
|
4279
|
+
selection: {
|
|
4280
|
+
anchor,
|
|
4281
|
+
head
|
|
4282
|
+
}
|
|
4283
|
+
});
|
|
4284
|
+
}
|
|
4285
|
+
}
|
|
4351
4286
|
}),
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4287
|
+
getState && keymap9.of([
|
|
4288
|
+
{
|
|
4289
|
+
key: "ctrl-r",
|
|
4290
|
+
run: (view) => {
|
|
4291
|
+
const state2 = getState(view.state.facet(documentId2));
|
|
4292
|
+
if (state2) {
|
|
4293
|
+
view.dispatch({
|
|
4294
|
+
effects: EditorView15.scrollIntoView(state2.scrollTo.from, {
|
|
4295
|
+
yMargin: 0
|
|
4296
|
+
}),
|
|
4297
|
+
selection: state2.selection,
|
|
4298
|
+
annotations: Transaction.userEvent.of(scrollAnnotation)
|
|
4299
|
+
});
|
|
4300
|
+
}
|
|
4301
|
+
return true;
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
])
|
|
4355
4305
|
].filter(isNotFalsy3);
|
|
4356
4306
|
};
|
|
4357
4307
|
|
|
4358
|
-
// packages/ui/react-ui-editor/src/
|
|
4359
|
-
import
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4308
|
+
// packages/ui/react-ui-editor/src/extensions/typewriter.ts
|
|
4309
|
+
import { keymap as keymap10 } from "@codemirror/view";
|
|
4310
|
+
var defaultItems = [
|
|
4311
|
+
"hello world!",
|
|
4312
|
+
"this is a test.",
|
|
4313
|
+
"this is [DXOS](https://dxos.org)"
|
|
4314
|
+
];
|
|
4315
|
+
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
4316
|
+
let t;
|
|
4317
|
+
let idx = 0;
|
|
4318
|
+
return [
|
|
4319
|
+
keymap10.of([
|
|
4320
|
+
{
|
|
4321
|
+
// Reset.
|
|
4322
|
+
key: "alt-meta-'",
|
|
4323
|
+
run: (view) => {
|
|
4324
|
+
clearTimeout(t);
|
|
4325
|
+
idx = 0;
|
|
4326
|
+
return true;
|
|
4327
|
+
}
|
|
4328
|
+
},
|
|
4329
|
+
{
|
|
4330
|
+
// Next prompt.
|
|
4331
|
+
// TODO(burdon): Press 1-9 to select prompt?
|
|
4332
|
+
key: "shift-meta-'",
|
|
4333
|
+
run: (view) => {
|
|
4334
|
+
clearTimeout(t);
|
|
4335
|
+
const text = items[idx++];
|
|
4336
|
+
if (idx === items?.length) {
|
|
4337
|
+
idx = 0;
|
|
4338
|
+
}
|
|
4339
|
+
let i = 0;
|
|
4340
|
+
const insert = (d = 0) => {
|
|
4341
|
+
t = setTimeout(() => {
|
|
4342
|
+
const pos = view.state.selection.main.head;
|
|
4343
|
+
view.dispatch({
|
|
4344
|
+
changes: {
|
|
4345
|
+
from: pos,
|
|
4346
|
+
insert: text[i++]
|
|
4347
|
+
},
|
|
4348
|
+
selection: {
|
|
4349
|
+
anchor: pos + 1
|
|
4350
|
+
}
|
|
4351
|
+
});
|
|
4352
|
+
if (i < text.length) {
|
|
4353
|
+
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
4354
|
+
}
|
|
4355
|
+
}, d);
|
|
4356
|
+
};
|
|
4357
|
+
insert();
|
|
4358
|
+
return true;
|
|
4359
|
+
}
|
|
4383
4360
|
}
|
|
4384
|
-
|
|
4385
|
-
extensions.push(awareness(awarenessProvider2));
|
|
4386
|
-
}
|
|
4387
|
-
return extensions;
|
|
4388
|
-
};
|
|
4389
|
-
var useTextModel = (props) => useMemo2(() => createModel(props), Object.values(props));
|
|
4390
|
-
var useInMemoryTextModel = ({ id, defaultContent }) => {
|
|
4391
|
-
const [content, setContent] = useState4(defaultContent ?? "");
|
|
4392
|
-
return {
|
|
4393
|
-
id,
|
|
4394
|
-
content,
|
|
4395
|
-
text: () => content,
|
|
4396
|
-
setContent
|
|
4397
|
-
};
|
|
4398
|
-
};
|
|
4399
|
-
var createModel = ({ space, identity, text }) => {
|
|
4400
|
-
if (!text) {
|
|
4401
|
-
return void 0;
|
|
4402
|
-
}
|
|
4403
|
-
invariant3(isAutomergeObject(text), void 0, {
|
|
4404
|
-
F: __dxlog_file10,
|
|
4405
|
-
L: 89,
|
|
4406
|
-
S: void 0,
|
|
4407
|
-
A: [
|
|
4408
|
-
"isAutomergeObject(text)",
|
|
4409
|
-
""
|
|
4410
|
-
]
|
|
4411
|
-
});
|
|
4412
|
-
const obj = text;
|
|
4413
|
-
const doc = getRawDoc(obj, [
|
|
4414
|
-
obj.field
|
|
4415
|
-
]);
|
|
4416
|
-
const peerId = identity?.identityKey.toHex();
|
|
4417
|
-
const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
|
|
4418
|
-
const awarenessProvider2 = space && new SpaceAwarenessProvider({
|
|
4419
|
-
space,
|
|
4420
|
-
channel: `automerge.awareness.${obj.id}`,
|
|
4421
|
-
info: {
|
|
4422
|
-
displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
|
|
4423
|
-
color: cursorLightValue,
|
|
4424
|
-
lightColor: cursorDarkValue
|
|
4425
|
-
},
|
|
4426
|
-
peerId: identity?.identityKey.toHex() ?? "Anonymous"
|
|
4427
|
-
});
|
|
4428
|
-
const extensions = [
|
|
4429
|
-
automerge({
|
|
4430
|
-
handle: doc.handle,
|
|
4431
|
-
path: doc.path
|
|
4432
|
-
})
|
|
4361
|
+
])
|
|
4433
4362
|
];
|
|
4434
|
-
if (awarenessProvider2) {
|
|
4435
|
-
extensions.push(awareness(awarenessProvider2));
|
|
4436
|
-
}
|
|
4437
|
-
return {
|
|
4438
|
-
id: obj.id,
|
|
4439
|
-
content: doc,
|
|
4440
|
-
text: () => get5(doc.handle.docSync(), doc.path),
|
|
4441
|
-
extension: extensions
|
|
4442
|
-
};
|
|
4443
4363
|
};
|
|
4444
4364
|
|
|
4445
4365
|
// packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
|
|
4446
|
-
var
|
|
4447
|
-
var
|
|
4366
|
+
var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
|
|
4367
|
+
var instanceCount = 0;
|
|
4368
|
+
var TextEditor = /* @__PURE__ */ forwardRef(({ id, doc, selection, extensions, className, autoFocus, scrollTo = EditorView16.scrollIntoView(0, {
|
|
4369
|
+
yMargin: 0
|
|
4370
|
+
}), moveToEndOfLine, debug, dataTestId }, forwardedRef) => {
|
|
4371
|
+
const [instanceId] = useState2(() => `text-editor-${++instanceCount}`);
|
|
4448
4372
|
const tabsterDOMAttribute = useFocusableGroup({
|
|
4449
4373
|
tabBehavior: "limited"
|
|
4450
4374
|
});
|
|
4451
|
-
const
|
|
4452
|
-
const
|
|
4453
|
-
const [view, setView] = useState5(null);
|
|
4375
|
+
const rootRef = useRef(null);
|
|
4376
|
+
const [view, setView] = useState2(null);
|
|
4454
4377
|
useImperativeHandle(forwardedRef, () => view, [
|
|
4455
4378
|
view
|
|
4456
4379
|
]);
|
|
4457
|
-
|
|
4380
|
+
useEffect2(() => {
|
|
4458
4381
|
if (autoFocus) {
|
|
4459
4382
|
view?.focus();
|
|
4460
4383
|
}
|
|
@@ -4462,56 +4385,43 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4462
4385
|
view,
|
|
4463
4386
|
autoFocus
|
|
4464
4387
|
]);
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4388
|
+
useEffect2(() => {
|
|
4389
|
+
log7("create", {
|
|
4390
|
+
id,
|
|
4391
|
+
instanceId
|
|
4392
|
+
}, {
|
|
4393
|
+
F: __dxlog_file10,
|
|
4394
|
+
L: 88,
|
|
4395
|
+
S: void 0,
|
|
4396
|
+
C: (f, a) => f(...a)
|
|
4397
|
+
});
|
|
4398
|
+
const state2 = EditorState2.create({
|
|
4399
|
+
doc,
|
|
4471
4400
|
selection,
|
|
4472
4401
|
extensions: [
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4402
|
+
id && documentId2.of(id),
|
|
4403
|
+
// TODO(burdon): NOTE: Doesn't catch errors in keymap functions.
|
|
4404
|
+
EditorView16.exceptionSink.of((err) => {
|
|
4405
|
+
log7.catch(err, void 0, {
|
|
4406
|
+
F: __dxlog_file10,
|
|
4407
|
+
L: 101,
|
|
4478
4408
|
S: void 0,
|
|
4479
4409
|
C: (f, a) => f(...a)
|
|
4480
4410
|
});
|
|
4481
4411
|
}),
|
|
4482
|
-
// Theme.
|
|
4483
|
-
// TODO(burdon): Make base theme configurable.
|
|
4484
|
-
EditorView17.baseTheme(defaultTheme),
|
|
4485
|
-
theme && EditorView17.theme(theme),
|
|
4486
|
-
EditorView17.darkTheme.of(themeMode === "dark"),
|
|
4487
|
-
slots.editor?.className && EditorView17.editorAttributes.of({
|
|
4488
|
-
class: slots.editor.className
|
|
4489
|
-
}),
|
|
4490
|
-
slots.content?.className && EditorView17.contentAttributes.of({
|
|
4491
|
-
class: slots.content.className
|
|
4492
|
-
}),
|
|
4493
|
-
// NOTE: Assumes default line height.
|
|
4494
|
-
_scrollPastEnd && scrollPastEnd2(),
|
|
4495
4412
|
// Focus.
|
|
4496
|
-
|
|
4413
|
+
EditorView16.updateListener.of((update2) => {
|
|
4497
4414
|
update2.transactions.forEach((transaction) => {
|
|
4498
|
-
if (transaction.isUserEvent(
|
|
4415
|
+
if (transaction.isUserEvent(focusEvent)) {
|
|
4499
4416
|
rootRef.current?.focus();
|
|
4500
4417
|
}
|
|
4501
4418
|
});
|
|
4502
4419
|
}),
|
|
4503
|
-
|
|
4504
|
-
EditorView17.editable.of(!readonly),
|
|
4505
|
-
EditorState3.readOnly.of(!!readonly),
|
|
4506
|
-
// Storage and replication.
|
|
4507
|
-
// NOTE: This must come before user extensions.
|
|
4508
|
-
model.extension,
|
|
4509
|
-
// Custom.
|
|
4510
|
-
...extensions
|
|
4420
|
+
extensions
|
|
4511
4421
|
].filter(isNotFalsy4)
|
|
4512
4422
|
});
|
|
4513
|
-
const view2 = new
|
|
4514
|
-
state,
|
|
4423
|
+
const view2 = new EditorView16({
|
|
4424
|
+
state: state2,
|
|
4515
4425
|
parent: rootRef.current,
|
|
4516
4426
|
scrollTo,
|
|
4517
4427
|
// NOTE: Uncomment to debug/monitor all transactions.
|
|
@@ -4523,28 +4433,34 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4523
4433
|
view3.update(trs);
|
|
4524
4434
|
}
|
|
4525
4435
|
});
|
|
4526
|
-
|
|
4527
|
-
if (moveToEndOfLine) {
|
|
4436
|
+
if (moveToEndOfLine && !(scrollTo || selection)) {
|
|
4528
4437
|
const { to } = view2.state.doc.lineAt(0);
|
|
4529
|
-
view2
|
|
4438
|
+
view2.dispatch({
|
|
4530
4439
|
selection: {
|
|
4531
4440
|
anchor: to
|
|
4532
4441
|
}
|
|
4533
4442
|
});
|
|
4534
4443
|
}
|
|
4535
|
-
if (
|
|
4536
|
-
rootRef.current
|
|
4444
|
+
if (state2.facet(editorMode).noTabster) {
|
|
4445
|
+
rootRef.current?.removeAttribute("data-tabster");
|
|
4537
4446
|
}
|
|
4447
|
+
setView(view2);
|
|
4538
4448
|
return () => {
|
|
4449
|
+
log7("destroy", {
|
|
4450
|
+
id,
|
|
4451
|
+
instanceId
|
|
4452
|
+
}, {
|
|
4453
|
+
F: __dxlog_file10,
|
|
4454
|
+
L: 150,
|
|
4455
|
+
S: void 0,
|
|
4456
|
+
C: (f, a) => f(...a)
|
|
4457
|
+
});
|
|
4539
4458
|
view2?.destroy();
|
|
4540
|
-
setView(null);
|
|
4541
4459
|
};
|
|
4542
4460
|
}, [
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
readonly,
|
|
4547
|
-
themeMode
|
|
4461
|
+
doc,
|
|
4462
|
+
selection,
|
|
4463
|
+
extensions
|
|
4548
4464
|
]);
|
|
4549
4465
|
const handleKeyUp = useCallback((event) => {
|
|
4550
4466
|
const { key } = event;
|
|
@@ -4560,82 +4476,19 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
|
|
|
4560
4476
|
return /* @__PURE__ */ React.createElement("div", {
|
|
4561
4477
|
role: "none",
|
|
4562
4478
|
ref: rootRef,
|
|
4563
|
-
key: model.id,
|
|
4564
4479
|
tabIndex: 0,
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
...tabsterDOMAttribute
|
|
4568
|
-
|
|
4569
|
-
});
|
|
4570
|
-
var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping = true, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4571
|
-
const { themeMode } = useThemeContext();
|
|
4572
|
-
const updatedSlots = defaultsDeep3({}, slots, defaultTextSlots);
|
|
4573
|
-
const extensions = useMemo3(() => [
|
|
4574
|
-
createBasicExtensions({
|
|
4575
|
-
lineWrapping,
|
|
4576
|
-
placeholder: placeholder3
|
|
4577
|
-
}),
|
|
4578
|
-
createThemeExtensions({
|
|
4579
|
-
themeMode
|
|
4580
|
-
}),
|
|
4581
|
-
..._extensions ?? []
|
|
4582
|
-
], [
|
|
4583
|
-
themeMode,
|
|
4584
|
-
placeholder3,
|
|
4585
|
-
lineWrapping,
|
|
4586
|
-
_extensions
|
|
4587
|
-
]);
|
|
4588
|
-
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
4589
|
-
ref: forwardedRef,
|
|
4590
|
-
readonly,
|
|
4591
|
-
extensions,
|
|
4592
|
-
theme,
|
|
4593
|
-
slots: updatedSlots,
|
|
4594
|
-
...props
|
|
4595
|
-
});
|
|
4596
|
-
});
|
|
4597
|
-
var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
|
|
4598
|
-
const { themeMode } = useThemeContext();
|
|
4599
|
-
const updatedSlots = defaultsDeep3({}, slots, defaultMarkdownSlots);
|
|
4600
|
-
const extensions = useMemo3(() => [
|
|
4601
|
-
createMarkdownExtensions({
|
|
4602
|
-
themeMode,
|
|
4603
|
-
placeholder: placeholder3
|
|
4604
|
-
}),
|
|
4605
|
-
..._extensions ?? []
|
|
4606
|
-
], [
|
|
4607
|
-
themeMode,
|
|
4608
|
-
placeholder3,
|
|
4609
|
-
_extensions
|
|
4610
|
-
]);
|
|
4611
|
-
return /* @__PURE__ */ React.createElement(BaseTextEditor, {
|
|
4612
|
-
ref: forwardedRef,
|
|
4613
|
-
readonly,
|
|
4614
|
-
extensions,
|
|
4615
|
-
theme,
|
|
4616
|
-
slots: updatedSlots,
|
|
4617
|
-
...props
|
|
4480
|
+
className,
|
|
4481
|
+
"data-testid": dataTestId,
|
|
4482
|
+
...tabsterDOMAttribute,
|
|
4483
|
+
onKeyUp: handleKeyUp
|
|
4618
4484
|
});
|
|
4619
4485
|
});
|
|
4620
|
-
var defaultSlots = {
|
|
4621
|
-
root: {
|
|
4622
|
-
className: focusRing
|
|
4623
|
-
},
|
|
4624
|
-
editor: {
|
|
4625
|
-
className: "bs-full"
|
|
4626
|
-
}
|
|
4627
|
-
};
|
|
4628
|
-
var defaultTextSlots = {
|
|
4629
|
-
...defaultSlots
|
|
4630
|
-
};
|
|
4631
|
-
var defaultMarkdownSlots = {
|
|
4632
|
-
...defaultSlots
|
|
4633
|
-
};
|
|
4634
4486
|
|
|
4635
4487
|
// packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
|
|
4636
|
-
import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic
|
|
4488
|
+
import { ChatText, Code, CodeBlock, Image, Link, ListBullets, ListChecks, ListNumbers, Paragraph, Quotes, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
|
|
4637
4489
|
import { createContext } from "@radix-ui/react-context";
|
|
4638
|
-
import React2, { useRef as
|
|
4490
|
+
import React2, { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
4491
|
+
import { useDropzone } from "react-dropzone";
|
|
4639
4492
|
import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
|
|
4640
4493
|
import { getSize } from "@dxos/react-ui-theme";
|
|
4641
4494
|
var tooltipProps = {
|
|
@@ -4652,10 +4505,10 @@ var HeadingIcons = {
|
|
|
4652
4505
|
"6": TextHSix
|
|
4653
4506
|
};
|
|
4654
4507
|
var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
|
|
4655
|
-
var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
|
4508
|
+
var ToolbarRoot = ({ children, onAction, classNames, state: state2 }) => {
|
|
4656
4509
|
return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
|
|
4657
4510
|
onAction,
|
|
4658
|
-
state
|
|
4511
|
+
state: state2
|
|
4659
4512
|
}, /* @__PURE__ */ React2.createElement(DensityProvider, {
|
|
4660
4513
|
density: "fine"
|
|
4661
4514
|
}, /* @__PURE__ */ React2.createElement(ElevationProvider, {
|
|
@@ -4669,7 +4522,7 @@ var ToolbarRoot = ({ children, onAction, classNames, state }) => {
|
|
|
4669
4522
|
};
|
|
4670
4523
|
var buttonStyles = "min-bs-0 p-2";
|
|
4671
4524
|
var iconStyles = getSize(5);
|
|
4672
|
-
var
|
|
4525
|
+
var ToolbarToggleButton = ({ Icon, children, ...props }) => {
|
|
4673
4526
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4674
4527
|
asChild: true
|
|
4675
4528
|
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroupItem, {
|
|
@@ -4682,20 +4535,33 @@ var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
|
4682
4535
|
className: "sr-only"
|
|
4683
4536
|
}, children))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4684
4537
|
};
|
|
4538
|
+
var ToolbarButton = ({ Icon, children, ...props }) => {
|
|
4539
|
+
return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
|
|
4540
|
+
asChild: true
|
|
4541
|
+
}, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
|
|
4542
|
+
variant: "ghost",
|
|
4543
|
+
...props,
|
|
4544
|
+
classNames: buttonStyles
|
|
4545
|
+
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
4546
|
+
className: iconStyles
|
|
4547
|
+
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4548
|
+
className: "sr-only"
|
|
4549
|
+
}, children))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4550
|
+
};
|
|
4685
4551
|
var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
|
|
4686
4552
|
role: "separator",
|
|
4687
4553
|
className: "grow"
|
|
4688
4554
|
});
|
|
4689
4555
|
var MarkdownHeading = () => {
|
|
4690
4556
|
const { t } = useTranslation(translationKey);
|
|
4691
|
-
const { onAction, state } = useToolbarContext("MarkdownFormatting");
|
|
4692
|
-
const blockType =
|
|
4557
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownFormatting");
|
|
4558
|
+
const blockType = state2 ? state2.blockType : "paragraph";
|
|
4693
4559
|
const header = blockType && /heading(\d)/.exec(blockType);
|
|
4694
4560
|
const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
|
|
4695
4561
|
const HeadingIcon = HeadingIcons[value ?? "0"];
|
|
4696
|
-
const suppressNextTooltip =
|
|
4697
|
-
const [tooltipOpen, setTooltipOpen] =
|
|
4698
|
-
const [selectOpen, setSelectOpen] =
|
|
4562
|
+
const suppressNextTooltip = useRef2(false);
|
|
4563
|
+
const [tooltipOpen, setTooltipOpen] = useState3(false);
|
|
4564
|
+
const [selectOpen, setSelectOpen] = useState3(false);
|
|
4699
4565
|
return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
|
|
4700
4566
|
open: tooltipOpen,
|
|
4701
4567
|
onOpenChange: (nextOpen) => {
|
|
@@ -4763,43 +4629,43 @@ var markdownStyles = [
|
|
|
4763
4629
|
{
|
|
4764
4630
|
type: "strong",
|
|
4765
4631
|
Icon: TextB,
|
|
4766
|
-
getState: (
|
|
4632
|
+
getState: (state2) => state2.strong
|
|
4767
4633
|
},
|
|
4768
4634
|
{
|
|
4769
4635
|
type: "emphasis",
|
|
4770
4636
|
Icon: TextItalic,
|
|
4771
|
-
getState: (
|
|
4637
|
+
getState: (state2) => state2.emphasis
|
|
4772
4638
|
},
|
|
4773
4639
|
{
|
|
4774
4640
|
type: "strikethrough",
|
|
4775
4641
|
Icon: TextStrikethrough,
|
|
4776
|
-
getState: (
|
|
4642
|
+
getState: (state2) => state2.strikethrough
|
|
4777
4643
|
},
|
|
4778
4644
|
{
|
|
4779
4645
|
type: "code",
|
|
4780
4646
|
Icon: Code,
|
|
4781
|
-
getState: (
|
|
4647
|
+
getState: (state2) => state2.code
|
|
4782
4648
|
},
|
|
4783
4649
|
{
|
|
4784
4650
|
type: "link",
|
|
4785
4651
|
Icon: Link,
|
|
4786
|
-
getState: (
|
|
4652
|
+
getState: (state2) => state2.link
|
|
4787
4653
|
}
|
|
4788
4654
|
];
|
|
4789
4655
|
var MarkdownStyles = () => {
|
|
4790
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4656
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4791
4657
|
const { t } = useTranslation(translationKey);
|
|
4792
4658
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4793
4659
|
type: "multiple",
|
|
4794
|
-
value: markdownStyles.filter(({ getState }) =>
|
|
4795
|
-
}, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4660
|
+
value: markdownStyles.filter(({ getState }) => state2 && getState(state2)).map(({ type }) => type)
|
|
4661
|
+
}, markdownStyles.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4796
4662
|
key: type,
|
|
4797
4663
|
value: type,
|
|
4798
4664
|
Icon,
|
|
4799
|
-
disabled:
|
|
4800
|
-
onClick:
|
|
4665
|
+
disabled: state2?.blockType === "codeblock",
|
|
4666
|
+
onClick: state2 ? () => onAction?.({
|
|
4801
4667
|
type,
|
|
4802
|
-
data: !getState(
|
|
4668
|
+
data: !getState(state2)
|
|
4803
4669
|
}) : void 0
|
|
4804
4670
|
}, t(`${type} label`))));
|
|
4805
4671
|
};
|
|
@@ -4807,32 +4673,32 @@ var markdownLists = [
|
|
|
4807
4673
|
{
|
|
4808
4674
|
type: "list-bullet",
|
|
4809
4675
|
Icon: ListBullets,
|
|
4810
|
-
getState: (
|
|
4676
|
+
getState: (state2) => state2.listStyle === "bullet"
|
|
4811
4677
|
},
|
|
4812
4678
|
{
|
|
4813
4679
|
type: "list-ordered",
|
|
4814
4680
|
Icon: ListNumbers,
|
|
4815
|
-
getState: (
|
|
4681
|
+
getState: (state2) => state2.listStyle === "ordered"
|
|
4816
4682
|
},
|
|
4817
4683
|
{
|
|
4818
4684
|
type: "list-task",
|
|
4819
4685
|
Icon: ListChecks,
|
|
4820
|
-
getState: (
|
|
4686
|
+
getState: (state2) => state2.listStyle === "task"
|
|
4821
4687
|
}
|
|
4822
4688
|
];
|
|
4823
4689
|
var MarkdownLists = () => {
|
|
4824
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4690
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4825
4691
|
const { t } = useTranslation(translationKey);
|
|
4826
4692
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4827
4693
|
type: "single",
|
|
4828
|
-
value:
|
|
4829
|
-
}, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4694
|
+
value: state2?.listStyle ? `list-${state2.listStyle}` : ""
|
|
4695
|
+
}, markdownLists.map(({ type, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4830
4696
|
key: type,
|
|
4831
4697
|
value: type,
|
|
4832
4698
|
Icon,
|
|
4833
|
-
onClick:
|
|
4699
|
+
onClick: state2 ? () => onAction?.({
|
|
4834
4700
|
type,
|
|
4835
|
-
data: !getState(
|
|
4701
|
+
data: !getState(state2)
|
|
4836
4702
|
}) : void 0
|
|
4837
4703
|
}, t(`${type} label`))));
|
|
4838
4704
|
};
|
|
@@ -4840,72 +4706,229 @@ var markdownBlocks = [
|
|
|
4840
4706
|
{
|
|
4841
4707
|
type: "blockquote",
|
|
4842
4708
|
Icon: Quotes,
|
|
4843
|
-
getState: (
|
|
4709
|
+
getState: (state2) => state2.blockQuote
|
|
4844
4710
|
},
|
|
4845
4711
|
{
|
|
4846
4712
|
type: "codeblock",
|
|
4847
4713
|
Icon: CodeBlock,
|
|
4848
|
-
getState: (
|
|
4714
|
+
getState: (state2) => state2.blockType === "codeblock"
|
|
4849
4715
|
},
|
|
4850
4716
|
{
|
|
4851
4717
|
type: "table",
|
|
4852
4718
|
Icon: Table2,
|
|
4853
|
-
getState: (
|
|
4854
|
-
disabled: (
|
|
4719
|
+
getState: (state2) => state2.blockType === "tablecell",
|
|
4720
|
+
disabled: (state2) => !state2.blankLine
|
|
4855
4721
|
}
|
|
4856
4722
|
];
|
|
4857
4723
|
var MarkdownBlocks = () => {
|
|
4858
|
-
const { onAction, state } = useToolbarContext("MarkdownStyles");
|
|
4724
|
+
const { onAction, state: state2 } = useToolbarContext("MarkdownStyles");
|
|
4859
4725
|
const { t } = useTranslation(translationKey);
|
|
4860
|
-
const value = markdownBlocks.find(({ getState }) =>
|
|
4726
|
+
const value = markdownBlocks.find(({ getState }) => state2 && getState(state2));
|
|
4861
4727
|
return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
|
|
4862
4728
|
type: "single",
|
|
4863
4729
|
value: value?.type ?? ""
|
|
4864
|
-
}, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(
|
|
4730
|
+
}, markdownBlocks.map(({ type, disabled, getState, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarToggleButton, {
|
|
4865
4731
|
key: type,
|
|
4866
4732
|
value: type,
|
|
4867
4733
|
Icon,
|
|
4868
|
-
disabled: !
|
|
4869
|
-
onClick:
|
|
4734
|
+
disabled: !state2 || disabled?.(state2),
|
|
4735
|
+
onClick: state2 ? () => onAction?.({
|
|
4870
4736
|
type,
|
|
4871
|
-
data: !getState(
|
|
4737
|
+
data: !getState(state2)
|
|
4872
4738
|
}) : void 0
|
|
4873
4739
|
}, t(`${type} label`))));
|
|
4874
4740
|
};
|
|
4875
4741
|
var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null));
|
|
4876
|
-
var
|
|
4742
|
+
var MarkdownCustom = ({ onUpload } = {}) => {
|
|
4877
4743
|
const { onAction } = useToolbarContext("MarkdownStyles");
|
|
4878
4744
|
const { t } = useTranslation(translationKey);
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4745
|
+
const { acceptedFiles, getInputProps, open } = useDropzone({
|
|
4746
|
+
multiple: false,
|
|
4747
|
+
noDrag: true,
|
|
4748
|
+
accept: {
|
|
4749
|
+
"image/*": [
|
|
4750
|
+
".jpg",
|
|
4751
|
+
".jpeg",
|
|
4752
|
+
".png",
|
|
4753
|
+
".gif"
|
|
4754
|
+
]
|
|
4755
|
+
}
|
|
4756
|
+
});
|
|
4757
|
+
useEffect3(() => {
|
|
4758
|
+
if (onUpload && acceptedFiles.length) {
|
|
4759
|
+
requestAnimationFrame(async () => {
|
|
4760
|
+
const f = acceptedFiles[0];
|
|
4761
|
+
const file = new File([
|
|
4762
|
+
f
|
|
4763
|
+
], f.name, {
|
|
4764
|
+
type: f.type,
|
|
4765
|
+
lastModified: f.lastModified
|
|
4766
|
+
});
|
|
4767
|
+
const { url } = await onUpload(file);
|
|
4768
|
+
if (url) {
|
|
4769
|
+
onAction?.({
|
|
4770
|
+
type: "image",
|
|
4771
|
+
data: url
|
|
4772
|
+
});
|
|
4773
|
+
}
|
|
4774
|
+
});
|
|
4775
|
+
}
|
|
4776
|
+
}, [
|
|
4777
|
+
acceptedFiles
|
|
4778
|
+
]);
|
|
4779
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("input", getInputProps()), /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4780
|
+
value: "image",
|
|
4781
|
+
Icon: Image,
|
|
4782
|
+
onClick: () => open()
|
|
4783
|
+
}, t("image label")));
|
|
4784
|
+
};
|
|
4785
|
+
var MarkdownActions = () => {
|
|
4786
|
+
const { onAction } = useToolbarContext("MarkdownStyles");
|
|
4787
|
+
const { t } = useTranslation(translationKey);
|
|
4788
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ToolbarButton, {
|
|
4789
|
+
value: "comment",
|
|
4790
|
+
Icon: ChatText,
|
|
4883
4791
|
"data-testid": "editor.toolbar.comment",
|
|
4884
4792
|
onClick: () => onAction?.({
|
|
4885
4793
|
type: "comment"
|
|
4886
|
-
})
|
|
4887
|
-
|
|
4888
|
-
}, /* @__PURE__ */ React2.createElement(ChatText, {
|
|
4889
|
-
className: iconStyles
|
|
4890
|
-
}), /* @__PURE__ */ React2.createElement("span", {
|
|
4891
|
-
className: "sr-only"
|
|
4892
|
-
}, t("comment label")))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, tooltipProps, t("comment label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
|
|
4794
|
+
})
|
|
4795
|
+
}, t("comment label")));
|
|
4893
4796
|
};
|
|
4894
4797
|
var Toolbar = {
|
|
4895
4798
|
Root: ToolbarRoot,
|
|
4896
|
-
Button:
|
|
4799
|
+
Button: ToolbarToggleButton,
|
|
4897
4800
|
Separator: ToolbarSeparator,
|
|
4898
4801
|
Markdown: MarkdownStandard,
|
|
4899
|
-
|
|
4802
|
+
Custom: MarkdownCustom,
|
|
4803
|
+
Actions: MarkdownActions
|
|
4804
|
+
};
|
|
4805
|
+
|
|
4806
|
+
// packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
|
|
4807
|
+
var useActionHandler = (view) => {
|
|
4808
|
+
return (action) => view && processAction(view, action);
|
|
4809
|
+
};
|
|
4810
|
+
|
|
4811
|
+
// packages/ui/react-ui-editor/src/hooks/useDocAccessor.ts
|
|
4812
|
+
import { useMemo as useMemo2 } from "react";
|
|
4813
|
+
import { createDocAccessor, getTextContent } from "@dxos/echo-schema";
|
|
4814
|
+
var useDocAccessor = (text) => {
|
|
4815
|
+
return useMemo2(() => ({
|
|
4816
|
+
id: text.id,
|
|
4817
|
+
doc: getTextContent(text),
|
|
4818
|
+
accessor: createDocAccessor(text)
|
|
4819
|
+
}), [
|
|
4820
|
+
text
|
|
4821
|
+
]);
|
|
4822
|
+
};
|
|
4823
|
+
|
|
4824
|
+
// packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
|
|
4825
|
+
import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
|
|
4826
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
4827
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
4828
|
+
import { log as log8 } from "@dxos/log";
|
|
4829
|
+
import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
|
|
4830
|
+
var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
|
|
4831
|
+
var useTextEditor = (cb = () => ({}), deps = []) => {
|
|
4832
|
+
let { id, doc, selection, extensions, autoFocus, scrollTo, debug } = useMemo3(cb, deps ?? []);
|
|
4833
|
+
const onUpdate = useRef3();
|
|
4834
|
+
const [view, setView] = useState4();
|
|
4835
|
+
const parentRef = useRef3(null);
|
|
4836
|
+
useEffect4(() => {
|
|
4837
|
+
let view2;
|
|
4838
|
+
if (parentRef.current) {
|
|
4839
|
+
log8("create", {
|
|
4840
|
+
id
|
|
4841
|
+
}, {
|
|
4842
|
+
F: __dxlog_file11,
|
|
4843
|
+
L: 36,
|
|
4844
|
+
S: void 0,
|
|
4845
|
+
C: (f, a) => f(...a)
|
|
4846
|
+
});
|
|
4847
|
+
const state2 = EditorState3.create({
|
|
4848
|
+
doc,
|
|
4849
|
+
selection,
|
|
4850
|
+
extensions: [
|
|
4851
|
+
id && documentId2.of(id),
|
|
4852
|
+
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
4853
|
+
EditorView17.exceptionSink.of((err) => {
|
|
4854
|
+
log8.catch(err, void 0, {
|
|
4855
|
+
F: __dxlog_file11,
|
|
4856
|
+
L: 46,
|
|
4857
|
+
S: void 0,
|
|
4858
|
+
C: (f, a) => f(...a)
|
|
4859
|
+
});
|
|
4860
|
+
}),
|
|
4861
|
+
extensions,
|
|
4862
|
+
EditorView17.updateListener.of(() => {
|
|
4863
|
+
onUpdate.current?.();
|
|
4864
|
+
})
|
|
4865
|
+
].filter(isNotFalsy5)
|
|
4866
|
+
});
|
|
4867
|
+
view2 = new EditorView17({
|
|
4868
|
+
parent: parentRef.current,
|
|
4869
|
+
scrollTo,
|
|
4870
|
+
state: state2,
|
|
4871
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
4872
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
4873
|
+
dispatchTransactions: (trs, view3) => {
|
|
4874
|
+
if (debug) {
|
|
4875
|
+
logChanges(trs);
|
|
4876
|
+
}
|
|
4877
|
+
view3.update(trs);
|
|
4878
|
+
}
|
|
4879
|
+
});
|
|
4880
|
+
setView(view2);
|
|
4881
|
+
}
|
|
4882
|
+
return () => {
|
|
4883
|
+
log8("destroy", {
|
|
4884
|
+
id
|
|
4885
|
+
}, {
|
|
4886
|
+
F: __dxlog_file11,
|
|
4887
|
+
L: 74,
|
|
4888
|
+
S: void 0,
|
|
4889
|
+
C: (f, a) => f(...a)
|
|
4890
|
+
});
|
|
4891
|
+
view2?.destroy();
|
|
4892
|
+
};
|
|
4893
|
+
}, deps);
|
|
4894
|
+
useEffect4(() => {
|
|
4895
|
+
if (view) {
|
|
4896
|
+
if (!selection && !view.state.selection.main.anchor) {
|
|
4897
|
+
selection = EditorSelection2.single(view.state.doc.line(1).to);
|
|
4898
|
+
}
|
|
4899
|
+
if (selection || scrollTo) {
|
|
4900
|
+
onUpdate.current = () => {
|
|
4901
|
+
onUpdate.current = void 0;
|
|
4902
|
+
view.dispatch({
|
|
4903
|
+
selection,
|
|
4904
|
+
effects: scrollTo && [
|
|
4905
|
+
scrollTo
|
|
4906
|
+
],
|
|
4907
|
+
scrollIntoView: !scrollTo
|
|
4908
|
+
});
|
|
4909
|
+
};
|
|
4910
|
+
}
|
|
4911
|
+
if (autoFocus) {
|
|
4912
|
+
view.focus();
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
}, [
|
|
4916
|
+
view,
|
|
4917
|
+
autoFocus,
|
|
4918
|
+
selection,
|
|
4919
|
+
scrollTo
|
|
4920
|
+
]);
|
|
4921
|
+
return {
|
|
4922
|
+
parentRef,
|
|
4923
|
+
view
|
|
4924
|
+
};
|
|
4900
4925
|
};
|
|
4901
4926
|
export {
|
|
4902
|
-
BaseTextEditor,
|
|
4903
4927
|
Cursor,
|
|
4904
4928
|
Doc,
|
|
4905
4929
|
EditorModes,
|
|
4906
4930
|
Inline,
|
|
4907
4931
|
List,
|
|
4908
|
-
MarkdownEditor,
|
|
4909
4932
|
RemoteSelectionsDecorator,
|
|
4910
4933
|
SpaceAwarenessProvider,
|
|
4911
4934
|
TextEditor,
|
|
@@ -4925,43 +4948,41 @@ export {
|
|
|
4925
4948
|
awarenessProvider,
|
|
4926
4949
|
blast,
|
|
4927
4950
|
callbackWrapper,
|
|
4928
|
-
codeTheme,
|
|
4929
4951
|
command,
|
|
4930
4952
|
comments,
|
|
4931
|
-
compareFormatting,
|
|
4932
4953
|
createBasicExtensions,
|
|
4933
4954
|
createComment,
|
|
4955
|
+
createDataExtensions,
|
|
4934
4956
|
createMarkdownExtensions,
|
|
4935
4957
|
createThemeExtensions,
|
|
4936
|
-
cursorLineMargin,
|
|
4937
|
-
cursorLineMarginFacet,
|
|
4938
4958
|
decorateMarkdown,
|
|
4939
|
-
defaultMarkdownSlots,
|
|
4940
4959
|
defaultOptions,
|
|
4941
|
-
defaultSlots,
|
|
4942
|
-
defaultTextSlots,
|
|
4943
4960
|
defaultTheme,
|
|
4944
|
-
|
|
4961
|
+
documentId2 as documentId,
|
|
4962
|
+
dropFile,
|
|
4945
4963
|
editorFillLayoutEditor,
|
|
4946
4964
|
editorFillLayoutRoot,
|
|
4947
4965
|
editorMode,
|
|
4948
4966
|
editorWithToolbarLayout,
|
|
4949
4967
|
focusComment,
|
|
4950
|
-
|
|
4968
|
+
focusEvent,
|
|
4969
|
+
formattingEquals,
|
|
4970
|
+
formattingKeymap,
|
|
4951
4971
|
getFormatting,
|
|
4952
4972
|
getToken,
|
|
4953
4973
|
image,
|
|
4974
|
+
imageUpload,
|
|
4954
4975
|
insertTable,
|
|
4955
|
-
|
|
4976
|
+
keymap11 as keymap,
|
|
4956
4977
|
linkTooltip,
|
|
4957
4978
|
listener,
|
|
4979
|
+
localStorageStateStoreAdapter,
|
|
4958
4980
|
logChanges,
|
|
4959
4981
|
markdownHighlightStyle,
|
|
4960
4982
|
markdownTags,
|
|
4961
4983
|
markdownTagsExtensions,
|
|
4962
|
-
markdownTheme,
|
|
4963
4984
|
mention,
|
|
4964
|
-
|
|
4985
|
+
processAction,
|
|
4965
4986
|
removeBlockquote,
|
|
4966
4987
|
removeCodeblock,
|
|
4967
4988
|
removeLink,
|
|
@@ -4972,9 +4993,9 @@ export {
|
|
|
4972
4993
|
setHeading,
|
|
4973
4994
|
setSelection,
|
|
4974
4995
|
setStyle,
|
|
4996
|
+
state,
|
|
4975
4997
|
table,
|
|
4976
4998
|
tags2 as tags,
|
|
4977
|
-
textTheme,
|
|
4978
4999
|
toggleBlockquote,
|
|
4979
5000
|
toggleCodeblock,
|
|
4980
5001
|
toggleEmphasis,
|
|
@@ -4987,12 +5008,9 @@ export {
|
|
|
4987
5008
|
typewriter,
|
|
4988
5009
|
useActionHandler,
|
|
4989
5010
|
useComments,
|
|
4990
|
-
|
|
5011
|
+
useDocAccessor,
|
|
4991
5012
|
useFormattingState,
|
|
4992
|
-
useInMemoryTextModel,
|
|
4993
5013
|
useTextEditor,
|
|
4994
|
-
useTextExtensions,
|
|
4995
|
-
useTextModel,
|
|
4996
5014
|
useToolbarContext
|
|
4997
5015
|
};
|
|
4998
5016
|
//# sourceMappingURL=index.mjs.map
|