@dxos/ui-editor 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/browser/index.mjs +1865 -1053
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +26 -6
- package/dist/lib/browser/types/index.mjs.map +4 -4
- package/dist/lib/node-esm/index.mjs +1865 -1052
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +27 -6
- package/dist/lib/node-esm/types/index.mjs.map +4 -4
- package/dist/types/src/defaults.d.ts +4 -10
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/annotations.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts +5 -2
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/blast.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/debug.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +4 -3
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.test.d.ts +2 -0
- package/dist/types/src/extensions/factories.test.d.ts.map +1 -0
- package/dist/types/src/extensions/focus.d.ts +1 -1
- package/dist/types/src/extensions/folding.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -3
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/json.d.ts.map +1 -1
- package/dist/types/src/extensions/listener.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +3 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/debug.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.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/menu.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/selection.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts +2 -0
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
- package/dist/types/src/extensions/replacer.d.ts.map +1 -1
- package/dist/types/src/extensions/scrolling/auto-scroll.d.ts +18 -0
- package/dist/types/src/extensions/scrolling/auto-scroll.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling/crawler.d.ts +75 -0
- package/dist/types/src/extensions/scrolling/crawler.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling/index.d.ts +5 -0
- package/dist/types/src/extensions/scrolling/index.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling/scroll-past-end.d.ts +3 -0
- package/dist/types/src/extensions/scrolling/scroll-past-end.d.ts.map +1 -0
- package/dist/types/src/extensions/scrolling/scroller.d.ts +16 -0
- package/dist/types/src/extensions/scrolling/scroller.d.ts.map +1 -0
- package/dist/types/src/extensions/selection.d.ts.map +1 -1
- package/dist/types/src/extensions/snippets.d.ts +10 -0
- package/dist/types/src/extensions/snippets.d.ts.map +1 -0
- package/dist/types/src/extensions/submit.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/fader.d.ts +12 -0
- package/dist/types/src/extensions/tags/fader.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/index.d.ts +4 -1
- package/dist/types/src/extensions/tags/index.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/typewriter.d.ts +43 -0
- package/dist/types/src/extensions/tags/typewriter.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/typewriter.test.d.ts +2 -0
- package/dist/types/src/extensions/tags/typewriter.test.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-block-decoration.d.ts +31 -0
- package/dist/types/src/extensions/tags/xml-block-decoration.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-formatting.d.ts +24 -0
- package/dist/types/src/extensions/tags/xml-formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts +28 -8
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts +2 -2
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +4 -4
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util/cursor.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/decorations.d.ts.map +1 -1
- package/dist/types/src/util/dom.d.ts.map +1 -1
- package/dist/types/src/util/facet.d.ts.map +1 -1
- package/dist/types/src/util/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -38
- package/src/defaults.ts +33 -20
- package/src/extensions/autocomplete/placeholder.ts +37 -18
- package/src/extensions/automerge/automerge.test.tsx +35 -9
- package/src/extensions/automerge/automerge.ts +5 -7
- package/src/extensions/comments.ts +0 -1
- package/src/extensions/factories.test.ts +88 -0
- package/src/extensions/factories.ts +26 -8
- package/src/extensions/folding.ts +3 -20
- package/src/extensions/index.ts +2 -3
- package/src/extensions/markdown/action.ts +0 -1
- package/src/extensions/markdown/bundle.ts +23 -9
- package/src/extensions/markdown/decorate.ts +11 -9
- package/src/extensions/markdown/highlight.ts +4 -10
- package/src/extensions/markdown/parser.test.ts +0 -1
- package/src/extensions/markdown/styles.ts +37 -4
- package/src/extensions/markdown/table.ts +24 -2
- package/src/extensions/outliner/outliner.test.ts +0 -1
- package/src/extensions/outliner/outliner.ts +1 -2
- package/src/extensions/outliner/tree.test.ts +0 -1
- package/src/extensions/preview/preview.ts +54 -7
- package/src/extensions/scrolling/auto-scroll.ts +244 -0
- package/src/extensions/{scroller.ts → scrolling/crawler.ts} +68 -37
- package/src/extensions/scrolling/index.ts +8 -0
- package/src/extensions/scrolling/scroll-past-end.ts +32 -0
- package/src/extensions/scrolling/scroller.ts +27 -0
- package/src/extensions/selection.ts +1 -1
- package/src/extensions/snippets.ts +67 -0
- package/src/extensions/tags/extended-markdown.test.ts +120 -2
- package/src/extensions/tags/extended-markdown.ts +80 -1
- package/src/extensions/tags/fader.ts +195 -0
- package/src/extensions/tags/index.ts +4 -1
- package/src/extensions/tags/testing/text.md +36 -0
- package/src/extensions/tags/testing/text.txt +35 -0
- package/src/extensions/tags/typewriter.test.ts +65 -0
- package/src/extensions/tags/typewriter.ts +594 -0
- package/src/extensions/tags/xml-block-decoration.ts +123 -0
- package/src/extensions/tags/xml-formatting.ts +125 -0
- package/src/extensions/tags/xml-tags.ts +183 -35
- package/src/extensions/tags/xml-util.test.ts +199 -24
- package/src/extensions/tags/xml-util.ts +62 -5
- package/src/index.ts +0 -1
- package/src/styles/theme.ts +46 -31
- package/src/types/types.ts +10 -2
- package/src/typings.d.ts +8 -0
- package/src/util/cursor.ts +0 -1
- package/dist/lib/browser/chunk-HL3YF6WC.mjs +0 -22
- package/dist/lib/browser/chunk-HL3YF6WC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs +0 -24
- package/dist/lib/node-esm/chunk-YJZGD3LY.mjs.map +0 -7
- package/dist/types/src/extensions/auto-scroll.d.ts +0 -6
- package/dist/types/src/extensions/auto-scroll.d.ts.map +0 -1
- package/dist/types/src/extensions/scroller.d.ts +0 -66
- package/dist/types/src/extensions/scroller.d.ts.map +0 -1
- package/dist/types/src/extensions/tags/streamer.d.ts +0 -12
- package/dist/types/src/extensions/tags/streamer.d.ts.map +0 -1
- package/dist/types/src/extensions/typewriter.d.ts +0 -10
- package/dist/types/src/extensions/typewriter.d.ts.map +0 -1
- package/src/extensions/auto-scroll.ts +0 -126
- package/src/extensions/tags/streamer.ts +0 -243
- package/src/extensions/typewriter.ts +0 -68
|
@@ -1,29 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EditorInputMode,
|
|
3
|
-
EditorInputModes,
|
|
4
|
-
EditorViewMode,
|
|
5
|
-
EditorViewModes
|
|
6
|
-
} from "./chunk-HL3YF6WC.mjs";
|
|
7
|
-
|
|
8
1
|
// src/index.ts
|
|
9
|
-
import { EditorState as
|
|
10
|
-
import { EditorView as
|
|
2
|
+
import { EditorState as EditorState4 } from "@codemirror/state";
|
|
3
|
+
import { EditorView as EditorView33, keymap as keymap15 } from "@codemirror/view";
|
|
11
4
|
import { tags as tags2 } from "@lezer/highlight";
|
|
12
5
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
13
6
|
|
|
14
7
|
// src/defaults.ts
|
|
15
8
|
import { mx } from "@dxos/ui-theme";
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
var editorClassNames = (role) => mx("dx-attention-surface p-0.5 data-[toolbar=disabled]:pt-2 dx-focus-ring-inset", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-h-24" : "dx-container overflow-hidden");
|
|
10
|
+
var documentSlots = {
|
|
11
|
+
content: {
|
|
12
|
+
/**
|
|
13
|
+
* CodeMirror content width.
|
|
14
|
+
* 40rem = 640px. Corresponds to initial plank width (Google docs, Stashpad, etc.)
|
|
15
|
+
* 50rem = 800px. Maximum content width for solo mode.
|
|
16
|
+
* NOTE: Max width - 4rem = 2rem left/right margin (or 2rem gutter plus 1rem left/right margin).
|
|
17
|
+
*/
|
|
18
|
+
className: mx(
|
|
19
|
+
// Inline-size container for widget sizing (children use `max-w-[100cqi]`).
|
|
20
|
+
// NOTE: Use inline-size, not full size containment — `container-type: size` on the
|
|
21
|
+
// editor content breaks CodeMirror's viewport measurement, leaving blank gaps during
|
|
22
|
+
// scroll until a click forces a re-measure.
|
|
23
|
+
"dx-inline-size-container",
|
|
24
|
+
// Wider margin for web (vs. mobile).
|
|
25
|
+
"pointer-fine:max-w-[min(50rem,100%-4rem)] pointer-coarse:max-w-[min(50rem,100%-2rem)]",
|
|
26
|
+
"mx-auto! w-full"
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var compactSlots = {
|
|
31
|
+
content: {
|
|
32
|
+
className: "mx-2!"
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var mobileSlots = {
|
|
21
36
|
content: {
|
|
22
|
-
className:
|
|
37
|
+
className: "mx-2!"
|
|
23
38
|
}
|
|
24
39
|
};
|
|
25
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
26
|
-
var stackItemContentEditorClassNames = (role) => mx("dx-attention-surface p-0.5 dx-focus-ring-inset data-[toolbar=disabled]:pt-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-h-24" : "dx-container overflow-hidden");
|
|
27
40
|
|
|
28
41
|
// src/extensions/annotations.ts
|
|
29
42
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
@@ -207,7 +220,7 @@ var singleValueFacet = (defaultValue) => Facet.define({
|
|
|
207
220
|
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
|
208
221
|
var defaultCursorConverter = {
|
|
209
222
|
toCursor: (position) => position.toString(),
|
|
210
|
-
fromCursor: (
|
|
223
|
+
fromCursor: (cursor) => parseInt(cursor)
|
|
211
224
|
};
|
|
212
225
|
var Cursor = class _Cursor {
|
|
213
226
|
static converter = singleValueFacet(defaultCursorConverter);
|
|
@@ -220,9 +233,9 @@ var Cursor = class _Cursor {
|
|
|
220
233
|
to
|
|
221
234
|
].join(":");
|
|
222
235
|
};
|
|
223
|
-
static getRangeFromCursor = (state,
|
|
236
|
+
static getRangeFromCursor = (state, cursor) => {
|
|
224
237
|
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
225
|
-
const parts =
|
|
238
|
+
const parts = cursor.split(":");
|
|
226
239
|
const from = cursorConverter2.fromCursor(parts[0]);
|
|
227
240
|
const to = cursorConverter2.fromCursor(parts[1]);
|
|
228
241
|
return from !== void 0 && to !== void 0 ? {
|
|
@@ -258,12 +271,7 @@ var wrapWithCatch = (fn, label) => {
|
|
|
258
271
|
} catch (err) {
|
|
259
272
|
log.catch(err, {
|
|
260
273
|
label
|
|
261
|
-
}, {
|
|
262
|
-
F: __dxlog_file,
|
|
263
|
-
L: 20,
|
|
264
|
-
S: void 0,
|
|
265
|
-
C: (f, a) => f(...a)
|
|
266
|
-
});
|
|
274
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 13, S: void 0 });
|
|
267
275
|
}
|
|
268
276
|
};
|
|
269
277
|
};
|
|
@@ -289,12 +297,7 @@ var logChanges = (trs) => {
|
|
|
289
297
|
if (changes.length) {
|
|
290
298
|
log("changes", {
|
|
291
299
|
changes
|
|
292
|
-
}, {
|
|
293
|
-
F: __dxlog_file,
|
|
294
|
-
L: 54,
|
|
295
|
-
S: void 0,
|
|
296
|
-
C: (f, a) => f(...a)
|
|
297
|
-
});
|
|
300
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 44, S: void 0 });
|
|
298
301
|
}
|
|
299
302
|
};
|
|
300
303
|
|
|
@@ -360,30 +363,37 @@ var insertAtLineStart = (view, from, insert) => {
|
|
|
360
363
|
};
|
|
361
364
|
|
|
362
365
|
// src/extensions/autocomplete/placeholder.ts
|
|
363
|
-
var placeholder = ({ content, delay = 3e3 }) => {
|
|
366
|
+
var placeholder = ({ content, delay = 3e3, focusOnly = false }) => {
|
|
364
367
|
const plugin = ViewPlugin3.fromClass(class {
|
|
365
368
|
_timeout;
|
|
366
369
|
_decorations = Decoration3.none;
|
|
367
370
|
update(update2) {
|
|
371
|
+
if (!update2.docChanged && !update2.selectionSet && !update2.focusChanged) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
368
374
|
if (this._timeout) {
|
|
369
375
|
window.clearTimeout(this._timeout);
|
|
370
376
|
this._timeout = void 0;
|
|
371
377
|
}
|
|
378
|
+
this._decorations = Decoration3.none;
|
|
379
|
+
if (focusOnly && !update2.view.hasFocus) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
372
382
|
const activeLine = update2.view.state.doc.lineAt(update2.view.state.selection.main.head);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const lineStart = activeLine.from;
|
|
376
|
-
this._timeout = setTimeout(() => {
|
|
377
|
-
this._decorations = Decoration3.set([
|
|
378
|
-
Decoration3.widget({
|
|
379
|
-
widget: new PlaceholderWidget(content),
|
|
380
|
-
side: 1
|
|
381
|
-
}).range(lineStart)
|
|
382
|
-
]);
|
|
383
|
-
update2.view.update([]);
|
|
384
|
-
}, delay);
|
|
383
|
+
if (activeLine.text.trim() !== "") {
|
|
384
|
+
return;
|
|
385
385
|
}
|
|
386
|
-
|
|
386
|
+
const lineStart = activeLine.from;
|
|
387
|
+
const view = update2.view;
|
|
388
|
+
this._timeout = setTimeout(() => {
|
|
389
|
+
this._decorations = Decoration3.set([
|
|
390
|
+
Decoration3.widget({
|
|
391
|
+
widget: new PlaceholderWidget(content),
|
|
392
|
+
side: 1
|
|
393
|
+
}).range(lineStart)
|
|
394
|
+
]);
|
|
395
|
+
view.update([]);
|
|
396
|
+
}, delay);
|
|
387
397
|
}
|
|
388
398
|
destroy() {
|
|
389
399
|
if (this._timeout) {
|
|
@@ -501,250 +511,10 @@ var typeahead = ({ onComplete } = {}) => {
|
|
|
501
511
|
];
|
|
502
512
|
};
|
|
503
513
|
|
|
504
|
-
// src/extensions/auto-scroll.ts
|
|
505
|
-
import { EditorView as EditorView5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
506
|
-
import { addEventListener, combine, throttle } from "@dxos/async";
|
|
507
|
-
import { Domino } from "@dxos/ui";
|
|
508
|
-
|
|
509
|
-
// src/extensions/scroller.ts
|
|
510
|
-
import { StateEffect } from "@codemirror/state";
|
|
511
|
-
import { EditorView as EditorView4, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
512
|
-
import { log as log2 } from "@dxos/log";
|
|
513
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/scroller.ts";
|
|
514
|
-
var scrollerLineEffect = StateEffect.define();
|
|
515
|
-
var scrollerCrawlEffect = StateEffect.define();
|
|
516
|
-
var scrollToLine = (view, options) => {
|
|
517
|
-
view.dispatch({
|
|
518
|
-
effects: scrollerLineEffect.of(options)
|
|
519
|
-
});
|
|
520
|
-
};
|
|
521
|
-
var scroller = ({ overScroll = 0 } = {}) => {
|
|
522
|
-
const scrollPlugin = ViewPlugin5.fromClass(class ScrollerPlugin {
|
|
523
|
-
view;
|
|
524
|
-
crawler;
|
|
525
|
-
constructor(view) {
|
|
526
|
-
this.view = view;
|
|
527
|
-
this.crawler = createCrawler(this.view);
|
|
528
|
-
}
|
|
529
|
-
// No-op.
|
|
530
|
-
destroy() {
|
|
531
|
-
this.crawler.cancel();
|
|
532
|
-
}
|
|
533
|
-
cancel() {
|
|
534
|
-
this.crawler.cancel();
|
|
535
|
-
}
|
|
536
|
-
crawl(start = false) {
|
|
537
|
-
if (start) {
|
|
538
|
-
this.crawler.scroll();
|
|
539
|
-
} else {
|
|
540
|
-
this.crawler.cancel();
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
scroll({ line, offset = 0, position, behavior = "instant" }) {
|
|
544
|
-
const { scrollTop, scrollHeight, clientHeight } = this.view.scrollDOM;
|
|
545
|
-
const scrollerRect = this.view.scrollDOM.getBoundingClientRect();
|
|
546
|
-
const doc = this.view.state.doc;
|
|
547
|
-
let targetScrollTop = scrollHeight - clientHeight + offset;
|
|
548
|
-
if (line >= 0 && line <= doc.lines - 1) {
|
|
549
|
-
const lineStart = doc.line(line + 1).from;
|
|
550
|
-
const coords = this.view.coordsAtPos(lineStart);
|
|
551
|
-
if (coords) {
|
|
552
|
-
const currentScrollTop = scrollTop;
|
|
553
|
-
const maxScrollTop = scrollHeight - clientHeight;
|
|
554
|
-
if (position === "end") {
|
|
555
|
-
targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + offset;
|
|
556
|
-
} else {
|
|
557
|
-
targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + offset;
|
|
558
|
-
}
|
|
559
|
-
targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
requestAnimationFrame(() => {
|
|
563
|
-
this.view.scrollDOM.scrollTo({
|
|
564
|
-
top: targetScrollTop,
|
|
565
|
-
behavior
|
|
566
|
-
});
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
return [
|
|
571
|
-
scrollPlugin,
|
|
572
|
-
// Listen for effect.s
|
|
573
|
-
EditorView4.updateListener.of((update2) => {
|
|
574
|
-
update2.transactions.forEach((transaction) => {
|
|
575
|
-
try {
|
|
576
|
-
const plugin = update2.view.plugin(scrollPlugin);
|
|
577
|
-
if (plugin) {
|
|
578
|
-
for (const effect of transaction.effects) {
|
|
579
|
-
if (effect.is(scrollerCrawlEffect)) {
|
|
580
|
-
plugin.crawl(effect.value);
|
|
581
|
-
} else if (effect.is(scrollerLineEffect)) {
|
|
582
|
-
plugin.scroll(effect.value);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
} catch (err) {
|
|
587
|
-
log2.catch(err, void 0, {
|
|
588
|
-
F: __dxlog_file2,
|
|
589
|
-
L: 145,
|
|
590
|
-
S: void 0,
|
|
591
|
-
C: (f, a) => f(...a)
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
});
|
|
595
|
-
}),
|
|
596
|
-
// Styles.
|
|
597
|
-
EditorView4.theme({
|
|
598
|
-
".cm-content": {
|
|
599
|
-
paddingBottom: `${overScroll}px`
|
|
600
|
-
},
|
|
601
|
-
".cm-scroller": {
|
|
602
|
-
overflowAnchor: "none",
|
|
603
|
-
paddingBottom: "0"
|
|
604
|
-
},
|
|
605
|
-
".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
|
|
606
|
-
display: "none"
|
|
607
|
-
},
|
|
608
|
-
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
609
|
-
background: "transparent",
|
|
610
|
-
transition: "background 0.15s"
|
|
611
|
-
},
|
|
612
|
-
"&:hover .cm-scroller::-webkit-scrollbar-thumb": {
|
|
613
|
-
background: "var(--color-scrollbar-thumb)"
|
|
614
|
-
},
|
|
615
|
-
".cm-scroll-button": {
|
|
616
|
-
position: "absolute",
|
|
617
|
-
bottom: "0.5rem",
|
|
618
|
-
right: "1rem"
|
|
619
|
-
}
|
|
620
|
-
})
|
|
621
|
-
];
|
|
622
|
-
};
|
|
623
|
-
function createCrawler(view, k = 0.3, maxStep = 2, targetDelta = 0.5) {
|
|
624
|
-
const el = view.scrollDOM;
|
|
625
|
-
let currentTop = 0;
|
|
626
|
-
let rafId = null;
|
|
627
|
-
function frame() {
|
|
628
|
-
const targetTop = el.scrollHeight - el.clientHeight;
|
|
629
|
-
const delta = targetTop - currentTop;
|
|
630
|
-
const absDelta = Math.abs(delta);
|
|
631
|
-
if (absDelta < targetDelta) {
|
|
632
|
-
el.scrollTop = targetTop;
|
|
633
|
-
currentTop = targetTop;
|
|
634
|
-
rafId = null;
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
const step = Math.sign(delta) * Math.min(absDelta, Math.max(1, Math.min(absDelta * k, maxStep)));
|
|
638
|
-
currentTop += step;
|
|
639
|
-
el.scrollTop = currentTop;
|
|
640
|
-
rafId = requestAnimationFrame(frame);
|
|
641
|
-
}
|
|
642
|
-
return {
|
|
643
|
-
scroll: () => {
|
|
644
|
-
if (rafId === null) {
|
|
645
|
-
currentTop = el.scrollTop;
|
|
646
|
-
rafId = requestAnimationFrame(frame);
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
cancel: () => {
|
|
650
|
-
if (rafId !== null) {
|
|
651
|
-
cancelAnimationFrame(rafId);
|
|
652
|
-
rafId = null;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// src/extensions/auto-scroll.ts
|
|
659
|
-
var autoScroll = (_ = {}) => {
|
|
660
|
-
let buttonContainer;
|
|
661
|
-
let isPinned = true;
|
|
662
|
-
const setPinned = (pinned) => {
|
|
663
|
-
buttonContainer?.classList.toggle("opacity-0", pinned);
|
|
664
|
-
isPinned = pinned;
|
|
665
|
-
};
|
|
666
|
-
return [
|
|
667
|
-
// Update listener for logging when scrolling is needed.
|
|
668
|
-
EditorView5.updateListener.of(({ view, heightChanged, state }) => {
|
|
669
|
-
if (heightChanged) {
|
|
670
|
-
if (isPinned) {
|
|
671
|
-
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
672
|
-
const delta = scrollHeight - scrollTop - clientHeight;
|
|
673
|
-
if (delta > 0 && scrollTop > 0) {
|
|
674
|
-
setPinned(true);
|
|
675
|
-
view.dispatch({
|
|
676
|
-
effects: scrollerCrawlEffect.of(true)
|
|
677
|
-
});
|
|
678
|
-
} else if (delta < 0) {
|
|
679
|
-
setPinned(false);
|
|
680
|
-
}
|
|
681
|
-
} else {
|
|
682
|
-
if (state.doc.length === 0) {
|
|
683
|
-
setPinned(true);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}),
|
|
688
|
-
// Detect user scroll and unpin (or re-pin if scrolled to the bottom).
|
|
689
|
-
ViewPlugin6.fromClass(class {
|
|
690
|
-
cleanup;
|
|
691
|
-
constructor(view) {
|
|
692
|
-
this.cleanup = createUserScrollDetector(view.scrollDOM, throttle(() => {
|
|
693
|
-
requestAnimationFrame(() => {
|
|
694
|
-
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
695
|
-
const delta = scrollHeight - scrollTop - clientHeight;
|
|
696
|
-
const pinned = delta === 0;
|
|
697
|
-
setPinned(pinned);
|
|
698
|
-
if (!pinned) {
|
|
699
|
-
view.dispatch({
|
|
700
|
-
effects: scrollerCrawlEffect.of(false)
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
}, 500));
|
|
705
|
-
}
|
|
706
|
-
destroy() {
|
|
707
|
-
this.cleanup();
|
|
708
|
-
}
|
|
709
|
-
}),
|
|
710
|
-
// Scroll button.
|
|
711
|
-
ViewPlugin6.fromClass(class {
|
|
712
|
-
constructor(view) {
|
|
713
|
-
const icon = Domino.of("dx-icon").attributes({
|
|
714
|
-
icon: "ph--arrow-down--regular"
|
|
715
|
-
});
|
|
716
|
-
const button = Domino.of("button").classNames("dx-button bg-accent-surface").attributes({
|
|
717
|
-
"data-density": "fine"
|
|
718
|
-
}).children(icon).on("click", () => {
|
|
719
|
-
setPinned(true);
|
|
720
|
-
view.dispatch({
|
|
721
|
-
effects: scrollerLineEffect.of({
|
|
722
|
-
line: -1,
|
|
723
|
-
position: "end",
|
|
724
|
-
behavior: "smooth"
|
|
725
|
-
})
|
|
726
|
-
});
|
|
727
|
-
});
|
|
728
|
-
buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").children(button).root;
|
|
729
|
-
view.scrollDOM.parentElement.appendChild(buttonContainer);
|
|
730
|
-
}
|
|
731
|
-
})
|
|
732
|
-
];
|
|
733
|
-
};
|
|
734
|
-
function createUserScrollDetector(element, onUserScroll) {
|
|
735
|
-
return combine(addEventListener(element, "wheel", () => onUserScroll(), {
|
|
736
|
-
passive: true
|
|
737
|
-
}), addEventListener(element, "pointerdown", (event) => {
|
|
738
|
-
if (event.clientX > element.getBoundingClientRect().right - (element.offsetWidth - element.clientWidth)) {
|
|
739
|
-
onUserScroll();
|
|
740
|
-
}
|
|
741
|
-
}));
|
|
742
|
-
}
|
|
743
|
-
|
|
744
514
|
// src/extensions/automerge/automerge.ts
|
|
745
515
|
import { next as A3 } from "@automerge/automerge";
|
|
746
516
|
import { StateField, Transaction as Transaction2 } from "@codemirror/state";
|
|
747
|
-
import { EditorView as
|
|
517
|
+
import { EditorView as EditorView4, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
748
518
|
import { DocAccessor } from "@dxos/echo-db";
|
|
749
519
|
|
|
750
520
|
// src/extensions/state.ts
|
|
@@ -753,42 +523,32 @@ var initialSync = Transaction.userEvent.of("initial.sync");
|
|
|
753
523
|
|
|
754
524
|
// src/extensions/automerge/cursor.ts
|
|
755
525
|
import { fromCursor, toCursor } from "@dxos/echo-db";
|
|
756
|
-
import { log as
|
|
757
|
-
var
|
|
526
|
+
import { log as log2 } from "@dxos/log";
|
|
527
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/cursor.ts";
|
|
758
528
|
var cursorConverter = (accessor) => ({
|
|
759
529
|
toCursor: (pos, assoc) => {
|
|
760
530
|
try {
|
|
761
531
|
return toCursor(accessor, pos, assoc);
|
|
762
532
|
} catch (err) {
|
|
763
|
-
|
|
764
|
-
F: __dxlog_file3,
|
|
765
|
-
L: 15,
|
|
766
|
-
S: void 0,
|
|
767
|
-
C: (f, a) => f(...a)
|
|
768
|
-
});
|
|
533
|
+
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 11, S: void 0 });
|
|
769
534
|
return "";
|
|
770
535
|
}
|
|
771
536
|
},
|
|
772
|
-
fromCursor: (
|
|
537
|
+
fromCursor: (cursor) => {
|
|
773
538
|
try {
|
|
774
|
-
return fromCursor(accessor,
|
|
539
|
+
return fromCursor(accessor, cursor);
|
|
775
540
|
} catch (err) {
|
|
776
|
-
|
|
777
|
-
F: __dxlog_file3,
|
|
778
|
-
L: 24,
|
|
779
|
-
S: void 0,
|
|
780
|
-
C: (f, a) => f(...a)
|
|
781
|
-
});
|
|
541
|
+
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 19, S: void 0 });
|
|
782
542
|
return 0;
|
|
783
543
|
}
|
|
784
544
|
}
|
|
785
545
|
});
|
|
786
546
|
|
|
787
547
|
// src/extensions/automerge/defs.ts
|
|
788
|
-
import { Annotation, StateEffect
|
|
548
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
789
549
|
var getPath = (state, field) => state.field(field).path;
|
|
790
550
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
791
|
-
var updateHeadsEffect =
|
|
551
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
792
552
|
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
793
553
|
newHeads
|
|
794
554
|
});
|
|
@@ -799,7 +559,7 @@ var isReconcile = (tr) => {
|
|
|
799
559
|
|
|
800
560
|
// src/extensions/automerge/sync.ts
|
|
801
561
|
import { next as A2 } from "@automerge/automerge";
|
|
802
|
-
import { log as
|
|
562
|
+
import { log as log3 } from "@dxos/log";
|
|
803
563
|
|
|
804
564
|
// src/extensions/automerge/update-automerge.ts
|
|
805
565
|
import { next as A } from "@automerge/automerge";
|
|
@@ -940,7 +700,7 @@ var charPath = (textPath, candidatePath) => {
|
|
|
940
700
|
};
|
|
941
701
|
|
|
942
702
|
// src/extensions/automerge/sync.ts
|
|
943
|
-
var
|
|
703
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/sync.ts";
|
|
944
704
|
var Syncer = class {
|
|
945
705
|
_handle;
|
|
946
706
|
_state;
|
|
@@ -963,12 +723,7 @@ var Syncer = class {
|
|
|
963
723
|
this._pending = false;
|
|
964
724
|
}
|
|
965
725
|
onEditorChange(view) {
|
|
966
|
-
|
|
967
|
-
F: __dxlog_file4,
|
|
968
|
-
L: 45,
|
|
969
|
-
S: this,
|
|
970
|
-
C: (f, a) => f(...a)
|
|
971
|
-
});
|
|
726
|
+
log3("onEditorChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 35, S: this });
|
|
972
727
|
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
973
728
|
const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
974
729
|
if (newHeads) {
|
|
@@ -979,12 +734,7 @@ var Syncer = class {
|
|
|
979
734
|
}
|
|
980
735
|
}
|
|
981
736
|
onAutomergeChange(view) {
|
|
982
|
-
|
|
983
|
-
F: __dxlog_file4,
|
|
984
|
-
L: 60,
|
|
985
|
-
S: this,
|
|
986
|
-
C: (f, a) => f(...a)
|
|
987
|
-
});
|
|
737
|
+
log3("onAutomergeChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 47, S: this });
|
|
988
738
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
989
739
|
const newHeads = A2.getHeads(this._handle.doc());
|
|
990
740
|
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.doc(), oldHeads, newHeads);
|
|
@@ -1037,7 +787,7 @@ var automerge = (accessor) => {
|
|
|
1037
787
|
// Track heads.
|
|
1038
788
|
syncState,
|
|
1039
789
|
// Reconcile external updates.
|
|
1040
|
-
|
|
790
|
+
ViewPlugin5.fromClass(class {
|
|
1041
791
|
_view;
|
|
1042
792
|
constructor(_view) {
|
|
1043
793
|
this._view = _view;
|
|
@@ -1046,6 +796,17 @@ var automerge = (accessor) => {
|
|
|
1046
796
|
const value = DocAccessor.getValue(accessor);
|
|
1047
797
|
const current = this._view.state.doc.toString();
|
|
1048
798
|
if (value !== current) {
|
|
799
|
+
this._view.dispatch({
|
|
800
|
+
changes: {
|
|
801
|
+
from: 0,
|
|
802
|
+
to: this._view.state.doc.length,
|
|
803
|
+
insert: value
|
|
804
|
+
},
|
|
805
|
+
annotations: [
|
|
806
|
+
initialSync,
|
|
807
|
+
reconcileAnnotation.of(true)
|
|
808
|
+
]
|
|
809
|
+
});
|
|
1049
810
|
}
|
|
1050
811
|
});
|
|
1051
812
|
}
|
|
@@ -1057,7 +818,7 @@ var automerge = (accessor) => {
|
|
|
1057
818
|
};
|
|
1058
819
|
}),
|
|
1059
820
|
// Reconcile local updates.
|
|
1060
|
-
|
|
821
|
+
EditorView4.updateListener.of(({ view, changes, transactions }) => {
|
|
1061
822
|
if (!changes.empty) {
|
|
1062
823
|
const isInitialSync = transactions.some((tr) => tr.annotation(Transaction2.userEvent) === initialSync.value);
|
|
1063
824
|
if (!isInitialSync) {
|
|
@@ -1070,10 +831,10 @@ var automerge = (accessor) => {
|
|
|
1070
831
|
|
|
1071
832
|
// src/extensions/awareness/awareness.ts
|
|
1072
833
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
|
1073
|
-
import { Decoration as Decoration5, EditorView as
|
|
834
|
+
import { Decoration as Decoration5, EditorView as EditorView5, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1074
835
|
import { Event } from "@dxos/async";
|
|
1075
836
|
import { Context } from "@dxos/context";
|
|
1076
|
-
var
|
|
837
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness.ts";
|
|
1077
838
|
var dummyProvider = {
|
|
1078
839
|
remoteStateChange: new Event(),
|
|
1079
840
|
open: () => {
|
|
@@ -1089,17 +850,14 @@ var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
|
1089
850
|
var awareness = (provider = dummyProvider) => {
|
|
1090
851
|
return [
|
|
1091
852
|
awarenessProvider.of(provider),
|
|
1092
|
-
|
|
853
|
+
ViewPlugin6.fromClass(RemoteSelectionsDecorator, {
|
|
1093
854
|
decorations: (value) => value.decorations
|
|
1094
855
|
}),
|
|
1095
856
|
styles
|
|
1096
857
|
];
|
|
1097
858
|
};
|
|
1098
859
|
var RemoteSelectionsDecorator = class {
|
|
1099
|
-
_ctx = new Context(void 0, {
|
|
1100
|
-
F: __dxlog_file5,
|
|
1101
|
-
L: 80
|
|
1102
|
-
});
|
|
860
|
+
_ctx = new Context(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 33 });
|
|
1103
861
|
_cursorConverter;
|
|
1104
862
|
_provider;
|
|
1105
863
|
_lastAnchor;
|
|
@@ -1248,7 +1006,7 @@ var RemoteCaretWidget = class extends WidgetType3 {
|
|
|
1248
1006
|
return true;
|
|
1249
1007
|
}
|
|
1250
1008
|
};
|
|
1251
|
-
var styles =
|
|
1009
|
+
var styles = EditorView5.theme({
|
|
1252
1010
|
".cm-collab-selection": {},
|
|
1253
1011
|
".cm-collab-selectionLine": {
|
|
1254
1012
|
padding: 0,
|
|
@@ -1310,8 +1068,8 @@ var styles = EditorView7.theme({
|
|
|
1310
1068
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
1311
1069
|
import { Context as Context2 } from "@dxos/context";
|
|
1312
1070
|
import { invariant } from "@dxos/invariant";
|
|
1313
|
-
import { log as
|
|
1314
|
-
var
|
|
1071
|
+
import { log as log4 } from "@dxos/log";
|
|
1072
|
+
var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness-provider.ts";
|
|
1315
1073
|
var DEBOUNCE_INTERVAL = 100;
|
|
1316
1074
|
var SpaceAwarenessProvider = class {
|
|
1317
1075
|
_remoteStates = /* @__PURE__ */ new Map();
|
|
@@ -1330,10 +1088,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1330
1088
|
this._info = info;
|
|
1331
1089
|
}
|
|
1332
1090
|
open() {
|
|
1333
|
-
this._ctx = new Context2(void 0, {
|
|
1334
|
-
F: __dxlog_file6,
|
|
1335
|
-
L: 57
|
|
1336
|
-
});
|
|
1091
|
+
this._ctx = new Context2(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 28 });
|
|
1337
1092
|
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
1338
1093
|
if (this._localState) {
|
|
1339
1094
|
await this._messenger.postMessage(this._channel, {
|
|
@@ -1358,14 +1113,9 @@ var SpaceAwarenessProvider = class {
|
|
|
1358
1113
|
void this._messenger.postMessage(this._channel, {
|
|
1359
1114
|
kind: "query"
|
|
1360
1115
|
}).catch((err) => {
|
|
1361
|
-
|
|
1116
|
+
log4.debug("failed to query awareness", {
|
|
1362
1117
|
err
|
|
1363
|
-
}, {
|
|
1364
|
-
F: __dxlog_file6,
|
|
1365
|
-
L: 91,
|
|
1366
|
-
S: this,
|
|
1367
|
-
C: (f, a) => f(...a)
|
|
1368
|
-
});
|
|
1118
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 57, S: this });
|
|
1369
1119
|
});
|
|
1370
1120
|
}
|
|
1371
1121
|
close() {
|
|
@@ -1377,15 +1127,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1377
1127
|
return Array.from(this._remoteStates.values());
|
|
1378
1128
|
}
|
|
1379
1129
|
update(position) {
|
|
1380
|
-
invariant(this._postTask, void 0, {
|
|
1381
|
-
F: __dxlog_file6,
|
|
1382
|
-
L: 106,
|
|
1383
|
-
S: this,
|
|
1384
|
-
A: [
|
|
1385
|
-
"this._postTask",
|
|
1386
|
-
""
|
|
1387
|
-
]
|
|
1388
|
-
});
|
|
1130
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 71, S: this, A: ["this._postTask", ""] });
|
|
1389
1131
|
this._localState = {
|
|
1390
1132
|
peerId: this._peerId,
|
|
1391
1133
|
position,
|
|
@@ -1394,38 +1136,22 @@ var SpaceAwarenessProvider = class {
|
|
|
1394
1136
|
this._postTask.schedule();
|
|
1395
1137
|
}
|
|
1396
1138
|
_handleQueryMessage() {
|
|
1397
|
-
invariant(this._postTask, void 0, {
|
|
1398
|
-
F: __dxlog_file6,
|
|
1399
|
-
L: 117,
|
|
1400
|
-
S: this,
|
|
1401
|
-
A: [
|
|
1402
|
-
"this._postTask",
|
|
1403
|
-
""
|
|
1404
|
-
]
|
|
1405
|
-
});
|
|
1139
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 80, S: this, A: ["this._postTask", ""] });
|
|
1406
1140
|
this._postTask.schedule();
|
|
1407
1141
|
}
|
|
1408
1142
|
_handlePostMessage(message) {
|
|
1409
|
-
invariant(message.kind === "post", void 0, {
|
|
1410
|
-
F: __dxlog_file6,
|
|
1411
|
-
L: 122,
|
|
1412
|
-
S: this,
|
|
1413
|
-
A: [
|
|
1414
|
-
"message.kind === 'post'",
|
|
1415
|
-
""
|
|
1416
|
-
]
|
|
1417
|
-
});
|
|
1143
|
+
invariant(message.kind === "post", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 84, S: this, A: ["message.kind === 'post'", ""] });
|
|
1418
1144
|
this._remoteStates.set(message.state.peerId, message.state);
|
|
1419
1145
|
this.remoteStateChange.emit();
|
|
1420
1146
|
}
|
|
1421
1147
|
};
|
|
1422
1148
|
|
|
1423
1149
|
// src/extensions/blast.ts
|
|
1424
|
-
import { EditorView as
|
|
1150
|
+
import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
|
|
1425
1151
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
1426
|
-
import { throttle
|
|
1152
|
+
import { throttle } from "@dxos/async";
|
|
1427
1153
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1428
|
-
var
|
|
1154
|
+
var __dxlog_file6 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/blast.ts";
|
|
1429
1155
|
var defaultOptions = {
|
|
1430
1156
|
effect: 2,
|
|
1431
1157
|
maxParticles: 200,
|
|
@@ -1470,7 +1196,7 @@ var blast = (options = defaultOptions) => {
|
|
|
1470
1196
|
};
|
|
1471
1197
|
return [
|
|
1472
1198
|
// Cursor moved.
|
|
1473
|
-
|
|
1199
|
+
EditorView6.updateListener.of((update2) => {
|
|
1474
1200
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
1475
1201
|
if (blaster) {
|
|
1476
1202
|
blaster.destroy();
|
|
@@ -1543,15 +1269,7 @@ var Blaster = class {
|
|
|
1543
1269
|
return this._node;
|
|
1544
1270
|
}
|
|
1545
1271
|
initialize() {
|
|
1546
|
-
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
1547
|
-
F: __dxlog_file7,
|
|
1548
|
-
L: 142,
|
|
1549
|
-
S: this,
|
|
1550
|
-
A: [
|
|
1551
|
-
"!this._canvas && !this._ctx",
|
|
1552
|
-
""
|
|
1553
|
-
]
|
|
1554
|
-
});
|
|
1272
|
+
invariant2(!this._canvas && !this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 134, S: this, A: ["!this._canvas && !this._ctx", ""] });
|
|
1555
1273
|
this._canvas = document.createElement("canvas");
|
|
1556
1274
|
this._canvas.id = "code-blast-canvas";
|
|
1557
1275
|
this._canvas.style.position = "absolute";
|
|
@@ -1580,15 +1298,7 @@ var Blaster = class {
|
|
|
1580
1298
|
}
|
|
1581
1299
|
}
|
|
1582
1300
|
start() {
|
|
1583
|
-
invariant2(this._canvas && this._ctx, void 0, {
|
|
1584
|
-
F: __dxlog_file7,
|
|
1585
|
-
L: 181,
|
|
1586
|
-
S: this,
|
|
1587
|
-
A: [
|
|
1588
|
-
"this._canvas && this._ctx",
|
|
1589
|
-
""
|
|
1590
|
-
]
|
|
1591
|
-
});
|
|
1301
|
+
invariant2(this._canvas && this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 166, S: this, A: ["this._canvas && this._ctx", ""] });
|
|
1592
1302
|
this._running = true;
|
|
1593
1303
|
this.loop();
|
|
1594
1304
|
}
|
|
@@ -1615,11 +1325,11 @@ var Blaster = class {
|
|
|
1615
1325
|
this.drawParticles();
|
|
1616
1326
|
requestAnimationFrame(this.loop.bind(this));
|
|
1617
1327
|
}
|
|
1618
|
-
shake =
|
|
1328
|
+
shake = throttle(({ time }) => {
|
|
1619
1329
|
this._shakeTime = this._shakeTimeMax || time;
|
|
1620
1330
|
this._shakeTimeMax = time;
|
|
1621
1331
|
}, 100);
|
|
1622
|
-
spawn =
|
|
1332
|
+
spawn = throttle(({ element, point }) => {
|
|
1623
1333
|
const color = getRGBComponents(element, this._options.color);
|
|
1624
1334
|
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
1625
1335
|
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
@@ -1728,9 +1438,9 @@ var random = (min, max) => {
|
|
|
1728
1438
|
|
|
1729
1439
|
// src/extensions/blocks.ts
|
|
1730
1440
|
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1731
|
-
import { Decoration as Decoration6, EditorView as
|
|
1441
|
+
import { Decoration as Decoration6, EditorView as EditorView7, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
1732
1442
|
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1733
|
-
var paragraphBlockPlugin =
|
|
1443
|
+
var paragraphBlockPlugin = ViewPlugin7.fromClass(class {
|
|
1734
1444
|
decorations;
|
|
1735
1445
|
constructor(view) {
|
|
1736
1446
|
this.decorations = this.build(view);
|
|
@@ -1789,7 +1499,7 @@ var paragraphBlockPlugin = ViewPlugin9.fromClass(class {
|
|
|
1789
1499
|
});
|
|
1790
1500
|
var blocks = () => [
|
|
1791
1501
|
paragraphBlockPlugin,
|
|
1792
|
-
|
|
1502
|
+
EditorView7.baseTheme({
|
|
1793
1503
|
".cm-line.block-line": {
|
|
1794
1504
|
paddingLeft: "0.75rem",
|
|
1795
1505
|
paddingRight: "0.75rem",
|
|
@@ -1823,13 +1533,13 @@ var blocks = () => [
|
|
|
1823
1533
|
];
|
|
1824
1534
|
|
|
1825
1535
|
// src/extensions/bookmarks.ts
|
|
1826
|
-
import { Prec as Prec3, StateEffect as
|
|
1536
|
+
import { Prec as Prec3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1827
1537
|
import { keymap as keymap4 } from "@codemirror/view";
|
|
1828
|
-
import { log as
|
|
1829
|
-
var
|
|
1830
|
-
var addBookmark =
|
|
1831
|
-
var removeBookmark =
|
|
1832
|
-
var clearBookmarks =
|
|
1538
|
+
import { log as log5 } from "@dxos/log";
|
|
1539
|
+
var __dxlog_file7 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/bookmarks.ts";
|
|
1540
|
+
var addBookmark = StateEffect2.define();
|
|
1541
|
+
var removeBookmark = StateEffect2.define();
|
|
1542
|
+
var clearBookmarks = StateEffect2.define();
|
|
1833
1543
|
var bookmarks = () => {
|
|
1834
1544
|
return [
|
|
1835
1545
|
bookmarksField,
|
|
@@ -1838,12 +1548,7 @@ var bookmarks = () => {
|
|
|
1838
1548
|
key: "Mod-ArrowUp",
|
|
1839
1549
|
run: (view) => {
|
|
1840
1550
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1841
|
-
|
|
1842
|
-
F: __dxlog_file8,
|
|
1843
|
-
L: 29,
|
|
1844
|
-
S: void 0,
|
|
1845
|
-
C: (f, a) => f(...a)
|
|
1846
|
-
});
|
|
1551
|
+
log5("up", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 18, S: void 0 });
|
|
1847
1552
|
return true;
|
|
1848
1553
|
}
|
|
1849
1554
|
},
|
|
@@ -1851,12 +1556,7 @@ var bookmarks = () => {
|
|
|
1851
1556
|
key: "Mod-ArrowDown",
|
|
1852
1557
|
run: (view) => {
|
|
1853
1558
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1854
|
-
|
|
1855
|
-
F: __dxlog_file8,
|
|
1856
|
-
L: 37,
|
|
1857
|
-
S: void 0,
|
|
1858
|
-
C: (f, a) => f(...a)
|
|
1859
|
-
});
|
|
1559
|
+
log5("down", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 26, S: void 0 });
|
|
1860
1560
|
return true;
|
|
1861
1561
|
}
|
|
1862
1562
|
}
|
|
@@ -1893,27 +1593,27 @@ var bookmarksField = StateField2.define({
|
|
|
1893
1593
|
|
|
1894
1594
|
// src/extensions/comments.ts
|
|
1895
1595
|
import { invertedEffects } from "@codemirror/commands";
|
|
1896
|
-
import { StateEffect as
|
|
1897
|
-
import { Decoration as Decoration7, EditorView as
|
|
1596
|
+
import { StateEffect as StateEffect3, StateField as StateField3 } from "@codemirror/state";
|
|
1597
|
+
import { Decoration as Decoration7, EditorView as EditorView9, ViewPlugin as ViewPlugin8, hoverTooltip, keymap as keymap6 } from "@codemirror/view";
|
|
1898
1598
|
import sortBy from "lodash.sortby";
|
|
1899
1599
|
import { debounce as debounce2 } from "@dxos/async";
|
|
1900
|
-
import { log as
|
|
1600
|
+
import { log as log6 } from "@dxos/log";
|
|
1901
1601
|
import { isNonNullable } from "@dxos/util";
|
|
1902
1602
|
|
|
1903
1603
|
// src/extensions/selection.ts
|
|
1904
1604
|
import { Transaction as Transaction3 } from "@codemirror/state";
|
|
1905
|
-
import { EditorView as
|
|
1605
|
+
import { EditorView as EditorView8, keymap as keymap5 } from "@codemirror/view";
|
|
1906
1606
|
import { debounce } from "@dxos/async";
|
|
1907
1607
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1908
1608
|
import { isTruthy } from "@dxos/util";
|
|
1909
|
-
var
|
|
1609
|
+
var __dxlog_file8 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/selection.ts";
|
|
1910
1610
|
var documentId = singleValueFacet();
|
|
1911
|
-
var stateRestoreAnnotation = "dxos.
|
|
1611
|
+
var stateRestoreAnnotation = "org.dxos.cm.state-restore";
|
|
1912
1612
|
var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1913
1613
|
return {
|
|
1914
1614
|
selection,
|
|
1915
1615
|
scrollIntoView: !scrollTo,
|
|
1916
|
-
effects: scrollTo ?
|
|
1616
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
|
1917
1617
|
yMargin: 96
|
|
1918
1618
|
}) : void 0,
|
|
1919
1619
|
annotations: Transaction3.userEvent.of(stateRestoreAnnotation)
|
|
@@ -1921,28 +1621,12 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
|
1921
1621
|
};
|
|
1922
1622
|
var createEditorStateStore = (keyPrefix) => ({
|
|
1923
1623
|
getState: (id) => {
|
|
1924
|
-
invariant3(id, void 0, {
|
|
1925
|
-
F: __dxlog_file9,
|
|
1926
|
-
L: 47,
|
|
1927
|
-
S: void 0,
|
|
1928
|
-
A: [
|
|
1929
|
-
"id",
|
|
1930
|
-
""
|
|
1931
|
-
]
|
|
1932
|
-
});
|
|
1624
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 26, S: void 0, A: ["id", ""] });
|
|
1933
1625
|
const state = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
1934
1626
|
return state ? JSON.parse(state) : void 0;
|
|
1935
1627
|
},
|
|
1936
1628
|
setState: (id, state) => {
|
|
1937
|
-
invariant3(id, void 0, {
|
|
1938
|
-
F: __dxlog_file9,
|
|
1939
|
-
L: 53,
|
|
1940
|
-
S: void 0,
|
|
1941
|
-
A: [
|
|
1942
|
-
"id",
|
|
1943
|
-
""
|
|
1944
|
-
]
|
|
1945
|
-
});
|
|
1629
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 31, S: void 0, A: ["id", ""] });
|
|
1946
1630
|
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
|
1947
1631
|
}
|
|
1948
1632
|
});
|
|
@@ -1955,7 +1639,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
|
1955
1639
|
// setStateDebounced(id, {});
|
|
1956
1640
|
// },
|
|
1957
1641
|
// }),
|
|
1958
|
-
|
|
1642
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
|
1959
1643
|
const id = view.state.facet(documentId);
|
|
1960
1644
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
|
1961
1645
|
return;
|
|
@@ -1994,10 +1678,10 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
|
1994
1678
|
};
|
|
1995
1679
|
|
|
1996
1680
|
// src/extensions/comments.ts
|
|
1997
|
-
var
|
|
1998
|
-
var setComments =
|
|
1999
|
-
var setSelection =
|
|
2000
|
-
var setCommentState =
|
|
1681
|
+
var __dxlog_file9 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/comments.ts";
|
|
1682
|
+
var setComments = StateEffect3.define();
|
|
1683
|
+
var setSelection = StateEffect3.define();
|
|
1684
|
+
var setCommentState = StateEffect3.define();
|
|
2001
1685
|
var commentsState = StateField3.define({
|
|
2002
1686
|
create: (state) => ({
|
|
2003
1687
|
id: state.facet(documentId),
|
|
@@ -2036,7 +1720,7 @@ var commentsState = StateField3.define({
|
|
|
2036
1720
|
return value;
|
|
2037
1721
|
}
|
|
2038
1722
|
});
|
|
2039
|
-
var styles2 =
|
|
1723
|
+
var styles2 = EditorView9.theme({
|
|
2040
1724
|
".cm-comment, .cm-comment-current": {
|
|
2041
1725
|
padding: "3px 0",
|
|
2042
1726
|
color: "var(--color-cm-comment-text)",
|
|
@@ -2057,19 +1741,14 @@ var createCommentMark = (id, isCurrent) => Decoration7.mark({
|
|
|
2057
1741
|
"data-comment-id": id
|
|
2058
1742
|
}
|
|
2059
1743
|
});
|
|
2060
|
-
var commentsDecorations =
|
|
1744
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
|
2061
1745
|
commentsState
|
|
2062
1746
|
], (state) => {
|
|
2063
1747
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
2064
1748
|
const decorations2 = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
2065
1749
|
const range = comment.range;
|
|
2066
1750
|
if (!range) {
|
|
2067
|
-
|
|
2068
|
-
F: __dxlog_file10,
|
|
2069
|
-
L: 140,
|
|
2070
|
-
S: void 0,
|
|
2071
|
-
C: (f, a) => f(...a)
|
|
2072
|
-
});
|
|
1751
|
+
log6.warn("Invalid range:", range, { "~LogMeta": "~LogMeta", F: __dxlog_file9, L: 93, S: void 0 });
|
|
2073
1752
|
return void 0;
|
|
2074
1753
|
} else if (range.from === range.to) {
|
|
2075
1754
|
return void 0;
|
|
@@ -2079,8 +1758,8 @@ var commentsDecorations = EditorView11.decorations.compute([
|
|
|
2079
1758
|
}).filter(isNonNullable);
|
|
2080
1759
|
return Decoration7.set(decorations2);
|
|
2081
1760
|
});
|
|
2082
|
-
var commentClickedEffect =
|
|
2083
|
-
var handleCommentClick =
|
|
1761
|
+
var commentClickedEffect = StateEffect3.define();
|
|
1762
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
|
2084
1763
|
click: (event, view) => {
|
|
2085
1764
|
let target = event.target;
|
|
2086
1765
|
const editorRoot = view.dom;
|
|
@@ -2119,7 +1798,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2119
1798
|
}
|
|
2120
1799
|
};
|
|
2121
1800
|
return [
|
|
2122
|
-
|
|
1801
|
+
EditorView9.domEventHandlers({
|
|
2123
1802
|
cut: handleTrack,
|
|
2124
1803
|
copy: handleTrack
|
|
2125
1804
|
}),
|
|
@@ -2141,7 +1820,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2141
1820
|
return effects;
|
|
2142
1821
|
}),
|
|
2143
1822
|
// Handle paste or the undo of comment deletion.
|
|
2144
|
-
|
|
1823
|
+
EditorView9.updateListener.of((update2) => {
|
|
2145
1824
|
const restore = [];
|
|
2146
1825
|
for (let i = 0; i < update2.transactions.length; i++) {
|
|
2147
1826
|
const tr = update2.transactions[i];
|
|
@@ -2182,10 +1861,10 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2182
1861
|
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
2183
1862
|
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
2184
1863
|
if (!exists) {
|
|
2185
|
-
const
|
|
1864
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
2186
1865
|
onUpdate({
|
|
2187
1866
|
id: comment.id,
|
|
2188
|
-
cursor
|
|
1867
|
+
cursor
|
|
2189
1868
|
});
|
|
2190
1869
|
}
|
|
2191
1870
|
}
|
|
@@ -2197,7 +1876,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
|
2197
1876
|
from: changes.mapPos(comment.from, 1),
|
|
2198
1877
|
to: changes.mapPos(comment.to, 1)
|
|
2199
1878
|
});
|
|
2200
|
-
var restoreCommentEffect =
|
|
1879
|
+
var restoreCommentEffect = StateEffect3.define({
|
|
2201
1880
|
map: mapTrackedComment
|
|
2202
1881
|
});
|
|
2203
1882
|
var createComment = (view) => {
|
|
@@ -2214,13 +1893,13 @@ var createComment = (view) => {
|
|
|
2214
1893
|
}
|
|
2215
1894
|
});
|
|
2216
1895
|
}
|
|
2217
|
-
const
|
|
1896
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
2218
1897
|
from,
|
|
2219
1898
|
to
|
|
2220
1899
|
});
|
|
2221
|
-
if (
|
|
1900
|
+
if (cursor) {
|
|
2222
1901
|
options.onCreate?.({
|
|
2223
|
-
cursor
|
|
1902
|
+
cursor,
|
|
2224
1903
|
from,
|
|
2225
1904
|
location: view.coordsAtPos(from)
|
|
2226
1905
|
});
|
|
@@ -2283,7 +1962,7 @@ var comments = (options = {}) => {
|
|
|
2283
1962
|
//
|
|
2284
1963
|
// Track deleted ranges and update ranges for decorations.
|
|
2285
1964
|
//
|
|
2286
|
-
|
|
1965
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
|
2287
1966
|
let mod = false;
|
|
2288
1967
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
2289
1968
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -2315,7 +1994,7 @@ var comments = (options = {}) => {
|
|
|
2315
1994
|
//
|
|
2316
1995
|
// Track selection/proximity.
|
|
2317
1996
|
//
|
|
2318
|
-
|
|
1997
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
|
2319
1998
|
let min = Infinity;
|
|
2320
1999
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
2321
2000
|
const { head } = state.selection.main;
|
|
@@ -2369,7 +2048,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
|
2369
2048
|
anchor: range.from
|
|
2370
2049
|
} : void 0,
|
|
2371
2050
|
effects: [
|
|
2372
|
-
needsScroll ?
|
|
2051
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
|
2373
2052
|
y: "center"
|
|
2374
2053
|
} : void 0) : [],
|
|
2375
2054
|
needsSelectionUpdate ? setSelection.of({
|
|
@@ -2400,7 +2079,7 @@ var ExternalCommentSync = class {
|
|
|
2400
2079
|
this.unsubscribe();
|
|
2401
2080
|
};
|
|
2402
2081
|
};
|
|
2403
|
-
var createExternalCommentSync = (id, subscribe, getComments) =>
|
|
2082
|
+
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin8.fromClass(class {
|
|
2404
2083
|
constructor(view) {
|
|
2405
2084
|
return new ExternalCommentSync(view, id, subscribe, getComments);
|
|
2406
2085
|
}
|
|
@@ -2420,12 +2099,12 @@ var debugNodeLogger = (log12 = console.log) => {
|
|
|
2420
2099
|
};
|
|
2421
2100
|
|
|
2422
2101
|
// src/extensions/dnd.ts
|
|
2423
|
-
import { EditorView as
|
|
2102
|
+
import { EditorView as EditorView10, dropCursor } from "@codemirror/view";
|
|
2424
2103
|
var dropFile = (options = {}) => {
|
|
2425
2104
|
return [
|
|
2426
2105
|
styles3,
|
|
2427
2106
|
dropCursor(),
|
|
2428
|
-
|
|
2107
|
+
EditorView10.domEventHandlers({
|
|
2429
2108
|
drop: (event, view) => {
|
|
2430
2109
|
event.preventDefault();
|
|
2431
2110
|
const files = event.dataTransfer?.files;
|
|
@@ -2444,7 +2123,7 @@ var dropFile = (options = {}) => {
|
|
|
2444
2123
|
})
|
|
2445
2124
|
];
|
|
2446
2125
|
};
|
|
2447
|
-
var styles3 =
|
|
2126
|
+
var styles3 = EditorView10.theme({
|
|
2448
2127
|
".cm-dropCursor": {
|
|
2449
2128
|
borderLeft: "2px solid var(--color-accent-text)",
|
|
2450
2129
|
color: "var(--color-accent-text)",
|
|
@@ -2461,40 +2140,40 @@ import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap }
|
|
|
2461
2140
|
import { HighlightStyle, bracketMatching, syntaxHighlighting } from "@codemirror/language";
|
|
2462
2141
|
import { searchKeymap } from "@codemirror/search";
|
|
2463
2142
|
import { EditorState } from "@codemirror/state";
|
|
2464
|
-
import { EditorView as
|
|
2143
|
+
import { EditorView as EditorView16, ViewPlugin as ViewPlugin12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap7, lineNumbers, placeholder as placeholder2 } from "@codemirror/view";
|
|
2465
2144
|
import { vscodeDarkStyle, vscodeLightStyle } from "@uiw/codemirror-theme-vscode";
|
|
2466
2145
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
2467
2146
|
import { generateName } from "@dxos/display-name";
|
|
2468
2147
|
import { log as log8 } from "@dxos/log";
|
|
2469
|
-
import { hexToHue, isTruthy as
|
|
2148
|
+
import { hexToHue, isTruthy as isTruthy3 } from "@dxos/util";
|
|
2470
2149
|
|
|
2471
2150
|
// src/styles/theme.ts
|
|
2472
|
-
import { EditorView as
|
|
2151
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
2473
2152
|
import { mx as mx3 } from "@dxos/ui-theme";
|
|
2474
2153
|
var headings = {
|
|
2475
2154
|
1: {
|
|
2476
|
-
className: "text-
|
|
2477
|
-
fontSize: "var(--text-
|
|
2155
|
+
className: "text-3xl",
|
|
2156
|
+
fontSize: "var(--text-3xl)",
|
|
2478
2157
|
lineHeight: "var(--text-4xl--line-height)"
|
|
2479
2158
|
},
|
|
2480
2159
|
2: {
|
|
2481
|
-
className: "text-
|
|
2482
|
-
fontSize: "var(--text-
|
|
2160
|
+
className: "text-2xl",
|
|
2161
|
+
fontSize: "var(--text-2xl)",
|
|
2483
2162
|
lineHeight: "var(--text-3xl--line-height)"
|
|
2484
2163
|
},
|
|
2485
2164
|
3: {
|
|
2486
|
-
className: "text-
|
|
2487
|
-
fontSize: "var(--text-
|
|
2165
|
+
className: "text-xl",
|
|
2166
|
+
fontSize: "var(--text-xl)",
|
|
2488
2167
|
lineHeight: "var(--text-2xl--line-height)"
|
|
2489
2168
|
},
|
|
2490
2169
|
4: {
|
|
2491
|
-
className: "text-
|
|
2492
|
-
fontSize: "var(--text-
|
|
2170
|
+
className: "text-lg",
|
|
2171
|
+
fontSize: "var(--text-lg)",
|
|
2493
2172
|
lineHeight: "var(--text-xl--line-height)"
|
|
2494
2173
|
},
|
|
2495
2174
|
5: {
|
|
2496
|
-
className: "text-
|
|
2497
|
-
fontSize: "var(--text-
|
|
2175
|
+
className: "text-base",
|
|
2176
|
+
fontSize: "var(--text-base)",
|
|
2498
2177
|
lineHeight: "var(--text-lg--line-height)"
|
|
2499
2178
|
},
|
|
2500
2179
|
6: {
|
|
@@ -2503,21 +2182,21 @@ var headings = {
|
|
|
2503
2182
|
lineHeight: "var(--text-base--line-height)"
|
|
2504
2183
|
}
|
|
2505
2184
|
};
|
|
2185
|
+
var fontBody = '"Inter Variable", ui-sans-serif, system-ui, sans-serif';
|
|
2186
|
+
var fontMono = '"JetBrains Mono Variable", ui-monospace, "Cascadia Code", "Source Code Pro", monospace';
|
|
2506
2187
|
var markdownTheme = {
|
|
2507
|
-
code: "font-mono
|
|
2508
|
-
codeMark: "font-mono
|
|
2509
|
-
mark: "
|
|
2188
|
+
code: "font-mono! cm-code-inline",
|
|
2189
|
+
codeMark: "font-mono! cm-code-mark",
|
|
2190
|
+
mark: "font-mono!",
|
|
2510
2191
|
heading: (level) => ({
|
|
2511
|
-
className: mx3(headings[level].className, "font-light text-cm-heading"),
|
|
2192
|
+
className: mx3(headings[level].className, "font-light text-(--color-cm-heading-number)"),
|
|
2512
2193
|
color: "var(--color-cm-heading) !important",
|
|
2513
2194
|
lineHeight: headings[level].lineHeight,
|
|
2514
2195
|
fontSize: headings[level].fontSize,
|
|
2515
2196
|
fontWeight: "100 !important"
|
|
2516
2197
|
})
|
|
2517
2198
|
};
|
|
2518
|
-
var
|
|
2519
|
-
var fontMono = "JetBrains Mono Variable, ui-monospace, Cascadia Code, Source Code Pro, monospace";
|
|
2520
|
-
var baseTheme = EditorView13.baseTheme({
|
|
2199
|
+
var baseTheme = EditorView11.baseTheme({
|
|
2521
2200
|
/**
|
|
2522
2201
|
* Outer frame.
|
|
2523
2202
|
*/
|
|
@@ -2529,12 +2208,21 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2529
2208
|
* Scroller
|
|
2530
2209
|
*/
|
|
2531
2210
|
".cm-scroller": {
|
|
2532
|
-
|
|
2211
|
+
// Browser scroll-anchoring: see comment in `scrolling/crawler.ts`. `auto` lets the browser pin a
|
|
2212
|
+
// stable element near the viewport top so widget resizes (e.g. tool-block TogglePanel
|
|
2213
|
+
// open/close) don't jump the user's view.
|
|
2214
|
+
overflowAnchor: "auto"
|
|
2533
2215
|
},
|
|
2534
2216
|
".cm-scroller::-webkit-scrollbar": {
|
|
2535
|
-
width: "8px"
|
|
2217
|
+
width: "var(--scrollbar-size,8px)",
|
|
2218
|
+
height: "var(--scrollbar-size,8px)"
|
|
2219
|
+
},
|
|
2220
|
+
".cm-scroller::-webkit-scrollbar-corner": {
|
|
2221
|
+
background: "transparent"
|
|
2222
|
+
},
|
|
2223
|
+
".cm-scroller::-webkit-scrollbar-track": {
|
|
2224
|
+
background: "transparent"
|
|
2536
2225
|
},
|
|
2537
|
-
".cm-scroller::-webkit-scrollbar-track": {},
|
|
2538
2226
|
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
2539
2227
|
background: "transparent",
|
|
2540
2228
|
transition: "background 0.15s"
|
|
@@ -2548,7 +2236,6 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2548
2236
|
*/
|
|
2549
2237
|
".cm-content": {
|
|
2550
2238
|
padding: "unset",
|
|
2551
|
-
lineHeight: "24px",
|
|
2552
2239
|
color: "unset"
|
|
2553
2240
|
},
|
|
2554
2241
|
/**
|
|
@@ -2579,9 +2266,16 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2579
2266
|
* Line.
|
|
2580
2267
|
*/
|
|
2581
2268
|
".cm-line": {
|
|
2582
|
-
lineHeight:
|
|
2269
|
+
lineHeight: 1.5,
|
|
2583
2270
|
paddingInline: 0
|
|
2584
2271
|
},
|
|
2272
|
+
/**
|
|
2273
|
+
* Force all inline children to inherit line-height to prevent monospace font metrics
|
|
2274
|
+
* (JetBrains Mono ascent/descent) from inflating the line box beyond 24px.
|
|
2275
|
+
*/
|
|
2276
|
+
".cm-line *": {
|
|
2277
|
+
lineHeight: "inherit"
|
|
2278
|
+
},
|
|
2585
2279
|
".cm-activeLine": {
|
|
2586
2280
|
background: "var(--color-cm-active-line)"
|
|
2587
2281
|
},
|
|
@@ -2625,7 +2319,8 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2625
2319
|
textDecorationThickness: "1px",
|
|
2626
2320
|
textDecorationColor: "var(--color-separator)",
|
|
2627
2321
|
textUnderlineOffset: "2px",
|
|
2628
|
-
borderRadius: ".125rem"
|
|
2322
|
+
borderRadius: ".125rem",
|
|
2323
|
+
cursor: "pointer"
|
|
2629
2324
|
},
|
|
2630
2325
|
".cm-link > span": {
|
|
2631
2326
|
color: "var(--color-accent-text)"
|
|
@@ -2663,12 +2358,12 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2663
2358
|
padding: "4px"
|
|
2664
2359
|
},
|
|
2665
2360
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
|
|
2666
|
-
background: "var(--color-
|
|
2667
|
-
color: "var(--color-base-
|
|
2361
|
+
background: "var(--color-current-surface)",
|
|
2362
|
+
color: "var(--color-base-foreground)"
|
|
2668
2363
|
},
|
|
2669
2364
|
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
|
2670
2365
|
paddingLeft: "4px !important",
|
|
2671
|
-
color: "var(--color-base-
|
|
2366
|
+
color: "var(--color-base-foreground)"
|
|
2672
2367
|
},
|
|
2673
2368
|
/**
|
|
2674
2369
|
* Completion info.
|
|
@@ -2687,7 +2382,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2687
2382
|
padding: "0 4px"
|
|
2688
2383
|
},
|
|
2689
2384
|
".cm-completionMatchedText": {
|
|
2690
|
-
color: "var(--color-base-
|
|
2385
|
+
color: "var(--color-base-foreground)",
|
|
2691
2386
|
textDecoration: "none !important"
|
|
2692
2387
|
},
|
|
2693
2388
|
/**
|
|
@@ -2722,7 +2417,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2722
2417
|
backgroundColor: "var(--color-input-surface)"
|
|
2723
2418
|
},
|
|
2724
2419
|
".cm-panel input:focus, .cm-panel button:focus": {
|
|
2725
|
-
outline: "1px solid var(--color-
|
|
2420
|
+
outline: "1px solid var(--color-focus-ring-subtle)"
|
|
2726
2421
|
},
|
|
2727
2422
|
".cm-panel label": {
|
|
2728
2423
|
display: "inline-flex",
|
|
@@ -2735,7 +2430,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2735
2430
|
height: "8px",
|
|
2736
2431
|
marginRight: "6px !important",
|
|
2737
2432
|
padding: "2px !important",
|
|
2738
|
-
color: "var(--color-
|
|
2433
|
+
color: "var(--color-focus-ring-subtle)"
|
|
2739
2434
|
},
|
|
2740
2435
|
".cm-panel button": {
|
|
2741
2436
|
"&:hover": {
|
|
@@ -2751,18 +2446,17 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2751
2446
|
borderTop: "1px solid var(--color-separator)"
|
|
2752
2447
|
}
|
|
2753
2448
|
});
|
|
2754
|
-
var editorGutter =
|
|
2449
|
+
var editorGutter = EditorView11.theme({
|
|
2755
2450
|
".cm-gutters": {
|
|
2756
2451
|
// NOTE: Non-transparent background required to cover content if scrolling horizontally.
|
|
2757
2452
|
background: "var(--color-base-surface) !important",
|
|
2758
2453
|
paddingRight: "1rem"
|
|
2759
2454
|
}
|
|
2760
2455
|
});
|
|
2761
|
-
var createFontTheme = ({ monospace } = {}) =>
|
|
2762
|
-
//
|
|
2456
|
+
var createFontTheme = ({ monospace } = {}) => EditorView11.theme({
|
|
2457
|
+
// Main content.
|
|
2763
2458
|
".cm-scroller": {
|
|
2764
|
-
fontFamily: monospace ? fontMono : fontBody
|
|
2765
|
-
fontSize: "16px"
|
|
2459
|
+
fontFamily: monospace ? fontMono : fontBody
|
|
2766
2460
|
},
|
|
2767
2461
|
// Maintain defaults for UI components.
|
|
2768
2462
|
".cm-content, .cm-gutters, .cm-panel": {
|
|
@@ -2772,9 +2466,9 @@ var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
|
|
|
2772
2466
|
});
|
|
2773
2467
|
|
|
2774
2468
|
// src/extensions/focus.ts
|
|
2775
|
-
import { StateEffect as
|
|
2776
|
-
import { EditorView as
|
|
2777
|
-
var focusEffect =
|
|
2469
|
+
import { StateEffect as StateEffect4, StateField as StateField5 } from "@codemirror/state";
|
|
2470
|
+
import { EditorView as EditorView12 } from "@codemirror/view";
|
|
2471
|
+
var focusEffect = StateEffect4.define();
|
|
2778
2472
|
var focusField = StateField5.define({
|
|
2779
2473
|
create: () => false,
|
|
2780
2474
|
update: (value, tr) => {
|
|
@@ -2788,7 +2482,7 @@ var focusField = StateField5.define({
|
|
|
2788
2482
|
});
|
|
2789
2483
|
var focus = [
|
|
2790
2484
|
focusField,
|
|
2791
|
-
|
|
2485
|
+
EditorView12.domEventHandlers({
|
|
2792
2486
|
focus: (_event, view) => {
|
|
2793
2487
|
requestAnimationFrame(() => view.dispatch({
|
|
2794
2488
|
effects: focusEffect.of(true)
|
|
@@ -2802,9 +2496,388 @@ var focus = [
|
|
|
2802
2496
|
})
|
|
2803
2497
|
];
|
|
2804
2498
|
|
|
2499
|
+
// src/extensions/scrolling/auto-scroll.ts
|
|
2500
|
+
import { StateEffect as StateEffect6 } from "@codemirror/state";
|
|
2501
|
+
import { EditorView as EditorView14, ViewPlugin as ViewPlugin10 } from "@codemirror/view";
|
|
2502
|
+
import { addEventListener, combine, throttle as throttle2 } from "@dxos/async";
|
|
2503
|
+
import { Domino } from "@dxos/ui";
|
|
2504
|
+
import { getSize } from "@dxos/ui-theme";
|
|
2505
|
+
|
|
2506
|
+
// src/extensions/scrolling/crawler.ts
|
|
2507
|
+
import { StateEffect as StateEffect5 } from "@codemirror/state";
|
|
2508
|
+
import { EditorView as EditorView13, ViewPlugin as ViewPlugin9 } from "@codemirror/view";
|
|
2509
|
+
import { log as log7 } from "@dxos/log";
|
|
2510
|
+
var __dxlog_file10 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/scrolling/crawler.ts";
|
|
2511
|
+
var crawlerLineEffect = StateEffect5.define();
|
|
2512
|
+
var crawlerActiveEffect = StateEffect5.define();
|
|
2513
|
+
var scrollToLine = (view, options) => {
|
|
2514
|
+
view.dispatch({
|
|
2515
|
+
effects: crawlerLineEffect.of(options)
|
|
2516
|
+
});
|
|
2517
|
+
};
|
|
2518
|
+
var crawler = ({ overScroll = 0 } = {}) => {
|
|
2519
|
+
const crawlerPlugin = ViewPlugin9.fromClass(class CrawlerPlugin {
|
|
2520
|
+
view;
|
|
2521
|
+
crawler;
|
|
2522
|
+
constructor(view) {
|
|
2523
|
+
this.view = view;
|
|
2524
|
+
this.crawler = createCrawler(this.view);
|
|
2525
|
+
}
|
|
2526
|
+
// No-op.
|
|
2527
|
+
destroy() {
|
|
2528
|
+
this.crawler.cancel();
|
|
2529
|
+
}
|
|
2530
|
+
cancel() {
|
|
2531
|
+
this.crawler.cancel();
|
|
2532
|
+
}
|
|
2533
|
+
crawl(start = false) {
|
|
2534
|
+
if (start) {
|
|
2535
|
+
this.crawler.scroll();
|
|
2536
|
+
} else {
|
|
2537
|
+
this.crawler.cancel();
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
scroll({ line, offset = 0, position, behavior = "instant" }) {
|
|
2541
|
+
const { scrollTop, scrollHeight, clientHeight } = this.view.scrollDOM;
|
|
2542
|
+
const scrollerRect = this.view.scrollDOM.getBoundingClientRect();
|
|
2543
|
+
const doc = this.view.state.doc;
|
|
2544
|
+
let targetScrollTop = scrollHeight - clientHeight + offset;
|
|
2545
|
+
if (line >= 0 && line <= doc.lines - 1) {
|
|
2546
|
+
const lineStart = doc.line(line + 1).from;
|
|
2547
|
+
const coords = this.view.coordsAtPos(lineStart);
|
|
2548
|
+
if (coords) {
|
|
2549
|
+
const currentScrollTop = scrollTop;
|
|
2550
|
+
const maxScrollTop = scrollHeight - clientHeight;
|
|
2551
|
+
if (position === "end") {
|
|
2552
|
+
targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + offset;
|
|
2553
|
+
} else {
|
|
2554
|
+
targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + offset;
|
|
2555
|
+
}
|
|
2556
|
+
targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
requestAnimationFrame(() => {
|
|
2560
|
+
this.view.scrollDOM.scrollTo({
|
|
2561
|
+
top: targetScrollTop
|
|
2562
|
+
});
|
|
2563
|
+
});
|
|
2564
|
+
}
|
|
2565
|
+
});
|
|
2566
|
+
return [
|
|
2567
|
+
crawlerPlugin,
|
|
2568
|
+
// Listen for effect.
|
|
2569
|
+
EditorView13.updateListener.of((update2) => {
|
|
2570
|
+
update2.transactions.forEach((transaction) => {
|
|
2571
|
+
try {
|
|
2572
|
+
const plugin = update2.view.plugin(crawlerPlugin);
|
|
2573
|
+
if (plugin) {
|
|
2574
|
+
for (const effect of transaction.effects) {
|
|
2575
|
+
if (effect.is(crawlerActiveEffect)) {
|
|
2576
|
+
plugin.crawl(effect.value);
|
|
2577
|
+
} else if (effect.is(crawlerLineEffect)) {
|
|
2578
|
+
plugin.scroll(effect.value);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
} catch (err) {
|
|
2583
|
+
log7.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file10, L: 98, S: void 0 });
|
|
2584
|
+
}
|
|
2585
|
+
});
|
|
2586
|
+
}),
|
|
2587
|
+
// Styles.
|
|
2588
|
+
EditorView13.theme({
|
|
2589
|
+
".cm-scroller": {
|
|
2590
|
+
overflowY: "scroll",
|
|
2591
|
+
// Browser scroll-anchoring: when widgets above the viewport resize (e.g. tool blocks
|
|
2592
|
+
// expanding their TogglePanel), the browser picks a stable element near the viewport
|
|
2593
|
+
// top and adjusts `scrollTop` so the user's view doesn't jump. Auto-scroll's pinning
|
|
2594
|
+
// logic still has the final word when pinned (forces scrollTop to scrollHeight).
|
|
2595
|
+
overflowAnchor: "auto"
|
|
2596
|
+
},
|
|
2597
|
+
".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
|
|
2598
|
+
display: "none"
|
|
2599
|
+
},
|
|
2600
|
+
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
2601
|
+
background: "transparent",
|
|
2602
|
+
transition: "background 0.15s"
|
|
2603
|
+
},
|
|
2604
|
+
"&:hover .cm-scroller::-webkit-scrollbar-thumb": {
|
|
2605
|
+
background: "var(--color-scrollbar-thumb)"
|
|
2606
|
+
},
|
|
2607
|
+
// Spacer below the last text line. Implemented as a real block pseudo-element
|
|
2608
|
+
// (rather than `padding-bottom` on `.cm-content`) so it materializes in the
|
|
2609
|
+
// scroller's `scrollHeight` regardless of how `padding` is reset by the base
|
|
2610
|
+
// theme or downstream classes — this is what gives auto-scroll its head-room
|
|
2611
|
+
// so the last line stays `overScroll` px above the viewport bottom.
|
|
2612
|
+
".cm-content::after": {
|
|
2613
|
+
content: '""',
|
|
2614
|
+
display: "block",
|
|
2615
|
+
height: `${overScroll}px`
|
|
2616
|
+
},
|
|
2617
|
+
".cm-scroll-button": {
|
|
2618
|
+
position: "absolute",
|
|
2619
|
+
bottom: "0.5rem",
|
|
2620
|
+
right: "1rem"
|
|
2621
|
+
}
|
|
2622
|
+
})
|
|
2623
|
+
];
|
|
2624
|
+
};
|
|
2625
|
+
function createCrawler(view, omega = 5, snapThreshold = 5, snapVelocity = 50) {
|
|
2626
|
+
const el = view.scrollDOM;
|
|
2627
|
+
let currentTop = 0;
|
|
2628
|
+
let velocity = 0;
|
|
2629
|
+
let rafId = null;
|
|
2630
|
+
let lastTime = 0;
|
|
2631
|
+
function frame(now) {
|
|
2632
|
+
const dt = lastTime === 0 ? 1 / 60 : Math.min(0.1, (now - lastTime) / 1e3);
|
|
2633
|
+
lastTime = now;
|
|
2634
|
+
const targetTop = el.scrollHeight - el.clientHeight;
|
|
2635
|
+
const delta = targetTop - currentTop;
|
|
2636
|
+
if (Math.abs(delta) < snapThreshold && Math.abs(velocity) < snapVelocity) {
|
|
2637
|
+
el.scrollTop = targetTop;
|
|
2638
|
+
currentTop = targetTop;
|
|
2639
|
+
velocity = 0;
|
|
2640
|
+
rafId = null;
|
|
2641
|
+
lastTime = 0;
|
|
2642
|
+
return;
|
|
2643
|
+
}
|
|
2644
|
+
const accel = omega * omega * delta - 2 * omega * velocity;
|
|
2645
|
+
velocity += accel * dt;
|
|
2646
|
+
currentTop += velocity * dt;
|
|
2647
|
+
el.scrollTop = currentTop;
|
|
2648
|
+
rafId = requestAnimationFrame(frame);
|
|
2649
|
+
}
|
|
2650
|
+
return {
|
|
2651
|
+
scroll: () => {
|
|
2652
|
+
if (rafId === null) {
|
|
2653
|
+
currentTop = el.scrollTop;
|
|
2654
|
+
lastTime = 0;
|
|
2655
|
+
rafId = requestAnimationFrame(frame);
|
|
2656
|
+
}
|
|
2657
|
+
},
|
|
2658
|
+
cancel: () => {
|
|
2659
|
+
if (rafId !== null) {
|
|
2660
|
+
cancelAnimationFrame(rafId);
|
|
2661
|
+
velocity = 0;
|
|
2662
|
+
lastTime = 0;
|
|
2663
|
+
rafId = null;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
// src/extensions/scrolling/auto-scroll.ts
|
|
2670
|
+
var autoScrollEffect = StateEffect6.define();
|
|
2671
|
+
var autoScroll = ({ scrollOnResize = true } = {}) => {
|
|
2672
|
+
let buttonContainer;
|
|
2673
|
+
let isPinned = true;
|
|
2674
|
+
let jumpPending = false;
|
|
2675
|
+
let enabled = true;
|
|
2676
|
+
let firstUpdate = true;
|
|
2677
|
+
const setPinned = (pinned) => {
|
|
2678
|
+
buttonContainer?.classList.toggle("opacity-0", pinned);
|
|
2679
|
+
isPinned = pinned;
|
|
2680
|
+
};
|
|
2681
|
+
return [
|
|
2682
|
+
// Update listener for scrolling when content changes.
|
|
2683
|
+
EditorView14.updateListener.of((update2) => {
|
|
2684
|
+
const { view, heightChanged, state, startState } = update2;
|
|
2685
|
+
for (const tr of update2.transactions) {
|
|
2686
|
+
for (const effect of tr.effects) {
|
|
2687
|
+
if (effect.is(autoScrollEffect)) {
|
|
2688
|
+
enabled = effect.value;
|
|
2689
|
+
if (enabled) {
|
|
2690
|
+
setPinned(true);
|
|
2691
|
+
view.dispatch({
|
|
2692
|
+
effects: crawlerActiveEffect.of(true)
|
|
2693
|
+
});
|
|
2694
|
+
} else {
|
|
2695
|
+
view.dispatch({
|
|
2696
|
+
effects: crawlerActiveEffect.of(false)
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
if (!enabled) {
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
if (isPinned && (firstUpdate || startState.doc.length === 0) && state.doc.length > 0) {
|
|
2706
|
+
firstUpdate = false;
|
|
2707
|
+
jumpPending = true;
|
|
2708
|
+
requestAnimationFrame(() => {
|
|
2709
|
+
view.scrollDOM.scrollTop = view.scrollDOM.scrollHeight;
|
|
2710
|
+
jumpPending = false;
|
|
2711
|
+
});
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2714
|
+
firstUpdate = false;
|
|
2715
|
+
if (jumpPending) {
|
|
2716
|
+
return;
|
|
2717
|
+
}
|
|
2718
|
+
if (heightChanged) {
|
|
2719
|
+
if (isPinned) {
|
|
2720
|
+
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
2721
|
+
const delta = scrollHeight - scrollTop - clientHeight;
|
|
2722
|
+
if (delta > 0) {
|
|
2723
|
+
setPinned(true);
|
|
2724
|
+
view.dispatch({
|
|
2725
|
+
effects: crawlerActiveEffect.of(true)
|
|
2726
|
+
});
|
|
2727
|
+
} else if (delta < -1) {
|
|
2728
|
+
setPinned(false);
|
|
2729
|
+
}
|
|
2730
|
+
} else {
|
|
2731
|
+
if (state.doc.length === 0) {
|
|
2732
|
+
setPinned(true);
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
}),
|
|
2737
|
+
// Re-pin and jump to bottom when the scroll container itself resizes (e.g. sidebar toggle,
|
|
2738
|
+
// window resize). Doc-driven height changes are handled by the updateListener above; this
|
|
2739
|
+
// observer covers the case where the viewport changes while the doc length is unchanged.
|
|
2740
|
+
scrollOnResize ? ViewPlugin10.fromClass(class {
|
|
2741
|
+
observer;
|
|
2742
|
+
firstObservation = true;
|
|
2743
|
+
destroyed = false;
|
|
2744
|
+
constructor(view) {
|
|
2745
|
+
const onResize = throttle2(() => {
|
|
2746
|
+
if (this.destroyed || !enabled) {
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2749
|
+
setPinned(true);
|
|
2750
|
+
requestAnimationFrame(() => {
|
|
2751
|
+
if (this.destroyed) {
|
|
2752
|
+
return;
|
|
2753
|
+
}
|
|
2754
|
+
view.scrollDOM.scrollTo({
|
|
2755
|
+
top: view.scrollDOM.scrollHeight,
|
|
2756
|
+
behavior: "instant"
|
|
2757
|
+
});
|
|
2758
|
+
view.dispatch({
|
|
2759
|
+
effects: crawlerActiveEffect.of(false)
|
|
2760
|
+
});
|
|
2761
|
+
});
|
|
2762
|
+
}, 50);
|
|
2763
|
+
this.observer = new ResizeObserver(() => {
|
|
2764
|
+
if (this.firstObservation) {
|
|
2765
|
+
this.firstObservation = false;
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
onResize();
|
|
2769
|
+
});
|
|
2770
|
+
this.observer.observe(view.scrollDOM);
|
|
2771
|
+
}
|
|
2772
|
+
destroy() {
|
|
2773
|
+
this.destroyed = true;
|
|
2774
|
+
this.observer.disconnect();
|
|
2775
|
+
}
|
|
2776
|
+
}) : [],
|
|
2777
|
+
// Detect user scroll and unpin (or re-pin if scrolled to the bottom).
|
|
2778
|
+
ViewPlugin10.fromClass(class {
|
|
2779
|
+
cleanup;
|
|
2780
|
+
constructor(view) {
|
|
2781
|
+
const onUserScroll = throttle2(() => {
|
|
2782
|
+
requestAnimationFrame(() => {
|
|
2783
|
+
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
2784
|
+
const delta = scrollHeight - scrollTop - clientHeight;
|
|
2785
|
+
const pinned = Math.abs(delta) <= 1;
|
|
2786
|
+
setPinned(pinned);
|
|
2787
|
+
if (!pinned) {
|
|
2788
|
+
view.dispatch({
|
|
2789
|
+
effects: crawlerActiveEffect.of(false)
|
|
2790
|
+
});
|
|
2791
|
+
}
|
|
2792
|
+
});
|
|
2793
|
+
}, 500);
|
|
2794
|
+
this.cleanup = createUserScrollDetector(view.scrollDOM, () => {
|
|
2795
|
+
if (isPinned) {
|
|
2796
|
+
setPinned(false);
|
|
2797
|
+
view.dispatch({
|
|
2798
|
+
effects: crawlerActiveEffect.of(false)
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2801
|
+
onUserScroll();
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
destroy() {
|
|
2805
|
+
this.cleanup();
|
|
2806
|
+
}
|
|
2807
|
+
}),
|
|
2808
|
+
// Scroll button.
|
|
2809
|
+
ViewPlugin10.fromClass(class {
|
|
2810
|
+
constructor(view) {
|
|
2811
|
+
const icon = Domino.of("dx-icon").classNames(getSize(4)).attributes({
|
|
2812
|
+
icon: "ph--arrow-down--regular"
|
|
2813
|
+
});
|
|
2814
|
+
const button = Domino.of("button").classNames("dx-button bg-accent-surface").attributes({
|
|
2815
|
+
"data-density": "fine"
|
|
2816
|
+
}).append(icon).on("click", () => {
|
|
2817
|
+
setPinned(true);
|
|
2818
|
+
view.dispatch({
|
|
2819
|
+
effects: crawlerLineEffect.of({
|
|
2820
|
+
line: -1,
|
|
2821
|
+
position: "end",
|
|
2822
|
+
behavior: "smooth"
|
|
2823
|
+
})
|
|
2824
|
+
});
|
|
2825
|
+
});
|
|
2826
|
+
buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").append(button).root;
|
|
2827
|
+
view.scrollDOM.parentElement.appendChild(buttonContainer);
|
|
2828
|
+
}
|
|
2829
|
+
})
|
|
2830
|
+
];
|
|
2831
|
+
};
|
|
2832
|
+
function createUserScrollDetector(element, onUserScroll) {
|
|
2833
|
+
return combine(addEventListener(element, "wheel", () => onUserScroll(), {
|
|
2834
|
+
passive: true
|
|
2835
|
+
}), addEventListener(element, "pointerdown", (event) => {
|
|
2836
|
+
if (event.clientX > element.getBoundingClientRect().right - (element.offsetWidth - element.clientWidth)) {
|
|
2837
|
+
onUserScroll();
|
|
2838
|
+
}
|
|
2839
|
+
}));
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
// src/extensions/scrolling/scroll-past-end.ts
|
|
2843
|
+
import { EditorView as EditorView15, ViewPlugin as ViewPlugin11 } from "@codemirror/view";
|
|
2844
|
+
var scrollPastEndPlugin = ViewPlugin11.fromClass(class {
|
|
2845
|
+
_height = 1e3;
|
|
2846
|
+
_attrs = {
|
|
2847
|
+
style: `padding-bottom: ${this._height}px`
|
|
2848
|
+
};
|
|
2849
|
+
update({ view }) {
|
|
2850
|
+
const lastLineBlock = view.lineBlockAt(view.state.doc.length);
|
|
2851
|
+
const height = view.dom.clientHeight - lastLineBlock.height - view.documentPadding.top - 0.5;
|
|
2852
|
+
if (height >= 0 && height !== this._height) {
|
|
2853
|
+
this._height = height;
|
|
2854
|
+
this._attrs = {
|
|
2855
|
+
style: `padding-bottom: ${height}px`
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
});
|
|
2860
|
+
var scrollPastEnd = () => [
|
|
2861
|
+
scrollPastEndPlugin,
|
|
2862
|
+
EditorView15.contentAttributes.of((view) => view.plugin(scrollPastEndPlugin)?._attrs ?? null)
|
|
2863
|
+
];
|
|
2864
|
+
|
|
2865
|
+
// src/extensions/scrolling/scroller.ts
|
|
2866
|
+
import { isTruthy as isTruthy2 } from "@dxos/util";
|
|
2867
|
+
var scroller = ({ overScroll, scrollOnResize, autoScroll: autoScroll2 = true } = {}) => {
|
|
2868
|
+
return [
|
|
2869
|
+
crawler({
|
|
2870
|
+
overScroll
|
|
2871
|
+
}),
|
|
2872
|
+
autoScroll2 && autoScroll({
|
|
2873
|
+
scrollOnResize
|
|
2874
|
+
})
|
|
2875
|
+
].filter(isTruthy2);
|
|
2876
|
+
};
|
|
2877
|
+
|
|
2805
2878
|
// src/extensions/factories.ts
|
|
2806
2879
|
var __dxlog_file11 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/factories.ts";
|
|
2807
|
-
var tabbable =
|
|
2880
|
+
var tabbable = EditorView16.contentAttributes.of({
|
|
2808
2881
|
tabindex: "0"
|
|
2809
2882
|
});
|
|
2810
2883
|
var filterChars = (chars) => {
|
|
@@ -2857,13 +2930,8 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2857
2930
|
const props = defaultsDeep2({}, propsProp, defaultBasicOptions);
|
|
2858
2931
|
return [
|
|
2859
2932
|
// NOTE: Doesn't catch errors in keymap functions.
|
|
2860
|
-
|
|
2861
|
-
log8.catch(err, void 0, {
|
|
2862
|
-
F: __dxlog_file11,
|
|
2863
|
-
L: 131,
|
|
2864
|
-
S: void 0,
|
|
2865
|
-
C: (f, a) => f(...a)
|
|
2866
|
-
});
|
|
2933
|
+
EditorView16.exceptionSink.of((err) => {
|
|
2934
|
+
log8.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file11, L: 79, S: void 0 });
|
|
2867
2935
|
}),
|
|
2868
2936
|
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2869
2937
|
props.bracketMatching && bracketMatching(),
|
|
@@ -2872,7 +2940,7 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2872
2940
|
props.drawSelection && drawSelection({
|
|
2873
2941
|
cursorBlinkRate: 1200
|
|
2874
2942
|
}),
|
|
2875
|
-
props.editable !== void 0 &&
|
|
2943
|
+
props.editable !== void 0 && EditorView16.editable.of(props.editable),
|
|
2876
2944
|
props.focus && focus,
|
|
2877
2945
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2878
2946
|
props.history && history(),
|
|
@@ -2880,9 +2948,16 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2880
2948
|
lineNumbers(),
|
|
2881
2949
|
editorGutter
|
|
2882
2950
|
],
|
|
2883
|
-
props.lineWrapping &&
|
|
2951
|
+
props.lineWrapping && EditorView16.lineWrapping,
|
|
2884
2952
|
props.placeholder && placeholder2(props.placeholder),
|
|
2885
2953
|
props.readOnly !== void 0 && EditorState.readOnly.of(props.readOnly),
|
|
2954
|
+
// `EditorState.readOnly` is advisory — CodeMirror doesn't auto-reject doc-changing
|
|
2955
|
+
// transactions. Some extensions (e.g. `@codemirror/lang-markdown`'s Enter handler that
|
|
2956
|
+
// continues a list) dispatch programmatic edits regardless. Drop user-initiated edits
|
|
2957
|
+
// (`input` / `delete` keymap dispatches plus `undo` / `redo` from the history extension)
|
|
2958
|
+
// but pass programmatic dispatches — streaming `MarkdownStream` and similar consumers
|
|
2959
|
+
// depend on being able to populate the doc themselves.
|
|
2960
|
+
props.readOnly && EditorState.transactionFilter.of((tr) => tr.docChanged && (tr.isUserEvent("input") || tr.isUserEvent("delete") || tr.isUserEvent("undo") || tr.isUserEvent("redo")) ? [] : tr),
|
|
2886
2961
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2887
2962
|
props.tabbable && tabbable,
|
|
2888
2963
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
@@ -2907,8 +2982,8 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2907
2982
|
preventDefault: true,
|
|
2908
2983
|
run: () => true
|
|
2909
2984
|
}
|
|
2910
|
-
].filter(
|
|
2911
|
-
].filter(
|
|
2985
|
+
].filter(isTruthy3))
|
|
2986
|
+
].filter(isTruthy3);
|
|
2912
2987
|
};
|
|
2913
2988
|
var grow = {
|
|
2914
2989
|
editor: {
|
|
@@ -2925,27 +3000,32 @@ var defaultStyles = {
|
|
|
2925
3000
|
dark: vscodeDarkStyle,
|
|
2926
3001
|
light: vscodeLightStyle
|
|
2927
3002
|
};
|
|
2928
|
-
var createThemeExtensions = ({ monospace,
|
|
3003
|
+
var createThemeExtensions = ({ monospace, scrollbarThin, slots: slotsProp, syntaxHighlighting: syntaxHighlightingProp, themeMode } = {}) => {
|
|
2929
3004
|
const slots = defaultsDeep2({}, slotsProp, defaultThemeSlots);
|
|
2930
3005
|
return [
|
|
2931
3006
|
baseTheme,
|
|
2932
|
-
|
|
3007
|
+
EditorView16.darkTheme.of(themeMode === "dark"),
|
|
2933
3008
|
createFontTheme({
|
|
2934
3009
|
monospace
|
|
2935
3010
|
}),
|
|
2936
3011
|
syntaxHighlightingProp && syntaxHighlighting(HighlightStyle.define(themeMode === "dark" ? defaultStyles.dark : defaultStyles.light)),
|
|
2937
|
-
slots.editor?.className &&
|
|
3012
|
+
slots.editor?.className && EditorView16.editorAttributes.of({
|
|
2938
3013
|
class: slots.editor.className
|
|
2939
3014
|
}),
|
|
2940
|
-
slots.content?.className &&
|
|
3015
|
+
slots.content?.className && EditorView16.contentAttributes.of({
|
|
2941
3016
|
class: slots.content.className
|
|
2942
3017
|
}),
|
|
2943
|
-
slots.
|
|
3018
|
+
(slots.scroller?.className || scrollbarThin) && ViewPlugin12.fromClass(class {
|
|
2944
3019
|
constructor(view) {
|
|
2945
|
-
|
|
3020
|
+
if (slots.scroller?.className) {
|
|
3021
|
+
view.scrollDOM.classList.add(...slots.scroller.className.split(/\s+/));
|
|
3022
|
+
}
|
|
3023
|
+
if (scrollbarThin) {
|
|
3024
|
+
view.scrollDOM.style.setProperty("--scrollbar-size", "4px");
|
|
3025
|
+
}
|
|
2946
3026
|
}
|
|
2947
3027
|
})
|
|
2948
|
-
].filter(
|
|
3028
|
+
].filter(isTruthy3);
|
|
2949
3029
|
};
|
|
2950
3030
|
var createDataExtensions = ({ id, text, messenger, identity }) => {
|
|
2951
3031
|
const extensions = [];
|
|
@@ -2971,7 +3051,7 @@ var createDataExtensions = ({ id, text, messenger, identity }) => {
|
|
|
2971
3051
|
|
|
2972
3052
|
// src/extensions/folding.ts
|
|
2973
3053
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
|
2974
|
-
import { EditorView as
|
|
3054
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
2975
3055
|
import { Domino as Domino2, mx as mx4 } from "@dxos/ui";
|
|
2976
3056
|
var folding = () => {
|
|
2977
3057
|
return [
|
|
@@ -2979,13 +3059,14 @@ var folding = () => {
|
|
|
2979
3059
|
placeholderDOM: () => Domino2.of("span").root
|
|
2980
3060
|
}),
|
|
2981
3061
|
foldGutter({
|
|
3062
|
+
// NOTE: We can't animate since the element is remounted on state change.
|
|
2982
3063
|
markerDOM: (open) => {
|
|
2983
|
-
return Domino2.of("div").classNames("flex h-full justify-center items-center").
|
|
3064
|
+
return Domino2.of("div").classNames("flex h-full justify-center items-center").append(Domino2.of("svg", Domino2.SVG).classNames(mx4("w-4 h-4 cursor-pointer", open && "rotate-90")).append(Domino2.of("use", Domino2.SVG).attributes({
|
|
2984
3065
|
href: Domino2.icon("ph--caret-right--regular")
|
|
2985
3066
|
}))).root;
|
|
2986
3067
|
}
|
|
2987
3068
|
}),
|
|
2988
|
-
|
|
3069
|
+
EditorView17.theme({
|
|
2989
3070
|
".cm-foldGutter": {
|
|
2990
3071
|
opacity: 0.3,
|
|
2991
3072
|
transition: "opacity 0.3s",
|
|
@@ -2999,7 +3080,7 @@ var folding = () => {
|
|
|
2999
3080
|
};
|
|
3000
3081
|
|
|
3001
3082
|
// src/extensions/hashtag.ts
|
|
3002
|
-
import { Decoration as Decoration8, EditorView as
|
|
3083
|
+
import { Decoration as Decoration8, EditorView as EditorView18, MatchDecorator, ViewPlugin as ViewPlugin13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3003
3084
|
import { getHashStyles, mx as mx5 } from "@dxos/ui-theme";
|
|
3004
3085
|
var TagWidget = class extends WidgetType4 {
|
|
3005
3086
|
_text;
|
|
@@ -3020,7 +3101,7 @@ var tagMatcher = new MatchDecorator({
|
|
|
3020
3101
|
})
|
|
3021
3102
|
});
|
|
3022
3103
|
var hashtag = () => [
|
|
3023
|
-
|
|
3104
|
+
ViewPlugin13.fromClass(class {
|
|
3024
3105
|
tags;
|
|
3025
3106
|
constructor(view) {
|
|
3026
3107
|
this.tags = tagMatcher.createDeco(view);
|
|
@@ -3030,11 +3111,11 @@ var hashtag = () => [
|
|
|
3030
3111
|
}
|
|
3031
3112
|
}, {
|
|
3032
3113
|
decorations: (instance) => instance.tags,
|
|
3033
|
-
provide: (plugin) =>
|
|
3114
|
+
provide: (plugin) => EditorView18.atomicRanges.of((view) => {
|
|
3034
3115
|
return view.plugin(plugin)?.tags || Decoration8.none;
|
|
3035
3116
|
})
|
|
3036
3117
|
}),
|
|
3037
|
-
|
|
3118
|
+
EditorView18.theme({
|
|
3038
3119
|
".cm-tag": {
|
|
3039
3120
|
borderRadius: "4px",
|
|
3040
3121
|
marginRight: "6px",
|
|
@@ -3089,18 +3170,18 @@ var schemaLinter = (validate) => (view) => {
|
|
|
3089
3170
|
};
|
|
3090
3171
|
|
|
3091
3172
|
// src/extensions/listener.ts
|
|
3092
|
-
import { EditorView as
|
|
3173
|
+
import { EditorView as EditorView19 } from "@codemirror/view";
|
|
3093
3174
|
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
3094
3175
|
var listener = ({ onFocus, onChange }) => {
|
|
3095
3176
|
return [
|
|
3096
|
-
onFocus &&
|
|
3177
|
+
onFocus && EditorView19.focusChangeEffect.of((state, focusing) => {
|
|
3097
3178
|
onFocus({
|
|
3098
3179
|
id: state.facet(documentId),
|
|
3099
3180
|
focusing
|
|
3100
3181
|
});
|
|
3101
3182
|
return null;
|
|
3102
3183
|
}),
|
|
3103
|
-
onChange &&
|
|
3184
|
+
onChange && EditorView19.updateListener.of(({ state, docChanged }) => {
|
|
3104
3185
|
if (docChanged) {
|
|
3105
3186
|
onChange({
|
|
3106
3187
|
id: state.facet(documentId),
|
|
@@ -3115,7 +3196,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
3115
3196
|
import { snippet } from "@codemirror/autocomplete";
|
|
3116
3197
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3117
3198
|
import { EditorSelection as EditorSelection2 } from "@codemirror/state";
|
|
3118
|
-
import { EditorView as
|
|
3199
|
+
import { EditorView as EditorView20, keymap as keymap8 } from "@codemirror/view";
|
|
3119
3200
|
import { debounceAndThrottle } from "@dxos/async";
|
|
3120
3201
|
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;
|
|
3121
3202
|
var Inline = /* @__PURE__ */ (function(Inline2) {
|
|
@@ -4204,7 +4285,7 @@ var getFormatting = (state) => {
|
|
|
4204
4285
|
};
|
|
4205
4286
|
};
|
|
4206
4287
|
var formattingListener = (onStateChange, delay = 100) => {
|
|
4207
|
-
return
|
|
4288
|
+
return EditorView20.updateListener.of(debounceAndThrottle((update2) => {
|
|
4208
4289
|
if (update2.docChanged || update2.selectionSet) {
|
|
4209
4290
|
onStateChange(getFormatting(update2.state));
|
|
4210
4291
|
}
|
|
@@ -4265,22 +4346,16 @@ import { completionKeymap } from "@codemirror/autocomplete";
|
|
|
4265
4346
|
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
4266
4347
|
import { jsonLanguage } from "@codemirror/lang-json";
|
|
4267
4348
|
import { markdown, markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
4268
|
-
import {
|
|
4269
|
-
import { LanguageDescription, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4349
|
+
import { foldNodeProp, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4270
4350
|
import { languages } from "@codemirror/language-data";
|
|
4271
4351
|
import { keymap as keymap9 } from "@codemirror/view";
|
|
4272
|
-
import { isTruthy as
|
|
4352
|
+
import { isTruthy as isTruthy4 } from "@dxos/util";
|
|
4273
4353
|
|
|
4274
4354
|
// src/extensions/markdown/highlight.ts
|
|
4275
4355
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
4276
4356
|
import { HighlightStyle as HighlightStyle2 } from "@codemirror/language";
|
|
4277
4357
|
import { Tag, styleTags, tags } from "@lezer/highlight";
|
|
4278
4358
|
import { Table } from "@lezer/markdown";
|
|
4279
|
-
var styles4 = {
|
|
4280
|
-
code: "font-mono no-underline! text-cm-code",
|
|
4281
|
-
codeMark: "font-mono text-cm-code-mark",
|
|
4282
|
-
mark: "opacity-50"
|
|
4283
|
-
};
|
|
4284
4359
|
var markdownTags = {
|
|
4285
4360
|
Blockquote: Tag.define(),
|
|
4286
4361
|
CodeMark: Tag.define(),
|
|
@@ -4362,7 +4437,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4362
4437
|
markdownTags.LinkReference,
|
|
4363
4438
|
markdownTags.ListMark
|
|
4364
4439
|
],
|
|
4365
|
-
class:
|
|
4440
|
+
class: markdownTheme.mark
|
|
4366
4441
|
},
|
|
4367
4442
|
// Markdown marks.
|
|
4368
4443
|
{
|
|
@@ -4373,7 +4448,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4373
4448
|
markdownTags.QuoteMark,
|
|
4374
4449
|
markdownTags.EmphasisMark
|
|
4375
4450
|
],
|
|
4376
|
-
class:
|
|
4451
|
+
class: markdownTheme.mark
|
|
4377
4452
|
},
|
|
4378
4453
|
// E.g., code block language (after ```).
|
|
4379
4454
|
{
|
|
@@ -4382,7 +4457,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4382
4457
|
tags.function(tags.variableName),
|
|
4383
4458
|
tags.labelName
|
|
4384
4459
|
],
|
|
4385
|
-
class:
|
|
4460
|
+
class: markdownTheme.codeMark
|
|
4386
4461
|
},
|
|
4387
4462
|
// Fonts.
|
|
4388
4463
|
{
|
|
@@ -4448,7 +4523,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4448
4523
|
markdownTags.CodeText,
|
|
4449
4524
|
markdownTags.InlineCode
|
|
4450
4525
|
],
|
|
4451
|
-
class:
|
|
4526
|
+
class: markdownTheme.code
|
|
4452
4527
|
},
|
|
4453
4528
|
{
|
|
4454
4529
|
tag: [
|
|
@@ -4478,15 +4553,23 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4478
4553
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
4479
4554
|
base: markdownLanguage2,
|
|
4480
4555
|
// Languages for syntax highlighting fenced code blocks.
|
|
4556
|
+
// Caller-supplied languages are checked first so they can override defaults.
|
|
4481
4557
|
defaultCodeLanguage: jsonLanguage,
|
|
4482
|
-
codeLanguages:
|
|
4558
|
+
codeLanguages: [
|
|
4559
|
+
...options.codeLanguages ?? [],
|
|
4560
|
+
...languages
|
|
4561
|
+
],
|
|
4483
4562
|
// Don't complete HTML tags.
|
|
4484
4563
|
completeHTMLTags: false,
|
|
4485
4564
|
// Parser extensions.
|
|
4486
4565
|
extensions: [
|
|
4487
4566
|
// GFM provided by default.
|
|
4488
4567
|
markdownTagsExtensions,
|
|
4489
|
-
...options.extensions ?? defaultExtensions()
|
|
4568
|
+
...options.extensions ?? defaultExtensions(),
|
|
4569
|
+
// Disable folding for fenced code blocks by overriding foldNodeProp.
|
|
4570
|
+
// Note: returning null from foldService does not prevent syntaxFolding fallback,
|
|
4571
|
+
// so we must override the node prop directly on the FencedCode node type.
|
|
4572
|
+
noFencedCodeFolding
|
|
4490
4573
|
]
|
|
4491
4574
|
}),
|
|
4492
4575
|
// Custom styles.
|
|
@@ -4498,21 +4581,16 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4498
4581
|
...defaultKeymap2,
|
|
4499
4582
|
// TODO(burdon): Remove?
|
|
4500
4583
|
...completionKeymap
|
|
4501
|
-
].filter(
|
|
4584
|
+
].filter(isTruthy4))
|
|
4502
4585
|
];
|
|
4503
4586
|
};
|
|
4504
|
-
var
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
]
|
|
4510
|
-
|
|
4511
|
-
"xml",
|
|
4512
|
-
"xhtml"
|
|
4513
|
-
],
|
|
4514
|
-
load: async () => xml()
|
|
4515
|
-
});
|
|
4587
|
+
var noFencedCodeFolding = {
|
|
4588
|
+
props: [
|
|
4589
|
+
foldNodeProp.add({
|
|
4590
|
+
FencedCode: () => null
|
|
4591
|
+
})
|
|
4592
|
+
]
|
|
4593
|
+
};
|
|
4516
4594
|
var defaultExtensions = () => [
|
|
4517
4595
|
noSetExtHeading,
|
|
4518
4596
|
noHtml
|
|
@@ -4532,19 +4610,19 @@ var debugTree = (cb) => StateField6.define({
|
|
|
4532
4610
|
update: (value, tr) => cb(convertTreeToJson(tr.state))
|
|
4533
4611
|
});
|
|
4534
4612
|
var convertTreeToJson = (state) => {
|
|
4535
|
-
const treeToJson = (
|
|
4613
|
+
const treeToJson = (cursor) => {
|
|
4536
4614
|
const node = {
|
|
4537
|
-
type:
|
|
4538
|
-
from:
|
|
4539
|
-
to:
|
|
4540
|
-
text: state.doc.slice(
|
|
4615
|
+
type: cursor.type.name,
|
|
4616
|
+
from: cursor.from,
|
|
4617
|
+
to: cursor.to,
|
|
4618
|
+
text: state.doc.slice(cursor.from, cursor.to).toString(),
|
|
4541
4619
|
children: []
|
|
4542
4620
|
};
|
|
4543
|
-
if (
|
|
4621
|
+
if (cursor.firstChild()) {
|
|
4544
4622
|
do {
|
|
4545
|
-
node.children.push(treeToJson(
|
|
4546
|
-
} while (
|
|
4547
|
-
|
|
4623
|
+
node.children.push(treeToJson(cursor));
|
|
4624
|
+
} while (cursor.nextSibling());
|
|
4625
|
+
cursor.parent();
|
|
4548
4626
|
}
|
|
4549
4627
|
return node;
|
|
4550
4628
|
};
|
|
@@ -4553,17 +4631,16 @@ var convertTreeToJson = (state) => {
|
|
|
4553
4631
|
|
|
4554
4632
|
// src/extensions/markdown/decorate.ts
|
|
4555
4633
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
4556
|
-
import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as
|
|
4557
|
-
import { Decoration as Decoration11, EditorView as
|
|
4634
|
+
import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as StateEffect7 } from "@codemirror/state";
|
|
4635
|
+
import { Decoration as Decoration11, EditorView as EditorView24, ViewPlugin as ViewPlugin15, WidgetType as WidgetType7 } from "@codemirror/view";
|
|
4558
4636
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4559
|
-
import { mx as mx6 } from "@dxos/ui-theme";
|
|
4560
4637
|
|
|
4561
4638
|
// src/extensions/markdown/changes.ts
|
|
4562
4639
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
4563
4640
|
import { Transaction as Transaction4 } from "@codemirror/state";
|
|
4564
|
-
import { ViewPlugin as
|
|
4641
|
+
import { ViewPlugin as ViewPlugin14 } from "@codemirror/view";
|
|
4565
4642
|
var adjustChanges = () => {
|
|
4566
|
-
return
|
|
4643
|
+
return ViewPlugin14.fromClass(class {
|
|
4567
4644
|
update(update2) {
|
|
4568
4645
|
const tree = syntaxTree4(update2.state);
|
|
4569
4646
|
const adjustments = [];
|
|
@@ -4705,7 +4782,7 @@ var getValidUrl = (str) => {
|
|
|
4705
4782
|
// src/extensions/markdown/image.ts
|
|
4706
4783
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4707
4784
|
import { StateField as StateField7 } from "@codemirror/state";
|
|
4708
|
-
import { Decoration as Decoration9, EditorView as
|
|
4785
|
+
import { Decoration as Decoration9, EditorView as EditorView21, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4709
4786
|
var image = (_options = {}) => {
|
|
4710
4787
|
return [
|
|
4711
4788
|
StateField7.define({
|
|
@@ -4716,10 +4793,10 @@ var image = (_options = {}) => {
|
|
|
4716
4793
|
if (!tr.docChanged && !tr.selection) {
|
|
4717
4794
|
return value;
|
|
4718
4795
|
}
|
|
4719
|
-
const
|
|
4796
|
+
const cursor = tr.state.selection.main.head;
|
|
4720
4797
|
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
4721
|
-
let from = Math.min(
|
|
4722
|
-
let to = Math.max(
|
|
4798
|
+
let from = Math.min(cursor, oldCursor);
|
|
4799
|
+
let to = Math.max(cursor, oldCursor);
|
|
4723
4800
|
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
4724
4801
|
from = Math.min(from, fromB);
|
|
4725
4802
|
to = Math.max(to, toB);
|
|
@@ -4733,19 +4810,19 @@ var image = (_options = {}) => {
|
|
|
4733
4810
|
add: buildDecorations(tr.state, from, to)
|
|
4734
4811
|
});
|
|
4735
4812
|
},
|
|
4736
|
-
provide: (field) =>
|
|
4813
|
+
provide: (field) => EditorView21.decorations.from(field)
|
|
4737
4814
|
})
|
|
4738
4815
|
];
|
|
4739
4816
|
};
|
|
4740
4817
|
var buildDecorations = (state, from, to) => {
|
|
4741
4818
|
const decorations2 = [];
|
|
4742
|
-
const
|
|
4819
|
+
const cursor = state.selection.main.head;
|
|
4743
4820
|
syntaxTree5(state).iterate({
|
|
4744
4821
|
enter: (node) => {
|
|
4745
4822
|
if (node.name === "Image") {
|
|
4746
4823
|
const urlNode = node.node.getChild("URL");
|
|
4747
4824
|
if (urlNode) {
|
|
4748
|
-
const hide2 = state.readOnly ||
|
|
4825
|
+
const hide2 = state.readOnly || cursor < node.from || cursor > node.to || !state.field(focusField);
|
|
4749
4826
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
4750
4827
|
if (url.match(/^https?:\/\//) === null && url.match(/^file?:\/\//) === null) {
|
|
4751
4828
|
return;
|
|
@@ -4793,10 +4870,10 @@ var ImageWidget = class extends WidgetType5 {
|
|
|
4793
4870
|
};
|
|
4794
4871
|
|
|
4795
4872
|
// src/extensions/markdown/styles.ts
|
|
4796
|
-
import { EditorView as
|
|
4873
|
+
import { EditorView as EditorView22 } from "@codemirror/view";
|
|
4797
4874
|
var bulletListIndentationWidth = 24;
|
|
4798
4875
|
var orderedListIndentationWidth = 36;
|
|
4799
|
-
var formattingStyles =
|
|
4876
|
+
var formattingStyles = EditorView22.theme({
|
|
4800
4877
|
/**
|
|
4801
4878
|
* Horizontal rule.
|
|
4802
4879
|
*/
|
|
@@ -4831,13 +4908,38 @@ var formattingStyles = EditorView21.theme({
|
|
|
4831
4908
|
background: "var(--color-cm-codeblock)",
|
|
4832
4909
|
borderLeft: "2px solid var(--color-cm-separator)",
|
|
4833
4910
|
paddingLeft: "1rem",
|
|
4834
|
-
margin:
|
|
4911
|
+
margin: 0
|
|
4835
4912
|
},
|
|
4836
4913
|
/**
|
|
4837
4914
|
* Code and codeblocks.
|
|
4838
4915
|
*/
|
|
4916
|
+
"& code": {
|
|
4917
|
+
fontFamily: fontMono,
|
|
4918
|
+
color: "var(--color-cm-code)",
|
|
4919
|
+
whiteSpace: "nowrap"
|
|
4920
|
+
},
|
|
4839
4921
|
"& .cm-code": {
|
|
4840
|
-
fontFamily: fontMono
|
|
4922
|
+
fontFamily: fontMono,
|
|
4923
|
+
color: "var(--color-cm-code)"
|
|
4924
|
+
},
|
|
4925
|
+
// Inline code spans (triggered by backticks) use `cm-code-inline` + `font-mono`.
|
|
4926
|
+
// Different monospace font metrics can slightly overflow the fixed CodeMirror line box,
|
|
4927
|
+
// so constrain them to the target 24px height.
|
|
4928
|
+
"& .cm-code-inline": {
|
|
4929
|
+
fontFamily: fontMono,
|
|
4930
|
+
height: "24px",
|
|
4931
|
+
// display: 'inline-flex',
|
|
4932
|
+
alignItems: "center",
|
|
4933
|
+
overflow: "hidden",
|
|
4934
|
+
whiteSpace: "nowrap",
|
|
4935
|
+
color: "var(--color-cm-code-inline)"
|
|
4936
|
+
},
|
|
4937
|
+
"& .cm-code-mark": {
|
|
4938
|
+
fontFamily: fontMono,
|
|
4939
|
+
height: "24px",
|
|
4940
|
+
display: "inline-flex",
|
|
4941
|
+
alignItems: "center",
|
|
4942
|
+
overflow: "hidden"
|
|
4841
4943
|
},
|
|
4842
4944
|
"& .cm-codeblock-line": {
|
|
4843
4945
|
background: "var(--color-cm-codeblock)",
|
|
@@ -4869,16 +4971,24 @@ var formattingStyles = EditorView21.theme({
|
|
|
4869
4971
|
*/
|
|
4870
4972
|
".cm-table *": {
|
|
4871
4973
|
fontFamily: fontMono,
|
|
4974
|
+
lineHeight: 1.5,
|
|
4872
4975
|
textDecoration: "none !important"
|
|
4873
4976
|
},
|
|
4874
4977
|
".cm-table-head": {
|
|
4875
4978
|
padding: "2px 16px 2px 0px",
|
|
4979
|
+
overflowWrap: "break-word",
|
|
4980
|
+
whiteSpace: "pre-wrap",
|
|
4981
|
+
wordBreak: "keep-all",
|
|
4876
4982
|
textAlign: "left",
|
|
4877
|
-
|
|
4878
|
-
|
|
4983
|
+
color: "var(--color-subdued)",
|
|
4984
|
+
borderBottom: "1px solid var(--color-cm-separator)"
|
|
4879
4985
|
},
|
|
4880
4986
|
".cm-table-cell": {
|
|
4881
|
-
padding: "2px 16px 2px 0px"
|
|
4987
|
+
padding: "2px 16px 2px 0px",
|
|
4988
|
+
overflowWrap: "break-word",
|
|
4989
|
+
whiteSpace: "pre-wrap",
|
|
4990
|
+
wordBreak: "keep-all",
|
|
4991
|
+
verticalAlign: "top"
|
|
4882
4992
|
},
|
|
4883
4993
|
/**
|
|
4884
4994
|
* Image.
|
|
@@ -4894,12 +5004,12 @@ var formattingStyles = EditorView21.theme({
|
|
|
4894
5004
|
},
|
|
4895
5005
|
".cm-image-with-loader": {
|
|
4896
5006
|
display: "block",
|
|
4897
|
-
opacity:
|
|
5007
|
+
opacity: 0,
|
|
4898
5008
|
transitionDuration: "350ms",
|
|
4899
5009
|
transitionProperty: "opacity"
|
|
4900
5010
|
},
|
|
4901
5011
|
".cm-image-with-loader.cm-loaded-image": {
|
|
4902
|
-
opacity:
|
|
5012
|
+
opacity: 1
|
|
4903
5013
|
},
|
|
4904
5014
|
".cm-image-wrapper": {
|
|
4905
5015
|
"grid-template-columns": "1fr",
|
|
@@ -4918,17 +5028,17 @@ var formattingStyles = EditorView21.theme({
|
|
|
4918
5028
|
// src/extensions/markdown/table.ts
|
|
4919
5029
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
4920
5030
|
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField8 } from "@codemirror/state";
|
|
4921
|
-
import { Decoration as Decoration10, EditorView as
|
|
5031
|
+
import { Decoration as Decoration10, EditorView as EditorView23, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
4922
5032
|
var table = (options = {}) => {
|
|
4923
5033
|
return StateField8.define({
|
|
4924
5034
|
create: (state) => update(state, options),
|
|
4925
5035
|
update: (_, tr) => update(tr.state, options),
|
|
4926
|
-
provide: (field) =>
|
|
5036
|
+
provide: (field) => EditorView23.decorations.from(field)
|
|
4927
5037
|
});
|
|
4928
5038
|
};
|
|
4929
5039
|
var update = (state, _options) => {
|
|
4930
5040
|
const builder = new RangeSetBuilder4();
|
|
4931
|
-
const
|
|
5041
|
+
const cursor = state.selection.main.head;
|
|
4932
5042
|
const tables = [];
|
|
4933
5043
|
const getTable = () => tables[tables.length - 1];
|
|
4934
5044
|
const getRow = () => {
|
|
@@ -4966,7 +5076,7 @@ var update = (state, _options) => {
|
|
|
4966
5076
|
}
|
|
4967
5077
|
});
|
|
4968
5078
|
tables.forEach((table2) => {
|
|
4969
|
-
const replace = state.readOnly ||
|
|
5079
|
+
const replace = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4970
5080
|
if (replace) {
|
|
4971
5081
|
builder.add(table2.from, table2.to, Decoration10.replace({
|
|
4972
5082
|
block: true,
|
|
@@ -4980,6 +5090,26 @@ var update = (state, _options) => {
|
|
|
4980
5090
|
});
|
|
4981
5091
|
return builder.finish();
|
|
4982
5092
|
};
|
|
5093
|
+
var renderCellContent = (el, text) => {
|
|
5094
|
+
const parts = text.split(/(`[^`\n]+`|\*\*[^*\n]+\*\*|__[^_\n]+__|\*[^*\n]+\*|_[^_\n]+_)/);
|
|
5095
|
+
for (const part of parts) {
|
|
5096
|
+
if (part.length > 2 && part.startsWith("`") && part.endsWith("`")) {
|
|
5097
|
+
const code = document.createElement("code");
|
|
5098
|
+
code.textContent = part.slice(1, -1);
|
|
5099
|
+
el.appendChild(code);
|
|
5100
|
+
} else if (part.startsWith("**") && part.endsWith("**") || part.startsWith("__") && part.endsWith("__")) {
|
|
5101
|
+
const strong = document.createElement("strong");
|
|
5102
|
+
strong.textContent = part.slice(2, -2);
|
|
5103
|
+
el.appendChild(strong);
|
|
5104
|
+
} else if (part.startsWith("*") && part.endsWith("*") || part.startsWith("_") && part.endsWith("_")) {
|
|
5105
|
+
const em = document.createElement("em");
|
|
5106
|
+
em.textContent = part.slice(1, -1);
|
|
5107
|
+
el.appendChild(em);
|
|
5108
|
+
} else {
|
|
5109
|
+
el.appendChild(document.createTextNode(part));
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
};
|
|
4983
5113
|
var TableWidget = class extends WidgetType6 {
|
|
4984
5114
|
_table;
|
|
4985
5115
|
constructor(_table) {
|
|
@@ -4999,7 +5129,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
4999
5129
|
this._table.header?.forEach((cell) => {
|
|
5000
5130
|
const th = document.createElement("th");
|
|
5001
5131
|
th.setAttribute("class", "cm-table-head");
|
|
5002
|
-
tr.appendChild(th)
|
|
5132
|
+
renderCellContent(tr.appendChild(th), cell);
|
|
5003
5133
|
});
|
|
5004
5134
|
const body = table2.appendChild(document.createElement("tbody"));
|
|
5005
5135
|
this._table.rows?.forEach((row) => {
|
|
@@ -5007,7 +5137,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
5007
5137
|
row.forEach((cell) => {
|
|
5008
5138
|
const td = document.createElement("td");
|
|
5009
5139
|
td.setAttribute("class", "cm-table-cell");
|
|
5010
|
-
tr2.appendChild(td)
|
|
5140
|
+
renderCellContent(tr2.appendChild(td), cell);
|
|
5011
5141
|
});
|
|
5012
5142
|
});
|
|
5013
5143
|
return div;
|
|
@@ -5114,10 +5244,10 @@ var fencedCodeLine = Decoration11.line({
|
|
|
5114
5244
|
class: "cm-code cm-codeblock-line"
|
|
5115
5245
|
});
|
|
5116
5246
|
var fencedCodeLineFirst = Decoration11.line({
|
|
5117
|
-
class:
|
|
5247
|
+
class: "cm-code cm-codeblock-line cm-codeblock-start"
|
|
5118
5248
|
});
|
|
5119
5249
|
var fencedCodeLineLast = Decoration11.line({
|
|
5120
|
-
class:
|
|
5250
|
+
class: "cm-code cm-codeblock-line cm-codeblock-end"
|
|
5121
5251
|
});
|
|
5122
5252
|
var commentBlockLine = fencedCodeLine;
|
|
5123
5253
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
|
@@ -5149,15 +5279,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5149
5279
|
const { state } = view;
|
|
5150
5280
|
const headerLevels = [];
|
|
5151
5281
|
const getHeaderLevels = (node, level) => {
|
|
5152
|
-
invariant4(level > 0, void 0, {
|
|
5153
|
-
F: __dxlog_file12,
|
|
5154
|
-
L: 179,
|
|
5155
|
-
S: void 0,
|
|
5156
|
-
A: [
|
|
5157
|
-
"level > 0",
|
|
5158
|
-
""
|
|
5159
|
-
]
|
|
5160
|
-
});
|
|
5282
|
+
invariant4(level > 0, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 160, S: void 0, A: ["level > 0", ""] });
|
|
5161
5283
|
if (level > headerLevels.length) {
|
|
5162
5284
|
const len = headerLevels.length;
|
|
5163
5285
|
headerLevels.length = level;
|
|
@@ -5188,15 +5310,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5188
5310
|
listLevels.pop();
|
|
5189
5311
|
};
|
|
5190
5312
|
const getCurrentListLevel = () => {
|
|
5191
|
-
invariant4(listLevels.length, void 0, {
|
|
5192
|
-
F: __dxlog_file12,
|
|
5193
|
-
L: 201,
|
|
5194
|
-
S: void 0,
|
|
5195
|
-
A: [
|
|
5196
|
-
"listLevels.length",
|
|
5197
|
-
""
|
|
5198
|
-
]
|
|
5199
|
-
});
|
|
5313
|
+
invariant4(listLevels.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 192, S: void 0, A: ["listLevels.length", ""] });
|
|
5200
5314
|
return listLevels[listLevels.length - 1];
|
|
5201
5315
|
};
|
|
5202
5316
|
const enterNode = (node) => {
|
|
@@ -5234,7 +5348,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5234
5348
|
deco: hide
|
|
5235
5349
|
});
|
|
5236
5350
|
} else {
|
|
5237
|
-
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
|
|
5351
|
+
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + "). ";
|
|
5238
5352
|
if (num.length) {
|
|
5239
5353
|
atomicDecoRanges.push({
|
|
5240
5354
|
from: mark.from,
|
|
@@ -5417,11 +5531,11 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5417
5531
|
}
|
|
5418
5532
|
decoRanges.push({
|
|
5419
5533
|
from: marks[0].to,
|
|
5420
|
-
to: marks[1].from,
|
|
5534
|
+
to: !editing && options.renderLinkButton ? node.to : marks[1].from,
|
|
5421
5535
|
deco: Decoration11.mark({
|
|
5422
5536
|
tagName: "a",
|
|
5423
5537
|
attributes: {
|
|
5424
|
-
class: "cm-link",
|
|
5538
|
+
class: options.renderLinkButton ? "cm-link cm-link-with-button" : "cm-link",
|
|
5425
5539
|
href: url,
|
|
5426
5540
|
rel: "noreferrer",
|
|
5427
5541
|
target: "_blank"
|
|
@@ -5499,18 +5613,21 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5499
5613
|
deco.add(from, to, d);
|
|
5500
5614
|
}
|
|
5501
5615
|
const atomicDeco = new RangeSetBuilder5();
|
|
5502
|
-
for (const { from, to, deco:
|
|
5503
|
-
|
|
5616
|
+
for (const { from, to, deco: deco2 } of atomicDecoRanges) {
|
|
5617
|
+
if (from < to && state.doc.lineAt(from).number !== state.doc.lineAt(to).number) {
|
|
5618
|
+
continue;
|
|
5619
|
+
}
|
|
5620
|
+
atomicDeco.add(from, to, deco2);
|
|
5504
5621
|
}
|
|
5505
5622
|
return {
|
|
5506
5623
|
deco: deco.finish(),
|
|
5507
5624
|
atomicDeco: atomicDeco.finish()
|
|
5508
5625
|
};
|
|
5509
5626
|
};
|
|
5510
|
-
var forceUpdate =
|
|
5627
|
+
var forceUpdate = StateEffect7.define();
|
|
5511
5628
|
var decorateMarkdown = (options = {}) => {
|
|
5512
5629
|
return [
|
|
5513
|
-
|
|
5630
|
+
ViewPlugin15.fromClass(class {
|
|
5514
5631
|
deco;
|
|
5515
5632
|
atomicDeco;
|
|
5516
5633
|
pendingUpdate;
|
|
@@ -5545,9 +5662,9 @@ var decorateMarkdown = (options = {}) => {
|
|
|
5545
5662
|
}
|
|
5546
5663
|
}, {
|
|
5547
5664
|
provide: (plugin) => [
|
|
5548
|
-
Prec4.low(
|
|
5549
|
-
|
|
5550
|
-
|
|
5665
|
+
Prec4.low(EditorView24.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration11.none)),
|
|
5666
|
+
EditorView24.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none),
|
|
5667
|
+
EditorView24.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none)
|
|
5551
5668
|
]
|
|
5552
5669
|
}),
|
|
5553
5670
|
image(),
|
|
@@ -5615,12 +5732,7 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5615
5732
|
(context) => {
|
|
5616
5733
|
log9.info("completion context", {
|
|
5617
5734
|
context
|
|
5618
|
-
}, {
|
|
5619
|
-
F: __dxlog_file13,
|
|
5620
|
-
L: 27,
|
|
5621
|
-
S: void 0,
|
|
5622
|
-
C: (f, a) => f(...a)
|
|
5623
|
-
});
|
|
5735
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file13, L: 18, S: void 0 });
|
|
5624
5736
|
const match = context.matchBefore(/@(\w+)?/);
|
|
5625
5737
|
if (!match || match.from === match.to && !context.explicit) {
|
|
5626
5738
|
return null;
|
|
@@ -5637,8 +5749,8 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5637
5749
|
};
|
|
5638
5750
|
|
|
5639
5751
|
// src/extensions/modal.ts
|
|
5640
|
-
import { StateEffect as
|
|
5641
|
-
var modalStateEffect =
|
|
5752
|
+
import { StateEffect as StateEffect8, StateField as StateField9 } from "@codemirror/state";
|
|
5753
|
+
var modalStateEffect = StateEffect8.define();
|
|
5642
5754
|
var modalStateField = StateField9.define({
|
|
5643
5755
|
create: () => false,
|
|
5644
5756
|
update: (value, tr) => {
|
|
@@ -5853,15 +5965,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5853
5965
|
break;
|
|
5854
5966
|
}
|
|
5855
5967
|
case "BulletList": {
|
|
5856
|
-
invariant5(current, void 0, {
|
|
5857
|
-
F: __dxlog_file14,
|
|
5858
|
-
L: 219,
|
|
5859
|
-
S: void 0,
|
|
5860
|
-
A: [
|
|
5861
|
-
"current",
|
|
5862
|
-
""
|
|
5863
|
-
]
|
|
5864
|
-
});
|
|
5968
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 169, S: void 0, A: ["current", ""] });
|
|
5865
5969
|
parent = current;
|
|
5866
5970
|
if (current) {
|
|
5867
5971
|
current.lineRange.to = current.node.from;
|
|
@@ -5870,15 +5974,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5870
5974
|
break;
|
|
5871
5975
|
}
|
|
5872
5976
|
case "ListItem": {
|
|
5873
|
-
invariant5(parent, void 0, {
|
|
5874
|
-
F: __dxlog_file14,
|
|
5875
|
-
L: 228,
|
|
5876
|
-
S: void 0,
|
|
5877
|
-
A: [
|
|
5878
|
-
"parent",
|
|
5879
|
-
""
|
|
5880
|
-
]
|
|
5881
|
-
});
|
|
5977
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 179, S: void 0, A: ["parent", ""] });
|
|
5882
5978
|
const nextSibling = node.node.nextSibling ?? node.node.parent?.nextSibling;
|
|
5883
5979
|
const docRange = {
|
|
5884
5980
|
from: state.doc.lineAt(node.from).from,
|
|
@@ -5912,42 +6008,18 @@ var outlinerTree = (_options = {}) => {
|
|
|
5912
6008
|
break;
|
|
5913
6009
|
}
|
|
5914
6010
|
case "ListMark": {
|
|
5915
|
-
invariant5(current, void 0, {
|
|
5916
|
-
F: __dxlog_file14,
|
|
5917
|
-
L: 272,
|
|
5918
|
-
S: void 0,
|
|
5919
|
-
A: [
|
|
5920
|
-
"current",
|
|
5921
|
-
""
|
|
5922
|
-
]
|
|
5923
|
-
});
|
|
6011
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 219, S: void 0, A: ["current", ""] });
|
|
5924
6012
|
current.type = "bullet";
|
|
5925
6013
|
current.contentRange.from = node.from + "- ".length;
|
|
5926
6014
|
break;
|
|
5927
6015
|
}
|
|
5928
6016
|
case "Task": {
|
|
5929
|
-
invariant5(current, void 0, {
|
|
5930
|
-
F: __dxlog_file14,
|
|
5931
|
-
L: 278,
|
|
5932
|
-
S: void 0,
|
|
5933
|
-
A: [
|
|
5934
|
-
"current",
|
|
5935
|
-
""
|
|
5936
|
-
]
|
|
5937
|
-
});
|
|
6017
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 226, S: void 0, A: ["current", ""] });
|
|
5938
6018
|
current.type = "task";
|
|
5939
6019
|
break;
|
|
5940
6020
|
}
|
|
5941
6021
|
case "TaskMarker": {
|
|
5942
|
-
invariant5(current, void 0, {
|
|
5943
|
-
F: __dxlog_file14,
|
|
5944
|
-
L: 283,
|
|
5945
|
-
S: void 0,
|
|
5946
|
-
A: [
|
|
5947
|
-
"current",
|
|
5948
|
-
""
|
|
5949
|
-
]
|
|
5950
|
-
});
|
|
6022
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 232, S: void 0, A: ["current", ""] });
|
|
5951
6023
|
current.contentRange.from = node.from + "[ ] ".length;
|
|
5952
6024
|
break;
|
|
5953
6025
|
}
|
|
@@ -5955,29 +6027,13 @@ var outlinerTree = (_options = {}) => {
|
|
|
5955
6027
|
},
|
|
5956
6028
|
leave: (node) => {
|
|
5957
6029
|
if (node.name === "BulletList") {
|
|
5958
|
-
invariant5(parent, void 0, {
|
|
5959
|
-
F: __dxlog_file14,
|
|
5960
|
-
L: 291,
|
|
5961
|
-
S: void 0,
|
|
5962
|
-
A: [
|
|
5963
|
-
"parent",
|
|
5964
|
-
""
|
|
5965
|
-
]
|
|
5966
|
-
});
|
|
6030
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 240, S: void 0, A: ["parent", ""] });
|
|
5967
6031
|
prevSiblings[level--] = void 0;
|
|
5968
6032
|
parent = parent.parent;
|
|
5969
6033
|
}
|
|
5970
6034
|
}
|
|
5971
6035
|
});
|
|
5972
|
-
invariant5(tree, void 0, {
|
|
5973
|
-
F: __dxlog_file14,
|
|
5974
|
-
L: 298,
|
|
5975
|
-
S: void 0,
|
|
5976
|
-
A: [
|
|
5977
|
-
"tree",
|
|
5978
|
-
""
|
|
5979
|
-
]
|
|
5980
|
-
});
|
|
6036
|
+
invariant5(tree, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 246, S: void 0, A: ["tree", ""] });
|
|
5981
6037
|
return tree;
|
|
5982
6038
|
};
|
|
5983
6039
|
return [
|
|
@@ -6262,17 +6318,17 @@ var commands = () => keymap11.of([
|
|
|
6262
6318
|
|
|
6263
6319
|
// src/extensions/outliner/outliner.ts
|
|
6264
6320
|
import { Prec as Prec5 } from "@codemirror/state";
|
|
6265
|
-
import { Decoration as Decoration12, EditorView as
|
|
6266
|
-
import { mx as
|
|
6321
|
+
import { Decoration as Decoration12, EditorView as EditorView26, ViewPlugin as ViewPlugin18 } from "@codemirror/view";
|
|
6322
|
+
import { mx as mx6 } from "@dxos/ui-theme";
|
|
6267
6323
|
|
|
6268
6324
|
// src/extensions/outliner/editor.ts
|
|
6269
6325
|
import { EditorSelection as EditorSelection4, EditorState as EditorState2 } from "@codemirror/state";
|
|
6270
|
-
import { ViewPlugin as
|
|
6326
|
+
import { ViewPlugin as ViewPlugin16 } from "@codemirror/view";
|
|
6271
6327
|
import { log as log10 } from "@dxos/log";
|
|
6272
6328
|
var __dxlog_file15 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/editor.ts";
|
|
6273
6329
|
var LIST_ITEM_REGEX = /^\s*- (\[ \]|\[x\])? /;
|
|
6274
6330
|
var initialize = () => {
|
|
6275
|
-
return
|
|
6331
|
+
return ViewPlugin16.fromClass(class {
|
|
6276
6332
|
constructor(view) {
|
|
6277
6333
|
const first = view.state.doc.lineAt(0);
|
|
6278
6334
|
const text = view.state.sliceDoc(first.from, first.to);
|
|
@@ -6419,35 +6475,20 @@ var editor = () => [
|
|
|
6419
6475
|
text: insert.toString(),
|
|
6420
6476
|
length: insert.length
|
|
6421
6477
|
}
|
|
6422
|
-
}, {
|
|
6423
|
-
F: __dxlog_file15,
|
|
6424
|
-
L: 164,
|
|
6425
|
-
S: void 0,
|
|
6426
|
-
C: (f, a) => f(...a)
|
|
6427
|
-
});
|
|
6478
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 174, S: void 0 });
|
|
6428
6479
|
}
|
|
6429
6480
|
});
|
|
6430
6481
|
if (changes.length > 0) {
|
|
6431
6482
|
log10("modified,", {
|
|
6432
6483
|
changes
|
|
6433
|
-
}, {
|
|
6434
|
-
F: __dxlog_file15,
|
|
6435
|
-
L: 175,
|
|
6436
|
-
S: void 0,
|
|
6437
|
-
C: (f, a) => f(...a)
|
|
6438
|
-
});
|
|
6484
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 196, S: void 0 });
|
|
6439
6485
|
return [
|
|
6440
6486
|
{
|
|
6441
6487
|
changes
|
|
6442
6488
|
}
|
|
6443
6489
|
];
|
|
6444
6490
|
} else if (cancel) {
|
|
6445
|
-
log10("cancel", void 0, {
|
|
6446
|
-
F: __dxlog_file15,
|
|
6447
|
-
L: 178,
|
|
6448
|
-
S: void 0,
|
|
6449
|
-
C: (f, a) => f(...a)
|
|
6450
|
-
});
|
|
6491
|
+
log10("cancel", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 205, S: void 0 });
|
|
6451
6492
|
return [];
|
|
6452
6493
|
}
|
|
6453
6494
|
return tr;
|
|
@@ -6455,10 +6496,10 @@ var editor = () => [
|
|
|
6455
6496
|
];
|
|
6456
6497
|
|
|
6457
6498
|
// src/extensions/outliner/menu.ts
|
|
6458
|
-
import { EditorView as
|
|
6499
|
+
import { EditorView as EditorView25, ViewPlugin as ViewPlugin17 } from "@codemirror/view";
|
|
6459
6500
|
import { addEventListener as addEventListener2 } from "@dxos/async";
|
|
6460
6501
|
var menu = (options = {}) => [
|
|
6461
|
-
|
|
6502
|
+
ViewPlugin17.fromClass(class {
|
|
6462
6503
|
view;
|
|
6463
6504
|
tag;
|
|
6464
6505
|
rafId;
|
|
@@ -6520,7 +6561,7 @@ var menu = (options = {}) => [
|
|
|
6520
6561
|
this.rafId = requestAnimationFrame(this.updateButtonPosition.bind(this));
|
|
6521
6562
|
}
|
|
6522
6563
|
}),
|
|
6523
|
-
|
|
6564
|
+
EditorView25.theme({
|
|
6524
6565
|
".cm-popover-trigger": {
|
|
6525
6566
|
position: "fixed",
|
|
6526
6567
|
padding: "0",
|
|
@@ -6556,12 +6597,12 @@ var outliner = (_options = {}) => [
|
|
|
6556
6597
|
listPaddingLeft: 8
|
|
6557
6598
|
}),
|
|
6558
6599
|
// Researve space for menu.
|
|
6559
|
-
|
|
6600
|
+
EditorView26.contentAttributes.of({
|
|
6560
6601
|
class: "w-full !mr-[3rem]"
|
|
6561
6602
|
})
|
|
6562
6603
|
];
|
|
6563
6604
|
var decorations = () => [
|
|
6564
|
-
|
|
6605
|
+
ViewPlugin18.fromClass(class {
|
|
6565
6606
|
decorations = Decoration12.none;
|
|
6566
6607
|
constructor(view) {
|
|
6567
6608
|
this.updateDecorations(view.state, view);
|
|
@@ -6586,7 +6627,7 @@ var decorations = () => [
|
|
|
6586
6627
|
const lineTo = doc.lineAt(item.contentRange.to);
|
|
6587
6628
|
const isSelected = selection.includes(item.index) || item === current;
|
|
6588
6629
|
decorations2.push(Decoration12.line({
|
|
6589
|
-
class:
|
|
6630
|
+
class: mx6("cm-list-item", lineFrom.number === line.number && "cm-list-item-start", lineTo.number === line.number && "cm-list-item-end", isSelected && (hasFocus ? "cm-list-item-focused" : "cm-list-item-selected"))
|
|
6590
6631
|
}).range(line.from, line.from));
|
|
6591
6632
|
}
|
|
6592
6633
|
}
|
|
@@ -6596,7 +6637,7 @@ var decorations = () => [
|
|
|
6596
6637
|
decorations: (v) => v.decorations
|
|
6597
6638
|
}),
|
|
6598
6639
|
// Theme.
|
|
6599
|
-
|
|
6640
|
+
EditorView26.theme(Object.assign({
|
|
6600
6641
|
".cm-list-item": {
|
|
6601
6642
|
borderLeftWidth: "1px",
|
|
6602
6643
|
borderRightWidth: "1px",
|
|
@@ -6621,7 +6662,7 @@ var decorations = () => [
|
|
|
6621
6662
|
marginBottom: "2px"
|
|
6622
6663
|
},
|
|
6623
6664
|
".cm-list-item-focused": {
|
|
6624
|
-
borderColor: "var(--color-
|
|
6665
|
+
borderColor: "var(--color-focus-ring-subtle)"
|
|
6625
6666
|
},
|
|
6626
6667
|
"&:focus-within .cm-list-item-selected": {
|
|
6627
6668
|
borderColor: "var(--color-separator)"
|
|
@@ -6631,28 +6672,57 @@ var decorations = () => [
|
|
|
6631
6672
|
|
|
6632
6673
|
// src/extensions/preview/preview.ts
|
|
6633
6674
|
import { syntaxTree as syntaxTree10 } from "@codemirror/language";
|
|
6634
|
-
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField11 } from "@codemirror/state";
|
|
6635
|
-
import { Decoration as Decoration13, EditorView as
|
|
6675
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateEffect as StateEffect9, StateField as StateField11 } from "@codemirror/state";
|
|
6676
|
+
import { Decoration as Decoration13, EditorView as EditorView27, ViewPlugin as ViewPlugin19, WidgetType as WidgetType8 } from "@codemirror/view";
|
|
6677
|
+
import { DXN, Entity } from "@dxos/echo";
|
|
6678
|
+
var labelResolvedEffect = StateEffect9.define();
|
|
6636
6679
|
var preview = (options = {}) => {
|
|
6680
|
+
const viewRef = {
|
|
6681
|
+
current: void 0
|
|
6682
|
+
};
|
|
6637
6683
|
return [
|
|
6638
6684
|
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
|
6639
6685
|
// "Block decorations may not be specified via plugins".
|
|
6640
6686
|
StateField11.define({
|
|
6641
|
-
create: (state) => buildDecorations3(state, options),
|
|
6687
|
+
create: (state) => buildDecorations3(state, options, viewRef),
|
|
6642
6688
|
update: (decorations2, tr) => {
|
|
6643
|
-
if (tr.docChanged) {
|
|
6644
|
-
return buildDecorations3(tr.state, options);
|
|
6689
|
+
if (tr.docChanged || tr.effects.some((effect) => effect.is(labelResolvedEffect))) {
|
|
6690
|
+
return buildDecorations3(tr.state, options, viewRef);
|
|
6645
6691
|
}
|
|
6646
6692
|
return decorations2.map(tr.changes);
|
|
6647
6693
|
},
|
|
6648
6694
|
provide: (field) => [
|
|
6649
|
-
|
|
6650
|
-
|
|
6695
|
+
EditorView27.decorations.from(field),
|
|
6696
|
+
EditorView27.atomicRanges.of((view) => view.state.field(field))
|
|
6651
6697
|
]
|
|
6698
|
+
}),
|
|
6699
|
+
ViewPlugin19.define((view) => {
|
|
6700
|
+
viewRef.current = view;
|
|
6701
|
+
return {
|
|
6702
|
+
destroy() {
|
|
6703
|
+
viewRef.current = void 0;
|
|
6704
|
+
}
|
|
6705
|
+
};
|
|
6652
6706
|
})
|
|
6653
6707
|
];
|
|
6654
6708
|
};
|
|
6655
|
-
var
|
|
6709
|
+
var resolveLabel = (db, dxnStr, viewRef) => {
|
|
6710
|
+
const dxn = DXN.tryParse(dxnStr);
|
|
6711
|
+
if (!dxn) {
|
|
6712
|
+
return;
|
|
6713
|
+
}
|
|
6714
|
+
const ref = db.makeRef(dxn);
|
|
6715
|
+
const target = ref.target;
|
|
6716
|
+
if (target) {
|
|
6717
|
+
return Entity.getLabel(target);
|
|
6718
|
+
}
|
|
6719
|
+
void ref.tryLoad().then(() => {
|
|
6720
|
+
viewRef.current?.dispatch({
|
|
6721
|
+
effects: labelResolvedEffect.of(void 0)
|
|
6722
|
+
});
|
|
6723
|
+
});
|
|
6724
|
+
};
|
|
6725
|
+
var buildDecorations3 = (state, options, viewRef) => {
|
|
6656
6726
|
const builder = new RangeSetBuilder6();
|
|
6657
6727
|
syntaxTree10(state).iterate({
|
|
6658
6728
|
enter: (node) => {
|
|
@@ -6664,8 +6734,13 @@ var buildDecorations3 = (state, options) => {
|
|
|
6664
6734
|
case "Link": {
|
|
6665
6735
|
const link = getLinkRef(state, node.node);
|
|
6666
6736
|
if (link) {
|
|
6737
|
+
const resolved = options.db ? resolveLabel(options.db, link.dxn, viewRef) : void 0;
|
|
6738
|
+
const displayLink = resolved ? {
|
|
6739
|
+
...link,
|
|
6740
|
+
label: resolved
|
|
6741
|
+
} : link;
|
|
6667
6742
|
builder.add(node.from, node.to, Decoration13.replace({
|
|
6668
|
-
widget: new PreviewInlineWidget(options,
|
|
6743
|
+
widget: new PreviewInlineWidget(options, displayLink),
|
|
6669
6744
|
side: 1
|
|
6670
6745
|
}));
|
|
6671
6746
|
}
|
|
@@ -6757,7 +6832,7 @@ var PreviewBlockWidget = class extends WidgetType8 {
|
|
|
6757
6832
|
};
|
|
6758
6833
|
|
|
6759
6834
|
// src/extensions/replacer.ts
|
|
6760
|
-
import { EditorView as
|
|
6835
|
+
import { EditorView as EditorView28 } from "@codemirror/view";
|
|
6761
6836
|
var defaultReplacements = [
|
|
6762
6837
|
{
|
|
6763
6838
|
input: "--",
|
|
@@ -6820,7 +6895,7 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6820
6895
|
const sortedReplacements = [
|
|
6821
6896
|
...replacements
|
|
6822
6897
|
].sort((a, b) => b.input.length - a.input.length);
|
|
6823
|
-
return
|
|
6898
|
+
return EditorView28.inputHandler.of((view, from, to, insert) => {
|
|
6824
6899
|
if (insert.length !== 1) {
|
|
6825
6900
|
return false;
|
|
6826
6901
|
}
|
|
@@ -6854,12 +6929,69 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6854
6929
|
});
|
|
6855
6930
|
};
|
|
6856
6931
|
|
|
6932
|
+
// src/extensions/snippets.ts
|
|
6933
|
+
import { keymap as keymap12 } from "@codemirror/view";
|
|
6934
|
+
var defaultItems = [
|
|
6935
|
+
"hello world!",
|
|
6936
|
+
"this is a test.",
|
|
6937
|
+
"this is [DXOS](https://dxos.org)"
|
|
6938
|
+
];
|
|
6939
|
+
var snippets2 = ({ delay = 75, items = defaultItems } = {}) => {
|
|
6940
|
+
let timer;
|
|
6941
|
+
let index = 0;
|
|
6942
|
+
return [
|
|
6943
|
+
keymap12.of([
|
|
6944
|
+
{
|
|
6945
|
+
// Reset.
|
|
6946
|
+
key: "alt-meta-'",
|
|
6947
|
+
run: () => {
|
|
6948
|
+
clearTimeout(timer);
|
|
6949
|
+
index = 0;
|
|
6950
|
+
return true;
|
|
6951
|
+
}
|
|
6952
|
+
},
|
|
6953
|
+
{
|
|
6954
|
+
// Next snippet.
|
|
6955
|
+
// TODO(burdon): Press 1-9 to select snippet?
|
|
6956
|
+
key: "Shift-Meta-'",
|
|
6957
|
+
run: (view) => {
|
|
6958
|
+
clearTimeout(timer);
|
|
6959
|
+
const text = items[index++];
|
|
6960
|
+
if (index === items?.length) {
|
|
6961
|
+
index = 0;
|
|
6962
|
+
}
|
|
6963
|
+
let offset = 0;
|
|
6964
|
+
const insert = (delayMs = 0) => {
|
|
6965
|
+
timer = setTimeout(() => {
|
|
6966
|
+
const pos = view.state.selection.main.head;
|
|
6967
|
+
view.dispatch({
|
|
6968
|
+
changes: {
|
|
6969
|
+
from: pos,
|
|
6970
|
+
insert: text[offset++]
|
|
6971
|
+
},
|
|
6972
|
+
selection: {
|
|
6973
|
+
anchor: pos + 1
|
|
6974
|
+
}
|
|
6975
|
+
});
|
|
6976
|
+
if (offset < text.length) {
|
|
6977
|
+
insert(Math.random() * delay * (text[offset] === " " ? 2 : 1));
|
|
6978
|
+
}
|
|
6979
|
+
}, delayMs);
|
|
6980
|
+
};
|
|
6981
|
+
insert();
|
|
6982
|
+
return true;
|
|
6983
|
+
}
|
|
6984
|
+
}
|
|
6985
|
+
])
|
|
6986
|
+
];
|
|
6987
|
+
};
|
|
6988
|
+
|
|
6857
6989
|
// src/extensions/submit.ts
|
|
6858
6990
|
import { Prec as Prec6 } from "@codemirror/state";
|
|
6859
|
-
import { keymap as
|
|
6991
|
+
import { keymap as keymap13 } from "@codemirror/view";
|
|
6860
6992
|
var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
6861
6993
|
return [
|
|
6862
|
-
Prec6.highest(
|
|
6994
|
+
Prec6.highest(keymap13.of([
|
|
6863
6995
|
{
|
|
6864
6996
|
key: "Enter",
|
|
6865
6997
|
preventDefault: true,
|
|
@@ -6904,6 +7036,7 @@ var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
|
6904
7036
|
// src/extensions/tags/extended-markdown.ts
|
|
6905
7037
|
import { xmlLanguage } from "@codemirror/lang-xml";
|
|
6906
7038
|
import { parseMixed } from "@lezer/common";
|
|
7039
|
+
var escapeRegExpSource = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6907
7040
|
var extendedMarkdown = ({ registry } = {}) => {
|
|
6908
7041
|
return [
|
|
6909
7042
|
createMarkdownExtensions({
|
|
@@ -6915,13 +7048,65 @@ var extendedMarkdown = ({ registry } = {}) => {
|
|
|
6915
7048
|
{
|
|
6916
7049
|
name: "SetextHeading",
|
|
6917
7050
|
parse: () => false
|
|
6918
|
-
}
|
|
7051
|
+
},
|
|
7052
|
+
// Custom XML block parser that keeps registered tags as a single HTMLBlock
|
|
7053
|
+
// even when their content contains blank lines.
|
|
7054
|
+
...xmlBlockParsers(registry)
|
|
6919
7055
|
]
|
|
6920
7056
|
}
|
|
6921
7057
|
]
|
|
6922
7058
|
})
|
|
6923
7059
|
];
|
|
6924
7060
|
};
|
|
7061
|
+
var xmlBlockParsers = (registry) => {
|
|
7062
|
+
const customTags = Object.keys(registry ?? {});
|
|
7063
|
+
if (customTags.length === 0) {
|
|
7064
|
+
return [];
|
|
7065
|
+
}
|
|
7066
|
+
const tagPattern = customTags.map(escapeRegExpSource).join("|");
|
|
7067
|
+
const selfClosePattern = new RegExp(`^\\s*<(${tagPattern})(\\s[^>]*)?\\/>\\s*$`);
|
|
7068
|
+
const openPattern = new RegExp(`^\\s*<(${tagPattern})(\\s[^>]*)?\\/?>`);
|
|
7069
|
+
return [
|
|
7070
|
+
{
|
|
7071
|
+
name: "XMLBlock",
|
|
7072
|
+
before: "HTMLBlock",
|
|
7073
|
+
parse: (cx, line) => {
|
|
7074
|
+
const match = openPattern.exec(line.text);
|
|
7075
|
+
if (!match) {
|
|
7076
|
+
return false;
|
|
7077
|
+
}
|
|
7078
|
+
if (selfClosePattern.test(line.text)) {
|
|
7079
|
+
const end2 = cx.lineStart + line.text.length;
|
|
7080
|
+
cx.addElement(cx.elt("HTMLBlock", cx.lineStart, end2));
|
|
7081
|
+
cx.nextLine();
|
|
7082
|
+
return true;
|
|
7083
|
+
}
|
|
7084
|
+
if (match[0].trimEnd().endsWith("/>")) {
|
|
7085
|
+
return false;
|
|
7086
|
+
}
|
|
7087
|
+
const tagName = match[1];
|
|
7088
|
+
const closeTag = `</${tagName}>`;
|
|
7089
|
+
const start = cx.lineStart;
|
|
7090
|
+
if (line.text.includes(closeTag)) {
|
|
7091
|
+
cx.addElement(cx.elt("HTMLBlock", start, start + line.text.length));
|
|
7092
|
+
cx.nextLine();
|
|
7093
|
+
return true;
|
|
7094
|
+
}
|
|
7095
|
+
let end = cx.lineStart + line.text.length;
|
|
7096
|
+
while (cx.nextLine()) {
|
|
7097
|
+
end = cx.lineStart + line.text.length;
|
|
7098
|
+
if (line.text.includes(closeTag)) {
|
|
7099
|
+
cx.addElement(cx.elt("HTMLBlock", start, end));
|
|
7100
|
+
cx.nextLine();
|
|
7101
|
+
return true;
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
7104
|
+
cx.addElement(cx.elt("HTMLBlock", start, end));
|
|
7105
|
+
return true;
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
];
|
|
7109
|
+
};
|
|
6925
7110
|
var mixedParser = (registry) => {
|
|
6926
7111
|
const customTags = Object.keys(registry ?? {});
|
|
6927
7112
|
const tagPattern = new RegExp(`<(${customTags.join("|")})`);
|
|
@@ -6948,226 +7133,800 @@ var mixedParser = (registry) => {
|
|
|
6948
7133
|
parser: xmlLanguage.parser
|
|
6949
7134
|
};
|
|
6950
7135
|
}
|
|
6951
|
-
return null;
|
|
7136
|
+
return null;
|
|
7137
|
+
}
|
|
7138
|
+
}
|
|
7139
|
+
return null;
|
|
7140
|
+
});
|
|
7141
|
+
};
|
|
7142
|
+
|
|
7143
|
+
// src/extensions/tags/fader.ts
|
|
7144
|
+
import { StateEffect as StateEffect10, StateField as StateField12 } from "@codemirror/state";
|
|
7145
|
+
import { Decoration as Decoration14, EditorView as EditorView29, ViewPlugin as ViewPlugin20 } from "@codemirror/view";
|
|
7146
|
+
var DEFAULT_REMOVAL_DELAY = 5e3;
|
|
7147
|
+
var DEFAULT_COALESCE_WINDOW = 100;
|
|
7148
|
+
var CLEANUP_INTERVAL = 1e3;
|
|
7149
|
+
var fader = (options = {}) => {
|
|
7150
|
+
const removalDelay = DEFAULT_REMOVAL_DELAY;
|
|
7151
|
+
const coalesceWindow = options.coalesce ?? DEFAULT_COALESCE_WINDOW;
|
|
7152
|
+
let lastCount = -1;
|
|
7153
|
+
const log12 = (expiries) => {
|
|
7154
|
+
if (expiries.length !== lastCount) {
|
|
7155
|
+
lastCount = expiries.length;
|
|
7156
|
+
}
|
|
7157
|
+
};
|
|
7158
|
+
const dequeue = StateEffect10.define();
|
|
7159
|
+
const fadeField = StateField12.define({
|
|
7160
|
+
create: () => ({
|
|
7161
|
+
decorations: Decoration14.none,
|
|
7162
|
+
expiries: [],
|
|
7163
|
+
batchStart: 0
|
|
7164
|
+
}),
|
|
7165
|
+
update: ({ decorations: decorations2, expiries, batchStart }, tr) => {
|
|
7166
|
+
for (const effect of tr.effects) {
|
|
7167
|
+
if (effect.is(dequeue)) {
|
|
7168
|
+
const now2 = effect.value;
|
|
7169
|
+
let removeCount = 0;
|
|
7170
|
+
while (removeCount < expiries.length && expiries[removeCount] <= now2) {
|
|
7171
|
+
removeCount++;
|
|
7172
|
+
}
|
|
7173
|
+
if (removeCount > 0) {
|
|
7174
|
+
expiries = expiries.slice(removeCount);
|
|
7175
|
+
let skipped = 0;
|
|
7176
|
+
decorations2 = decorations2.update({
|
|
7177
|
+
filter: () => {
|
|
7178
|
+
if (skipped < removeCount) {
|
|
7179
|
+
skipped++;
|
|
7180
|
+
return false;
|
|
7181
|
+
}
|
|
7182
|
+
return true;
|
|
7183
|
+
}
|
|
7184
|
+
});
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
if (!tr.docChanged) {
|
|
7189
|
+
log12(expiries);
|
|
7190
|
+
return {
|
|
7191
|
+
decorations: decorations2,
|
|
7192
|
+
expiries,
|
|
7193
|
+
batchStart
|
|
7194
|
+
};
|
|
7195
|
+
}
|
|
7196
|
+
let isReset = tr.state.doc.length === 0;
|
|
7197
|
+
if (!isReset && tr.startState.doc.length > 0) {
|
|
7198
|
+
tr.changes.iterChanges((fromA, toA) => {
|
|
7199
|
+
if (fromA === 0 && toA === tr.startState.doc.length) {
|
|
7200
|
+
isReset = true;
|
|
7201
|
+
}
|
|
7202
|
+
});
|
|
7203
|
+
}
|
|
7204
|
+
if (isReset) {
|
|
7205
|
+
log12([]);
|
|
7206
|
+
return {
|
|
7207
|
+
decorations: Decoration14.none,
|
|
7208
|
+
expiries: [],
|
|
7209
|
+
batchStart: 0
|
|
7210
|
+
};
|
|
7211
|
+
}
|
|
7212
|
+
const now = Date.now();
|
|
7213
|
+
const add = [];
|
|
7214
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
7215
|
+
if (toA === tr.startState.doc.length && inserted.length > 0) {
|
|
7216
|
+
add.push({
|
|
7217
|
+
from: fromB,
|
|
7218
|
+
to: toB
|
|
7219
|
+
});
|
|
7220
|
+
}
|
|
7221
|
+
});
|
|
7222
|
+
if (add.length > 0) {
|
|
7223
|
+
const canCoalesce = expiries.length > 0 && batchStart > 0 && now - batchStart < coalesceWindow;
|
|
7224
|
+
if (canCoalesce) {
|
|
7225
|
+
let lastFrom = -1;
|
|
7226
|
+
let lastTo = -1;
|
|
7227
|
+
decorations2.between(0, tr.state.doc.length, (from, to) => {
|
|
7228
|
+
lastFrom = from;
|
|
7229
|
+
lastTo = to;
|
|
7230
|
+
});
|
|
7231
|
+
if (lastFrom >= 0) {
|
|
7232
|
+
decorations2 = decorations2.update({
|
|
7233
|
+
filter: (from, to) => !(from === lastFrom && to === lastTo)
|
|
7234
|
+
});
|
|
7235
|
+
const mergedFrom = Math.min(lastFrom, add[0].from);
|
|
7236
|
+
const mergedTo = add[add.length - 1].to;
|
|
7237
|
+
decorations2 = decorations2.update({
|
|
7238
|
+
add: [
|
|
7239
|
+
Decoration14.mark({
|
|
7240
|
+
class: "cm-fader"
|
|
7241
|
+
}).range(mergedFrom, mergedTo)
|
|
7242
|
+
]
|
|
7243
|
+
});
|
|
7244
|
+
expiries = [
|
|
7245
|
+
...expiries.slice(0, -1),
|
|
7246
|
+
now + removalDelay
|
|
7247
|
+
];
|
|
7248
|
+
}
|
|
7249
|
+
} else {
|
|
7250
|
+
batchStart = now;
|
|
7251
|
+
expiries = [
|
|
7252
|
+
...expiries,
|
|
7253
|
+
now + removalDelay
|
|
7254
|
+
];
|
|
7255
|
+
decorations2 = decorations2.update({
|
|
7256
|
+
add: add.map(({ from, to }) => Decoration14.mark({
|
|
7257
|
+
class: "cm-fader"
|
|
7258
|
+
}).range(from, to))
|
|
7259
|
+
});
|
|
7260
|
+
}
|
|
7261
|
+
}
|
|
7262
|
+
log12(expiries);
|
|
7263
|
+
return {
|
|
7264
|
+
decorations: decorations2,
|
|
7265
|
+
expiries,
|
|
7266
|
+
batchStart
|
|
7267
|
+
};
|
|
7268
|
+
},
|
|
7269
|
+
provide: (f) => EditorView29.decorations.from(f, (value) => value.decorations)
|
|
7270
|
+
});
|
|
7271
|
+
const cleanup = ViewPlugin20.fromClass(class {
|
|
7272
|
+
view;
|
|
7273
|
+
#timer;
|
|
7274
|
+
constructor(view) {
|
|
7275
|
+
this.view = view;
|
|
7276
|
+
this.#schedule();
|
|
7277
|
+
}
|
|
7278
|
+
update() {
|
|
7279
|
+
this.#schedule();
|
|
7280
|
+
}
|
|
7281
|
+
#schedule() {
|
|
7282
|
+
const { expiries } = this.view.state.field(fadeField);
|
|
7283
|
+
if (expiries.length === 0) {
|
|
7284
|
+
clearTimeout(this.#timer);
|
|
7285
|
+
this.#timer = void 0;
|
|
7286
|
+
return;
|
|
7287
|
+
}
|
|
7288
|
+
if (this.#timer !== void 0) {
|
|
7289
|
+
return;
|
|
7290
|
+
}
|
|
7291
|
+
const delay = Math.max(CLEANUP_INTERVAL, expiries[0] - Date.now());
|
|
7292
|
+
this.#timer = setTimeout(() => {
|
|
7293
|
+
this.#timer = void 0;
|
|
7294
|
+
this.view.dispatch({
|
|
7295
|
+
effects: dequeue.of(Date.now())
|
|
7296
|
+
});
|
|
7297
|
+
}, delay);
|
|
7298
|
+
}
|
|
7299
|
+
destroy() {
|
|
7300
|
+
clearTimeout(this.#timer);
|
|
7301
|
+
}
|
|
7302
|
+
});
|
|
7303
|
+
return [
|
|
7304
|
+
fadeField,
|
|
7305
|
+
cleanup,
|
|
7306
|
+
EditorView29.theme({
|
|
7307
|
+
".cm-fader": {
|
|
7308
|
+
animation: "fader 1s ease-out forwards"
|
|
7309
|
+
},
|
|
7310
|
+
"@keyframes fader": {
|
|
7311
|
+
"0%": {
|
|
7312
|
+
textShadow: "0 0 16px rgba(100, 200, 255, 1), 0 0 32px rgba(100, 200, 255, 0.6)"
|
|
7313
|
+
},
|
|
7314
|
+
"100%": {}
|
|
7315
|
+
}
|
|
7316
|
+
})
|
|
7317
|
+
];
|
|
7318
|
+
};
|
|
7319
|
+
|
|
7320
|
+
// src/extensions/tags/typewriter.ts
|
|
7321
|
+
import { Annotation as Annotation3, ChangeSet as ChangeSet2, EditorState as EditorState3, StateEffect as StateEffect11, StateField as StateField13 } from "@codemirror/state";
|
|
7322
|
+
import { Decoration as Decoration15, EditorView as EditorView30, ViewPlugin as ViewPlugin21, WidgetType as WidgetType9 } from "@codemirror/view";
|
|
7323
|
+
import { Domino as Domino3 } from "@dxos/ui";
|
|
7324
|
+
var typewriterBypass = Annotation3.define();
|
|
7325
|
+
var typewriterDrainingEffect = StateEffect11.define();
|
|
7326
|
+
var CURSOR_LINGER = 3e3;
|
|
7327
|
+
var FRAME_BUDGET_MS = 4;
|
|
7328
|
+
var CHARS_PER_FRAME = 5;
|
|
7329
|
+
var FLUSH_THRESHOLD = 2e3;
|
|
7330
|
+
var COMPACT_HEAD_THRESHOLD = 4096;
|
|
7331
|
+
var typewriter = (options = {}) => {
|
|
7332
|
+
const streamingTags = options.streamingTags ?? /* @__PURE__ */ new Set();
|
|
7333
|
+
const flushThreshold = options.flushThreshold ?? FLUSH_THRESHOLD;
|
|
7334
|
+
const frameBudgetMs = options.frameBudgetMs ?? FRAME_BUDGET_MS;
|
|
7335
|
+
const charsPerFrame = options.charsPerFrame ?? CHARS_PER_FRAME;
|
|
7336
|
+
const suppressAppend = StateEffect11.define();
|
|
7337
|
+
const insertChunk = StateEffect11.define();
|
|
7338
|
+
const bufferField = StateField13.define({
|
|
7339
|
+
create: () => ({
|
|
7340
|
+
text: "",
|
|
7341
|
+
head: 0,
|
|
7342
|
+
insertAt: 0
|
|
7343
|
+
}),
|
|
7344
|
+
update: (value, tr) => {
|
|
7345
|
+
let { text, head, insertAt } = value;
|
|
7346
|
+
for (const effect of tr.effects) {
|
|
7347
|
+
if (effect.is(suppressAppend)) {
|
|
7348
|
+
if (text.length === head) {
|
|
7349
|
+
insertAt = effect.value.from;
|
|
7350
|
+
}
|
|
7351
|
+
text += effect.value.text;
|
|
7352
|
+
}
|
|
7353
|
+
if (effect.is(insertChunk)) {
|
|
7354
|
+
head += effect.value.text.length;
|
|
7355
|
+
insertAt = effect.value.from + effect.value.text.length;
|
|
7356
|
+
if (head >= COMPACT_HEAD_THRESHOLD || head > 0 && head * 2 >= text.length) {
|
|
7357
|
+
text = text.slice(head);
|
|
7358
|
+
head = 0;
|
|
7359
|
+
}
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7362
|
+
if (tr.docChanged) {
|
|
7363
|
+
let isReset = tr.state.doc.length === 0;
|
|
7364
|
+
if (!isReset && tr.startState.doc.length > 0) {
|
|
7365
|
+
tr.changes.iterChanges((fromA, toA) => {
|
|
7366
|
+
if (fromA === 0 && toA === tr.startState.doc.length) {
|
|
7367
|
+
isReset = true;
|
|
7368
|
+
}
|
|
7369
|
+
});
|
|
7370
|
+
}
|
|
7371
|
+
if (isReset) {
|
|
7372
|
+
return {
|
|
7373
|
+
text: "",
|
|
7374
|
+
head: 0,
|
|
7375
|
+
insertAt: 0
|
|
7376
|
+
};
|
|
7377
|
+
}
|
|
7378
|
+
if (!tr.effects.some((effect) => effect.is(insertChunk))) {
|
|
7379
|
+
insertAt = tr.changes.mapPos(Math.min(insertAt, tr.startState.doc.length));
|
|
7380
|
+
}
|
|
7381
|
+
}
|
|
7382
|
+
return {
|
|
7383
|
+
text,
|
|
7384
|
+
head,
|
|
7385
|
+
insertAt
|
|
7386
|
+
};
|
|
7387
|
+
}
|
|
7388
|
+
});
|
|
7389
|
+
const filter = EditorState3.transactionFilter.of((tr) => {
|
|
7390
|
+
if (!tr.docChanged) {
|
|
7391
|
+
return tr;
|
|
7392
|
+
}
|
|
7393
|
+
if (tr.annotation(typewriterBypass) || tr.effects.some((effect) => effect.is(insertChunk))) {
|
|
7394
|
+
return tr;
|
|
7395
|
+
}
|
|
7396
|
+
let appendedText = "";
|
|
7397
|
+
let appendFrom = -1;
|
|
7398
|
+
let isAppendOnly = true;
|
|
7399
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
7400
|
+
if (toA === tr.startState.doc.length && fromA === toA && inserted.length > 0) {
|
|
7401
|
+
appendedText += inserted.sliceString(0);
|
|
7402
|
+
if (appendFrom === -1) {
|
|
7403
|
+
appendFrom = fromA;
|
|
7404
|
+
}
|
|
7405
|
+
} else {
|
|
7406
|
+
isAppendOnly = false;
|
|
7407
|
+
}
|
|
7408
|
+
});
|
|
7409
|
+
if (!isAppendOnly || appendedText.length === 0) {
|
|
7410
|
+
return tr;
|
|
7411
|
+
}
|
|
7412
|
+
return {
|
|
7413
|
+
changes: ChangeSet2.empty(tr.startState.doc.length),
|
|
7414
|
+
effects: suppressAppend.of({
|
|
7415
|
+
from: appendFrom,
|
|
7416
|
+
text: appendedText
|
|
7417
|
+
})
|
|
7418
|
+
};
|
|
7419
|
+
});
|
|
7420
|
+
const drainPlugin = ViewPlugin21.fromClass(class {
|
|
7421
|
+
view;
|
|
7422
|
+
_raf;
|
|
7423
|
+
_activeStreamTag = null;
|
|
7424
|
+
constructor(view) {
|
|
7425
|
+
this.view = view;
|
|
7426
|
+
}
|
|
7427
|
+
update(update2) {
|
|
7428
|
+
const { text, head } = update2.state.field(bufferField);
|
|
7429
|
+
const pending = text.length - head;
|
|
7430
|
+
if (pending === 0) {
|
|
7431
|
+
this._activeStreamTag = null;
|
|
7432
|
+
}
|
|
7433
|
+
if (pending > 0 && this._raf === void 0) {
|
|
7434
|
+
this._start();
|
|
7435
|
+
}
|
|
7436
|
+
}
|
|
7437
|
+
_start() {
|
|
7438
|
+
queueMicrotask(() => {
|
|
7439
|
+
this.view.dispatch({
|
|
7440
|
+
effects: typewriterDrainingEffect.of(true),
|
|
7441
|
+
annotations: typewriterBypass.of(true)
|
|
7442
|
+
});
|
|
7443
|
+
});
|
|
7444
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7445
|
+
}
|
|
7446
|
+
_tick = () => {
|
|
7447
|
+
const { text, head, insertAt } = this.view.state.field(bufferField);
|
|
7448
|
+
const pending = text.length - head;
|
|
7449
|
+
if (pending === 0) {
|
|
7450
|
+
this.view.dispatch({
|
|
7451
|
+
effects: typewriterDrainingEffect.of(false),
|
|
7452
|
+
annotations: typewriterBypass.of(true)
|
|
7453
|
+
});
|
|
7454
|
+
this._raf = void 0;
|
|
7455
|
+
return;
|
|
7456
|
+
}
|
|
7457
|
+
if (pending > flushThreshold) {
|
|
7458
|
+
const chunk = text.slice(head);
|
|
7459
|
+
this._activeStreamTag = null;
|
|
7460
|
+
this.view.dispatch({
|
|
7461
|
+
changes: {
|
|
7462
|
+
from: insertAt,
|
|
7463
|
+
insert: chunk
|
|
7464
|
+
},
|
|
7465
|
+
effects: insertChunk.of({
|
|
7466
|
+
from: insertAt,
|
|
7467
|
+
text: chunk
|
|
7468
|
+
})
|
|
7469
|
+
});
|
|
7470
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7471
|
+
return;
|
|
7472
|
+
}
|
|
7473
|
+
const startTime = performance.now();
|
|
7474
|
+
let pos = head;
|
|
7475
|
+
let activeTag = this._activeStreamTag;
|
|
7476
|
+
let charsEmitted = 0;
|
|
7477
|
+
while (pos < text.length && performance.now() - startTime < frameBudgetMs) {
|
|
7478
|
+
const result = flushable(text, pos, streamingTags, activeTag);
|
|
7479
|
+
if (result.count === 0) {
|
|
7480
|
+
break;
|
|
7481
|
+
}
|
|
7482
|
+
if (charsEmitted > 0 && charsEmitted + result.count > charsPerFrame) {
|
|
7483
|
+
break;
|
|
7484
|
+
}
|
|
7485
|
+
if (result.enterTag) {
|
|
7486
|
+
activeTag = result.enterTag;
|
|
7487
|
+
}
|
|
7488
|
+
if (result.exitTag) {
|
|
7489
|
+
activeTag = null;
|
|
7490
|
+
}
|
|
7491
|
+
pos += result.count;
|
|
7492
|
+
charsEmitted += result.count;
|
|
7493
|
+
}
|
|
7494
|
+
const totalCount = pos - head;
|
|
7495
|
+
if (totalCount > 0) {
|
|
7496
|
+
const chunk = text.slice(head, head + totalCount);
|
|
7497
|
+
this._activeStreamTag = activeTag;
|
|
7498
|
+
this.view.dispatch({
|
|
7499
|
+
changes: {
|
|
7500
|
+
from: insertAt,
|
|
7501
|
+
insert: chunk
|
|
7502
|
+
},
|
|
7503
|
+
effects: insertChunk.of({
|
|
7504
|
+
from: insertAt,
|
|
7505
|
+
text: chunk
|
|
7506
|
+
})
|
|
7507
|
+
});
|
|
7508
|
+
}
|
|
7509
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7510
|
+
};
|
|
7511
|
+
destroy() {
|
|
7512
|
+
if (this._raf !== void 0) {
|
|
7513
|
+
cancelAnimationFrame(this._raf);
|
|
6952
7514
|
}
|
|
6953
7515
|
}
|
|
6954
|
-
return null;
|
|
6955
7516
|
});
|
|
6956
|
-
};
|
|
6957
|
-
|
|
6958
|
-
// src/extensions/tags/streamer.ts
|
|
6959
|
-
import { StateEffect as StateEffect8, StateField as StateField12 } from "@codemirror/state";
|
|
6960
|
-
import { Decoration as Decoration14, EditorView as EditorView28, ViewPlugin as ViewPlugin18, WidgetType as WidgetType9 } from "@codemirror/view";
|
|
6961
|
-
import { Domino as Domino3 } from "@dxos/ui";
|
|
6962
|
-
import { isTruthy as isTruthy4 } from "@dxos/util";
|
|
6963
|
-
var BLINK_RATE = 2e3;
|
|
6964
|
-
var streamer = (options = {}) => {
|
|
6965
7517
|
return [
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
7518
|
+
bufferField,
|
|
7519
|
+
filter,
|
|
7520
|
+
drainPlugin,
|
|
7521
|
+
options.cursor && typewriterCursor(bufferField)
|
|
7522
|
+
].filter(Boolean);
|
|
7523
|
+
};
|
|
7524
|
+
var typewriterCursor = (bufferField) => {
|
|
7525
|
+
const hideCursor = StateEffect11.define();
|
|
7526
|
+
const visibilityField = StateField13.define({
|
|
7527
|
+
create: () => ({
|
|
7528
|
+
visible: false,
|
|
7529
|
+
insertAt: 0,
|
|
7530
|
+
lastNonWsAt: 0
|
|
7531
|
+
}),
|
|
6974
7532
|
update: (value, tr) => {
|
|
7533
|
+
const { text, head, insertAt } = tr.state.field(bufferField);
|
|
7534
|
+
const pending = text.length - head;
|
|
7535
|
+
if (pending > 0) {
|
|
7536
|
+
let lastNonWsAt = tr.changes.mapPos(Math.min(value.lastNonWsAt, tr.startState.doc.length));
|
|
7537
|
+
if (tr.docChanged) {
|
|
7538
|
+
tr.changes.iterChanges((_fromA, _toA, _fromB, _toB, inserted) => {
|
|
7539
|
+
const chunk = inserted.sliceString(0);
|
|
7540
|
+
if (chunk.trim().length > 0) {
|
|
7541
|
+
lastNonWsAt = _fromB + chunk.length;
|
|
7542
|
+
}
|
|
7543
|
+
});
|
|
7544
|
+
}
|
|
7545
|
+
return {
|
|
7546
|
+
visible: true,
|
|
7547
|
+
insertAt,
|
|
7548
|
+
lastNonWsAt
|
|
7549
|
+
};
|
|
7550
|
+
}
|
|
6975
7551
|
for (const effect of tr.effects) {
|
|
6976
7552
|
if (effect.is(hideCursor)) {
|
|
6977
|
-
return
|
|
7553
|
+
return {
|
|
7554
|
+
...value,
|
|
7555
|
+
visible: false
|
|
7556
|
+
};
|
|
6978
7557
|
}
|
|
6979
7558
|
}
|
|
6980
|
-
if (tr.docChanged) {
|
|
6981
|
-
return true;
|
|
6982
|
-
}
|
|
6983
7559
|
return value;
|
|
6984
7560
|
}
|
|
6985
7561
|
});
|
|
6986
|
-
const
|
|
7562
|
+
const decorationField = StateField13.define({
|
|
7563
|
+
create: () => Decoration15.none,
|
|
7564
|
+
update: (_decorations, tr) => {
|
|
7565
|
+
const { visible, insertAt, lastNonWsAt } = tr.state.field(visibilityField);
|
|
7566
|
+
if (!visible) {
|
|
7567
|
+
return Decoration15.none;
|
|
7568
|
+
}
|
|
7569
|
+
const { text, head } = tr.state.field(bufferField);
|
|
7570
|
+
const cursorAt = text.length > head ? insertAt : lastNonWsAt;
|
|
7571
|
+
const pos = Math.min(cursorAt, tr.state.doc.length);
|
|
7572
|
+
return Decoration15.set([
|
|
7573
|
+
Decoration15.widget({
|
|
7574
|
+
widget: new CursorWidget(),
|
|
7575
|
+
side: 1
|
|
7576
|
+
}).range(pos)
|
|
7577
|
+
]);
|
|
7578
|
+
},
|
|
7579
|
+
provide: (field) => EditorView30.decorations.from(field)
|
|
7580
|
+
});
|
|
7581
|
+
const timerPlugin = ViewPlugin21.fromClass(class {
|
|
6987
7582
|
view;
|
|
6988
|
-
|
|
7583
|
+
_timer;
|
|
6989
7584
|
constructor(view) {
|
|
6990
7585
|
this.view = view;
|
|
6991
7586
|
}
|
|
6992
7587
|
update(update2) {
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
7588
|
+
const { text, head } = update2.state.field(bufferField);
|
|
7589
|
+
const { visible } = update2.state.field(visibilityField);
|
|
7590
|
+
const pending = text.length - head;
|
|
7591
|
+
if (pending > 0) {
|
|
7592
|
+
clearTimeout(this._timer);
|
|
7593
|
+
this._timer = void 0;
|
|
7594
|
+
} else if (visible && this._timer === void 0) {
|
|
7595
|
+
this._timer = setTimeout(() => {
|
|
6996
7596
|
this.view.dispatch({
|
|
6997
7597
|
effects: hideCursor.of(null)
|
|
6998
7598
|
});
|
|
6999
|
-
|
|
7599
|
+
this._timer = void 0;
|
|
7600
|
+
}, CURSOR_LINGER);
|
|
7000
7601
|
}
|
|
7001
7602
|
}
|
|
7002
7603
|
destroy() {
|
|
7003
|
-
clearTimeout(this.
|
|
7604
|
+
clearTimeout(this._timer);
|
|
7004
7605
|
}
|
|
7005
7606
|
});
|
|
7006
|
-
const cursorDecoration = StateField12.define({
|
|
7007
|
-
create: () => Decoration14.none,
|
|
7008
|
-
update: (_decorations, tr) => {
|
|
7009
|
-
const show = tr.state.field(showCursor);
|
|
7010
|
-
if (!show) {
|
|
7011
|
-
return Decoration14.none;
|
|
7012
|
-
}
|
|
7013
|
-
const endPos = tr.state.doc.length;
|
|
7014
|
-
return Decoration14.set([
|
|
7015
|
-
Decoration14.widget({
|
|
7016
|
-
widget: new CursorWidget(),
|
|
7017
|
-
side: 1
|
|
7018
|
-
}).range(endPos)
|
|
7019
|
-
]);
|
|
7020
|
-
},
|
|
7021
|
-
provide: (f) => EditorView28.decorations.from(f)
|
|
7022
|
-
});
|
|
7023
7607
|
return [
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7608
|
+
visibilityField,
|
|
7609
|
+
decorationField,
|
|
7610
|
+
timerPlugin
|
|
7027
7611
|
];
|
|
7028
7612
|
};
|
|
7029
|
-
var CursorWidget = class extends WidgetType9 {
|
|
7613
|
+
var CursorWidget = class _CursorWidget extends WidgetType9 {
|
|
7614
|
+
// All instances are interchangeable — let CM reuse the existing DOM across drips so
|
|
7615
|
+
// the blink animation isn't restarted on every transaction.
|
|
7616
|
+
eq(other) {
|
|
7617
|
+
return other instanceof _CursorWidget;
|
|
7618
|
+
}
|
|
7030
7619
|
toDOM() {
|
|
7031
|
-
const inner = Domino3.of("span").text("\
|
|
7032
|
-
animation: "blink
|
|
7620
|
+
const inner = Domino3.of("span").text("\u2217").style({
|
|
7621
|
+
animation: "blink 1s infinite",
|
|
7622
|
+
animationDelay: "250ms"
|
|
7033
7623
|
});
|
|
7034
7624
|
return Domino3.of("span").style({
|
|
7035
7625
|
opacity: "0.8"
|
|
7036
|
-
}).
|
|
7626
|
+
}).append(inner).root;
|
|
7037
7627
|
}
|
|
7038
7628
|
};
|
|
7039
|
-
var
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7629
|
+
var OPENING_TAG_NAME = /^<([a-zA-Z][\w-]*)/;
|
|
7630
|
+
var TAG_NAME_PROBE = 64;
|
|
7631
|
+
var escapeRegExpSource2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7632
|
+
var flushable = (buffer, start, streamingTags, activeStreamTag) => {
|
|
7633
|
+
if (start >= buffer.length) {
|
|
7634
|
+
return {
|
|
7635
|
+
count: 0
|
|
7636
|
+
};
|
|
7637
|
+
}
|
|
7638
|
+
if (activeStreamTag) {
|
|
7639
|
+
const closeTag = `</${activeStreamTag}>`;
|
|
7640
|
+
if (buffer.startsWith(closeTag, start)) {
|
|
7641
|
+
return {
|
|
7642
|
+
count: closeTag.length,
|
|
7643
|
+
exitTag: true
|
|
7644
|
+
};
|
|
7645
|
+
}
|
|
7646
|
+
if (buffer[start] === "<") {
|
|
7647
|
+
return {
|
|
7648
|
+
count: xmlElementLength(buffer, start)
|
|
7649
|
+
};
|
|
7650
|
+
}
|
|
7651
|
+
return {
|
|
7652
|
+
count: 1
|
|
7653
|
+
};
|
|
7654
|
+
}
|
|
7655
|
+
const ch = buffer[start];
|
|
7656
|
+
if (ch === "<") {
|
|
7657
|
+
const probe = buffer.slice(start, start + TAG_NAME_PROBE);
|
|
7658
|
+
const nameMatch = probe.match(OPENING_TAG_NAME);
|
|
7659
|
+
if (nameMatch && streamingTags.has(nameMatch[1])) {
|
|
7660
|
+
const close = buffer.indexOf(">", start);
|
|
7661
|
+
if (close === -1) {
|
|
7662
|
+
return {
|
|
7663
|
+
count: 0
|
|
7664
|
+
};
|
|
7058
7665
|
}
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
isReset = true;
|
|
7064
|
-
}
|
|
7065
|
-
});
|
|
7666
|
+
if (buffer[close - 1] === "/") {
|
|
7667
|
+
return {
|
|
7668
|
+
count: close + 1 - start
|
|
7669
|
+
};
|
|
7066
7670
|
}
|
|
7067
|
-
|
|
7068
|
-
|
|
7671
|
+
return {
|
|
7672
|
+
count: close + 1 - start,
|
|
7673
|
+
enterTag: nameMatch[1]
|
|
7674
|
+
};
|
|
7675
|
+
}
|
|
7676
|
+
return {
|
|
7677
|
+
count: xmlElementLength(buffer, start)
|
|
7678
|
+
};
|
|
7679
|
+
}
|
|
7680
|
+
if (ch === "!" && buffer.length > start + 1 && buffer[start + 1] === "[") {
|
|
7681
|
+
return {
|
|
7682
|
+
count: linkLength(buffer, start, start + 1)
|
|
7683
|
+
};
|
|
7684
|
+
}
|
|
7685
|
+
if (ch === "[") {
|
|
7686
|
+
return {
|
|
7687
|
+
count: linkLength(buffer, start, start)
|
|
7688
|
+
};
|
|
7689
|
+
}
|
|
7690
|
+
return {
|
|
7691
|
+
count: 1
|
|
7692
|
+
};
|
|
7693
|
+
};
|
|
7694
|
+
var xmlElementLength = (buffer, start = 0) => {
|
|
7695
|
+
const close = buffer.indexOf(">", start);
|
|
7696
|
+
if (close === -1) {
|
|
7697
|
+
return 0;
|
|
7698
|
+
}
|
|
7699
|
+
if (buffer[close - 1] === "/") {
|
|
7700
|
+
return close + 1 - start;
|
|
7701
|
+
}
|
|
7702
|
+
if (buffer[start + 1] === "/") {
|
|
7703
|
+
return close + 1 - start;
|
|
7704
|
+
}
|
|
7705
|
+
const probe = buffer.slice(start, start + TAG_NAME_PROBE);
|
|
7706
|
+
const nameMatch = probe.match(OPENING_TAG_NAME);
|
|
7707
|
+
if (!nameMatch) {
|
|
7708
|
+
return 1;
|
|
7709
|
+
}
|
|
7710
|
+
const tagName = nameMatch[1];
|
|
7711
|
+
let depth = 0;
|
|
7712
|
+
const tagPattern = new RegExp(`<(/?)${escapeRegExpSource2(tagName)}(\\s[^>]*)?>`, "g");
|
|
7713
|
+
tagPattern.lastIndex = start;
|
|
7714
|
+
let match;
|
|
7715
|
+
while ((match = tagPattern.exec(buffer)) !== null) {
|
|
7716
|
+
const isSelfClosing = match[0].endsWith("/>");
|
|
7717
|
+
const isClosing = match[1] === "/";
|
|
7718
|
+
if (isSelfClosing) {
|
|
7719
|
+
if (depth === 0) {
|
|
7720
|
+
return match.index + match[0].length - start;
|
|
7721
|
+
}
|
|
7722
|
+
} else if (isClosing) {
|
|
7723
|
+
depth--;
|
|
7724
|
+
if (depth === 0) {
|
|
7725
|
+
return match.index + match[0].length - start;
|
|
7069
7726
|
}
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7727
|
+
} else {
|
|
7728
|
+
depth++;
|
|
7729
|
+
}
|
|
7730
|
+
}
|
|
7731
|
+
return 0;
|
|
7732
|
+
};
|
|
7733
|
+
var linkLength = (buffer, start, bracketAt) => {
|
|
7734
|
+
const bracketClose = buffer.indexOf("]", bracketAt + 1);
|
|
7735
|
+
if (bracketClose === -1) {
|
|
7736
|
+
return 0;
|
|
7737
|
+
}
|
|
7738
|
+
if (bracketClose + 1 >= buffer.length) {
|
|
7739
|
+
return 0;
|
|
7740
|
+
}
|
|
7741
|
+
if (buffer[bracketClose + 1] !== "(") {
|
|
7742
|
+
return 1;
|
|
7743
|
+
}
|
|
7744
|
+
const parenClose = buffer.indexOf(")", bracketClose + 2);
|
|
7745
|
+
if (parenClose === -1) {
|
|
7746
|
+
return 0;
|
|
7747
|
+
}
|
|
7748
|
+
return parenClose + 1 - start;
|
|
7749
|
+
};
|
|
7750
|
+
|
|
7751
|
+
// src/extensions/tags/xml-block-decoration.ts
|
|
7752
|
+
import { xmlLanguage as xmlLanguage2 } from "@codemirror/lang-xml";
|
|
7753
|
+
import { Decoration as Decoration16, ViewPlugin as ViewPlugin22 } from "@codemirror/view";
|
|
7754
|
+
var xmlBlockDecoration = ({ tag, lineClass, contentClass, hideTags }) => {
|
|
7755
|
+
const lineDecoration = lineClass ? Decoration16.line({
|
|
7756
|
+
class: lineClass
|
|
7757
|
+
}) : void 0;
|
|
7758
|
+
const contentDecoration = contentClass ? Decoration16.mark({
|
|
7759
|
+
class: contentClass
|
|
7760
|
+
}) : void 0;
|
|
7761
|
+
const hideDecoration = hideTags ? Decoration16.replace({}) : void 0;
|
|
7762
|
+
const buildDecorations5 = (view) => {
|
|
7763
|
+
const text = view.state.sliceDoc(0, view.state.doc.length);
|
|
7764
|
+
if (!text.includes(`<${tag}`)) {
|
|
7765
|
+
return Decoration16.none;
|
|
7766
|
+
}
|
|
7767
|
+
const tree = xmlLanguage2.parser.parse(text);
|
|
7768
|
+
const ranges = [];
|
|
7769
|
+
tree.iterate({
|
|
7770
|
+
enter: (node) => {
|
|
7771
|
+
if (node.type.name !== "Element") {
|
|
7073
7772
|
return;
|
|
7074
7773
|
}
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7774
|
+
const openTag = node.node.getChild("OpenTag");
|
|
7775
|
+
const closeTag = node.node.getChild("CloseTag") ?? node.node.getChild("MismatchedCloseTag");
|
|
7776
|
+
const tagNameNode = openTag?.getChild("TagName");
|
|
7777
|
+
if (!openTag || !tagNameNode) {
|
|
7778
|
+
return;
|
|
7079
7779
|
}
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7780
|
+
if (text.slice(tagNameNode.from, tagNameNode.to) !== tag) {
|
|
7781
|
+
return;
|
|
7782
|
+
}
|
|
7783
|
+
const contentFrom = openTag.to;
|
|
7784
|
+
const contentTo = closeTag?.from ?? node.node.to;
|
|
7785
|
+
if (hideDecoration) {
|
|
7786
|
+
ranges.push(hideDecoration.range(openTag.from, openTag.to));
|
|
7787
|
+
if (closeTag) {
|
|
7788
|
+
ranges.push(hideDecoration.range(closeTag.from, closeTag.to));
|
|
7789
|
+
}
|
|
7790
|
+
}
|
|
7791
|
+
if (contentDecoration && contentFrom < contentTo) {
|
|
7792
|
+
ranges.push(contentDecoration.range(contentFrom, contentTo));
|
|
7793
|
+
}
|
|
7794
|
+
if (lineDecoration && contentFrom <= view.state.doc.length) {
|
|
7795
|
+
let pos = contentFrom;
|
|
7796
|
+
while (pos <= contentTo && pos <= view.state.doc.length) {
|
|
7797
|
+
const line = view.state.doc.lineAt(pos);
|
|
7798
|
+
ranges.push(lineDecoration.range(line.from));
|
|
7799
|
+
if (line.to >= contentTo) {
|
|
7800
|
+
break;
|
|
7801
|
+
}
|
|
7802
|
+
pos = line.to + 1;
|
|
7803
|
+
}
|
|
7804
|
+
}
|
|
7805
|
+
}
|
|
7806
|
+
});
|
|
7807
|
+
return Decoration16.set(ranges, true);
|
|
7808
|
+
};
|
|
7809
|
+
return ViewPlugin22.fromClass(class {
|
|
7810
|
+
decorations;
|
|
7091
7811
|
constructor(view) {
|
|
7092
|
-
this.
|
|
7812
|
+
this.decorations = buildDecorations5(view);
|
|
7093
7813
|
}
|
|
7094
7814
|
update(update2) {
|
|
7095
|
-
if (
|
|
7096
|
-
|
|
7815
|
+
if (update2.docChanged) {
|
|
7816
|
+
this.decorations = buildDecorations5(update2.view);
|
|
7097
7817
|
}
|
|
7098
|
-
|
|
7099
|
-
|
|
7818
|
+
}
|
|
7819
|
+
}, {
|
|
7820
|
+
decorations: (instance) => instance.decorations
|
|
7821
|
+
});
|
|
7822
|
+
};
|
|
7823
|
+
|
|
7824
|
+
// src/extensions/tags/xml-formatting.ts
|
|
7825
|
+
import { xmlLanguage as xmlLanguage3 } from "@codemirror/lang-xml";
|
|
7826
|
+
import { Decoration as Decoration17, EditorView as EditorView31, ViewPlugin as ViewPlugin23 } from "@codemirror/view";
|
|
7827
|
+
var XML_TAG_NODES = /* @__PURE__ */ new Set([
|
|
7828
|
+
"OpenTag",
|
|
7829
|
+
"CloseTag",
|
|
7830
|
+
"SelfClosingTag",
|
|
7831
|
+
"MismatchedCloseTag"
|
|
7832
|
+
]);
|
|
7833
|
+
var xmlElementMark = Decoration17.mark({
|
|
7834
|
+
class: "cm-xml-element"
|
|
7835
|
+
});
|
|
7836
|
+
var xmlTagMark = Decoration17.mark({
|
|
7837
|
+
class: "cm-xml-tag"
|
|
7838
|
+
});
|
|
7839
|
+
var xmlContentMark = Decoration17.mark({
|
|
7840
|
+
class: "cm-xml-content"
|
|
7841
|
+
});
|
|
7842
|
+
var xmlFormatting = ({ skip } = {}) => {
|
|
7843
|
+
const skipSet = skip && skip.length > 0 ? new Set(skip) : void 0;
|
|
7844
|
+
const buildDecorations5 = (view) => {
|
|
7845
|
+
const text = view.state.sliceDoc(0, view.state.doc.length);
|
|
7846
|
+
if (!text.includes("<")) {
|
|
7847
|
+
return Decoration17.none;
|
|
7848
|
+
}
|
|
7849
|
+
const tagNameAt = (node) => text.slice(node.from, node.to);
|
|
7850
|
+
const tree = xmlLanguage3.parser.parse(text);
|
|
7851
|
+
const ranges = [];
|
|
7852
|
+
tree.iterate({
|
|
7853
|
+
enter: (node) => {
|
|
7854
|
+
const name = node.type.name;
|
|
7855
|
+
if (name === "SelfClosingTag" && node.from < node.to) {
|
|
7856
|
+
if (skipSet) {
|
|
7857
|
+
const tagNameNode = node.node.getChild("TagName");
|
|
7858
|
+
if (tagNameNode && skipSet.has(tagNameAt(tagNameNode))) {
|
|
7859
|
+
return false;
|
|
7860
|
+
}
|
|
7861
|
+
}
|
|
7862
|
+
ranges.push(xmlElementMark.range(node.from, node.to));
|
|
7863
|
+
ranges.push(xmlTagMark.range(node.from, node.to));
|
|
7100
7864
|
return;
|
|
7101
7865
|
}
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7866
|
+
if (XML_TAG_NODES.has(name) && node.from < node.to) {
|
|
7867
|
+
ranges.push(xmlTagMark.range(node.from, node.to));
|
|
7868
|
+
return;
|
|
7869
|
+
}
|
|
7870
|
+
if (name === "Element" && node.from < node.to) {
|
|
7871
|
+
const openTag = node.node.getChild("OpenTag");
|
|
7872
|
+
if (openTag && skipSet) {
|
|
7873
|
+
const tagNameNode = openTag.getChild("TagName");
|
|
7874
|
+
if (tagNameNode && skipSet.has(tagNameAt(tagNameNode))) {
|
|
7875
|
+
return false;
|
|
7876
|
+
}
|
|
7877
|
+
}
|
|
7878
|
+
const closeTag = node.node.getChild("CloseTag") ?? node.node.getChild("MismatchedCloseTag");
|
|
7879
|
+
ranges.push(xmlElementMark.range(node.from, node.to));
|
|
7880
|
+
if (openTag && closeTag && openTag.to < closeTag.from) {
|
|
7881
|
+
ranges.push(xmlContentMark.range(openTag.to, closeTag.from));
|
|
7882
|
+
}
|
|
7105
7883
|
}
|
|
7106
|
-
const totalDelay = FADE_IN_DURATION + removalDelay;
|
|
7107
|
-
const id = setTimeout(() => {
|
|
7108
|
-
this.view.dispatch({
|
|
7109
|
-
effects: removeDecoration.of({
|
|
7110
|
-
from: fromB,
|
|
7111
|
-
to: toB
|
|
7112
|
-
})
|
|
7113
|
-
});
|
|
7114
|
-
this._timers.delete(key);
|
|
7115
|
-
}, totalDelay);
|
|
7116
|
-
this._timers.set(key, id);
|
|
7117
|
-
});
|
|
7118
|
-
}
|
|
7119
|
-
destroy() {
|
|
7120
|
-
for (const id of this._timers.values()) {
|
|
7121
|
-
clearTimeout(id);
|
|
7122
7884
|
}
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
}
|
|
7885
|
+
});
|
|
7886
|
+
return Decoration17.set(ranges, true);
|
|
7887
|
+
};
|
|
7126
7888
|
return [
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
},
|
|
7136
|
-
"@keyframes fade-in": {
|
|
7137
|
-
"0%": {
|
|
7138
|
-
opacity: "0"
|
|
7139
|
-
},
|
|
7140
|
-
"80%": {
|
|
7141
|
-
opacity: "1"
|
|
7142
|
-
},
|
|
7143
|
-
"100%": {
|
|
7144
|
-
opacity: "0.8"
|
|
7889
|
+
ViewPlugin23.fromClass(class {
|
|
7890
|
+
decorations;
|
|
7891
|
+
constructor(view) {
|
|
7892
|
+
this.decorations = buildDecorations5(view);
|
|
7893
|
+
}
|
|
7894
|
+
update(update2) {
|
|
7895
|
+
if (update2.docChanged) {
|
|
7896
|
+
this.decorations = buildDecorations5(update2.view);
|
|
7145
7897
|
}
|
|
7146
7898
|
}
|
|
7899
|
+
}, {
|
|
7900
|
+
decorations: (instance) => instance.decorations
|
|
7901
|
+
}),
|
|
7902
|
+
EditorView31.baseTheme({
|
|
7903
|
+
".cm-xml-element": {
|
|
7904
|
+
backgroundColor: "var(--color-current-surface)",
|
|
7905
|
+
borderRadius: "0.25rem",
|
|
7906
|
+
padding: "0.25rem"
|
|
7907
|
+
},
|
|
7908
|
+
".cm-xml-tag": {
|
|
7909
|
+
color: "var(--color-blue-500)",
|
|
7910
|
+
fontFamily: "var(--font-mono)"
|
|
7911
|
+
},
|
|
7912
|
+
".cm-xml-content": {}
|
|
7147
7913
|
})
|
|
7148
7914
|
];
|
|
7149
7915
|
};
|
|
7150
7916
|
|
|
7151
7917
|
// src/extensions/tags/xml-tags.ts
|
|
7152
7918
|
import { syntaxTree as syntaxTree11 } from "@codemirror/language";
|
|
7153
|
-
import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as
|
|
7154
|
-
import { Decoration as
|
|
7919
|
+
import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as StateEffect12, StateField as StateField14 } from "@codemirror/state";
|
|
7920
|
+
import { Decoration as Decoration18, EditorView as EditorView32, ViewPlugin as ViewPlugin24, WidgetType as WidgetType10, keymap as keymap14 } from "@codemirror/view";
|
|
7155
7921
|
import { invariant as invariant7 } from "@dxos/invariant";
|
|
7156
7922
|
import { log as log11 } from "@dxos/log";
|
|
7923
|
+
import { Domino as Domino4 } from "@dxos/ui";
|
|
7157
7924
|
|
|
7158
7925
|
// src/extensions/tags/xml-util.ts
|
|
7159
7926
|
import { invariant as invariant6 } from "@dxos/invariant";
|
|
7160
7927
|
var __dxlog_file16 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-util.ts";
|
|
7161
7928
|
var nodeToJson = (state, node) => {
|
|
7162
|
-
invariant6(node.type.name === "Element", "Node is not an Element", {
|
|
7163
|
-
F: __dxlog_file16,
|
|
7164
|
-
L: 18,
|
|
7165
|
-
S: void 0,
|
|
7166
|
-
A: [
|
|
7167
|
-
"node.type.name === 'Element'",
|
|
7168
|
-
"'Node is not an Element'"
|
|
7169
|
-
]
|
|
7170
|
-
});
|
|
7929
|
+
invariant6(node.type.name === "Element", "Node is not an Element", { "~LogMeta": "~LogMeta", F: __dxlog_file16, L: 8, S: void 0, A: ["node.type.name === 'Element'", "'Node is not an Element'"] });
|
|
7171
7930
|
const openTag = node.node.getChild("OpenTag") || node.node.getChild("SelfClosingTag");
|
|
7172
7931
|
if (openTag) {
|
|
7173
7932
|
const tagName = openTag.getChild("TagName");
|
|
@@ -7199,13 +7958,23 @@ var nodeToJson = (state, node) => {
|
|
|
7199
7958
|
if (node.type.name === "Element" && openTag.type.name !== "SelfClosingTag") {
|
|
7200
7959
|
const children = [];
|
|
7201
7960
|
let child = node.node.firstChild;
|
|
7961
|
+
const appendText = (raw) => {
|
|
7962
|
+
if (raw.length === 0) {
|
|
7963
|
+
return;
|
|
7964
|
+
}
|
|
7965
|
+
const last = children[children.length - 1];
|
|
7966
|
+
if (typeof last === "string") {
|
|
7967
|
+
children[children.length - 1] = last + raw;
|
|
7968
|
+
} else {
|
|
7969
|
+
children.push(raw);
|
|
7970
|
+
}
|
|
7971
|
+
};
|
|
7202
7972
|
while (child) {
|
|
7203
7973
|
if (child.type.name !== "OpenTag" && child.type.name !== "CloseTag") {
|
|
7204
7974
|
if (child.type.name === "Text") {
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
}
|
|
7975
|
+
appendText(state.doc.sliceString(child.from, child.to));
|
|
7976
|
+
} else if (child.type.name === "EntityReference" || child.type.name === "CharacterReference") {
|
|
7977
|
+
appendText(decodeXmlEntity(state.doc.sliceString(child.from, child.to)));
|
|
7209
7978
|
} else if (child.type.name === "Element") {
|
|
7210
7979
|
const data = nodeToJson(state, child);
|
|
7211
7980
|
if (data) {
|
|
@@ -7215,26 +7984,63 @@ var nodeToJson = (state, node) => {
|
|
|
7215
7984
|
}
|
|
7216
7985
|
child = child.nextSibling;
|
|
7217
7986
|
}
|
|
7987
|
+
if (children.length > 0 && typeof children[0] === "string") {
|
|
7988
|
+
children[0] = children[0].trimStart();
|
|
7989
|
+
}
|
|
7218
7990
|
if (children.length > 0) {
|
|
7219
|
-
|
|
7991
|
+
const lastIndex = children.length - 1;
|
|
7992
|
+
const last = children[lastIndex];
|
|
7993
|
+
if (typeof last === "string") {
|
|
7994
|
+
children[lastIndex] = last.trimEnd();
|
|
7995
|
+
}
|
|
7996
|
+
}
|
|
7997
|
+
const trimmed = children.filter((value) => typeof value !== "string" || value.length > 0);
|
|
7998
|
+
if (trimmed.length > 0) {
|
|
7999
|
+
tag.children = trimmed;
|
|
7220
8000
|
}
|
|
7221
8001
|
}
|
|
7222
8002
|
return tag;
|
|
7223
8003
|
}
|
|
7224
8004
|
};
|
|
8005
|
+
var XML_NAMED_ENTITIES = {
|
|
8006
|
+
"<": "<",
|
|
8007
|
+
">": ">",
|
|
8008
|
+
"&": "&",
|
|
8009
|
+
""": '"',
|
|
8010
|
+
"'": "'"
|
|
8011
|
+
};
|
|
8012
|
+
var decodeXmlEntity = (raw) => {
|
|
8013
|
+
const named = XML_NAMED_ENTITIES[raw];
|
|
8014
|
+
if (named !== void 0) {
|
|
8015
|
+
return named;
|
|
8016
|
+
}
|
|
8017
|
+
const numeric = /^&#(x?)([0-9a-fA-F]+);$/.exec(raw);
|
|
8018
|
+
if (numeric) {
|
|
8019
|
+
const code = parseInt(numeric[2], numeric[1] ? 16 : 10);
|
|
8020
|
+
if (Number.isFinite(code)) {
|
|
8021
|
+
try {
|
|
8022
|
+
return String.fromCodePoint(code);
|
|
8023
|
+
} catch {
|
|
8024
|
+
}
|
|
8025
|
+
}
|
|
8026
|
+
}
|
|
8027
|
+
return raw;
|
|
8028
|
+
};
|
|
7225
8029
|
|
|
7226
8030
|
// src/extensions/tags/xml-tags.ts
|
|
7227
8031
|
var __dxlog_file17 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-tags.ts";
|
|
7228
|
-
var navigatePreviousEffect =
|
|
7229
|
-
var navigateNextEffect =
|
|
8032
|
+
var navigatePreviousEffect = StateEffect12.define();
|
|
8033
|
+
var navigateNextEffect = StateEffect12.define();
|
|
7230
8034
|
var getXmlTextChild = (children) => {
|
|
7231
8035
|
const child = children?.[0];
|
|
7232
8036
|
return typeof child === "string" ? child : null;
|
|
7233
8037
|
};
|
|
7234
|
-
var
|
|
7235
|
-
var
|
|
7236
|
-
var
|
|
7237
|
-
var
|
|
8038
|
+
var xmlWidgetId = (explicit, fallback) => typeof explicit === "string" && explicit.length > 0 ? explicit : fallback;
|
|
8039
|
+
var escapeRegExpSource3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8040
|
+
var xmlTagContextEffect = StateEffect12.define();
|
|
8041
|
+
var xmlTagResetEffect = StateEffect12.define();
|
|
8042
|
+
var xmlTagUpdateEffect = StateEffect12.define();
|
|
8043
|
+
var widgetContextStateField = StateField14.define({
|
|
7238
8044
|
create: () => void 0,
|
|
7239
8045
|
update: (value, tr) => {
|
|
7240
8046
|
for (const effect of tr.effects) {
|
|
@@ -7245,7 +8051,7 @@ var widgetContextStateField = StateField13.define({
|
|
|
7245
8051
|
return value;
|
|
7246
8052
|
}
|
|
7247
8053
|
});
|
|
7248
|
-
var widgetStateMapStateField =
|
|
8054
|
+
var widgetStateMapStateField = StateField14.define({
|
|
7249
8055
|
create: () => ({}),
|
|
7250
8056
|
update: (map, tr) => {
|
|
7251
8057
|
for (const effect of tr.effects) {
|
|
@@ -7257,12 +8063,7 @@ var widgetStateMapStateField = StateField13.define({
|
|
|
7257
8063
|
log11("widget updated", {
|
|
7258
8064
|
id,
|
|
7259
8065
|
value
|
|
7260
|
-
}, {
|
|
7261
|
-
F: __dxlog_file17,
|
|
7262
|
-
L: 153,
|
|
7263
|
-
S: void 0,
|
|
7264
|
-
C: (f, a) => f(...a)
|
|
7265
|
-
});
|
|
8066
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 59, S: void 0 });
|
|
7266
8067
|
const state = typeof value === "function" ? value(map[id]) : value;
|
|
7267
8068
|
return {
|
|
7268
8069
|
...map,
|
|
@@ -7292,12 +8093,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7292
8093
|
log11("widget mounted", {
|
|
7293
8094
|
id: state.id,
|
|
7294
8095
|
tag: state.props._tag
|
|
7295
|
-
}, {
|
|
7296
|
-
F: __dxlog_file17,
|
|
7297
|
-
L: 206,
|
|
7298
|
-
S: void 0,
|
|
7299
|
-
C: (f, a) => f(...a)
|
|
7300
|
-
});
|
|
8096
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 101, S: void 0 });
|
|
7301
8097
|
widgets.set(state.id, state);
|
|
7302
8098
|
setWidgets?.([
|
|
7303
8099
|
...widgets.values()
|
|
@@ -7308,12 +8104,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7308
8104
|
log11("widget unmounted", {
|
|
7309
8105
|
id,
|
|
7310
8106
|
tag: state?.props._tag
|
|
7311
|
-
}, {
|
|
7312
|
-
F: __dxlog_file17,
|
|
7313
|
-
L: 212,
|
|
7314
|
-
S: void 0,
|
|
7315
|
-
C: (f, a) => f(...a)
|
|
7316
|
-
});
|
|
8107
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 112, S: void 0 });
|
|
7317
8108
|
widgets.delete(id);
|
|
7318
8109
|
setWidgets?.([
|
|
7319
8110
|
...widgets.values()
|
|
@@ -7322,7 +8113,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7322
8113
|
};
|
|
7323
8114
|
return notifier;
|
|
7324
8115
|
};
|
|
7325
|
-
var keyHandlers =
|
|
8116
|
+
var keyHandlers = keymap14.of([
|
|
7326
8117
|
{
|
|
7327
8118
|
key: "Mod-ArrowUp",
|
|
7328
8119
|
run: (view) => {
|
|
@@ -7343,7 +8134,7 @@ var keyHandlers = keymap13.of([
|
|
|
7343
8134
|
}
|
|
7344
8135
|
]);
|
|
7345
8136
|
var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
7346
|
-
return
|
|
8137
|
+
return EditorView32.updateListener.of((update2) => {
|
|
7347
8138
|
update2.transactions.forEach((transaction) => {
|
|
7348
8139
|
for (const effect of transaction.effects) {
|
|
7349
8140
|
if (effect.is(navigatePreviousEffect)) {
|
|
@@ -7371,7 +8162,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7371
8162
|
anchor: line.from,
|
|
7372
8163
|
head: line.from
|
|
7373
8164
|
},
|
|
7374
|
-
effects:
|
|
8165
|
+
effects: crawlerLineEffect.of({
|
|
7375
8166
|
line: line.number - 1,
|
|
7376
8167
|
offset: -16
|
|
7377
8168
|
})
|
|
@@ -7404,7 +8195,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7404
8195
|
anchor: line.to,
|
|
7405
8196
|
head: line.to
|
|
7406
8197
|
},
|
|
7407
|
-
effects:
|
|
8198
|
+
effects: crawlerLineEffect.of({
|
|
7408
8199
|
line: line.number - 1,
|
|
7409
8200
|
offset: -16
|
|
7410
8201
|
})
|
|
@@ -7416,7 +8207,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7416
8207
|
anchor: line.to,
|
|
7417
8208
|
head: line.to
|
|
7418
8209
|
},
|
|
7419
|
-
effects:
|
|
8210
|
+
effects: crawlerLineEffect.of({
|
|
7420
8211
|
line: line.number - 1,
|
|
7421
8212
|
position: "end"
|
|
7422
8213
|
})
|
|
@@ -7428,7 +8219,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7428
8219
|
});
|
|
7429
8220
|
});
|
|
7430
8221
|
};
|
|
7431
|
-
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) =>
|
|
8222
|
+
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin24.fromClass(class {
|
|
7432
8223
|
update(update2) {
|
|
7433
8224
|
const widgetStateMap = update2.state.field(widgetStateMapStateField);
|
|
7434
8225
|
const { decorations: decorations2 } = update2.state.field(widgetDecorationsField);
|
|
@@ -7455,14 +8246,14 @@ var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin1
|
|
|
7455
8246
|
}
|
|
7456
8247
|
}
|
|
7457
8248
|
});
|
|
7458
|
-
var createWidgetDecorationsField = (registry = {}, notifier) =>
|
|
8249
|
+
var createWidgetDecorationsField = (registry = {}, notifier) => StateField14.define({
|
|
7459
8250
|
create: (state) => {
|
|
7460
8251
|
return buildDecorations4(state, {
|
|
7461
8252
|
from: 0,
|
|
7462
8253
|
to: state.doc.length
|
|
7463
8254
|
}, registry, notifier);
|
|
7464
8255
|
},
|
|
7465
|
-
update: ({ from, decorations: decorations2 }, tr) => {
|
|
8256
|
+
update: ({ from, streamingFrom, decorations: decorations2 }, tr) => {
|
|
7466
8257
|
for (const effect of tr.effects) {
|
|
7467
8258
|
if (effect.is(xmlTagResetEffect)) {
|
|
7468
8259
|
if (tr.docChanged) {
|
|
@@ -7473,7 +8264,7 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7473
8264
|
}
|
|
7474
8265
|
return {
|
|
7475
8266
|
from: 0,
|
|
7476
|
-
decorations:
|
|
8267
|
+
decorations: Decoration18.none
|
|
7477
8268
|
};
|
|
7478
8269
|
}
|
|
7479
8270
|
}
|
|
@@ -7484,24 +8275,23 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7484
8275
|
log11("document reset", {
|
|
7485
8276
|
from,
|
|
7486
8277
|
to: state.doc.length
|
|
7487
|
-
}, {
|
|
7488
|
-
F: __dxlog_file17,
|
|
7489
|
-
L: 374,
|
|
7490
|
-
S: void 0,
|
|
7491
|
-
C: (f, a) => f(...a)
|
|
7492
|
-
});
|
|
8278
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 298, S: void 0 });
|
|
7493
8279
|
return buildDecorations4(state, {
|
|
7494
8280
|
from: 0,
|
|
7495
8281
|
to: state.doc.length
|
|
7496
8282
|
}, registry, notifier);
|
|
7497
8283
|
} else {
|
|
8284
|
+
const rebuildFrom = streamingFrom ?? from;
|
|
7498
8285
|
const result = buildDecorations4(state, {
|
|
7499
|
-
from,
|
|
8286
|
+
from: rebuildFrom,
|
|
7500
8287
|
to: state.doc.length
|
|
7501
8288
|
}, registry, notifier);
|
|
7502
8289
|
return {
|
|
7503
8290
|
from: result.from,
|
|
8291
|
+
streamingFrom: result.streamingFrom,
|
|
7504
8292
|
decorations: decorations2.update({
|
|
8293
|
+
// Remove old streaming decorations — they are rebuilt each tick.
|
|
8294
|
+
filter: (_f, _t, deco) => !deco.spec.streaming,
|
|
7505
8295
|
add: decorationSetToArray(result.decorations)
|
|
7506
8296
|
})
|
|
7507
8297
|
};
|
|
@@ -7509,12 +8299,13 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7509
8299
|
}
|
|
7510
8300
|
return {
|
|
7511
8301
|
from,
|
|
8302
|
+
streamingFrom,
|
|
7512
8303
|
decorations: decorations2
|
|
7513
8304
|
};
|
|
7514
8305
|
},
|
|
7515
8306
|
provide: (field) => [
|
|
7516
|
-
|
|
7517
|
-
|
|
8307
|
+
EditorView32.decorations.from(field, (v) => v.decorations),
|
|
8308
|
+
EditorView32.atomicRanges.of((view) => view.state.field(field).decorations || Decoration18.none)
|
|
7518
8309
|
]
|
|
7519
8310
|
});
|
|
7520
8311
|
var buildDecorations4 = (state, range, registry, notifier) => {
|
|
@@ -7525,10 +8316,11 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7525
8316
|
if (!tree || tree.type.name === "Program" && tree.length === 0) {
|
|
7526
8317
|
return {
|
|
7527
8318
|
from: range.from,
|
|
7528
|
-
decorations:
|
|
8319
|
+
decorations: Decoration18.none
|
|
7529
8320
|
};
|
|
7530
8321
|
}
|
|
7531
8322
|
let last = range.from;
|
|
8323
|
+
let streamingFrom;
|
|
7532
8324
|
tree.iterate({
|
|
7533
8325
|
from: range.from,
|
|
7534
8326
|
to: range.to,
|
|
@@ -7541,21 +8333,26 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7541
8333
|
if (args) {
|
|
7542
8334
|
const def = registry[args._tag];
|
|
7543
8335
|
if (def) {
|
|
8336
|
+
if (def.streaming && !node.node.getChild("CloseTag")) {
|
|
8337
|
+
return false;
|
|
8338
|
+
}
|
|
7544
8339
|
const { block, factory, Component } = def;
|
|
7545
|
-
const widgetState = args.id ? widgetStateMap[args.id] : void 0;
|
|
7546
8340
|
const nodeRange = {
|
|
7547
8341
|
from: node.node.from,
|
|
7548
8342
|
to: node.node.to
|
|
7549
8343
|
};
|
|
8344
|
+
const widgetId = xmlWidgetId(args.id, def.streaming ? `cm-xml-${nodeRange.from}` : `cm-xml-${nodeRange.from}-${nodeRange.to}`);
|
|
8345
|
+
const widgetState = widgetStateMap[widgetId];
|
|
7550
8346
|
const props = {
|
|
7551
|
-
|
|
8347
|
+
id: widgetId,
|
|
7552
8348
|
range: nodeRange,
|
|
8349
|
+
context,
|
|
7553
8350
|
...args,
|
|
7554
8351
|
...widgetState
|
|
7555
8352
|
};
|
|
7556
|
-
const widget = factory ? factory(props) : Component ?
|
|
8353
|
+
const widget = factory ? factory(props) ?? void 0 : Component ? new PlaceholderWidget2(widgetId, Component, props, notifier) : void 0;
|
|
7557
8354
|
if (widget) {
|
|
7558
|
-
builder.add(nodeRange.from, nodeRange.to,
|
|
8355
|
+
builder.add(nodeRange.from, nodeRange.to, Decoration18.replace({
|
|
7559
8356
|
widget,
|
|
7560
8357
|
block,
|
|
7561
8358
|
atomic: true,
|
|
@@ -7567,20 +8364,72 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7567
8364
|
}
|
|
7568
8365
|
}
|
|
7569
8366
|
} catch (err) {
|
|
7570
|
-
log11.catch(err, void 0, {
|
|
7571
|
-
F: __dxlog_file17,
|
|
7572
|
-
L: 459,
|
|
7573
|
-
S: void 0,
|
|
7574
|
-
C: (f, a) => f(...a)
|
|
7575
|
-
});
|
|
8367
|
+
log11.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 401, S: void 0 });
|
|
7576
8368
|
}
|
|
7577
8369
|
return false;
|
|
7578
8370
|
}
|
|
7579
8371
|
}
|
|
7580
8372
|
}
|
|
7581
8373
|
});
|
|
8374
|
+
const streamingTagNames = Object.entries(registry).filter(([, def]) => def.streaming).map(([name]) => name).sort((a, b) => b.length - a.length);
|
|
8375
|
+
if (streamingTagNames.length > 0) {
|
|
8376
|
+
const tailText = state.sliceDoc(range.from, range.to);
|
|
8377
|
+
const streamingPattern = streamingTagNames.map(escapeRegExpSource3).join("|");
|
|
8378
|
+
const tagPattern = new RegExp(`<(${streamingPattern})(\\s[^>]*)?>`, "g");
|
|
8379
|
+
let match;
|
|
8380
|
+
while ((match = tagPattern.exec(tailText)) !== null) {
|
|
8381
|
+
const tagName = match[1];
|
|
8382
|
+
const closeTag = `</${tagName}>`;
|
|
8383
|
+
const afterOpen = match.index + match[0].length;
|
|
8384
|
+
if (tailText.indexOf(closeTag, afterOpen) === -1) {
|
|
8385
|
+
const absoluteFrom = range.from + match.index;
|
|
8386
|
+
const contentFrom = range.from + afterOpen;
|
|
8387
|
+
const innerText = state.sliceDoc(contentFrom, range.to).trim();
|
|
8388
|
+
const def = registry[tagName];
|
|
8389
|
+
const props = {
|
|
8390
|
+
_tag: tagName,
|
|
8391
|
+
context,
|
|
8392
|
+
range: {
|
|
8393
|
+
from: absoluteFrom,
|
|
8394
|
+
to: range.to
|
|
8395
|
+
},
|
|
8396
|
+
children: innerText ? [
|
|
8397
|
+
innerText
|
|
8398
|
+
] : void 0
|
|
8399
|
+
};
|
|
8400
|
+
const attrPattern = /(\w+)="([^"]*)"/g;
|
|
8401
|
+
let attrMatch;
|
|
8402
|
+
while ((attrMatch = attrPattern.exec(match[0])) !== null) {
|
|
8403
|
+
props[attrMatch[1]] = attrMatch[2];
|
|
8404
|
+
}
|
|
8405
|
+
const widgetId = xmlWidgetId(props.id, `cm-xml-${absoluteFrom}`);
|
|
8406
|
+
const widgetState = widgetStateMap[widgetId];
|
|
8407
|
+
const mergedProps = {
|
|
8408
|
+
...props,
|
|
8409
|
+
id: widgetId,
|
|
8410
|
+
...widgetState
|
|
8411
|
+
};
|
|
8412
|
+
const widget = def.factory ? def.factory(mergedProps) ?? void 0 : def.Component ? new PlaceholderWidget2(widgetId, def.Component, mergedProps, notifier, true) : void 0;
|
|
8413
|
+
if (widget) {
|
|
8414
|
+
builder.add(absoluteFrom, range.to, Decoration18.replace({
|
|
8415
|
+
widget,
|
|
8416
|
+
block: def.block,
|
|
8417
|
+
atomic: true,
|
|
8418
|
+
inclusive: true,
|
|
8419
|
+
tag: tagName,
|
|
8420
|
+
streaming: true,
|
|
8421
|
+
contentFrom
|
|
8422
|
+
}));
|
|
8423
|
+
streamingFrom = absoluteFrom;
|
|
8424
|
+
last = absoluteFrom;
|
|
8425
|
+
}
|
|
8426
|
+
break;
|
|
8427
|
+
}
|
|
8428
|
+
}
|
|
8429
|
+
}
|
|
7582
8430
|
return {
|
|
7583
8431
|
from: last,
|
|
8432
|
+
streamingFrom,
|
|
7584
8433
|
decorations: builder.finish()
|
|
7585
8434
|
};
|
|
7586
8435
|
};
|
|
@@ -7589,108 +8438,62 @@ var PlaceholderWidget2 = class extends WidgetType10 {
|
|
|
7589
8438
|
Component;
|
|
7590
8439
|
props;
|
|
7591
8440
|
notifier;
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
S: this,
|
|
7599
|
-
A: [
|
|
7600
|
-
"id",
|
|
7601
|
-
""
|
|
7602
|
-
]
|
|
7603
|
-
});
|
|
8441
|
+
streaming;
|
|
8442
|
+
#root = null;
|
|
8443
|
+
#view;
|
|
8444
|
+
constructor(id, Component, props, notifier, streaming) {
|
|
8445
|
+
super(), this.id = id, this.Component = Component, this.props = props, this.notifier = notifier, this.streaming = streaming;
|
|
8446
|
+
invariant7(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 488, S: this, A: ["id", ""] });
|
|
7604
8447
|
}
|
|
7605
8448
|
get root() {
|
|
7606
|
-
return this
|
|
8449
|
+
return this.#root;
|
|
7607
8450
|
}
|
|
7608
8451
|
eq(other) {
|
|
8452
|
+
if (this.streaming) {
|
|
8453
|
+
return false;
|
|
8454
|
+
}
|
|
7609
8455
|
return this.id === other.id;
|
|
7610
8456
|
}
|
|
7611
8457
|
ignoreEvent() {
|
|
7612
8458
|
return true;
|
|
7613
8459
|
}
|
|
7614
|
-
toDOM(
|
|
7615
|
-
this
|
|
8460
|
+
toDOM(view) {
|
|
8461
|
+
this.#view = view;
|
|
8462
|
+
this.#root = Domino4.of("div").classNames("min-h-[24px]").root;
|
|
8463
|
+
const props = Object.assign({}, this.props, {
|
|
8464
|
+
view
|
|
8465
|
+
});
|
|
8466
|
+
this.notifier.mounted({
|
|
8467
|
+
id: this.id,
|
|
8468
|
+
root: this.#root,
|
|
8469
|
+
props,
|
|
8470
|
+
Component: this.Component
|
|
8471
|
+
});
|
|
8472
|
+
return this.#root;
|
|
8473
|
+
}
|
|
8474
|
+
updateDOM(dom) {
|
|
8475
|
+
this.#root = dom;
|
|
8476
|
+
const props = Object.assign({}, this.props, {
|
|
8477
|
+
view: this.#view
|
|
8478
|
+
});
|
|
7616
8479
|
this.notifier.mounted({
|
|
7617
8480
|
id: this.id,
|
|
7618
|
-
root: this
|
|
7619
|
-
props
|
|
8481
|
+
root: this.#root,
|
|
8482
|
+
props,
|
|
7620
8483
|
Component: this.Component
|
|
7621
8484
|
});
|
|
7622
|
-
return
|
|
8485
|
+
return true;
|
|
7623
8486
|
}
|
|
7624
8487
|
destroy(_dom) {
|
|
7625
8488
|
this.notifier.unmounted(this.id);
|
|
7626
|
-
this
|
|
8489
|
+
this.#root = null;
|
|
8490
|
+
this.#view = void 0;
|
|
7627
8491
|
}
|
|
7628
8492
|
};
|
|
7629
|
-
|
|
7630
|
-
// src/extensions/typewriter.ts
|
|
7631
|
-
import { keymap as keymap14 } from "@codemirror/view";
|
|
7632
|
-
var defaultItems = [
|
|
7633
|
-
"hello world!",
|
|
7634
|
-
"this is a test.",
|
|
7635
|
-
"this is [DXOS](https://dxos.org)"
|
|
7636
|
-
];
|
|
7637
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
7638
|
-
let t;
|
|
7639
|
-
let idx = 0;
|
|
7640
|
-
return [
|
|
7641
|
-
keymap14.of([
|
|
7642
|
-
{
|
|
7643
|
-
// Reset.
|
|
7644
|
-
key: "alt-meta-'",
|
|
7645
|
-
run: () => {
|
|
7646
|
-
clearTimeout(t);
|
|
7647
|
-
idx = 0;
|
|
7648
|
-
return true;
|
|
7649
|
-
}
|
|
7650
|
-
},
|
|
7651
|
-
{
|
|
7652
|
-
// Next prompt.
|
|
7653
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
|
7654
|
-
key: "Shift-Meta-'",
|
|
7655
|
-
run: (view) => {
|
|
7656
|
-
clearTimeout(t);
|
|
7657
|
-
const text = items[idx++];
|
|
7658
|
-
if (idx === items?.length) {
|
|
7659
|
-
idx = 0;
|
|
7660
|
-
}
|
|
7661
|
-
let i = 0;
|
|
7662
|
-
const insert = (d = 0) => {
|
|
7663
|
-
t = setTimeout(() => {
|
|
7664
|
-
const pos = view.state.selection.main.head;
|
|
7665
|
-
view.dispatch({
|
|
7666
|
-
changes: {
|
|
7667
|
-
from: pos,
|
|
7668
|
-
insert: text[i++]
|
|
7669
|
-
},
|
|
7670
|
-
selection: {
|
|
7671
|
-
anchor: pos + 1
|
|
7672
|
-
}
|
|
7673
|
-
});
|
|
7674
|
-
if (i < text.length) {
|
|
7675
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
7676
|
-
}
|
|
7677
|
-
}, d);
|
|
7678
|
-
};
|
|
7679
|
-
insert();
|
|
7680
|
-
return true;
|
|
7681
|
-
}
|
|
7682
|
-
}
|
|
7683
|
-
])
|
|
7684
|
-
];
|
|
7685
|
-
};
|
|
7686
8493
|
export {
|
|
7687
8494
|
Cursor,
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
EditorState3 as EditorState,
|
|
7691
|
-
EditorView30 as EditorView,
|
|
7692
|
-
EditorViewMode,
|
|
7693
|
-
EditorViewModes,
|
|
8495
|
+
EditorState4 as EditorState,
|
|
8496
|
+
EditorView33 as EditorView,
|
|
7694
8497
|
Inline,
|
|
7695
8498
|
InputModeExtensions,
|
|
7696
8499
|
List,
|
|
@@ -7707,6 +8510,7 @@ export {
|
|
|
7707
8510
|
addStyle,
|
|
7708
8511
|
annotations,
|
|
7709
8512
|
autoScroll,
|
|
8513
|
+
autoScrollEffect,
|
|
7710
8514
|
autocomplete,
|
|
7711
8515
|
automerge,
|
|
7712
8516
|
awareness,
|
|
@@ -7720,7 +8524,11 @@ export {
|
|
|
7720
8524
|
commentClickedEffect,
|
|
7721
8525
|
comments,
|
|
7722
8526
|
commentsState,
|
|
8527
|
+
compactSlots,
|
|
7723
8528
|
convertTreeToJson,
|
|
8529
|
+
crawler,
|
|
8530
|
+
crawlerActiveEffect,
|
|
8531
|
+
crawlerLineEffect,
|
|
7724
8532
|
createBasicExtensions,
|
|
7725
8533
|
createComment,
|
|
7726
8534
|
createCrawler,
|
|
@@ -7743,12 +8551,12 @@ export {
|
|
|
7743
8551
|
defaultThemeSlots,
|
|
7744
8552
|
deleteItem,
|
|
7745
8553
|
documentId,
|
|
8554
|
+
documentSlots,
|
|
7746
8555
|
dropFile,
|
|
8556
|
+
editorClassNames,
|
|
7747
8557
|
editorInputMode,
|
|
7748
|
-
editorSlots,
|
|
7749
|
-
editorWidth,
|
|
7750
|
-
editorWithToolbarLayout,
|
|
7751
8558
|
extendedMarkdown,
|
|
8559
|
+
fader,
|
|
7752
8560
|
filterChars,
|
|
7753
8561
|
flattenRect,
|
|
7754
8562
|
focus,
|
|
@@ -7784,6 +8592,7 @@ export {
|
|
|
7784
8592
|
markdownTagsExtensions,
|
|
7785
8593
|
matchCompletion,
|
|
7786
8594
|
mention,
|
|
8595
|
+
mobileSlots,
|
|
7787
8596
|
modalStateEffect,
|
|
7788
8597
|
modalStateField,
|
|
7789
8598
|
moveItemDown,
|
|
@@ -7803,11 +8612,10 @@ export {
|
|
|
7803
8612
|
removeList,
|
|
7804
8613
|
removeStyle,
|
|
7805
8614
|
replacer,
|
|
8615
|
+
scrollPastEnd,
|
|
7806
8616
|
scrollThreadIntoView,
|
|
7807
8617
|
scrollToLine,
|
|
7808
8618
|
scroller,
|
|
7809
|
-
scrollerCrawlEffect,
|
|
7810
|
-
scrollerLineEffect,
|
|
7811
8619
|
selectionState,
|
|
7812
8620
|
setBlockquote,
|
|
7813
8621
|
setComments,
|
|
@@ -7815,9 +8623,8 @@ export {
|
|
|
7815
8623
|
setSelection,
|
|
7816
8624
|
setStyle,
|
|
7817
8625
|
singleValueFacet,
|
|
7818
|
-
|
|
8626
|
+
snippets2 as snippets,
|
|
7819
8627
|
staticCompletion,
|
|
7820
|
-
streamer,
|
|
7821
8628
|
submit,
|
|
7822
8629
|
tabbable,
|
|
7823
8630
|
table,
|
|
@@ -7836,7 +8643,12 @@ export {
|
|
|
7836
8643
|
treeFacet,
|
|
7837
8644
|
typeahead,
|
|
7838
8645
|
typewriter,
|
|
8646
|
+
typewriterBypass,
|
|
8647
|
+
typewriterDrainingEffect,
|
|
7839
8648
|
wrapWithCatch,
|
|
8649
|
+
xmlBlockDecoration,
|
|
8650
|
+
xmlElementLength,
|
|
8651
|
+
xmlFormatting,
|
|
7840
8652
|
xmlTagContextEffect,
|
|
7841
8653
|
xmlTagResetEffect,
|
|
7842
8654
|
xmlTagUpdateEffect,
|