@dxos/ui-editor 0.8.4-main.8360d9e660 → 0.8.4-main.8baae0fced
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 +1858 -1051
- 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 +1857 -1049
- 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 -17
- package/src/extensions/autocomplete/placeholder.ts +37 -18
- package/src/extensions/automerge/automerge.test.tsx +35 -9
- package/src/extensions/automerge/automerge.ts +2 -5
- 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} +66 -36
- 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/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,26 +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
|
|
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 = {
|
|
18
36
|
content: {
|
|
19
|
-
className:
|
|
37
|
+
className: "mx-2!"
|
|
20
38
|
}
|
|
21
39
|
};
|
|
22
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
23
|
-
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");
|
|
24
40
|
|
|
25
41
|
// src/extensions/annotations.ts
|
|
26
42
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
@@ -204,7 +220,7 @@ var singleValueFacet = (defaultValue) => Facet.define({
|
|
|
204
220
|
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
|
205
221
|
var defaultCursorConverter = {
|
|
206
222
|
toCursor: (position) => position.toString(),
|
|
207
|
-
fromCursor: (
|
|
223
|
+
fromCursor: (cursor) => parseInt(cursor)
|
|
208
224
|
};
|
|
209
225
|
var Cursor = class _Cursor {
|
|
210
226
|
static converter = singleValueFacet(defaultCursorConverter);
|
|
@@ -217,9 +233,9 @@ var Cursor = class _Cursor {
|
|
|
217
233
|
to
|
|
218
234
|
].join(":");
|
|
219
235
|
};
|
|
220
|
-
static getRangeFromCursor = (state,
|
|
236
|
+
static getRangeFromCursor = (state, cursor) => {
|
|
221
237
|
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
222
|
-
const parts =
|
|
238
|
+
const parts = cursor.split(":");
|
|
223
239
|
const from = cursorConverter2.fromCursor(parts[0]);
|
|
224
240
|
const to = cursorConverter2.fromCursor(parts[1]);
|
|
225
241
|
return from !== void 0 && to !== void 0 ? {
|
|
@@ -255,12 +271,7 @@ var wrapWithCatch = (fn, label) => {
|
|
|
255
271
|
} catch (err) {
|
|
256
272
|
log.catch(err, {
|
|
257
273
|
label
|
|
258
|
-
}, {
|
|
259
|
-
F: __dxlog_file,
|
|
260
|
-
L: 20,
|
|
261
|
-
S: void 0,
|
|
262
|
-
C: (f, a) => f(...a)
|
|
263
|
-
});
|
|
274
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 13, S: void 0 });
|
|
264
275
|
}
|
|
265
276
|
};
|
|
266
277
|
};
|
|
@@ -286,12 +297,7 @@ var logChanges = (trs) => {
|
|
|
286
297
|
if (changes.length) {
|
|
287
298
|
log("changes", {
|
|
288
299
|
changes
|
|
289
|
-
}, {
|
|
290
|
-
F: __dxlog_file,
|
|
291
|
-
L: 54,
|
|
292
|
-
S: void 0,
|
|
293
|
-
C: (f, a) => f(...a)
|
|
294
|
-
});
|
|
300
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 44, S: void 0 });
|
|
295
301
|
}
|
|
296
302
|
};
|
|
297
303
|
|
|
@@ -357,30 +363,37 @@ var insertAtLineStart = (view, from, insert) => {
|
|
|
357
363
|
};
|
|
358
364
|
|
|
359
365
|
// src/extensions/autocomplete/placeholder.ts
|
|
360
|
-
var placeholder = ({ content, delay = 3e3 }) => {
|
|
366
|
+
var placeholder = ({ content, delay = 3e3, focusOnly = false }) => {
|
|
361
367
|
const plugin = ViewPlugin3.fromClass(class {
|
|
362
368
|
_timeout;
|
|
363
369
|
_decorations = Decoration3.none;
|
|
364
370
|
update(update2) {
|
|
371
|
+
if (!update2.docChanged && !update2.selectionSet && !update2.focusChanged) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
365
374
|
if (this._timeout) {
|
|
366
375
|
window.clearTimeout(this._timeout);
|
|
367
376
|
this._timeout = void 0;
|
|
368
377
|
}
|
|
378
|
+
this._decorations = Decoration3.none;
|
|
379
|
+
if (focusOnly && !update2.view.hasFocus) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
369
382
|
const activeLine = update2.view.state.doc.lineAt(update2.view.state.selection.main.head);
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const lineStart = activeLine.from;
|
|
373
|
-
this._timeout = setTimeout(() => {
|
|
374
|
-
this._decorations = Decoration3.set([
|
|
375
|
-
Decoration3.widget({
|
|
376
|
-
widget: new PlaceholderWidget(content),
|
|
377
|
-
side: 1
|
|
378
|
-
}).range(lineStart)
|
|
379
|
-
]);
|
|
380
|
-
update2.view.update([]);
|
|
381
|
-
}, delay);
|
|
383
|
+
if (activeLine.text.trim() !== "") {
|
|
384
|
+
return;
|
|
382
385
|
}
|
|
383
|
-
|
|
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);
|
|
384
397
|
}
|
|
385
398
|
destroy() {
|
|
386
399
|
if (this._timeout) {
|
|
@@ -498,249 +511,10 @@ var typeahead = ({ onComplete } = {}) => {
|
|
|
498
511
|
];
|
|
499
512
|
};
|
|
500
513
|
|
|
501
|
-
// src/extensions/auto-scroll.ts
|
|
502
|
-
import { EditorView as EditorView5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
503
|
-
import { addEventListener, combine, throttle } from "@dxos/async";
|
|
504
|
-
import { Domino } from "@dxos/ui";
|
|
505
|
-
|
|
506
|
-
// src/extensions/scroller.ts
|
|
507
|
-
import { StateEffect } from "@codemirror/state";
|
|
508
|
-
import { EditorView as EditorView4, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
509
|
-
import { log as log2 } from "@dxos/log";
|
|
510
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/scroller.ts";
|
|
511
|
-
var scrollerLineEffect = StateEffect.define();
|
|
512
|
-
var scrollerCrawlEffect = StateEffect.define();
|
|
513
|
-
var scrollToLine = (view, options) => {
|
|
514
|
-
view.dispatch({
|
|
515
|
-
effects: scrollerLineEffect.of(options)
|
|
516
|
-
});
|
|
517
|
-
};
|
|
518
|
-
var scroller = ({ overScroll = 0 } = {}) => {
|
|
519
|
-
const scrollPlugin = ViewPlugin5.fromClass(class ScrollerPlugin {
|
|
520
|
-
view;
|
|
521
|
-
crawler;
|
|
522
|
-
constructor(view) {
|
|
523
|
-
this.view = view;
|
|
524
|
-
this.crawler = createCrawler(this.view);
|
|
525
|
-
}
|
|
526
|
-
// No-op.
|
|
527
|
-
destroy() {
|
|
528
|
-
this.crawler.cancel();
|
|
529
|
-
}
|
|
530
|
-
cancel() {
|
|
531
|
-
this.crawler.cancel();
|
|
532
|
-
}
|
|
533
|
-
crawl(start = false) {
|
|
534
|
-
if (start) {
|
|
535
|
-
this.crawler.scroll();
|
|
536
|
-
} else {
|
|
537
|
-
this.crawler.cancel();
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
scroll({ line, offset = 0, position, behavior = "instant" }) {
|
|
541
|
-
const { scrollTop, scrollHeight, clientHeight } = this.view.scrollDOM;
|
|
542
|
-
const scrollerRect = this.view.scrollDOM.getBoundingClientRect();
|
|
543
|
-
const doc = this.view.state.doc;
|
|
544
|
-
let targetScrollTop = scrollHeight - clientHeight + offset;
|
|
545
|
-
if (line >= 0 && line <= doc.lines - 1) {
|
|
546
|
-
const lineStart = doc.line(line + 1).from;
|
|
547
|
-
const coords = this.view.coordsAtPos(lineStart);
|
|
548
|
-
if (coords) {
|
|
549
|
-
const currentScrollTop = scrollTop;
|
|
550
|
-
const maxScrollTop = scrollHeight - clientHeight;
|
|
551
|
-
if (position === "end") {
|
|
552
|
-
targetScrollTop = currentScrollTop + coords.bottom - scrollerRect.bottom + offset;
|
|
553
|
-
} else {
|
|
554
|
-
targetScrollTop = currentScrollTop + coords.top - scrollerRect.top + offset;
|
|
555
|
-
}
|
|
556
|
-
targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop));
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
requestAnimationFrame(() => {
|
|
560
|
-
this.view.scrollDOM.scrollTo({
|
|
561
|
-
top: targetScrollTop
|
|
562
|
-
});
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
});
|
|
566
|
-
return [
|
|
567
|
-
scrollPlugin,
|
|
568
|
-
// Listen for effect.s
|
|
569
|
-
EditorView4.updateListener.of((update2) => {
|
|
570
|
-
update2.transactions.forEach((transaction) => {
|
|
571
|
-
try {
|
|
572
|
-
const plugin = update2.view.plugin(scrollPlugin);
|
|
573
|
-
if (plugin) {
|
|
574
|
-
for (const effect of transaction.effects) {
|
|
575
|
-
if (effect.is(scrollerCrawlEffect)) {
|
|
576
|
-
plugin.crawl(effect.value);
|
|
577
|
-
} else if (effect.is(scrollerLineEffect)) {
|
|
578
|
-
plugin.scroll(effect.value);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
} catch (err) {
|
|
583
|
-
log2.catch(err, void 0, {
|
|
584
|
-
F: __dxlog_file2,
|
|
585
|
-
L: 146,
|
|
586
|
-
S: void 0,
|
|
587
|
-
C: (f, a) => f(...a)
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
}),
|
|
592
|
-
// Styles.
|
|
593
|
-
EditorView4.theme({
|
|
594
|
-
".cm-content": {
|
|
595
|
-
paddingBottom: `${overScroll}px`
|
|
596
|
-
},
|
|
597
|
-
".cm-scroller": {
|
|
598
|
-
overflowAnchor: "none",
|
|
599
|
-
paddingBottom: "0"
|
|
600
|
-
},
|
|
601
|
-
".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
|
|
602
|
-
display: "none"
|
|
603
|
-
},
|
|
604
|
-
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
605
|
-
background: "transparent",
|
|
606
|
-
transition: "background 0.15s"
|
|
607
|
-
},
|
|
608
|
-
"&:hover .cm-scroller::-webkit-scrollbar-thumb": {
|
|
609
|
-
background: "var(--color-scrollbar-thumb)"
|
|
610
|
-
},
|
|
611
|
-
".cm-scroll-button": {
|
|
612
|
-
position: "absolute",
|
|
613
|
-
bottom: "0.5rem",
|
|
614
|
-
right: "1rem"
|
|
615
|
-
}
|
|
616
|
-
})
|
|
617
|
-
];
|
|
618
|
-
};
|
|
619
|
-
function createCrawler(view, k = 0.3, maxStep = 2, targetDelta = 0.5) {
|
|
620
|
-
const el = view.scrollDOM;
|
|
621
|
-
let currentTop = 0;
|
|
622
|
-
let rafId = null;
|
|
623
|
-
function frame() {
|
|
624
|
-
const targetTop = el.scrollHeight - el.clientHeight;
|
|
625
|
-
const delta = targetTop - currentTop;
|
|
626
|
-
const absDelta = Math.abs(delta);
|
|
627
|
-
if (absDelta < targetDelta) {
|
|
628
|
-
el.scrollTop = targetTop;
|
|
629
|
-
currentTop = targetTop;
|
|
630
|
-
rafId = null;
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
const step = Math.sign(delta) * Math.min(absDelta, Math.max(1, Math.min(absDelta * k, maxStep)));
|
|
634
|
-
currentTop += step;
|
|
635
|
-
el.scrollTop = currentTop;
|
|
636
|
-
rafId = requestAnimationFrame(frame);
|
|
637
|
-
}
|
|
638
|
-
return {
|
|
639
|
-
scroll: () => {
|
|
640
|
-
if (rafId === null) {
|
|
641
|
-
currentTop = el.scrollTop;
|
|
642
|
-
rafId = requestAnimationFrame(frame);
|
|
643
|
-
}
|
|
644
|
-
},
|
|
645
|
-
cancel: () => {
|
|
646
|
-
if (rafId !== null) {
|
|
647
|
-
cancelAnimationFrame(rafId);
|
|
648
|
-
rafId = null;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// src/extensions/auto-scroll.ts
|
|
655
|
-
var autoScroll = (_ = {}) => {
|
|
656
|
-
let buttonContainer;
|
|
657
|
-
let isPinned = true;
|
|
658
|
-
const setPinned = (pinned) => {
|
|
659
|
-
buttonContainer?.classList.toggle("opacity-0", pinned);
|
|
660
|
-
isPinned = pinned;
|
|
661
|
-
};
|
|
662
|
-
return [
|
|
663
|
-
// Update listener for logging when scrolling is needed.
|
|
664
|
-
EditorView5.updateListener.of(({ view, heightChanged, state }) => {
|
|
665
|
-
if (heightChanged) {
|
|
666
|
-
if (isPinned) {
|
|
667
|
-
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
668
|
-
const delta = scrollHeight - scrollTop - clientHeight;
|
|
669
|
-
if (delta > 0 && scrollTop > 0) {
|
|
670
|
-
setPinned(true);
|
|
671
|
-
view.dispatch({
|
|
672
|
-
effects: scrollerCrawlEffect.of(true)
|
|
673
|
-
});
|
|
674
|
-
} else if (delta < 0) {
|
|
675
|
-
setPinned(false);
|
|
676
|
-
}
|
|
677
|
-
} else {
|
|
678
|
-
if (state.doc.length === 0) {
|
|
679
|
-
setPinned(true);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}),
|
|
684
|
-
// Detect user scroll and unpin (or re-pin if scrolled to the bottom).
|
|
685
|
-
ViewPlugin6.fromClass(class {
|
|
686
|
-
cleanup;
|
|
687
|
-
constructor(view) {
|
|
688
|
-
this.cleanup = createUserScrollDetector(view.scrollDOM, throttle(() => {
|
|
689
|
-
requestAnimationFrame(() => {
|
|
690
|
-
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
691
|
-
const delta = scrollHeight - scrollTop - clientHeight;
|
|
692
|
-
const pinned = delta === 0;
|
|
693
|
-
setPinned(pinned);
|
|
694
|
-
if (!pinned) {
|
|
695
|
-
view.dispatch({
|
|
696
|
-
effects: scrollerCrawlEffect.of(false)
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
}, 500));
|
|
701
|
-
}
|
|
702
|
-
destroy() {
|
|
703
|
-
this.cleanup();
|
|
704
|
-
}
|
|
705
|
-
}),
|
|
706
|
-
// Scroll button.
|
|
707
|
-
ViewPlugin6.fromClass(class {
|
|
708
|
-
constructor(view) {
|
|
709
|
-
const icon = Domino.of("dx-icon").attributes({
|
|
710
|
-
icon: "ph--arrow-down--regular"
|
|
711
|
-
});
|
|
712
|
-
const button = Domino.of("button").classNames("dx-button bg-accent-surface").attributes({
|
|
713
|
-
"data-density": "fine"
|
|
714
|
-
}).children(icon).on("click", () => {
|
|
715
|
-
setPinned(true);
|
|
716
|
-
view.dispatch({
|
|
717
|
-
effects: scrollerLineEffect.of({
|
|
718
|
-
line: -1,
|
|
719
|
-
position: "end",
|
|
720
|
-
behavior: "smooth"
|
|
721
|
-
})
|
|
722
|
-
});
|
|
723
|
-
});
|
|
724
|
-
buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").children(button).root;
|
|
725
|
-
view.scrollDOM.parentElement.appendChild(buttonContainer);
|
|
726
|
-
}
|
|
727
|
-
})
|
|
728
|
-
];
|
|
729
|
-
};
|
|
730
|
-
function createUserScrollDetector(element, onUserScroll) {
|
|
731
|
-
return combine(addEventListener(element, "wheel", () => onUserScroll(), {
|
|
732
|
-
passive: true
|
|
733
|
-
}), addEventListener(element, "pointerdown", (event) => {
|
|
734
|
-
if (event.clientX > element.getBoundingClientRect().right - (element.offsetWidth - element.clientWidth)) {
|
|
735
|
-
onUserScroll();
|
|
736
|
-
}
|
|
737
|
-
}));
|
|
738
|
-
}
|
|
739
|
-
|
|
740
514
|
// src/extensions/automerge/automerge.ts
|
|
741
515
|
import { next as A3 } from "@automerge/automerge";
|
|
742
516
|
import { StateField, Transaction as Transaction2 } from "@codemirror/state";
|
|
743
|
-
import { EditorView as
|
|
517
|
+
import { EditorView as EditorView4, ViewPlugin as ViewPlugin5 } from "@codemirror/view";
|
|
744
518
|
import { DocAccessor } from "@dxos/echo-db";
|
|
745
519
|
|
|
746
520
|
// src/extensions/state.ts
|
|
@@ -749,42 +523,32 @@ var initialSync = Transaction.userEvent.of("initial.sync");
|
|
|
749
523
|
|
|
750
524
|
// src/extensions/automerge/cursor.ts
|
|
751
525
|
import { fromCursor, toCursor } from "@dxos/echo-db";
|
|
752
|
-
import { log as
|
|
753
|
-
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";
|
|
754
528
|
var cursorConverter = (accessor) => ({
|
|
755
529
|
toCursor: (pos, assoc) => {
|
|
756
530
|
try {
|
|
757
531
|
return toCursor(accessor, pos, assoc);
|
|
758
532
|
} catch (err) {
|
|
759
|
-
|
|
760
|
-
F: __dxlog_file3,
|
|
761
|
-
L: 15,
|
|
762
|
-
S: void 0,
|
|
763
|
-
C: (f, a) => f(...a)
|
|
764
|
-
});
|
|
533
|
+
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 11, S: void 0 });
|
|
765
534
|
return "";
|
|
766
535
|
}
|
|
767
536
|
},
|
|
768
|
-
fromCursor: (
|
|
537
|
+
fromCursor: (cursor) => {
|
|
769
538
|
try {
|
|
770
|
-
return fromCursor(accessor,
|
|
539
|
+
return fromCursor(accessor, cursor);
|
|
771
540
|
} catch (err) {
|
|
772
|
-
|
|
773
|
-
F: __dxlog_file3,
|
|
774
|
-
L: 24,
|
|
775
|
-
S: void 0,
|
|
776
|
-
C: (f, a) => f(...a)
|
|
777
|
-
});
|
|
541
|
+
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 19, S: void 0 });
|
|
778
542
|
return 0;
|
|
779
543
|
}
|
|
780
544
|
}
|
|
781
545
|
});
|
|
782
546
|
|
|
783
547
|
// src/extensions/automerge/defs.ts
|
|
784
|
-
import { Annotation, StateEffect
|
|
548
|
+
import { Annotation, StateEffect } from "@codemirror/state";
|
|
785
549
|
var getPath = (state, field) => state.field(field).path;
|
|
786
550
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
787
|
-
var updateHeadsEffect =
|
|
551
|
+
var updateHeadsEffect = StateEffect.define({});
|
|
788
552
|
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
789
553
|
newHeads
|
|
790
554
|
});
|
|
@@ -795,7 +559,7 @@ var isReconcile = (tr) => {
|
|
|
795
559
|
|
|
796
560
|
// src/extensions/automerge/sync.ts
|
|
797
561
|
import { next as A2 } from "@automerge/automerge";
|
|
798
|
-
import { log as
|
|
562
|
+
import { log as log3 } from "@dxos/log";
|
|
799
563
|
|
|
800
564
|
// src/extensions/automerge/update-automerge.ts
|
|
801
565
|
import { next as A } from "@automerge/automerge";
|
|
@@ -936,7 +700,7 @@ var charPath = (textPath, candidatePath) => {
|
|
|
936
700
|
};
|
|
937
701
|
|
|
938
702
|
// src/extensions/automerge/sync.ts
|
|
939
|
-
var
|
|
703
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/automerge/sync.ts";
|
|
940
704
|
var Syncer = class {
|
|
941
705
|
_handle;
|
|
942
706
|
_state;
|
|
@@ -959,12 +723,7 @@ var Syncer = class {
|
|
|
959
723
|
this._pending = false;
|
|
960
724
|
}
|
|
961
725
|
onEditorChange(view) {
|
|
962
|
-
|
|
963
|
-
F: __dxlog_file4,
|
|
964
|
-
L: 45,
|
|
965
|
-
S: this,
|
|
966
|
-
C: (f, a) => f(...a)
|
|
967
|
-
});
|
|
726
|
+
log3("onEditorChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 35, S: this });
|
|
968
727
|
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
969
728
|
const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
970
729
|
if (newHeads) {
|
|
@@ -975,12 +734,7 @@ var Syncer = class {
|
|
|
975
734
|
}
|
|
976
735
|
}
|
|
977
736
|
onAutomergeChange(view) {
|
|
978
|
-
|
|
979
|
-
F: __dxlog_file4,
|
|
980
|
-
L: 60,
|
|
981
|
-
S: this,
|
|
982
|
-
C: (f, a) => f(...a)
|
|
983
|
-
});
|
|
737
|
+
log3("onAutomergeChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 47, S: this });
|
|
984
738
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
985
739
|
const newHeads = A2.getHeads(this._handle.doc());
|
|
986
740
|
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.doc(), oldHeads, newHeads);
|
|
@@ -1033,7 +787,7 @@ var automerge = (accessor) => {
|
|
|
1033
787
|
// Track heads.
|
|
1034
788
|
syncState,
|
|
1035
789
|
// Reconcile external updates.
|
|
1036
|
-
|
|
790
|
+
ViewPlugin5.fromClass(class {
|
|
1037
791
|
_view;
|
|
1038
792
|
constructor(_view) {
|
|
1039
793
|
this._view = _view;
|
|
@@ -1042,14 +796,16 @@ var automerge = (accessor) => {
|
|
|
1042
796
|
const value = DocAccessor.getValue(accessor);
|
|
1043
797
|
const current = this._view.state.doc.toString();
|
|
1044
798
|
if (value !== current) {
|
|
1045
|
-
console.warn("ENABLING INITIAL SYNC -- THIS MAY BE A REGRESSION");
|
|
1046
799
|
this._view.dispatch({
|
|
1047
800
|
changes: {
|
|
1048
801
|
from: 0,
|
|
1049
802
|
to: this._view.state.doc.length,
|
|
1050
803
|
insert: value
|
|
1051
804
|
},
|
|
1052
|
-
annotations:
|
|
805
|
+
annotations: [
|
|
806
|
+
initialSync,
|
|
807
|
+
reconcileAnnotation.of(true)
|
|
808
|
+
]
|
|
1053
809
|
});
|
|
1054
810
|
}
|
|
1055
811
|
});
|
|
@@ -1062,7 +818,7 @@ var automerge = (accessor) => {
|
|
|
1062
818
|
};
|
|
1063
819
|
}),
|
|
1064
820
|
// Reconcile local updates.
|
|
1065
|
-
|
|
821
|
+
EditorView4.updateListener.of(({ view, changes, transactions }) => {
|
|
1066
822
|
if (!changes.empty) {
|
|
1067
823
|
const isInitialSync = transactions.some((tr) => tr.annotation(Transaction2.userEvent) === initialSync.value);
|
|
1068
824
|
if (!isInitialSync) {
|
|
@@ -1075,10 +831,10 @@ var automerge = (accessor) => {
|
|
|
1075
831
|
|
|
1076
832
|
// src/extensions/awareness/awareness.ts
|
|
1077
833
|
import { Annotation as Annotation2, RangeSet } from "@codemirror/state";
|
|
1078
|
-
import { Decoration as Decoration5, EditorView as
|
|
834
|
+
import { Decoration as Decoration5, EditorView as EditorView5, ViewPlugin as ViewPlugin6, WidgetType as WidgetType3 } from "@codemirror/view";
|
|
1079
835
|
import { Event } from "@dxos/async";
|
|
1080
836
|
import { Context } from "@dxos/context";
|
|
1081
|
-
var
|
|
837
|
+
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/awareness/awareness.ts";
|
|
1082
838
|
var dummyProvider = {
|
|
1083
839
|
remoteStateChange: new Event(),
|
|
1084
840
|
open: () => {
|
|
@@ -1094,17 +850,14 @@ var RemoteSelectionChangedAnnotation = Annotation2.define();
|
|
|
1094
850
|
var awareness = (provider = dummyProvider) => {
|
|
1095
851
|
return [
|
|
1096
852
|
awarenessProvider.of(provider),
|
|
1097
|
-
|
|
853
|
+
ViewPlugin6.fromClass(RemoteSelectionsDecorator, {
|
|
1098
854
|
decorations: (value) => value.decorations
|
|
1099
855
|
}),
|
|
1100
856
|
styles
|
|
1101
857
|
];
|
|
1102
858
|
};
|
|
1103
859
|
var RemoteSelectionsDecorator = class {
|
|
1104
|
-
_ctx = new Context(void 0, {
|
|
1105
|
-
F: __dxlog_file5,
|
|
1106
|
-
L: 80
|
|
1107
|
-
});
|
|
860
|
+
_ctx = new Context(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 33 });
|
|
1108
861
|
_cursorConverter;
|
|
1109
862
|
_provider;
|
|
1110
863
|
_lastAnchor;
|
|
@@ -1253,7 +1006,7 @@ var RemoteCaretWidget = class extends WidgetType3 {
|
|
|
1253
1006
|
return true;
|
|
1254
1007
|
}
|
|
1255
1008
|
};
|
|
1256
|
-
var styles =
|
|
1009
|
+
var styles = EditorView5.theme({
|
|
1257
1010
|
".cm-collab-selection": {},
|
|
1258
1011
|
".cm-collab-selectionLine": {
|
|
1259
1012
|
padding: 0,
|
|
@@ -1315,8 +1068,8 @@ var styles = EditorView7.theme({
|
|
|
1315
1068
|
import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
|
|
1316
1069
|
import { Context as Context2 } from "@dxos/context";
|
|
1317
1070
|
import { invariant } from "@dxos/invariant";
|
|
1318
|
-
import { log as
|
|
1319
|
-
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";
|
|
1320
1073
|
var DEBOUNCE_INTERVAL = 100;
|
|
1321
1074
|
var SpaceAwarenessProvider = class {
|
|
1322
1075
|
_remoteStates = /* @__PURE__ */ new Map();
|
|
@@ -1335,10 +1088,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1335
1088
|
this._info = info;
|
|
1336
1089
|
}
|
|
1337
1090
|
open() {
|
|
1338
|
-
this._ctx = new Context2(void 0, {
|
|
1339
|
-
F: __dxlog_file6,
|
|
1340
|
-
L: 57
|
|
1341
|
-
});
|
|
1091
|
+
this._ctx = new Context2(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 28 });
|
|
1342
1092
|
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
1343
1093
|
if (this._localState) {
|
|
1344
1094
|
await this._messenger.postMessage(this._channel, {
|
|
@@ -1363,14 +1113,9 @@ var SpaceAwarenessProvider = class {
|
|
|
1363
1113
|
void this._messenger.postMessage(this._channel, {
|
|
1364
1114
|
kind: "query"
|
|
1365
1115
|
}).catch((err) => {
|
|
1366
|
-
|
|
1116
|
+
log4.debug("failed to query awareness", {
|
|
1367
1117
|
err
|
|
1368
|
-
}, {
|
|
1369
|
-
F: __dxlog_file6,
|
|
1370
|
-
L: 91,
|
|
1371
|
-
S: this,
|
|
1372
|
-
C: (f, a) => f(...a)
|
|
1373
|
-
});
|
|
1118
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 57, S: this });
|
|
1374
1119
|
});
|
|
1375
1120
|
}
|
|
1376
1121
|
close() {
|
|
@@ -1382,15 +1127,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1382
1127
|
return Array.from(this._remoteStates.values());
|
|
1383
1128
|
}
|
|
1384
1129
|
update(position) {
|
|
1385
|
-
invariant(this._postTask, void 0, {
|
|
1386
|
-
F: __dxlog_file6,
|
|
1387
|
-
L: 106,
|
|
1388
|
-
S: this,
|
|
1389
|
-
A: [
|
|
1390
|
-
"this._postTask",
|
|
1391
|
-
""
|
|
1392
|
-
]
|
|
1393
|
-
});
|
|
1130
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 71, S: this, A: ["this._postTask", ""] });
|
|
1394
1131
|
this._localState = {
|
|
1395
1132
|
peerId: this._peerId,
|
|
1396
1133
|
position,
|
|
@@ -1399,38 +1136,22 @@ var SpaceAwarenessProvider = class {
|
|
|
1399
1136
|
this._postTask.schedule();
|
|
1400
1137
|
}
|
|
1401
1138
|
_handleQueryMessage() {
|
|
1402
|
-
invariant(this._postTask, void 0, {
|
|
1403
|
-
F: __dxlog_file6,
|
|
1404
|
-
L: 117,
|
|
1405
|
-
S: this,
|
|
1406
|
-
A: [
|
|
1407
|
-
"this._postTask",
|
|
1408
|
-
""
|
|
1409
|
-
]
|
|
1410
|
-
});
|
|
1139
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 80, S: this, A: ["this._postTask", ""] });
|
|
1411
1140
|
this._postTask.schedule();
|
|
1412
1141
|
}
|
|
1413
1142
|
_handlePostMessage(message) {
|
|
1414
|
-
invariant(message.kind === "post", void 0, {
|
|
1415
|
-
F: __dxlog_file6,
|
|
1416
|
-
L: 122,
|
|
1417
|
-
S: this,
|
|
1418
|
-
A: [
|
|
1419
|
-
"message.kind === 'post'",
|
|
1420
|
-
""
|
|
1421
|
-
]
|
|
1422
|
-
});
|
|
1143
|
+
invariant(message.kind === "post", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 84, S: this, A: ["message.kind === 'post'", ""] });
|
|
1423
1144
|
this._remoteStates.set(message.state.peerId, message.state);
|
|
1424
1145
|
this.remoteStateChange.emit();
|
|
1425
1146
|
}
|
|
1426
1147
|
};
|
|
1427
1148
|
|
|
1428
1149
|
// src/extensions/blast.ts
|
|
1429
|
-
import { EditorView as
|
|
1150
|
+
import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
|
|
1430
1151
|
import defaultsDeep from "lodash.defaultsdeep";
|
|
1431
|
-
import { throttle
|
|
1152
|
+
import { throttle } from "@dxos/async";
|
|
1432
1153
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1433
|
-
var
|
|
1154
|
+
var __dxlog_file6 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/blast.ts";
|
|
1434
1155
|
var defaultOptions = {
|
|
1435
1156
|
effect: 2,
|
|
1436
1157
|
maxParticles: 200,
|
|
@@ -1475,7 +1196,7 @@ var blast = (options = defaultOptions) => {
|
|
|
1475
1196
|
};
|
|
1476
1197
|
return [
|
|
1477
1198
|
// Cursor moved.
|
|
1478
|
-
|
|
1199
|
+
EditorView6.updateListener.of((update2) => {
|
|
1479
1200
|
if (blaster?.node !== update2.view.scrollDOM) {
|
|
1480
1201
|
if (blaster) {
|
|
1481
1202
|
blaster.destroy();
|
|
@@ -1548,15 +1269,7 @@ var Blaster = class {
|
|
|
1548
1269
|
return this._node;
|
|
1549
1270
|
}
|
|
1550
1271
|
initialize() {
|
|
1551
|
-
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
1552
|
-
F: __dxlog_file7,
|
|
1553
|
-
L: 142,
|
|
1554
|
-
S: this,
|
|
1555
|
-
A: [
|
|
1556
|
-
"!this._canvas && !this._ctx",
|
|
1557
|
-
""
|
|
1558
|
-
]
|
|
1559
|
-
});
|
|
1272
|
+
invariant2(!this._canvas && !this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 134, S: this, A: ["!this._canvas && !this._ctx", ""] });
|
|
1560
1273
|
this._canvas = document.createElement("canvas");
|
|
1561
1274
|
this._canvas.id = "code-blast-canvas";
|
|
1562
1275
|
this._canvas.style.position = "absolute";
|
|
@@ -1585,15 +1298,7 @@ var Blaster = class {
|
|
|
1585
1298
|
}
|
|
1586
1299
|
}
|
|
1587
1300
|
start() {
|
|
1588
|
-
invariant2(this._canvas && this._ctx, void 0, {
|
|
1589
|
-
F: __dxlog_file7,
|
|
1590
|
-
L: 181,
|
|
1591
|
-
S: this,
|
|
1592
|
-
A: [
|
|
1593
|
-
"this._canvas && this._ctx",
|
|
1594
|
-
""
|
|
1595
|
-
]
|
|
1596
|
-
});
|
|
1301
|
+
invariant2(this._canvas && this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 166, S: this, A: ["this._canvas && this._ctx", ""] });
|
|
1597
1302
|
this._running = true;
|
|
1598
1303
|
this.loop();
|
|
1599
1304
|
}
|
|
@@ -1620,11 +1325,11 @@ var Blaster = class {
|
|
|
1620
1325
|
this.drawParticles();
|
|
1621
1326
|
requestAnimationFrame(this.loop.bind(this));
|
|
1622
1327
|
}
|
|
1623
|
-
shake =
|
|
1328
|
+
shake = throttle(({ time }) => {
|
|
1624
1329
|
this._shakeTime = this._shakeTimeMax || time;
|
|
1625
1330
|
this._shakeTimeMax = time;
|
|
1626
1331
|
}, 100);
|
|
1627
|
-
spawn =
|
|
1332
|
+
spawn = throttle(({ element, point }) => {
|
|
1628
1333
|
const color = getRGBComponents(element, this._options.color);
|
|
1629
1334
|
const numParticles = random(this._options.particleNumRange.min, this._options.particleNumRange.max);
|
|
1630
1335
|
const dir = this._lastPoint.x === point.x ? 0 : this._lastPoint.x < point.x ? 1 : -1;
|
|
@@ -1733,9 +1438,9 @@ var random = (min, max) => {
|
|
|
1733
1438
|
|
|
1734
1439
|
// src/extensions/blocks.ts
|
|
1735
1440
|
import { RangeSetBuilder as RangeSetBuilder3 } from "@codemirror/state";
|
|
1736
|
-
import { Decoration as Decoration6, EditorView as
|
|
1441
|
+
import { Decoration as Decoration6, EditorView as EditorView7, ViewPlugin as ViewPlugin7 } from "@codemirror/view";
|
|
1737
1442
|
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1738
|
-
var paragraphBlockPlugin =
|
|
1443
|
+
var paragraphBlockPlugin = ViewPlugin7.fromClass(class {
|
|
1739
1444
|
decorations;
|
|
1740
1445
|
constructor(view) {
|
|
1741
1446
|
this.decorations = this.build(view);
|
|
@@ -1794,7 +1499,7 @@ var paragraphBlockPlugin = ViewPlugin9.fromClass(class {
|
|
|
1794
1499
|
});
|
|
1795
1500
|
var blocks = () => [
|
|
1796
1501
|
paragraphBlockPlugin,
|
|
1797
|
-
|
|
1502
|
+
EditorView7.baseTheme({
|
|
1798
1503
|
".cm-line.block-line": {
|
|
1799
1504
|
paddingLeft: "0.75rem",
|
|
1800
1505
|
paddingRight: "0.75rem",
|
|
@@ -1828,13 +1533,13 @@ var blocks = () => [
|
|
|
1828
1533
|
];
|
|
1829
1534
|
|
|
1830
1535
|
// src/extensions/bookmarks.ts
|
|
1831
|
-
import { Prec as Prec3, StateEffect as
|
|
1536
|
+
import { Prec as Prec3, StateEffect as StateEffect2, StateField as StateField2 } from "@codemirror/state";
|
|
1832
1537
|
import { keymap as keymap4 } from "@codemirror/view";
|
|
1833
|
-
import { log as
|
|
1834
|
-
var
|
|
1835
|
-
var addBookmark =
|
|
1836
|
-
var removeBookmark =
|
|
1837
|
-
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();
|
|
1838
1543
|
var bookmarks = () => {
|
|
1839
1544
|
return [
|
|
1840
1545
|
bookmarksField,
|
|
@@ -1843,12 +1548,7 @@ var bookmarks = () => {
|
|
|
1843
1548
|
key: "Mod-ArrowUp",
|
|
1844
1549
|
run: (view) => {
|
|
1845
1550
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1846
|
-
|
|
1847
|
-
F: __dxlog_file8,
|
|
1848
|
-
L: 29,
|
|
1849
|
-
S: void 0,
|
|
1850
|
-
C: (f, a) => f(...a)
|
|
1851
|
-
});
|
|
1551
|
+
log5("up", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 18, S: void 0 });
|
|
1852
1552
|
return true;
|
|
1853
1553
|
}
|
|
1854
1554
|
},
|
|
@@ -1856,12 +1556,7 @@ var bookmarks = () => {
|
|
|
1856
1556
|
key: "Mod-ArrowDown",
|
|
1857
1557
|
run: (view) => {
|
|
1858
1558
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1859
|
-
|
|
1860
|
-
F: __dxlog_file8,
|
|
1861
|
-
L: 37,
|
|
1862
|
-
S: void 0,
|
|
1863
|
-
C: (f, a) => f(...a)
|
|
1864
|
-
});
|
|
1559
|
+
log5("down", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 26, S: void 0 });
|
|
1865
1560
|
return true;
|
|
1866
1561
|
}
|
|
1867
1562
|
}
|
|
@@ -1898,27 +1593,27 @@ var bookmarksField = StateField2.define({
|
|
|
1898
1593
|
|
|
1899
1594
|
// src/extensions/comments.ts
|
|
1900
1595
|
import { invertedEffects } from "@codemirror/commands";
|
|
1901
|
-
import { StateEffect as
|
|
1902
|
-
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";
|
|
1903
1598
|
import sortBy from "lodash.sortby";
|
|
1904
1599
|
import { debounce as debounce2 } from "@dxos/async";
|
|
1905
|
-
import { log as
|
|
1600
|
+
import { log as log6 } from "@dxos/log";
|
|
1906
1601
|
import { isNonNullable } from "@dxos/util";
|
|
1907
1602
|
|
|
1908
1603
|
// src/extensions/selection.ts
|
|
1909
1604
|
import { Transaction as Transaction3 } from "@codemirror/state";
|
|
1910
|
-
import { EditorView as
|
|
1605
|
+
import { EditorView as EditorView8, keymap as keymap5 } from "@codemirror/view";
|
|
1911
1606
|
import { debounce } from "@dxos/async";
|
|
1912
1607
|
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1913
1608
|
import { isTruthy } from "@dxos/util";
|
|
1914
|
-
var
|
|
1609
|
+
var __dxlog_file8 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/selection.ts";
|
|
1915
1610
|
var documentId = singleValueFacet();
|
|
1916
1611
|
var stateRestoreAnnotation = "org.dxos.cm.state-restore";
|
|
1917
1612
|
var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
1918
1613
|
return {
|
|
1919
1614
|
selection,
|
|
1920
1615
|
scrollIntoView: !scrollTo,
|
|
1921
|
-
effects: scrollTo ?
|
|
1616
|
+
effects: scrollTo ? EditorView8.scrollIntoView(scrollTo, {
|
|
1922
1617
|
yMargin: 96
|
|
1923
1618
|
}) : void 0,
|
|
1924
1619
|
annotations: Transaction3.userEvent.of(stateRestoreAnnotation)
|
|
@@ -1926,28 +1621,12 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
|
1926
1621
|
};
|
|
1927
1622
|
var createEditorStateStore = (keyPrefix) => ({
|
|
1928
1623
|
getState: (id) => {
|
|
1929
|
-
invariant3(id, void 0, {
|
|
1930
|
-
F: __dxlog_file9,
|
|
1931
|
-
L: 47,
|
|
1932
|
-
S: void 0,
|
|
1933
|
-
A: [
|
|
1934
|
-
"id",
|
|
1935
|
-
""
|
|
1936
|
-
]
|
|
1937
|
-
});
|
|
1624
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 26, S: void 0, A: ["id", ""] });
|
|
1938
1625
|
const state = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
1939
1626
|
return state ? JSON.parse(state) : void 0;
|
|
1940
1627
|
},
|
|
1941
1628
|
setState: (id, state) => {
|
|
1942
|
-
invariant3(id, void 0, {
|
|
1943
|
-
F: __dxlog_file9,
|
|
1944
|
-
L: 53,
|
|
1945
|
-
S: void 0,
|
|
1946
|
-
A: [
|
|
1947
|
-
"id",
|
|
1948
|
-
""
|
|
1949
|
-
]
|
|
1950
|
-
});
|
|
1629
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 31, S: void 0, A: ["id", ""] });
|
|
1951
1630
|
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
|
1952
1631
|
}
|
|
1953
1632
|
});
|
|
@@ -1960,7 +1639,7 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
|
1960
1639
|
// setStateDebounced(id, {});
|
|
1961
1640
|
// },
|
|
1962
1641
|
// }),
|
|
1963
|
-
|
|
1642
|
+
EditorView8.updateListener.of(({ view, transactions }) => {
|
|
1964
1643
|
const id = view.state.facet(documentId);
|
|
1965
1644
|
if (!id || transactions.some((tr) => tr.isUserEvent(stateRestoreAnnotation))) {
|
|
1966
1645
|
return;
|
|
@@ -1999,10 +1678,10 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
|
1999
1678
|
};
|
|
2000
1679
|
|
|
2001
1680
|
// src/extensions/comments.ts
|
|
2002
|
-
var
|
|
2003
|
-
var setComments =
|
|
2004
|
-
var setSelection =
|
|
2005
|
-
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();
|
|
2006
1685
|
var commentsState = StateField3.define({
|
|
2007
1686
|
create: (state) => ({
|
|
2008
1687
|
id: state.facet(documentId),
|
|
@@ -2041,7 +1720,7 @@ var commentsState = StateField3.define({
|
|
|
2041
1720
|
return value;
|
|
2042
1721
|
}
|
|
2043
1722
|
});
|
|
2044
|
-
var styles2 =
|
|
1723
|
+
var styles2 = EditorView9.theme({
|
|
2045
1724
|
".cm-comment, .cm-comment-current": {
|
|
2046
1725
|
padding: "3px 0",
|
|
2047
1726
|
color: "var(--color-cm-comment-text)",
|
|
@@ -2062,19 +1741,14 @@ var createCommentMark = (id, isCurrent) => Decoration7.mark({
|
|
|
2062
1741
|
"data-comment-id": id
|
|
2063
1742
|
}
|
|
2064
1743
|
});
|
|
2065
|
-
var commentsDecorations =
|
|
1744
|
+
var commentsDecorations = EditorView9.decorations.compute([
|
|
2066
1745
|
commentsState
|
|
2067
1746
|
], (state) => {
|
|
2068
1747
|
const { selection: { current }, comments: comments2 } = state.field(commentsState);
|
|
2069
1748
|
const decorations2 = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
2070
1749
|
const range = comment.range;
|
|
2071
1750
|
if (!range) {
|
|
2072
|
-
|
|
2073
|
-
F: __dxlog_file10,
|
|
2074
|
-
L: 140,
|
|
2075
|
-
S: void 0,
|
|
2076
|
-
C: (f, a) => f(...a)
|
|
2077
|
-
});
|
|
1751
|
+
log6.warn("Invalid range:", range, { "~LogMeta": "~LogMeta", F: __dxlog_file9, L: 93, S: void 0 });
|
|
2078
1752
|
return void 0;
|
|
2079
1753
|
} else if (range.from === range.to) {
|
|
2080
1754
|
return void 0;
|
|
@@ -2084,8 +1758,8 @@ var commentsDecorations = EditorView11.decorations.compute([
|
|
|
2084
1758
|
}).filter(isNonNullable);
|
|
2085
1759
|
return Decoration7.set(decorations2);
|
|
2086
1760
|
});
|
|
2087
|
-
var commentClickedEffect =
|
|
2088
|
-
var handleCommentClick =
|
|
1761
|
+
var commentClickedEffect = StateEffect3.define();
|
|
1762
|
+
var handleCommentClick = EditorView9.domEventHandlers({
|
|
2089
1763
|
click: (event, view) => {
|
|
2090
1764
|
let target = event.target;
|
|
2091
1765
|
const editorRoot = view.dom;
|
|
@@ -2124,7 +1798,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2124
1798
|
}
|
|
2125
1799
|
};
|
|
2126
1800
|
return [
|
|
2127
|
-
|
|
1801
|
+
EditorView9.domEventHandlers({
|
|
2128
1802
|
cut: handleTrack,
|
|
2129
1803
|
copy: handleTrack
|
|
2130
1804
|
}),
|
|
@@ -2146,7 +1820,7 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2146
1820
|
return effects;
|
|
2147
1821
|
}),
|
|
2148
1822
|
// Handle paste or the undo of comment deletion.
|
|
2149
|
-
|
|
1823
|
+
EditorView9.updateListener.of((update2) => {
|
|
2150
1824
|
const restore = [];
|
|
2151
1825
|
for (let i = 0; i < update2.transactions.length; i++) {
|
|
2152
1826
|
const tr = update2.transactions[i];
|
|
@@ -2187,10 +1861,10 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2187
1861
|
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
2188
1862
|
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
2189
1863
|
if (!exists) {
|
|
2190
|
-
const
|
|
1864
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
2191
1865
|
onUpdate({
|
|
2192
1866
|
id: comment.id,
|
|
2193
|
-
cursor
|
|
1867
|
+
cursor
|
|
2194
1868
|
});
|
|
2195
1869
|
}
|
|
2196
1870
|
}
|
|
@@ -2202,7 +1876,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
|
2202
1876
|
from: changes.mapPos(comment.from, 1),
|
|
2203
1877
|
to: changes.mapPos(comment.to, 1)
|
|
2204
1878
|
});
|
|
2205
|
-
var restoreCommentEffect =
|
|
1879
|
+
var restoreCommentEffect = StateEffect3.define({
|
|
2206
1880
|
map: mapTrackedComment
|
|
2207
1881
|
});
|
|
2208
1882
|
var createComment = (view) => {
|
|
@@ -2219,13 +1893,13 @@ var createComment = (view) => {
|
|
|
2219
1893
|
}
|
|
2220
1894
|
});
|
|
2221
1895
|
}
|
|
2222
|
-
const
|
|
1896
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
2223
1897
|
from,
|
|
2224
1898
|
to
|
|
2225
1899
|
});
|
|
2226
|
-
if (
|
|
1900
|
+
if (cursor) {
|
|
2227
1901
|
options.onCreate?.({
|
|
2228
|
-
cursor
|
|
1902
|
+
cursor,
|
|
2229
1903
|
from,
|
|
2230
1904
|
location: view.coordsAtPos(from)
|
|
2231
1905
|
});
|
|
@@ -2288,7 +1962,7 @@ var comments = (options = {}) => {
|
|
|
2288
1962
|
//
|
|
2289
1963
|
// Track deleted ranges and update ranges for decorations.
|
|
2290
1964
|
//
|
|
2291
|
-
|
|
1965
|
+
EditorView9.updateListener.of(({ view, state, changes }) => {
|
|
2292
1966
|
let mod = false;
|
|
2293
1967
|
const { comments: comments2, ...value } = state.field(commentsState);
|
|
2294
1968
|
changes.iterChanges((from, to, from2, to2) => {
|
|
@@ -2320,7 +1994,7 @@ var comments = (options = {}) => {
|
|
|
2320
1994
|
//
|
|
2321
1995
|
// Track selection/proximity.
|
|
2322
1996
|
//
|
|
2323
|
-
|
|
1997
|
+
EditorView9.updateListener.of(({ view, state }) => {
|
|
2324
1998
|
let min = Infinity;
|
|
2325
1999
|
const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
|
|
2326
2000
|
const { head } = state.selection.main;
|
|
@@ -2374,7 +2048,7 @@ var scrollThreadIntoView = (view, id, center = true) => {
|
|
|
2374
2048
|
anchor: range.from
|
|
2375
2049
|
} : void 0,
|
|
2376
2050
|
effects: [
|
|
2377
|
-
needsScroll ?
|
|
2051
|
+
needsScroll ? EditorView9.scrollIntoView(range.from, center ? {
|
|
2378
2052
|
y: "center"
|
|
2379
2053
|
} : void 0) : [],
|
|
2380
2054
|
needsSelectionUpdate ? setSelection.of({
|
|
@@ -2405,7 +2079,7 @@ var ExternalCommentSync = class {
|
|
|
2405
2079
|
this.unsubscribe();
|
|
2406
2080
|
};
|
|
2407
2081
|
};
|
|
2408
|
-
var createExternalCommentSync = (id, subscribe, getComments) =>
|
|
2082
|
+
var createExternalCommentSync = (id, subscribe, getComments) => ViewPlugin8.fromClass(class {
|
|
2409
2083
|
constructor(view) {
|
|
2410
2084
|
return new ExternalCommentSync(view, id, subscribe, getComments);
|
|
2411
2085
|
}
|
|
@@ -2425,12 +2099,12 @@ var debugNodeLogger = (log12 = console.log) => {
|
|
|
2425
2099
|
};
|
|
2426
2100
|
|
|
2427
2101
|
// src/extensions/dnd.ts
|
|
2428
|
-
import { EditorView as
|
|
2102
|
+
import { EditorView as EditorView10, dropCursor } from "@codemirror/view";
|
|
2429
2103
|
var dropFile = (options = {}) => {
|
|
2430
2104
|
return [
|
|
2431
2105
|
styles3,
|
|
2432
2106
|
dropCursor(),
|
|
2433
|
-
|
|
2107
|
+
EditorView10.domEventHandlers({
|
|
2434
2108
|
drop: (event, view) => {
|
|
2435
2109
|
event.preventDefault();
|
|
2436
2110
|
const files = event.dataTransfer?.files;
|
|
@@ -2449,7 +2123,7 @@ var dropFile = (options = {}) => {
|
|
|
2449
2123
|
})
|
|
2450
2124
|
];
|
|
2451
2125
|
};
|
|
2452
|
-
var styles3 =
|
|
2126
|
+
var styles3 = EditorView10.theme({
|
|
2453
2127
|
".cm-dropCursor": {
|
|
2454
2128
|
borderLeft: "2px solid var(--color-accent-text)",
|
|
2455
2129
|
color: "var(--color-accent-text)",
|
|
@@ -2466,40 +2140,40 @@ import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap }
|
|
|
2466
2140
|
import { HighlightStyle, bracketMatching, syntaxHighlighting } from "@codemirror/language";
|
|
2467
2141
|
import { searchKeymap } from "@codemirror/search";
|
|
2468
2142
|
import { EditorState } from "@codemirror/state";
|
|
2469
|
-
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";
|
|
2470
2144
|
import { vscodeDarkStyle, vscodeLightStyle } from "@uiw/codemirror-theme-vscode";
|
|
2471
2145
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
2472
2146
|
import { generateName } from "@dxos/display-name";
|
|
2473
2147
|
import { log as log8 } from "@dxos/log";
|
|
2474
|
-
import { hexToHue, isTruthy as
|
|
2148
|
+
import { hexToHue, isTruthy as isTruthy3 } from "@dxos/util";
|
|
2475
2149
|
|
|
2476
2150
|
// src/styles/theme.ts
|
|
2477
|
-
import { EditorView as
|
|
2151
|
+
import { EditorView as EditorView11 } from "@codemirror/view";
|
|
2478
2152
|
import { mx as mx3 } from "@dxos/ui-theme";
|
|
2479
2153
|
var headings = {
|
|
2480
2154
|
1: {
|
|
2481
|
-
className: "text-4xl",
|
|
2482
|
-
fontSize: "var(--text-4xl)",
|
|
2483
|
-
lineHeight: "var(--text-4xl--line-height)"
|
|
2484
|
-
},
|
|
2485
|
-
2: {
|
|
2486
2155
|
className: "text-3xl",
|
|
2487
2156
|
fontSize: "var(--text-3xl)",
|
|
2488
|
-
lineHeight: "var(--text-
|
|
2157
|
+
lineHeight: "var(--text-4xl--line-height)"
|
|
2489
2158
|
},
|
|
2490
|
-
|
|
2159
|
+
2: {
|
|
2491
2160
|
className: "text-2xl",
|
|
2492
2161
|
fontSize: "var(--text-2xl)",
|
|
2493
|
-
lineHeight: "var(--text-
|
|
2162
|
+
lineHeight: "var(--text-3xl--line-height)"
|
|
2494
2163
|
},
|
|
2495
|
-
|
|
2164
|
+
3: {
|
|
2496
2165
|
className: "text-xl",
|
|
2497
2166
|
fontSize: "var(--text-xl)",
|
|
2498
|
-
lineHeight: "var(--text-
|
|
2167
|
+
lineHeight: "var(--text-2xl--line-height)"
|
|
2499
2168
|
},
|
|
2500
|
-
|
|
2169
|
+
4: {
|
|
2501
2170
|
className: "text-lg",
|
|
2502
2171
|
fontSize: "var(--text-lg)",
|
|
2172
|
+
lineHeight: "var(--text-xl--line-height)"
|
|
2173
|
+
},
|
|
2174
|
+
5: {
|
|
2175
|
+
className: "text-base",
|
|
2176
|
+
fontSize: "var(--text-base)",
|
|
2503
2177
|
lineHeight: "var(--text-lg--line-height)"
|
|
2504
2178
|
},
|
|
2505
2179
|
6: {
|
|
@@ -2508,21 +2182,21 @@ var headings = {
|
|
|
2508
2182
|
lineHeight: "var(--text-base--line-height)"
|
|
2509
2183
|
}
|
|
2510
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';
|
|
2511
2187
|
var markdownTheme = {
|
|
2512
|
-
code: "font-mono
|
|
2513
|
-
codeMark: "font-mono
|
|
2514
|
-
mark: "
|
|
2188
|
+
code: "font-mono! cm-code-inline",
|
|
2189
|
+
codeMark: "font-mono! cm-code-mark",
|
|
2190
|
+
mark: "font-mono!",
|
|
2515
2191
|
heading: (level) => ({
|
|
2516
|
-
className: mx3(headings[level].className, "font-light text-cm-heading"),
|
|
2192
|
+
className: mx3(headings[level].className, "font-light text-(--color-cm-heading-number)"),
|
|
2517
2193
|
color: "var(--color-cm-heading) !important",
|
|
2518
2194
|
lineHeight: headings[level].lineHeight,
|
|
2519
2195
|
fontSize: headings[level].fontSize,
|
|
2520
2196
|
fontWeight: "100 !important"
|
|
2521
2197
|
})
|
|
2522
2198
|
};
|
|
2523
|
-
var
|
|
2524
|
-
var fontMono = "JetBrains Mono Variable, ui-monospace, Cascadia Code, Source Code Pro, monospace";
|
|
2525
|
-
var baseTheme = EditorView13.baseTheme({
|
|
2199
|
+
var baseTheme = EditorView11.baseTheme({
|
|
2526
2200
|
/**
|
|
2527
2201
|
* Outer frame.
|
|
2528
2202
|
*/
|
|
@@ -2534,12 +2208,21 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2534
2208
|
* Scroller
|
|
2535
2209
|
*/
|
|
2536
2210
|
".cm-scroller": {
|
|
2537
|
-
|
|
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"
|
|
2538
2215
|
},
|
|
2539
2216
|
".cm-scroller::-webkit-scrollbar": {
|
|
2540
|
-
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"
|
|
2541
2225
|
},
|
|
2542
|
-
".cm-scroller::-webkit-scrollbar-track": {},
|
|
2543
2226
|
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
2544
2227
|
background: "transparent",
|
|
2545
2228
|
transition: "background 0.15s"
|
|
@@ -2553,7 +2236,6 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2553
2236
|
*/
|
|
2554
2237
|
".cm-content": {
|
|
2555
2238
|
padding: "unset",
|
|
2556
|
-
lineHeight: "24px",
|
|
2557
2239
|
color: "unset"
|
|
2558
2240
|
},
|
|
2559
2241
|
/**
|
|
@@ -2584,9 +2266,16 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2584
2266
|
* Line.
|
|
2585
2267
|
*/
|
|
2586
2268
|
".cm-line": {
|
|
2587
|
-
lineHeight:
|
|
2269
|
+
lineHeight: 1.5,
|
|
2588
2270
|
paddingInline: 0
|
|
2589
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
|
+
},
|
|
2590
2279
|
".cm-activeLine": {
|
|
2591
2280
|
background: "var(--color-cm-active-line)"
|
|
2592
2281
|
},
|
|
@@ -2630,7 +2319,8 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2630
2319
|
textDecorationThickness: "1px",
|
|
2631
2320
|
textDecorationColor: "var(--color-separator)",
|
|
2632
2321
|
textUnderlineOffset: "2px",
|
|
2633
|
-
borderRadius: ".125rem"
|
|
2322
|
+
borderRadius: ".125rem",
|
|
2323
|
+
cursor: "pointer"
|
|
2634
2324
|
},
|
|
2635
2325
|
".cm-link > span": {
|
|
2636
2326
|
color: "var(--color-accent-text)"
|
|
@@ -2668,12 +2358,12 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2668
2358
|
padding: "4px"
|
|
2669
2359
|
},
|
|
2670
2360
|
".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
|
|
2671
|
-
background: "var(--color-
|
|
2672
|
-
color: "var(--color-base-
|
|
2361
|
+
background: "var(--color-current-surface)",
|
|
2362
|
+
color: "var(--color-base-foreground)"
|
|
2673
2363
|
},
|
|
2674
2364
|
".cm-tooltip.cm-tooltip-autocomplete > ul > completion-section": {
|
|
2675
2365
|
paddingLeft: "4px !important",
|
|
2676
|
-
color: "var(--color-base-
|
|
2366
|
+
color: "var(--color-base-foreground)"
|
|
2677
2367
|
},
|
|
2678
2368
|
/**
|
|
2679
2369
|
* Completion info.
|
|
@@ -2692,7 +2382,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2692
2382
|
padding: "0 4px"
|
|
2693
2383
|
},
|
|
2694
2384
|
".cm-completionMatchedText": {
|
|
2695
|
-
color: "var(--color-base-
|
|
2385
|
+
color: "var(--color-base-foreground)",
|
|
2696
2386
|
textDecoration: "none !important"
|
|
2697
2387
|
},
|
|
2698
2388
|
/**
|
|
@@ -2727,7 +2417,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2727
2417
|
backgroundColor: "var(--color-input-surface)"
|
|
2728
2418
|
},
|
|
2729
2419
|
".cm-panel input:focus, .cm-panel button:focus": {
|
|
2730
|
-
outline: "1px solid var(--color-
|
|
2420
|
+
outline: "1px solid var(--color-focus-ring-subtle)"
|
|
2731
2421
|
},
|
|
2732
2422
|
".cm-panel label": {
|
|
2733
2423
|
display: "inline-flex",
|
|
@@ -2740,7 +2430,7 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2740
2430
|
height: "8px",
|
|
2741
2431
|
marginRight: "6px !important",
|
|
2742
2432
|
padding: "2px !important",
|
|
2743
|
-
color: "var(--color-
|
|
2433
|
+
color: "var(--color-focus-ring-subtle)"
|
|
2744
2434
|
},
|
|
2745
2435
|
".cm-panel button": {
|
|
2746
2436
|
"&:hover": {
|
|
@@ -2756,18 +2446,17 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2756
2446
|
borderTop: "1px solid var(--color-separator)"
|
|
2757
2447
|
}
|
|
2758
2448
|
});
|
|
2759
|
-
var editorGutter =
|
|
2449
|
+
var editorGutter = EditorView11.theme({
|
|
2760
2450
|
".cm-gutters": {
|
|
2761
2451
|
// NOTE: Non-transparent background required to cover content if scrolling horizontally.
|
|
2762
2452
|
background: "var(--color-base-surface) !important",
|
|
2763
2453
|
paddingRight: "1rem"
|
|
2764
2454
|
}
|
|
2765
2455
|
});
|
|
2766
|
-
var createFontTheme = ({ monospace } = {}) =>
|
|
2767
|
-
//
|
|
2456
|
+
var createFontTheme = ({ monospace } = {}) => EditorView11.theme({
|
|
2457
|
+
// Main content.
|
|
2768
2458
|
".cm-scroller": {
|
|
2769
|
-
fontFamily: monospace ? fontMono : fontBody
|
|
2770
|
-
fontSize: "16px"
|
|
2459
|
+
fontFamily: monospace ? fontMono : fontBody
|
|
2771
2460
|
},
|
|
2772
2461
|
// Maintain defaults for UI components.
|
|
2773
2462
|
".cm-content, .cm-gutters, .cm-panel": {
|
|
@@ -2777,9 +2466,9 @@ var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
|
|
|
2777
2466
|
});
|
|
2778
2467
|
|
|
2779
2468
|
// src/extensions/focus.ts
|
|
2780
|
-
import { StateEffect as
|
|
2781
|
-
import { EditorView as
|
|
2782
|
-
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();
|
|
2783
2472
|
var focusField = StateField5.define({
|
|
2784
2473
|
create: () => false,
|
|
2785
2474
|
update: (value, tr) => {
|
|
@@ -2793,7 +2482,7 @@ var focusField = StateField5.define({
|
|
|
2793
2482
|
});
|
|
2794
2483
|
var focus = [
|
|
2795
2484
|
focusField,
|
|
2796
|
-
|
|
2485
|
+
EditorView12.domEventHandlers({
|
|
2797
2486
|
focus: (_event, view) => {
|
|
2798
2487
|
requestAnimationFrame(() => view.dispatch({
|
|
2799
2488
|
effects: focusEffect.of(true)
|
|
@@ -2807,9 +2496,388 @@ var focus = [
|
|
|
2807
2496
|
})
|
|
2808
2497
|
];
|
|
2809
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
|
+
|
|
2810
2878
|
// src/extensions/factories.ts
|
|
2811
2879
|
var __dxlog_file11 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/factories.ts";
|
|
2812
|
-
var tabbable =
|
|
2880
|
+
var tabbable = EditorView16.contentAttributes.of({
|
|
2813
2881
|
tabindex: "0"
|
|
2814
2882
|
});
|
|
2815
2883
|
var filterChars = (chars) => {
|
|
@@ -2862,13 +2930,8 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2862
2930
|
const props = defaultsDeep2({}, propsProp, defaultBasicOptions);
|
|
2863
2931
|
return [
|
|
2864
2932
|
// NOTE: Doesn't catch errors in keymap functions.
|
|
2865
|
-
|
|
2866
|
-
log8.catch(err, void 0, {
|
|
2867
|
-
F: __dxlog_file11,
|
|
2868
|
-
L: 131,
|
|
2869
|
-
S: void 0,
|
|
2870
|
-
C: (f, a) => f(...a)
|
|
2871
|
-
});
|
|
2933
|
+
EditorView16.exceptionSink.of((err) => {
|
|
2934
|
+
log8.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file11, L: 79, S: void 0 });
|
|
2872
2935
|
}),
|
|
2873
2936
|
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2874
2937
|
props.bracketMatching && bracketMatching(),
|
|
@@ -2877,7 +2940,7 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2877
2940
|
props.drawSelection && drawSelection({
|
|
2878
2941
|
cursorBlinkRate: 1200
|
|
2879
2942
|
}),
|
|
2880
|
-
props.editable !== void 0 &&
|
|
2943
|
+
props.editable !== void 0 && EditorView16.editable.of(props.editable),
|
|
2881
2944
|
props.focus && focus,
|
|
2882
2945
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2883
2946
|
props.history && history(),
|
|
@@ -2885,9 +2948,16 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2885
2948
|
lineNumbers(),
|
|
2886
2949
|
editorGutter
|
|
2887
2950
|
],
|
|
2888
|
-
props.lineWrapping &&
|
|
2951
|
+
props.lineWrapping && EditorView16.lineWrapping,
|
|
2889
2952
|
props.placeholder && placeholder2(props.placeholder),
|
|
2890
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),
|
|
2891
2961
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2892
2962
|
props.tabbable && tabbable,
|
|
2893
2963
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
@@ -2912,8 +2982,8 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2912
2982
|
preventDefault: true,
|
|
2913
2983
|
run: () => true
|
|
2914
2984
|
}
|
|
2915
|
-
].filter(
|
|
2916
|
-
].filter(
|
|
2985
|
+
].filter(isTruthy3))
|
|
2986
|
+
].filter(isTruthy3);
|
|
2917
2987
|
};
|
|
2918
2988
|
var grow = {
|
|
2919
2989
|
editor: {
|
|
@@ -2930,27 +3000,32 @@ var defaultStyles = {
|
|
|
2930
3000
|
dark: vscodeDarkStyle,
|
|
2931
3001
|
light: vscodeLightStyle
|
|
2932
3002
|
};
|
|
2933
|
-
var createThemeExtensions = ({ monospace,
|
|
3003
|
+
var createThemeExtensions = ({ monospace, scrollbarThin, slots: slotsProp, syntaxHighlighting: syntaxHighlightingProp, themeMode } = {}) => {
|
|
2934
3004
|
const slots = defaultsDeep2({}, slotsProp, defaultThemeSlots);
|
|
2935
3005
|
return [
|
|
2936
3006
|
baseTheme,
|
|
2937
|
-
|
|
3007
|
+
EditorView16.darkTheme.of(themeMode === "dark"),
|
|
2938
3008
|
createFontTheme({
|
|
2939
3009
|
monospace
|
|
2940
3010
|
}),
|
|
2941
3011
|
syntaxHighlightingProp && syntaxHighlighting(HighlightStyle.define(themeMode === "dark" ? defaultStyles.dark : defaultStyles.light)),
|
|
2942
|
-
slots.editor?.className &&
|
|
3012
|
+
slots.editor?.className && EditorView16.editorAttributes.of({
|
|
2943
3013
|
class: slots.editor.className
|
|
2944
3014
|
}),
|
|
2945
|
-
slots.content?.className &&
|
|
3015
|
+
slots.content?.className && EditorView16.contentAttributes.of({
|
|
2946
3016
|
class: slots.content.className
|
|
2947
3017
|
}),
|
|
2948
|
-
slots.
|
|
3018
|
+
(slots.scroller?.className || scrollbarThin) && ViewPlugin12.fromClass(class {
|
|
2949
3019
|
constructor(view) {
|
|
2950
|
-
|
|
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
|
+
}
|
|
2951
3026
|
}
|
|
2952
3027
|
})
|
|
2953
|
-
].filter(
|
|
3028
|
+
].filter(isTruthy3);
|
|
2954
3029
|
};
|
|
2955
3030
|
var createDataExtensions = ({ id, text, messenger, identity }) => {
|
|
2956
3031
|
const extensions = [];
|
|
@@ -2976,7 +3051,7 @@ var createDataExtensions = ({ id, text, messenger, identity }) => {
|
|
|
2976
3051
|
|
|
2977
3052
|
// src/extensions/folding.ts
|
|
2978
3053
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
|
2979
|
-
import { EditorView as
|
|
3054
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
2980
3055
|
import { Domino as Domino2, mx as mx4 } from "@dxos/ui";
|
|
2981
3056
|
var folding = () => {
|
|
2982
3057
|
return [
|
|
@@ -2984,13 +3059,14 @@ var folding = () => {
|
|
|
2984
3059
|
placeholderDOM: () => Domino2.of("span").root
|
|
2985
3060
|
}),
|
|
2986
3061
|
foldGutter({
|
|
3062
|
+
// NOTE: We can't animate since the element is remounted on state change.
|
|
2987
3063
|
markerDOM: (open) => {
|
|
2988
|
-
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({
|
|
2989
3065
|
href: Domino2.icon("ph--caret-right--regular")
|
|
2990
3066
|
}))).root;
|
|
2991
3067
|
}
|
|
2992
3068
|
}),
|
|
2993
|
-
|
|
3069
|
+
EditorView17.theme({
|
|
2994
3070
|
".cm-foldGutter": {
|
|
2995
3071
|
opacity: 0.3,
|
|
2996
3072
|
transition: "opacity 0.3s",
|
|
@@ -3004,7 +3080,7 @@ var folding = () => {
|
|
|
3004
3080
|
};
|
|
3005
3081
|
|
|
3006
3082
|
// src/extensions/hashtag.ts
|
|
3007
|
-
import { Decoration as Decoration8, EditorView as
|
|
3083
|
+
import { Decoration as Decoration8, EditorView as EditorView18, MatchDecorator, ViewPlugin as ViewPlugin13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3008
3084
|
import { getHashStyles, mx as mx5 } from "@dxos/ui-theme";
|
|
3009
3085
|
var TagWidget = class extends WidgetType4 {
|
|
3010
3086
|
_text;
|
|
@@ -3025,7 +3101,7 @@ var tagMatcher = new MatchDecorator({
|
|
|
3025
3101
|
})
|
|
3026
3102
|
});
|
|
3027
3103
|
var hashtag = () => [
|
|
3028
|
-
|
|
3104
|
+
ViewPlugin13.fromClass(class {
|
|
3029
3105
|
tags;
|
|
3030
3106
|
constructor(view) {
|
|
3031
3107
|
this.tags = tagMatcher.createDeco(view);
|
|
@@ -3035,11 +3111,11 @@ var hashtag = () => [
|
|
|
3035
3111
|
}
|
|
3036
3112
|
}, {
|
|
3037
3113
|
decorations: (instance) => instance.tags,
|
|
3038
|
-
provide: (plugin) =>
|
|
3114
|
+
provide: (plugin) => EditorView18.atomicRanges.of((view) => {
|
|
3039
3115
|
return view.plugin(plugin)?.tags || Decoration8.none;
|
|
3040
3116
|
})
|
|
3041
3117
|
}),
|
|
3042
|
-
|
|
3118
|
+
EditorView18.theme({
|
|
3043
3119
|
".cm-tag": {
|
|
3044
3120
|
borderRadius: "4px",
|
|
3045
3121
|
marginRight: "6px",
|
|
@@ -3094,18 +3170,18 @@ var schemaLinter = (validate) => (view) => {
|
|
|
3094
3170
|
};
|
|
3095
3171
|
|
|
3096
3172
|
// src/extensions/listener.ts
|
|
3097
|
-
import { EditorView as
|
|
3173
|
+
import { EditorView as EditorView19 } from "@codemirror/view";
|
|
3098
3174
|
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
3099
3175
|
var listener = ({ onFocus, onChange }) => {
|
|
3100
3176
|
return [
|
|
3101
|
-
onFocus &&
|
|
3177
|
+
onFocus && EditorView19.focusChangeEffect.of((state, focusing) => {
|
|
3102
3178
|
onFocus({
|
|
3103
3179
|
id: state.facet(documentId),
|
|
3104
3180
|
focusing
|
|
3105
3181
|
});
|
|
3106
3182
|
return null;
|
|
3107
3183
|
}),
|
|
3108
|
-
onChange &&
|
|
3184
|
+
onChange && EditorView19.updateListener.of(({ state, docChanged }) => {
|
|
3109
3185
|
if (docChanged) {
|
|
3110
3186
|
onChange({
|
|
3111
3187
|
id: state.facet(documentId),
|
|
@@ -3120,7 +3196,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
3120
3196
|
import { snippet } from "@codemirror/autocomplete";
|
|
3121
3197
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3122
3198
|
import { EditorSelection as EditorSelection2 } from "@codemirror/state";
|
|
3123
|
-
import { EditorView as
|
|
3199
|
+
import { EditorView as EditorView20, keymap as keymap8 } from "@codemirror/view";
|
|
3124
3200
|
import { debounceAndThrottle } from "@dxos/async";
|
|
3125
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;
|
|
3126
3202
|
var Inline = /* @__PURE__ */ (function(Inline2) {
|
|
@@ -4209,7 +4285,7 @@ var getFormatting = (state) => {
|
|
|
4209
4285
|
};
|
|
4210
4286
|
};
|
|
4211
4287
|
var formattingListener = (onStateChange, delay = 100) => {
|
|
4212
|
-
return
|
|
4288
|
+
return EditorView20.updateListener.of(debounceAndThrottle((update2) => {
|
|
4213
4289
|
if (update2.docChanged || update2.selectionSet) {
|
|
4214
4290
|
onStateChange(getFormatting(update2.state));
|
|
4215
4291
|
}
|
|
@@ -4270,22 +4346,16 @@ import { completionKeymap } from "@codemirror/autocomplete";
|
|
|
4270
4346
|
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
4271
4347
|
import { jsonLanguage } from "@codemirror/lang-json";
|
|
4272
4348
|
import { markdown, markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
4273
|
-
import {
|
|
4274
|
-
import { LanguageDescription, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4349
|
+
import { foldNodeProp, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4275
4350
|
import { languages } from "@codemirror/language-data";
|
|
4276
4351
|
import { keymap as keymap9 } from "@codemirror/view";
|
|
4277
|
-
import { isTruthy as
|
|
4352
|
+
import { isTruthy as isTruthy4 } from "@dxos/util";
|
|
4278
4353
|
|
|
4279
4354
|
// src/extensions/markdown/highlight.ts
|
|
4280
4355
|
import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
4281
4356
|
import { HighlightStyle as HighlightStyle2 } from "@codemirror/language";
|
|
4282
4357
|
import { Tag, styleTags, tags } from "@lezer/highlight";
|
|
4283
4358
|
import { Table } from "@lezer/markdown";
|
|
4284
|
-
var styles4 = {
|
|
4285
|
-
code: "font-mono no-underline! text-cm-code",
|
|
4286
|
-
codeMark: "font-mono text-cm-code-mark",
|
|
4287
|
-
mark: "opacity-50"
|
|
4288
|
-
};
|
|
4289
4359
|
var markdownTags = {
|
|
4290
4360
|
Blockquote: Tag.define(),
|
|
4291
4361
|
CodeMark: Tag.define(),
|
|
@@ -4367,7 +4437,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4367
4437
|
markdownTags.LinkReference,
|
|
4368
4438
|
markdownTags.ListMark
|
|
4369
4439
|
],
|
|
4370
|
-
class:
|
|
4440
|
+
class: markdownTheme.mark
|
|
4371
4441
|
},
|
|
4372
4442
|
// Markdown marks.
|
|
4373
4443
|
{
|
|
@@ -4378,7 +4448,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4378
4448
|
markdownTags.QuoteMark,
|
|
4379
4449
|
markdownTags.EmphasisMark
|
|
4380
4450
|
],
|
|
4381
|
-
class:
|
|
4451
|
+
class: markdownTheme.mark
|
|
4382
4452
|
},
|
|
4383
4453
|
// E.g., code block language (after ```).
|
|
4384
4454
|
{
|
|
@@ -4387,7 +4457,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4387
4457
|
tags.function(tags.variableName),
|
|
4388
4458
|
tags.labelName
|
|
4389
4459
|
],
|
|
4390
|
-
class:
|
|
4460
|
+
class: markdownTheme.codeMark
|
|
4391
4461
|
},
|
|
4392
4462
|
// Fonts.
|
|
4393
4463
|
{
|
|
@@ -4453,7 +4523,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4453
4523
|
markdownTags.CodeText,
|
|
4454
4524
|
markdownTags.InlineCode
|
|
4455
4525
|
],
|
|
4456
|
-
class:
|
|
4526
|
+
class: markdownTheme.code
|
|
4457
4527
|
},
|
|
4458
4528
|
{
|
|
4459
4529
|
tag: [
|
|
@@ -4483,15 +4553,23 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4483
4553
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
4484
4554
|
base: markdownLanguage2,
|
|
4485
4555
|
// Languages for syntax highlighting fenced code blocks.
|
|
4556
|
+
// Caller-supplied languages are checked first so they can override defaults.
|
|
4486
4557
|
defaultCodeLanguage: jsonLanguage,
|
|
4487
|
-
codeLanguages:
|
|
4558
|
+
codeLanguages: [
|
|
4559
|
+
...options.codeLanguages ?? [],
|
|
4560
|
+
...languages
|
|
4561
|
+
],
|
|
4488
4562
|
// Don't complete HTML tags.
|
|
4489
4563
|
completeHTMLTags: false,
|
|
4490
4564
|
// Parser extensions.
|
|
4491
4565
|
extensions: [
|
|
4492
4566
|
// GFM provided by default.
|
|
4493
4567
|
markdownTagsExtensions,
|
|
4494
|
-
...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
|
|
4495
4573
|
]
|
|
4496
4574
|
}),
|
|
4497
4575
|
// Custom styles.
|
|
@@ -4503,21 +4581,16 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4503
4581
|
...defaultKeymap2,
|
|
4504
4582
|
// TODO(burdon): Remove?
|
|
4505
4583
|
...completionKeymap
|
|
4506
|
-
].filter(
|
|
4584
|
+
].filter(isTruthy4))
|
|
4507
4585
|
];
|
|
4508
4586
|
};
|
|
4509
|
-
var
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
]
|
|
4515
|
-
|
|
4516
|
-
"xml",
|
|
4517
|
-
"xhtml"
|
|
4518
|
-
],
|
|
4519
|
-
load: async () => xml()
|
|
4520
|
-
});
|
|
4587
|
+
var noFencedCodeFolding = {
|
|
4588
|
+
props: [
|
|
4589
|
+
foldNodeProp.add({
|
|
4590
|
+
FencedCode: () => null
|
|
4591
|
+
})
|
|
4592
|
+
]
|
|
4593
|
+
};
|
|
4521
4594
|
var defaultExtensions = () => [
|
|
4522
4595
|
noSetExtHeading,
|
|
4523
4596
|
noHtml
|
|
@@ -4537,19 +4610,19 @@ var debugTree = (cb) => StateField6.define({
|
|
|
4537
4610
|
update: (value, tr) => cb(convertTreeToJson(tr.state))
|
|
4538
4611
|
});
|
|
4539
4612
|
var convertTreeToJson = (state) => {
|
|
4540
|
-
const treeToJson = (
|
|
4613
|
+
const treeToJson = (cursor) => {
|
|
4541
4614
|
const node = {
|
|
4542
|
-
type:
|
|
4543
|
-
from:
|
|
4544
|
-
to:
|
|
4545
|
-
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(),
|
|
4546
4619
|
children: []
|
|
4547
4620
|
};
|
|
4548
|
-
if (
|
|
4621
|
+
if (cursor.firstChild()) {
|
|
4549
4622
|
do {
|
|
4550
|
-
node.children.push(treeToJson(
|
|
4551
|
-
} while (
|
|
4552
|
-
|
|
4623
|
+
node.children.push(treeToJson(cursor));
|
|
4624
|
+
} while (cursor.nextSibling());
|
|
4625
|
+
cursor.parent();
|
|
4553
4626
|
}
|
|
4554
4627
|
return node;
|
|
4555
4628
|
};
|
|
@@ -4558,17 +4631,16 @@ var convertTreeToJson = (state) => {
|
|
|
4558
4631
|
|
|
4559
4632
|
// src/extensions/markdown/decorate.ts
|
|
4560
4633
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
4561
|
-
import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as
|
|
4562
|
-
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";
|
|
4563
4636
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4564
|
-
import { mx as mx6 } from "@dxos/ui-theme";
|
|
4565
4637
|
|
|
4566
4638
|
// src/extensions/markdown/changes.ts
|
|
4567
4639
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
4568
4640
|
import { Transaction as Transaction4 } from "@codemirror/state";
|
|
4569
|
-
import { ViewPlugin as
|
|
4641
|
+
import { ViewPlugin as ViewPlugin14 } from "@codemirror/view";
|
|
4570
4642
|
var adjustChanges = () => {
|
|
4571
|
-
return
|
|
4643
|
+
return ViewPlugin14.fromClass(class {
|
|
4572
4644
|
update(update2) {
|
|
4573
4645
|
const tree = syntaxTree4(update2.state);
|
|
4574
4646
|
const adjustments = [];
|
|
@@ -4710,7 +4782,7 @@ var getValidUrl = (str) => {
|
|
|
4710
4782
|
// src/extensions/markdown/image.ts
|
|
4711
4783
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4712
4784
|
import { StateField as StateField7 } from "@codemirror/state";
|
|
4713
|
-
import { Decoration as Decoration9, EditorView as
|
|
4785
|
+
import { Decoration as Decoration9, EditorView as EditorView21, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4714
4786
|
var image = (_options = {}) => {
|
|
4715
4787
|
return [
|
|
4716
4788
|
StateField7.define({
|
|
@@ -4721,10 +4793,10 @@ var image = (_options = {}) => {
|
|
|
4721
4793
|
if (!tr.docChanged && !tr.selection) {
|
|
4722
4794
|
return value;
|
|
4723
4795
|
}
|
|
4724
|
-
const
|
|
4796
|
+
const cursor = tr.state.selection.main.head;
|
|
4725
4797
|
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
4726
|
-
let from = Math.min(
|
|
4727
|
-
let to = Math.max(
|
|
4798
|
+
let from = Math.min(cursor, oldCursor);
|
|
4799
|
+
let to = Math.max(cursor, oldCursor);
|
|
4728
4800
|
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
4729
4801
|
from = Math.min(from, fromB);
|
|
4730
4802
|
to = Math.max(to, toB);
|
|
@@ -4738,19 +4810,19 @@ var image = (_options = {}) => {
|
|
|
4738
4810
|
add: buildDecorations(tr.state, from, to)
|
|
4739
4811
|
});
|
|
4740
4812
|
},
|
|
4741
|
-
provide: (field) =>
|
|
4813
|
+
provide: (field) => EditorView21.decorations.from(field)
|
|
4742
4814
|
})
|
|
4743
4815
|
];
|
|
4744
4816
|
};
|
|
4745
4817
|
var buildDecorations = (state, from, to) => {
|
|
4746
4818
|
const decorations2 = [];
|
|
4747
|
-
const
|
|
4819
|
+
const cursor = state.selection.main.head;
|
|
4748
4820
|
syntaxTree5(state).iterate({
|
|
4749
4821
|
enter: (node) => {
|
|
4750
4822
|
if (node.name === "Image") {
|
|
4751
4823
|
const urlNode = node.node.getChild("URL");
|
|
4752
4824
|
if (urlNode) {
|
|
4753
|
-
const hide2 = state.readOnly ||
|
|
4825
|
+
const hide2 = state.readOnly || cursor < node.from || cursor > node.to || !state.field(focusField);
|
|
4754
4826
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
4755
4827
|
if (url.match(/^https?:\/\//) === null && url.match(/^file?:\/\//) === null) {
|
|
4756
4828
|
return;
|
|
@@ -4798,10 +4870,10 @@ var ImageWidget = class extends WidgetType5 {
|
|
|
4798
4870
|
};
|
|
4799
4871
|
|
|
4800
4872
|
// src/extensions/markdown/styles.ts
|
|
4801
|
-
import { EditorView as
|
|
4873
|
+
import { EditorView as EditorView22 } from "@codemirror/view";
|
|
4802
4874
|
var bulletListIndentationWidth = 24;
|
|
4803
4875
|
var orderedListIndentationWidth = 36;
|
|
4804
|
-
var formattingStyles =
|
|
4876
|
+
var formattingStyles = EditorView22.theme({
|
|
4805
4877
|
/**
|
|
4806
4878
|
* Horizontal rule.
|
|
4807
4879
|
*/
|
|
@@ -4836,13 +4908,38 @@ var formattingStyles = EditorView21.theme({
|
|
|
4836
4908
|
background: "var(--color-cm-codeblock)",
|
|
4837
4909
|
borderLeft: "2px solid var(--color-cm-separator)",
|
|
4838
4910
|
paddingLeft: "1rem",
|
|
4839
|
-
margin:
|
|
4911
|
+
margin: 0
|
|
4840
4912
|
},
|
|
4841
4913
|
/**
|
|
4842
4914
|
* Code and codeblocks.
|
|
4843
4915
|
*/
|
|
4916
|
+
"& code": {
|
|
4917
|
+
fontFamily: fontMono,
|
|
4918
|
+
color: "var(--color-cm-code)",
|
|
4919
|
+
whiteSpace: "nowrap"
|
|
4920
|
+
},
|
|
4844
4921
|
"& .cm-code": {
|
|
4845
|
-
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"
|
|
4846
4943
|
},
|
|
4847
4944
|
"& .cm-codeblock-line": {
|
|
4848
4945
|
background: "var(--color-cm-codeblock)",
|
|
@@ -4874,16 +4971,24 @@ var formattingStyles = EditorView21.theme({
|
|
|
4874
4971
|
*/
|
|
4875
4972
|
".cm-table *": {
|
|
4876
4973
|
fontFamily: fontMono,
|
|
4974
|
+
lineHeight: 1.5,
|
|
4877
4975
|
textDecoration: "none !important"
|
|
4878
4976
|
},
|
|
4879
4977
|
".cm-table-head": {
|
|
4880
4978
|
padding: "2px 16px 2px 0px",
|
|
4979
|
+
overflowWrap: "break-word",
|
|
4980
|
+
whiteSpace: "pre-wrap",
|
|
4981
|
+
wordBreak: "keep-all",
|
|
4881
4982
|
textAlign: "left",
|
|
4882
|
-
|
|
4883
|
-
|
|
4983
|
+
color: "var(--color-subdued)",
|
|
4984
|
+
borderBottom: "1px solid var(--color-cm-separator)"
|
|
4884
4985
|
},
|
|
4885
4986
|
".cm-table-cell": {
|
|
4886
|
-
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"
|
|
4887
4992
|
},
|
|
4888
4993
|
/**
|
|
4889
4994
|
* Image.
|
|
@@ -4899,12 +5004,12 @@ var formattingStyles = EditorView21.theme({
|
|
|
4899
5004
|
},
|
|
4900
5005
|
".cm-image-with-loader": {
|
|
4901
5006
|
display: "block",
|
|
4902
|
-
opacity:
|
|
5007
|
+
opacity: 0,
|
|
4903
5008
|
transitionDuration: "350ms",
|
|
4904
5009
|
transitionProperty: "opacity"
|
|
4905
5010
|
},
|
|
4906
5011
|
".cm-image-with-loader.cm-loaded-image": {
|
|
4907
|
-
opacity:
|
|
5012
|
+
opacity: 1
|
|
4908
5013
|
},
|
|
4909
5014
|
".cm-image-wrapper": {
|
|
4910
5015
|
"grid-template-columns": "1fr",
|
|
@@ -4923,17 +5028,17 @@ var formattingStyles = EditorView21.theme({
|
|
|
4923
5028
|
// src/extensions/markdown/table.ts
|
|
4924
5029
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
4925
5030
|
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField8 } from "@codemirror/state";
|
|
4926
|
-
import { Decoration as Decoration10, EditorView as
|
|
5031
|
+
import { Decoration as Decoration10, EditorView as EditorView23, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
4927
5032
|
var table = (options = {}) => {
|
|
4928
5033
|
return StateField8.define({
|
|
4929
5034
|
create: (state) => update(state, options),
|
|
4930
5035
|
update: (_, tr) => update(tr.state, options),
|
|
4931
|
-
provide: (field) =>
|
|
5036
|
+
provide: (field) => EditorView23.decorations.from(field)
|
|
4932
5037
|
});
|
|
4933
5038
|
};
|
|
4934
5039
|
var update = (state, _options) => {
|
|
4935
5040
|
const builder = new RangeSetBuilder4();
|
|
4936
|
-
const
|
|
5041
|
+
const cursor = state.selection.main.head;
|
|
4937
5042
|
const tables = [];
|
|
4938
5043
|
const getTable = () => tables[tables.length - 1];
|
|
4939
5044
|
const getRow = () => {
|
|
@@ -4971,7 +5076,7 @@ var update = (state, _options) => {
|
|
|
4971
5076
|
}
|
|
4972
5077
|
});
|
|
4973
5078
|
tables.forEach((table2) => {
|
|
4974
|
-
const replace = state.readOnly ||
|
|
5079
|
+
const replace = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4975
5080
|
if (replace) {
|
|
4976
5081
|
builder.add(table2.from, table2.to, Decoration10.replace({
|
|
4977
5082
|
block: true,
|
|
@@ -4985,6 +5090,26 @@ var update = (state, _options) => {
|
|
|
4985
5090
|
});
|
|
4986
5091
|
return builder.finish();
|
|
4987
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
|
+
};
|
|
4988
5113
|
var TableWidget = class extends WidgetType6 {
|
|
4989
5114
|
_table;
|
|
4990
5115
|
constructor(_table) {
|
|
@@ -5004,7 +5129,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
5004
5129
|
this._table.header?.forEach((cell) => {
|
|
5005
5130
|
const th = document.createElement("th");
|
|
5006
5131
|
th.setAttribute("class", "cm-table-head");
|
|
5007
|
-
tr.appendChild(th)
|
|
5132
|
+
renderCellContent(tr.appendChild(th), cell);
|
|
5008
5133
|
});
|
|
5009
5134
|
const body = table2.appendChild(document.createElement("tbody"));
|
|
5010
5135
|
this._table.rows?.forEach((row) => {
|
|
@@ -5012,7 +5137,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
5012
5137
|
row.forEach((cell) => {
|
|
5013
5138
|
const td = document.createElement("td");
|
|
5014
5139
|
td.setAttribute("class", "cm-table-cell");
|
|
5015
|
-
tr2.appendChild(td)
|
|
5140
|
+
renderCellContent(tr2.appendChild(td), cell);
|
|
5016
5141
|
});
|
|
5017
5142
|
});
|
|
5018
5143
|
return div;
|
|
@@ -5119,10 +5244,10 @@ var fencedCodeLine = Decoration11.line({
|
|
|
5119
5244
|
class: "cm-code cm-codeblock-line"
|
|
5120
5245
|
});
|
|
5121
5246
|
var fencedCodeLineFirst = Decoration11.line({
|
|
5122
|
-
class:
|
|
5247
|
+
class: "cm-code cm-codeblock-line cm-codeblock-start"
|
|
5123
5248
|
});
|
|
5124
5249
|
var fencedCodeLineLast = Decoration11.line({
|
|
5125
|
-
class:
|
|
5250
|
+
class: "cm-code cm-codeblock-line cm-codeblock-end"
|
|
5126
5251
|
});
|
|
5127
5252
|
var commentBlockLine = fencedCodeLine;
|
|
5128
5253
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
|
@@ -5154,15 +5279,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5154
5279
|
const { state } = view;
|
|
5155
5280
|
const headerLevels = [];
|
|
5156
5281
|
const getHeaderLevels = (node, level) => {
|
|
5157
|
-
invariant4(level > 0, void 0, {
|
|
5158
|
-
F: __dxlog_file12,
|
|
5159
|
-
L: 179,
|
|
5160
|
-
S: void 0,
|
|
5161
|
-
A: [
|
|
5162
|
-
"level > 0",
|
|
5163
|
-
""
|
|
5164
|
-
]
|
|
5165
|
-
});
|
|
5282
|
+
invariant4(level > 0, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 160, S: void 0, A: ["level > 0", ""] });
|
|
5166
5283
|
if (level > headerLevels.length) {
|
|
5167
5284
|
const len = headerLevels.length;
|
|
5168
5285
|
headerLevels.length = level;
|
|
@@ -5193,15 +5310,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5193
5310
|
listLevels.pop();
|
|
5194
5311
|
};
|
|
5195
5312
|
const getCurrentListLevel = () => {
|
|
5196
|
-
invariant4(listLevels.length, void 0, {
|
|
5197
|
-
F: __dxlog_file12,
|
|
5198
|
-
L: 201,
|
|
5199
|
-
S: void 0,
|
|
5200
|
-
A: [
|
|
5201
|
-
"listLevels.length",
|
|
5202
|
-
""
|
|
5203
|
-
]
|
|
5204
|
-
});
|
|
5313
|
+
invariant4(listLevels.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 192, S: void 0, A: ["listLevels.length", ""] });
|
|
5205
5314
|
return listLevels[listLevels.length - 1];
|
|
5206
5315
|
};
|
|
5207
5316
|
const enterNode = (node) => {
|
|
@@ -5239,7 +5348,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5239
5348
|
deco: hide
|
|
5240
5349
|
});
|
|
5241
5350
|
} else {
|
|
5242
|
-
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(".") + "). ";
|
|
5243
5352
|
if (num.length) {
|
|
5244
5353
|
atomicDecoRanges.push({
|
|
5245
5354
|
from: mark.from,
|
|
@@ -5422,11 +5531,11 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5422
5531
|
}
|
|
5423
5532
|
decoRanges.push({
|
|
5424
5533
|
from: marks[0].to,
|
|
5425
|
-
to: marks[1].from,
|
|
5534
|
+
to: !editing && options.renderLinkButton ? node.to : marks[1].from,
|
|
5426
5535
|
deco: Decoration11.mark({
|
|
5427
5536
|
tagName: "a",
|
|
5428
5537
|
attributes: {
|
|
5429
|
-
class: "cm-link",
|
|
5538
|
+
class: options.renderLinkButton ? "cm-link cm-link-with-button" : "cm-link",
|
|
5430
5539
|
href: url,
|
|
5431
5540
|
rel: "noreferrer",
|
|
5432
5541
|
target: "_blank"
|
|
@@ -5504,18 +5613,21 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5504
5613
|
deco.add(from, to, d);
|
|
5505
5614
|
}
|
|
5506
5615
|
const atomicDeco = new RangeSetBuilder5();
|
|
5507
|
-
for (const { from, to, deco:
|
|
5508
|
-
|
|
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);
|
|
5509
5621
|
}
|
|
5510
5622
|
return {
|
|
5511
5623
|
deco: deco.finish(),
|
|
5512
5624
|
atomicDeco: atomicDeco.finish()
|
|
5513
5625
|
};
|
|
5514
5626
|
};
|
|
5515
|
-
var forceUpdate =
|
|
5627
|
+
var forceUpdate = StateEffect7.define();
|
|
5516
5628
|
var decorateMarkdown = (options = {}) => {
|
|
5517
5629
|
return [
|
|
5518
|
-
|
|
5630
|
+
ViewPlugin15.fromClass(class {
|
|
5519
5631
|
deco;
|
|
5520
5632
|
atomicDeco;
|
|
5521
5633
|
pendingUpdate;
|
|
@@ -5550,9 +5662,9 @@ var decorateMarkdown = (options = {}) => {
|
|
|
5550
5662
|
}
|
|
5551
5663
|
}, {
|
|
5552
5664
|
provide: (plugin) => [
|
|
5553
|
-
Prec4.low(
|
|
5554
|
-
|
|
5555
|
-
|
|
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)
|
|
5556
5668
|
]
|
|
5557
5669
|
}),
|
|
5558
5670
|
image(),
|
|
@@ -5620,12 +5732,7 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5620
5732
|
(context) => {
|
|
5621
5733
|
log9.info("completion context", {
|
|
5622
5734
|
context
|
|
5623
|
-
}, {
|
|
5624
|
-
F: __dxlog_file13,
|
|
5625
|
-
L: 27,
|
|
5626
|
-
S: void 0,
|
|
5627
|
-
C: (f, a) => f(...a)
|
|
5628
|
-
});
|
|
5735
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file13, L: 18, S: void 0 });
|
|
5629
5736
|
const match = context.matchBefore(/@(\w+)?/);
|
|
5630
5737
|
if (!match || match.from === match.to && !context.explicit) {
|
|
5631
5738
|
return null;
|
|
@@ -5642,8 +5749,8 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5642
5749
|
};
|
|
5643
5750
|
|
|
5644
5751
|
// src/extensions/modal.ts
|
|
5645
|
-
import { StateEffect as
|
|
5646
|
-
var modalStateEffect =
|
|
5752
|
+
import { StateEffect as StateEffect8, StateField as StateField9 } from "@codemirror/state";
|
|
5753
|
+
var modalStateEffect = StateEffect8.define();
|
|
5647
5754
|
var modalStateField = StateField9.define({
|
|
5648
5755
|
create: () => false,
|
|
5649
5756
|
update: (value, tr) => {
|
|
@@ -5858,15 +5965,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5858
5965
|
break;
|
|
5859
5966
|
}
|
|
5860
5967
|
case "BulletList": {
|
|
5861
|
-
invariant5(current, void 0, {
|
|
5862
|
-
F: __dxlog_file14,
|
|
5863
|
-
L: 219,
|
|
5864
|
-
S: void 0,
|
|
5865
|
-
A: [
|
|
5866
|
-
"current",
|
|
5867
|
-
""
|
|
5868
|
-
]
|
|
5869
|
-
});
|
|
5968
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 169, S: void 0, A: ["current", ""] });
|
|
5870
5969
|
parent = current;
|
|
5871
5970
|
if (current) {
|
|
5872
5971
|
current.lineRange.to = current.node.from;
|
|
@@ -5875,15 +5974,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5875
5974
|
break;
|
|
5876
5975
|
}
|
|
5877
5976
|
case "ListItem": {
|
|
5878
|
-
invariant5(parent, void 0, {
|
|
5879
|
-
F: __dxlog_file14,
|
|
5880
|
-
L: 228,
|
|
5881
|
-
S: void 0,
|
|
5882
|
-
A: [
|
|
5883
|
-
"parent",
|
|
5884
|
-
""
|
|
5885
|
-
]
|
|
5886
|
-
});
|
|
5977
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 179, S: void 0, A: ["parent", ""] });
|
|
5887
5978
|
const nextSibling = node.node.nextSibling ?? node.node.parent?.nextSibling;
|
|
5888
5979
|
const docRange = {
|
|
5889
5980
|
from: state.doc.lineAt(node.from).from,
|
|
@@ -5917,42 +6008,18 @@ var outlinerTree = (_options = {}) => {
|
|
|
5917
6008
|
break;
|
|
5918
6009
|
}
|
|
5919
6010
|
case "ListMark": {
|
|
5920
|
-
invariant5(current, void 0, {
|
|
5921
|
-
F: __dxlog_file14,
|
|
5922
|
-
L: 272,
|
|
5923
|
-
S: void 0,
|
|
5924
|
-
A: [
|
|
5925
|
-
"current",
|
|
5926
|
-
""
|
|
5927
|
-
]
|
|
5928
|
-
});
|
|
6011
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 219, S: void 0, A: ["current", ""] });
|
|
5929
6012
|
current.type = "bullet";
|
|
5930
6013
|
current.contentRange.from = node.from + "- ".length;
|
|
5931
6014
|
break;
|
|
5932
6015
|
}
|
|
5933
6016
|
case "Task": {
|
|
5934
|
-
invariant5(current, void 0, {
|
|
5935
|
-
F: __dxlog_file14,
|
|
5936
|
-
L: 278,
|
|
5937
|
-
S: void 0,
|
|
5938
|
-
A: [
|
|
5939
|
-
"current",
|
|
5940
|
-
""
|
|
5941
|
-
]
|
|
5942
|
-
});
|
|
6017
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 226, S: void 0, A: ["current", ""] });
|
|
5943
6018
|
current.type = "task";
|
|
5944
6019
|
break;
|
|
5945
6020
|
}
|
|
5946
6021
|
case "TaskMarker": {
|
|
5947
|
-
invariant5(current, void 0, {
|
|
5948
|
-
F: __dxlog_file14,
|
|
5949
|
-
L: 283,
|
|
5950
|
-
S: void 0,
|
|
5951
|
-
A: [
|
|
5952
|
-
"current",
|
|
5953
|
-
""
|
|
5954
|
-
]
|
|
5955
|
-
});
|
|
6022
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 232, S: void 0, A: ["current", ""] });
|
|
5956
6023
|
current.contentRange.from = node.from + "[ ] ".length;
|
|
5957
6024
|
break;
|
|
5958
6025
|
}
|
|
@@ -5960,29 +6027,13 @@ var outlinerTree = (_options = {}) => {
|
|
|
5960
6027
|
},
|
|
5961
6028
|
leave: (node) => {
|
|
5962
6029
|
if (node.name === "BulletList") {
|
|
5963
|
-
invariant5(parent, void 0, {
|
|
5964
|
-
F: __dxlog_file14,
|
|
5965
|
-
L: 291,
|
|
5966
|
-
S: void 0,
|
|
5967
|
-
A: [
|
|
5968
|
-
"parent",
|
|
5969
|
-
""
|
|
5970
|
-
]
|
|
5971
|
-
});
|
|
6030
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 240, S: void 0, A: ["parent", ""] });
|
|
5972
6031
|
prevSiblings[level--] = void 0;
|
|
5973
6032
|
parent = parent.parent;
|
|
5974
6033
|
}
|
|
5975
6034
|
}
|
|
5976
6035
|
});
|
|
5977
|
-
invariant5(tree, void 0, {
|
|
5978
|
-
F: __dxlog_file14,
|
|
5979
|
-
L: 298,
|
|
5980
|
-
S: void 0,
|
|
5981
|
-
A: [
|
|
5982
|
-
"tree",
|
|
5983
|
-
""
|
|
5984
|
-
]
|
|
5985
|
-
});
|
|
6036
|
+
invariant5(tree, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 246, S: void 0, A: ["tree", ""] });
|
|
5986
6037
|
return tree;
|
|
5987
6038
|
};
|
|
5988
6039
|
return [
|
|
@@ -6267,17 +6318,17 @@ var commands = () => keymap11.of([
|
|
|
6267
6318
|
|
|
6268
6319
|
// src/extensions/outliner/outliner.ts
|
|
6269
6320
|
import { Prec as Prec5 } from "@codemirror/state";
|
|
6270
|
-
import { Decoration as Decoration12, EditorView as
|
|
6271
|
-
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";
|
|
6272
6323
|
|
|
6273
6324
|
// src/extensions/outliner/editor.ts
|
|
6274
6325
|
import { EditorSelection as EditorSelection4, EditorState as EditorState2 } from "@codemirror/state";
|
|
6275
|
-
import { ViewPlugin as
|
|
6326
|
+
import { ViewPlugin as ViewPlugin16 } from "@codemirror/view";
|
|
6276
6327
|
import { log as log10 } from "@dxos/log";
|
|
6277
6328
|
var __dxlog_file15 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/editor.ts";
|
|
6278
6329
|
var LIST_ITEM_REGEX = /^\s*- (\[ \]|\[x\])? /;
|
|
6279
6330
|
var initialize = () => {
|
|
6280
|
-
return
|
|
6331
|
+
return ViewPlugin16.fromClass(class {
|
|
6281
6332
|
constructor(view) {
|
|
6282
6333
|
const first = view.state.doc.lineAt(0);
|
|
6283
6334
|
const text = view.state.sliceDoc(first.from, first.to);
|
|
@@ -6424,35 +6475,20 @@ var editor = () => [
|
|
|
6424
6475
|
text: insert.toString(),
|
|
6425
6476
|
length: insert.length
|
|
6426
6477
|
}
|
|
6427
|
-
}, {
|
|
6428
|
-
F: __dxlog_file15,
|
|
6429
|
-
L: 164,
|
|
6430
|
-
S: void 0,
|
|
6431
|
-
C: (f, a) => f(...a)
|
|
6432
|
-
});
|
|
6478
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 174, S: void 0 });
|
|
6433
6479
|
}
|
|
6434
6480
|
});
|
|
6435
6481
|
if (changes.length > 0) {
|
|
6436
6482
|
log10("modified,", {
|
|
6437
6483
|
changes
|
|
6438
|
-
}, {
|
|
6439
|
-
F: __dxlog_file15,
|
|
6440
|
-
L: 175,
|
|
6441
|
-
S: void 0,
|
|
6442
|
-
C: (f, a) => f(...a)
|
|
6443
|
-
});
|
|
6484
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 196, S: void 0 });
|
|
6444
6485
|
return [
|
|
6445
6486
|
{
|
|
6446
6487
|
changes
|
|
6447
6488
|
}
|
|
6448
6489
|
];
|
|
6449
6490
|
} else if (cancel) {
|
|
6450
|
-
log10("cancel", void 0, {
|
|
6451
|
-
F: __dxlog_file15,
|
|
6452
|
-
L: 178,
|
|
6453
|
-
S: void 0,
|
|
6454
|
-
C: (f, a) => f(...a)
|
|
6455
|
-
});
|
|
6491
|
+
log10("cancel", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 205, S: void 0 });
|
|
6456
6492
|
return [];
|
|
6457
6493
|
}
|
|
6458
6494
|
return tr;
|
|
@@ -6460,10 +6496,10 @@ var editor = () => [
|
|
|
6460
6496
|
];
|
|
6461
6497
|
|
|
6462
6498
|
// src/extensions/outliner/menu.ts
|
|
6463
|
-
import { EditorView as
|
|
6499
|
+
import { EditorView as EditorView25, ViewPlugin as ViewPlugin17 } from "@codemirror/view";
|
|
6464
6500
|
import { addEventListener as addEventListener2 } from "@dxos/async";
|
|
6465
6501
|
var menu = (options = {}) => [
|
|
6466
|
-
|
|
6502
|
+
ViewPlugin17.fromClass(class {
|
|
6467
6503
|
view;
|
|
6468
6504
|
tag;
|
|
6469
6505
|
rafId;
|
|
@@ -6525,7 +6561,7 @@ var menu = (options = {}) => [
|
|
|
6525
6561
|
this.rafId = requestAnimationFrame(this.updateButtonPosition.bind(this));
|
|
6526
6562
|
}
|
|
6527
6563
|
}),
|
|
6528
|
-
|
|
6564
|
+
EditorView25.theme({
|
|
6529
6565
|
".cm-popover-trigger": {
|
|
6530
6566
|
position: "fixed",
|
|
6531
6567
|
padding: "0",
|
|
@@ -6561,12 +6597,12 @@ var outliner = (_options = {}) => [
|
|
|
6561
6597
|
listPaddingLeft: 8
|
|
6562
6598
|
}),
|
|
6563
6599
|
// Researve space for menu.
|
|
6564
|
-
|
|
6600
|
+
EditorView26.contentAttributes.of({
|
|
6565
6601
|
class: "w-full !mr-[3rem]"
|
|
6566
6602
|
})
|
|
6567
6603
|
];
|
|
6568
6604
|
var decorations = () => [
|
|
6569
|
-
|
|
6605
|
+
ViewPlugin18.fromClass(class {
|
|
6570
6606
|
decorations = Decoration12.none;
|
|
6571
6607
|
constructor(view) {
|
|
6572
6608
|
this.updateDecorations(view.state, view);
|
|
@@ -6591,7 +6627,7 @@ var decorations = () => [
|
|
|
6591
6627
|
const lineTo = doc.lineAt(item.contentRange.to);
|
|
6592
6628
|
const isSelected = selection.includes(item.index) || item === current;
|
|
6593
6629
|
decorations2.push(Decoration12.line({
|
|
6594
|
-
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"))
|
|
6595
6631
|
}).range(line.from, line.from));
|
|
6596
6632
|
}
|
|
6597
6633
|
}
|
|
@@ -6601,7 +6637,7 @@ var decorations = () => [
|
|
|
6601
6637
|
decorations: (v) => v.decorations
|
|
6602
6638
|
}),
|
|
6603
6639
|
// Theme.
|
|
6604
|
-
|
|
6640
|
+
EditorView26.theme(Object.assign({
|
|
6605
6641
|
".cm-list-item": {
|
|
6606
6642
|
borderLeftWidth: "1px",
|
|
6607
6643
|
borderRightWidth: "1px",
|
|
@@ -6626,7 +6662,7 @@ var decorations = () => [
|
|
|
6626
6662
|
marginBottom: "2px"
|
|
6627
6663
|
},
|
|
6628
6664
|
".cm-list-item-focused": {
|
|
6629
|
-
borderColor: "var(--color-
|
|
6665
|
+
borderColor: "var(--color-focus-ring-subtle)"
|
|
6630
6666
|
},
|
|
6631
6667
|
"&:focus-within .cm-list-item-selected": {
|
|
6632
6668
|
borderColor: "var(--color-separator)"
|
|
@@ -6636,28 +6672,57 @@ var decorations = () => [
|
|
|
6636
6672
|
|
|
6637
6673
|
// src/extensions/preview/preview.ts
|
|
6638
6674
|
import { syntaxTree as syntaxTree10 } from "@codemirror/language";
|
|
6639
|
-
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField11 } from "@codemirror/state";
|
|
6640
|
-
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();
|
|
6641
6679
|
var preview = (options = {}) => {
|
|
6680
|
+
const viewRef = {
|
|
6681
|
+
current: void 0
|
|
6682
|
+
};
|
|
6642
6683
|
return [
|
|
6643
6684
|
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
|
6644
6685
|
// "Block decorations may not be specified via plugins".
|
|
6645
6686
|
StateField11.define({
|
|
6646
|
-
create: (state) => buildDecorations3(state, options),
|
|
6687
|
+
create: (state) => buildDecorations3(state, options, viewRef),
|
|
6647
6688
|
update: (decorations2, tr) => {
|
|
6648
|
-
if (tr.docChanged) {
|
|
6649
|
-
return buildDecorations3(tr.state, options);
|
|
6689
|
+
if (tr.docChanged || tr.effects.some((effect) => effect.is(labelResolvedEffect))) {
|
|
6690
|
+
return buildDecorations3(tr.state, options, viewRef);
|
|
6650
6691
|
}
|
|
6651
6692
|
return decorations2.map(tr.changes);
|
|
6652
6693
|
},
|
|
6653
6694
|
provide: (field) => [
|
|
6654
|
-
|
|
6655
|
-
|
|
6695
|
+
EditorView27.decorations.from(field),
|
|
6696
|
+
EditorView27.atomicRanges.of((view) => view.state.field(field))
|
|
6656
6697
|
]
|
|
6698
|
+
}),
|
|
6699
|
+
ViewPlugin19.define((view) => {
|
|
6700
|
+
viewRef.current = view;
|
|
6701
|
+
return {
|
|
6702
|
+
destroy() {
|
|
6703
|
+
viewRef.current = void 0;
|
|
6704
|
+
}
|
|
6705
|
+
};
|
|
6657
6706
|
})
|
|
6658
6707
|
];
|
|
6659
6708
|
};
|
|
6660
|
-
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) => {
|
|
6661
6726
|
const builder = new RangeSetBuilder6();
|
|
6662
6727
|
syntaxTree10(state).iterate({
|
|
6663
6728
|
enter: (node) => {
|
|
@@ -6669,8 +6734,13 @@ var buildDecorations3 = (state, options) => {
|
|
|
6669
6734
|
case "Link": {
|
|
6670
6735
|
const link = getLinkRef(state, node.node);
|
|
6671
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;
|
|
6672
6742
|
builder.add(node.from, node.to, Decoration13.replace({
|
|
6673
|
-
widget: new PreviewInlineWidget(options,
|
|
6743
|
+
widget: new PreviewInlineWidget(options, displayLink),
|
|
6674
6744
|
side: 1
|
|
6675
6745
|
}));
|
|
6676
6746
|
}
|
|
@@ -6762,7 +6832,7 @@ var PreviewBlockWidget = class extends WidgetType8 {
|
|
|
6762
6832
|
};
|
|
6763
6833
|
|
|
6764
6834
|
// src/extensions/replacer.ts
|
|
6765
|
-
import { EditorView as
|
|
6835
|
+
import { EditorView as EditorView28 } from "@codemirror/view";
|
|
6766
6836
|
var defaultReplacements = [
|
|
6767
6837
|
{
|
|
6768
6838
|
input: "--",
|
|
@@ -6825,7 +6895,7 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6825
6895
|
const sortedReplacements = [
|
|
6826
6896
|
...replacements
|
|
6827
6897
|
].sort((a, b) => b.input.length - a.input.length);
|
|
6828
|
-
return
|
|
6898
|
+
return EditorView28.inputHandler.of((view, from, to, insert) => {
|
|
6829
6899
|
if (insert.length !== 1) {
|
|
6830
6900
|
return false;
|
|
6831
6901
|
}
|
|
@@ -6859,12 +6929,69 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6859
6929
|
});
|
|
6860
6930
|
};
|
|
6861
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
|
+
|
|
6862
6989
|
// src/extensions/submit.ts
|
|
6863
6990
|
import { Prec as Prec6 } from "@codemirror/state";
|
|
6864
|
-
import { keymap as
|
|
6991
|
+
import { keymap as keymap13 } from "@codemirror/view";
|
|
6865
6992
|
var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
6866
6993
|
return [
|
|
6867
|
-
Prec6.highest(
|
|
6994
|
+
Prec6.highest(keymap13.of([
|
|
6868
6995
|
{
|
|
6869
6996
|
key: "Enter",
|
|
6870
6997
|
preventDefault: true,
|
|
@@ -6909,6 +7036,7 @@ var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
|
6909
7036
|
// src/extensions/tags/extended-markdown.ts
|
|
6910
7037
|
import { xmlLanguage } from "@codemirror/lang-xml";
|
|
6911
7038
|
import { parseMixed } from "@lezer/common";
|
|
7039
|
+
var escapeRegExpSource = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6912
7040
|
var extendedMarkdown = ({ registry } = {}) => {
|
|
6913
7041
|
return [
|
|
6914
7042
|
createMarkdownExtensions({
|
|
@@ -6920,13 +7048,65 @@ var extendedMarkdown = ({ registry } = {}) => {
|
|
|
6920
7048
|
{
|
|
6921
7049
|
name: "SetextHeading",
|
|
6922
7050
|
parse: () => false
|
|
6923
|
-
}
|
|
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)
|
|
6924
7055
|
]
|
|
6925
7056
|
}
|
|
6926
7057
|
]
|
|
6927
7058
|
})
|
|
6928
7059
|
];
|
|
6929
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
|
+
};
|
|
6930
7110
|
var mixedParser = (registry) => {
|
|
6931
7111
|
const customTags = Object.keys(registry ?? {});
|
|
6932
7112
|
const tagPattern = new RegExp(`<(${customTags.join("|")})`);
|
|
@@ -6953,226 +7133,800 @@ var mixedParser = (registry) => {
|
|
|
6953
7133
|
parser: xmlLanguage.parser
|
|
6954
7134
|
};
|
|
6955
7135
|
}
|
|
6956
|
-
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);
|
|
6957
7514
|
}
|
|
6958
7515
|
}
|
|
6959
|
-
return null;
|
|
6960
7516
|
});
|
|
6961
|
-
};
|
|
6962
|
-
|
|
6963
|
-
// src/extensions/tags/streamer.ts
|
|
6964
|
-
import { StateEffect as StateEffect8, StateField as StateField12 } from "@codemirror/state";
|
|
6965
|
-
import { Decoration as Decoration14, EditorView as EditorView28, ViewPlugin as ViewPlugin18, WidgetType as WidgetType9 } from "@codemirror/view";
|
|
6966
|
-
import { Domino as Domino3 } from "@dxos/ui";
|
|
6967
|
-
import { isTruthy as isTruthy4 } from "@dxos/util";
|
|
6968
|
-
var BLINK_RATE = 2e3;
|
|
6969
|
-
var streamer = (options = {}) => {
|
|
6970
7517
|
return [
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
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
|
+
}),
|
|
6979
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
|
+
}
|
|
6980
7551
|
for (const effect of tr.effects) {
|
|
6981
7552
|
if (effect.is(hideCursor)) {
|
|
6982
|
-
return
|
|
7553
|
+
return {
|
|
7554
|
+
...value,
|
|
7555
|
+
visible: false
|
|
7556
|
+
};
|
|
6983
7557
|
}
|
|
6984
7558
|
}
|
|
6985
|
-
if (tr.docChanged) {
|
|
6986
|
-
return true;
|
|
6987
|
-
}
|
|
6988
7559
|
return value;
|
|
6989
7560
|
}
|
|
6990
7561
|
});
|
|
6991
|
-
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 {
|
|
6992
7582
|
view;
|
|
6993
|
-
|
|
7583
|
+
_timer;
|
|
6994
7584
|
constructor(view) {
|
|
6995
7585
|
this.view = view;
|
|
6996
7586
|
}
|
|
6997
7587
|
update(update2) {
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
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(() => {
|
|
7001
7596
|
this.view.dispatch({
|
|
7002
7597
|
effects: hideCursor.of(null)
|
|
7003
7598
|
});
|
|
7004
|
-
|
|
7599
|
+
this._timer = void 0;
|
|
7600
|
+
}, CURSOR_LINGER);
|
|
7005
7601
|
}
|
|
7006
7602
|
}
|
|
7007
7603
|
destroy() {
|
|
7008
|
-
clearTimeout(this.
|
|
7604
|
+
clearTimeout(this._timer);
|
|
7009
7605
|
}
|
|
7010
7606
|
});
|
|
7011
|
-
const cursorDecoration = StateField12.define({
|
|
7012
|
-
create: () => Decoration14.none,
|
|
7013
|
-
update: (_decorations, tr) => {
|
|
7014
|
-
const show = tr.state.field(showCursor);
|
|
7015
|
-
if (!show) {
|
|
7016
|
-
return Decoration14.none;
|
|
7017
|
-
}
|
|
7018
|
-
const endPos = tr.state.doc.length;
|
|
7019
|
-
return Decoration14.set([
|
|
7020
|
-
Decoration14.widget({
|
|
7021
|
-
widget: new CursorWidget(),
|
|
7022
|
-
side: 1
|
|
7023
|
-
}).range(endPos)
|
|
7024
|
-
]);
|
|
7025
|
-
},
|
|
7026
|
-
provide: (f) => EditorView28.decorations.from(f)
|
|
7027
|
-
});
|
|
7028
7607
|
return [
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7608
|
+
visibilityField,
|
|
7609
|
+
decorationField,
|
|
7610
|
+
timerPlugin
|
|
7032
7611
|
];
|
|
7033
7612
|
};
|
|
7034
|
-
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
|
+
}
|
|
7035
7619
|
toDOM() {
|
|
7036
|
-
const inner = Domino3.of("span").text("\
|
|
7037
|
-
animation: "blink
|
|
7620
|
+
const inner = Domino3.of("span").text("\u2217").style({
|
|
7621
|
+
animation: "blink 1s infinite",
|
|
7622
|
+
animationDelay: "250ms"
|
|
7038
7623
|
});
|
|
7039
7624
|
return Domino3.of("span").style({
|
|
7040
7625
|
opacity: "0.8"
|
|
7041
|
-
}).
|
|
7626
|
+
}).append(inner).root;
|
|
7042
7627
|
}
|
|
7043
7628
|
};
|
|
7044
|
-
var
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
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
|
+
};
|
|
7063
7665
|
}
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
isReset = true;
|
|
7069
|
-
}
|
|
7070
|
-
});
|
|
7666
|
+
if (buffer[close - 1] === "/") {
|
|
7667
|
+
return {
|
|
7668
|
+
count: close + 1 - start
|
|
7669
|
+
};
|
|
7071
7670
|
}
|
|
7072
|
-
|
|
7073
|
-
|
|
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;
|
|
7074
7726
|
}
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
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") {
|
|
7078
7772
|
return;
|
|
7079
7773
|
}
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
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;
|
|
7084
7779
|
}
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
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;
|
|
7096
7811
|
constructor(view) {
|
|
7097
|
-
this.
|
|
7812
|
+
this.decorations = buildDecorations5(view);
|
|
7098
7813
|
}
|
|
7099
7814
|
update(update2) {
|
|
7100
|
-
if (
|
|
7101
|
-
|
|
7815
|
+
if (update2.docChanged) {
|
|
7816
|
+
this.decorations = buildDecorations5(update2.view);
|
|
7102
7817
|
}
|
|
7103
|
-
|
|
7104
|
-
|
|
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));
|
|
7105
7864
|
return;
|
|
7106
7865
|
}
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
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
|
+
}
|
|
7110
7883
|
}
|
|
7111
|
-
const totalDelay = FADE_IN_DURATION + removalDelay;
|
|
7112
|
-
const id = setTimeout(() => {
|
|
7113
|
-
this.view.dispatch({
|
|
7114
|
-
effects: removeDecoration.of({
|
|
7115
|
-
from: fromB,
|
|
7116
|
-
to: toB
|
|
7117
|
-
})
|
|
7118
|
-
});
|
|
7119
|
-
this._timers.delete(key);
|
|
7120
|
-
}, totalDelay);
|
|
7121
|
-
this._timers.set(key, id);
|
|
7122
|
-
});
|
|
7123
|
-
}
|
|
7124
|
-
destroy() {
|
|
7125
|
-
for (const id of this._timers.values()) {
|
|
7126
|
-
clearTimeout(id);
|
|
7127
7884
|
}
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
}
|
|
7885
|
+
});
|
|
7886
|
+
return Decoration17.set(ranges, true);
|
|
7887
|
+
};
|
|
7131
7888
|
return [
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
},
|
|
7141
|
-
"@keyframes fade-in": {
|
|
7142
|
-
"0%": {
|
|
7143
|
-
opacity: "0"
|
|
7144
|
-
},
|
|
7145
|
-
"80%": {
|
|
7146
|
-
opacity: "1"
|
|
7147
|
-
},
|
|
7148
|
-
"100%": {
|
|
7149
|
-
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);
|
|
7150
7897
|
}
|
|
7151
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": {}
|
|
7152
7913
|
})
|
|
7153
7914
|
];
|
|
7154
7915
|
};
|
|
7155
7916
|
|
|
7156
7917
|
// src/extensions/tags/xml-tags.ts
|
|
7157
7918
|
import { syntaxTree as syntaxTree11 } from "@codemirror/language";
|
|
7158
|
-
import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as
|
|
7159
|
-
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";
|
|
7160
7921
|
import { invariant as invariant7 } from "@dxos/invariant";
|
|
7161
7922
|
import { log as log11 } from "@dxos/log";
|
|
7923
|
+
import { Domino as Domino4 } from "@dxos/ui";
|
|
7162
7924
|
|
|
7163
7925
|
// src/extensions/tags/xml-util.ts
|
|
7164
7926
|
import { invariant as invariant6 } from "@dxos/invariant";
|
|
7165
7927
|
var __dxlog_file16 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-util.ts";
|
|
7166
7928
|
var nodeToJson = (state, node) => {
|
|
7167
|
-
invariant6(node.type.name === "Element", "Node is not an Element", {
|
|
7168
|
-
F: __dxlog_file16,
|
|
7169
|
-
L: 18,
|
|
7170
|
-
S: void 0,
|
|
7171
|
-
A: [
|
|
7172
|
-
"node.type.name === 'Element'",
|
|
7173
|
-
"'Node is not an Element'"
|
|
7174
|
-
]
|
|
7175
|
-
});
|
|
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'"] });
|
|
7176
7930
|
const openTag = node.node.getChild("OpenTag") || node.node.getChild("SelfClosingTag");
|
|
7177
7931
|
if (openTag) {
|
|
7178
7932
|
const tagName = openTag.getChild("TagName");
|
|
@@ -7204,13 +7958,23 @@ var nodeToJson = (state, node) => {
|
|
|
7204
7958
|
if (node.type.name === "Element" && openTag.type.name !== "SelfClosingTag") {
|
|
7205
7959
|
const children = [];
|
|
7206
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
|
+
};
|
|
7207
7972
|
while (child) {
|
|
7208
7973
|
if (child.type.name !== "OpenTag" && child.type.name !== "CloseTag") {
|
|
7209
7974
|
if (child.type.name === "Text") {
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
}
|
|
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)));
|
|
7214
7978
|
} else if (child.type.name === "Element") {
|
|
7215
7979
|
const data = nodeToJson(state, child);
|
|
7216
7980
|
if (data) {
|
|
@@ -7220,26 +7984,63 @@ var nodeToJson = (state, node) => {
|
|
|
7220
7984
|
}
|
|
7221
7985
|
child = child.nextSibling;
|
|
7222
7986
|
}
|
|
7987
|
+
if (children.length > 0 && typeof children[0] === "string") {
|
|
7988
|
+
children[0] = children[0].trimStart();
|
|
7989
|
+
}
|
|
7223
7990
|
if (children.length > 0) {
|
|
7224
|
-
|
|
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;
|
|
7225
8000
|
}
|
|
7226
8001
|
}
|
|
7227
8002
|
return tag;
|
|
7228
8003
|
}
|
|
7229
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
|
+
};
|
|
7230
8029
|
|
|
7231
8030
|
// src/extensions/tags/xml-tags.ts
|
|
7232
8031
|
var __dxlog_file17 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-tags.ts";
|
|
7233
|
-
var navigatePreviousEffect =
|
|
7234
|
-
var navigateNextEffect =
|
|
8032
|
+
var navigatePreviousEffect = StateEffect12.define();
|
|
8033
|
+
var navigateNextEffect = StateEffect12.define();
|
|
7235
8034
|
var getXmlTextChild = (children) => {
|
|
7236
8035
|
const child = children?.[0];
|
|
7237
8036
|
return typeof child === "string" ? child : null;
|
|
7238
8037
|
};
|
|
7239
|
-
var
|
|
7240
|
-
var
|
|
7241
|
-
var
|
|
7242
|
-
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({
|
|
7243
8044
|
create: () => void 0,
|
|
7244
8045
|
update: (value, tr) => {
|
|
7245
8046
|
for (const effect of tr.effects) {
|
|
@@ -7250,7 +8051,7 @@ var widgetContextStateField = StateField13.define({
|
|
|
7250
8051
|
return value;
|
|
7251
8052
|
}
|
|
7252
8053
|
});
|
|
7253
|
-
var widgetStateMapStateField =
|
|
8054
|
+
var widgetStateMapStateField = StateField14.define({
|
|
7254
8055
|
create: () => ({}),
|
|
7255
8056
|
update: (map, tr) => {
|
|
7256
8057
|
for (const effect of tr.effects) {
|
|
@@ -7262,12 +8063,7 @@ var widgetStateMapStateField = StateField13.define({
|
|
|
7262
8063
|
log11("widget updated", {
|
|
7263
8064
|
id,
|
|
7264
8065
|
value
|
|
7265
|
-
}, {
|
|
7266
|
-
F: __dxlog_file17,
|
|
7267
|
-
L: 153,
|
|
7268
|
-
S: void 0,
|
|
7269
|
-
C: (f, a) => f(...a)
|
|
7270
|
-
});
|
|
8066
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 59, S: void 0 });
|
|
7271
8067
|
const state = typeof value === "function" ? value(map[id]) : value;
|
|
7272
8068
|
return {
|
|
7273
8069
|
...map,
|
|
@@ -7297,12 +8093,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7297
8093
|
log11("widget mounted", {
|
|
7298
8094
|
id: state.id,
|
|
7299
8095
|
tag: state.props._tag
|
|
7300
|
-
}, {
|
|
7301
|
-
F: __dxlog_file17,
|
|
7302
|
-
L: 206,
|
|
7303
|
-
S: void 0,
|
|
7304
|
-
C: (f, a) => f(...a)
|
|
7305
|
-
});
|
|
8096
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 101, S: void 0 });
|
|
7306
8097
|
widgets.set(state.id, state);
|
|
7307
8098
|
setWidgets?.([
|
|
7308
8099
|
...widgets.values()
|
|
@@ -7313,12 +8104,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7313
8104
|
log11("widget unmounted", {
|
|
7314
8105
|
id,
|
|
7315
8106
|
tag: state?.props._tag
|
|
7316
|
-
}, {
|
|
7317
|
-
F: __dxlog_file17,
|
|
7318
|
-
L: 212,
|
|
7319
|
-
S: void 0,
|
|
7320
|
-
C: (f, a) => f(...a)
|
|
7321
|
-
});
|
|
8107
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 112, S: void 0 });
|
|
7322
8108
|
widgets.delete(id);
|
|
7323
8109
|
setWidgets?.([
|
|
7324
8110
|
...widgets.values()
|
|
@@ -7327,7 +8113,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7327
8113
|
};
|
|
7328
8114
|
return notifier;
|
|
7329
8115
|
};
|
|
7330
|
-
var keyHandlers =
|
|
8116
|
+
var keyHandlers = keymap14.of([
|
|
7331
8117
|
{
|
|
7332
8118
|
key: "Mod-ArrowUp",
|
|
7333
8119
|
run: (view) => {
|
|
@@ -7348,7 +8134,7 @@ var keyHandlers = keymap13.of([
|
|
|
7348
8134
|
}
|
|
7349
8135
|
]);
|
|
7350
8136
|
var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
7351
|
-
return
|
|
8137
|
+
return EditorView32.updateListener.of((update2) => {
|
|
7352
8138
|
update2.transactions.forEach((transaction) => {
|
|
7353
8139
|
for (const effect of transaction.effects) {
|
|
7354
8140
|
if (effect.is(navigatePreviousEffect)) {
|
|
@@ -7376,7 +8162,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7376
8162
|
anchor: line.from,
|
|
7377
8163
|
head: line.from
|
|
7378
8164
|
},
|
|
7379
|
-
effects:
|
|
8165
|
+
effects: crawlerLineEffect.of({
|
|
7380
8166
|
line: line.number - 1,
|
|
7381
8167
|
offset: -16
|
|
7382
8168
|
})
|
|
@@ -7409,7 +8195,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7409
8195
|
anchor: line.to,
|
|
7410
8196
|
head: line.to
|
|
7411
8197
|
},
|
|
7412
|
-
effects:
|
|
8198
|
+
effects: crawlerLineEffect.of({
|
|
7413
8199
|
line: line.number - 1,
|
|
7414
8200
|
offset: -16
|
|
7415
8201
|
})
|
|
@@ -7421,7 +8207,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7421
8207
|
anchor: line.to,
|
|
7422
8208
|
head: line.to
|
|
7423
8209
|
},
|
|
7424
|
-
effects:
|
|
8210
|
+
effects: crawlerLineEffect.of({
|
|
7425
8211
|
line: line.number - 1,
|
|
7426
8212
|
position: "end"
|
|
7427
8213
|
})
|
|
@@ -7433,7 +8219,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7433
8219
|
});
|
|
7434
8220
|
});
|
|
7435
8221
|
};
|
|
7436
|
-
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) =>
|
|
8222
|
+
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin24.fromClass(class {
|
|
7437
8223
|
update(update2) {
|
|
7438
8224
|
const widgetStateMap = update2.state.field(widgetStateMapStateField);
|
|
7439
8225
|
const { decorations: decorations2 } = update2.state.field(widgetDecorationsField);
|
|
@@ -7460,14 +8246,14 @@ var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin1
|
|
|
7460
8246
|
}
|
|
7461
8247
|
}
|
|
7462
8248
|
});
|
|
7463
|
-
var createWidgetDecorationsField = (registry = {}, notifier) =>
|
|
8249
|
+
var createWidgetDecorationsField = (registry = {}, notifier) => StateField14.define({
|
|
7464
8250
|
create: (state) => {
|
|
7465
8251
|
return buildDecorations4(state, {
|
|
7466
8252
|
from: 0,
|
|
7467
8253
|
to: state.doc.length
|
|
7468
8254
|
}, registry, notifier);
|
|
7469
8255
|
},
|
|
7470
|
-
update: ({ from, decorations: decorations2 }, tr) => {
|
|
8256
|
+
update: ({ from, streamingFrom, decorations: decorations2 }, tr) => {
|
|
7471
8257
|
for (const effect of tr.effects) {
|
|
7472
8258
|
if (effect.is(xmlTagResetEffect)) {
|
|
7473
8259
|
if (tr.docChanged) {
|
|
@@ -7478,7 +8264,7 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7478
8264
|
}
|
|
7479
8265
|
return {
|
|
7480
8266
|
from: 0,
|
|
7481
|
-
decorations:
|
|
8267
|
+
decorations: Decoration18.none
|
|
7482
8268
|
};
|
|
7483
8269
|
}
|
|
7484
8270
|
}
|
|
@@ -7489,24 +8275,23 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7489
8275
|
log11("document reset", {
|
|
7490
8276
|
from,
|
|
7491
8277
|
to: state.doc.length
|
|
7492
|
-
}, {
|
|
7493
|
-
F: __dxlog_file17,
|
|
7494
|
-
L: 374,
|
|
7495
|
-
S: void 0,
|
|
7496
|
-
C: (f, a) => f(...a)
|
|
7497
|
-
});
|
|
8278
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 298, S: void 0 });
|
|
7498
8279
|
return buildDecorations4(state, {
|
|
7499
8280
|
from: 0,
|
|
7500
8281
|
to: state.doc.length
|
|
7501
8282
|
}, registry, notifier);
|
|
7502
8283
|
} else {
|
|
8284
|
+
const rebuildFrom = streamingFrom ?? from;
|
|
7503
8285
|
const result = buildDecorations4(state, {
|
|
7504
|
-
from,
|
|
8286
|
+
from: rebuildFrom,
|
|
7505
8287
|
to: state.doc.length
|
|
7506
8288
|
}, registry, notifier);
|
|
7507
8289
|
return {
|
|
7508
8290
|
from: result.from,
|
|
8291
|
+
streamingFrom: result.streamingFrom,
|
|
7509
8292
|
decorations: decorations2.update({
|
|
8293
|
+
// Remove old streaming decorations — they are rebuilt each tick.
|
|
8294
|
+
filter: (_f, _t, deco) => !deco.spec.streaming,
|
|
7510
8295
|
add: decorationSetToArray(result.decorations)
|
|
7511
8296
|
})
|
|
7512
8297
|
};
|
|
@@ -7514,12 +8299,13 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7514
8299
|
}
|
|
7515
8300
|
return {
|
|
7516
8301
|
from,
|
|
8302
|
+
streamingFrom,
|
|
7517
8303
|
decorations: decorations2
|
|
7518
8304
|
};
|
|
7519
8305
|
},
|
|
7520
8306
|
provide: (field) => [
|
|
7521
|
-
|
|
7522
|
-
|
|
8307
|
+
EditorView32.decorations.from(field, (v) => v.decorations),
|
|
8308
|
+
EditorView32.atomicRanges.of((view) => view.state.field(field).decorations || Decoration18.none)
|
|
7523
8309
|
]
|
|
7524
8310
|
});
|
|
7525
8311
|
var buildDecorations4 = (state, range, registry, notifier) => {
|
|
@@ -7530,10 +8316,11 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7530
8316
|
if (!tree || tree.type.name === "Program" && tree.length === 0) {
|
|
7531
8317
|
return {
|
|
7532
8318
|
from: range.from,
|
|
7533
|
-
decorations:
|
|
8319
|
+
decorations: Decoration18.none
|
|
7534
8320
|
};
|
|
7535
8321
|
}
|
|
7536
8322
|
let last = range.from;
|
|
8323
|
+
let streamingFrom;
|
|
7537
8324
|
tree.iterate({
|
|
7538
8325
|
from: range.from,
|
|
7539
8326
|
to: range.to,
|
|
@@ -7546,21 +8333,26 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7546
8333
|
if (args) {
|
|
7547
8334
|
const def = registry[args._tag];
|
|
7548
8335
|
if (def) {
|
|
8336
|
+
if (def.streaming && !node.node.getChild("CloseTag")) {
|
|
8337
|
+
return false;
|
|
8338
|
+
}
|
|
7549
8339
|
const { block, factory, Component } = def;
|
|
7550
|
-
const widgetState = args.id ? widgetStateMap[args.id] : void 0;
|
|
7551
8340
|
const nodeRange = {
|
|
7552
8341
|
from: node.node.from,
|
|
7553
8342
|
to: node.node.to
|
|
7554
8343
|
};
|
|
8344
|
+
const widgetId = xmlWidgetId(args.id, def.streaming ? `cm-xml-${nodeRange.from}` : `cm-xml-${nodeRange.from}-${nodeRange.to}`);
|
|
8345
|
+
const widgetState = widgetStateMap[widgetId];
|
|
7555
8346
|
const props = {
|
|
7556
|
-
|
|
8347
|
+
id: widgetId,
|
|
7557
8348
|
range: nodeRange,
|
|
8349
|
+
context,
|
|
7558
8350
|
...args,
|
|
7559
8351
|
...widgetState
|
|
7560
8352
|
};
|
|
7561
|
-
const widget = factory ? factory(props) : Component ?
|
|
8353
|
+
const widget = factory ? factory(props) ?? void 0 : Component ? new PlaceholderWidget2(widgetId, Component, props, notifier) : void 0;
|
|
7562
8354
|
if (widget) {
|
|
7563
|
-
builder.add(nodeRange.from, nodeRange.to,
|
|
8355
|
+
builder.add(nodeRange.from, nodeRange.to, Decoration18.replace({
|
|
7564
8356
|
widget,
|
|
7565
8357
|
block,
|
|
7566
8358
|
atomic: true,
|
|
@@ -7572,20 +8364,72 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7572
8364
|
}
|
|
7573
8365
|
}
|
|
7574
8366
|
} catch (err) {
|
|
7575
|
-
log11.catch(err, void 0, {
|
|
7576
|
-
F: __dxlog_file17,
|
|
7577
|
-
L: 459,
|
|
7578
|
-
S: void 0,
|
|
7579
|
-
C: (f, a) => f(...a)
|
|
7580
|
-
});
|
|
8367
|
+
log11.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 401, S: void 0 });
|
|
7581
8368
|
}
|
|
7582
8369
|
return false;
|
|
7583
8370
|
}
|
|
7584
8371
|
}
|
|
7585
8372
|
}
|
|
7586
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
|
+
}
|
|
7587
8430
|
return {
|
|
7588
8431
|
from: last,
|
|
8432
|
+
streamingFrom,
|
|
7589
8433
|
decorations: builder.finish()
|
|
7590
8434
|
};
|
|
7591
8435
|
};
|
|
@@ -7594,108 +8438,62 @@ var PlaceholderWidget2 = class extends WidgetType10 {
|
|
|
7594
8438
|
Component;
|
|
7595
8439
|
props;
|
|
7596
8440
|
notifier;
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
S: this,
|
|
7604
|
-
A: [
|
|
7605
|
-
"id",
|
|
7606
|
-
""
|
|
7607
|
-
]
|
|
7608
|
-
});
|
|
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", ""] });
|
|
7609
8447
|
}
|
|
7610
8448
|
get root() {
|
|
7611
|
-
return this
|
|
8449
|
+
return this.#root;
|
|
7612
8450
|
}
|
|
7613
8451
|
eq(other) {
|
|
8452
|
+
if (this.streaming) {
|
|
8453
|
+
return false;
|
|
8454
|
+
}
|
|
7614
8455
|
return this.id === other.id;
|
|
7615
8456
|
}
|
|
7616
8457
|
ignoreEvent() {
|
|
7617
8458
|
return true;
|
|
7618
8459
|
}
|
|
7619
|
-
toDOM(
|
|
7620
|
-
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
|
+
});
|
|
7621
8479
|
this.notifier.mounted({
|
|
7622
8480
|
id: this.id,
|
|
7623
|
-
root: this
|
|
7624
|
-
props
|
|
8481
|
+
root: this.#root,
|
|
8482
|
+
props,
|
|
7625
8483
|
Component: this.Component
|
|
7626
8484
|
});
|
|
7627
|
-
return
|
|
8485
|
+
return true;
|
|
7628
8486
|
}
|
|
7629
8487
|
destroy(_dom) {
|
|
7630
8488
|
this.notifier.unmounted(this.id);
|
|
7631
|
-
this
|
|
8489
|
+
this.#root = null;
|
|
8490
|
+
this.#view = void 0;
|
|
7632
8491
|
}
|
|
7633
8492
|
};
|
|
7634
|
-
|
|
7635
|
-
// src/extensions/typewriter.ts
|
|
7636
|
-
import { keymap as keymap14 } from "@codemirror/view";
|
|
7637
|
-
var defaultItems = [
|
|
7638
|
-
"hello world!",
|
|
7639
|
-
"this is a test.",
|
|
7640
|
-
"this is [DXOS](https://dxos.org)"
|
|
7641
|
-
];
|
|
7642
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
7643
|
-
let t;
|
|
7644
|
-
let idx = 0;
|
|
7645
|
-
return [
|
|
7646
|
-
keymap14.of([
|
|
7647
|
-
{
|
|
7648
|
-
// Reset.
|
|
7649
|
-
key: "alt-meta-'",
|
|
7650
|
-
run: () => {
|
|
7651
|
-
clearTimeout(t);
|
|
7652
|
-
idx = 0;
|
|
7653
|
-
return true;
|
|
7654
|
-
}
|
|
7655
|
-
},
|
|
7656
|
-
{
|
|
7657
|
-
// Next prompt.
|
|
7658
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
|
7659
|
-
key: "Shift-Meta-'",
|
|
7660
|
-
run: (view) => {
|
|
7661
|
-
clearTimeout(t);
|
|
7662
|
-
const text = items[idx++];
|
|
7663
|
-
if (idx === items?.length) {
|
|
7664
|
-
idx = 0;
|
|
7665
|
-
}
|
|
7666
|
-
let i = 0;
|
|
7667
|
-
const insert = (d = 0) => {
|
|
7668
|
-
t = setTimeout(() => {
|
|
7669
|
-
const pos = view.state.selection.main.head;
|
|
7670
|
-
view.dispatch({
|
|
7671
|
-
changes: {
|
|
7672
|
-
from: pos,
|
|
7673
|
-
insert: text[i++]
|
|
7674
|
-
},
|
|
7675
|
-
selection: {
|
|
7676
|
-
anchor: pos + 1
|
|
7677
|
-
}
|
|
7678
|
-
});
|
|
7679
|
-
if (i < text.length) {
|
|
7680
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
7681
|
-
}
|
|
7682
|
-
}, d);
|
|
7683
|
-
};
|
|
7684
|
-
insert();
|
|
7685
|
-
return true;
|
|
7686
|
-
}
|
|
7687
|
-
}
|
|
7688
|
-
])
|
|
7689
|
-
];
|
|
7690
|
-
};
|
|
7691
8493
|
export {
|
|
7692
8494
|
Cursor,
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
EditorState3 as EditorState,
|
|
7696
|
-
EditorView30 as EditorView,
|
|
7697
|
-
EditorViewMode,
|
|
7698
|
-
EditorViewModes,
|
|
8495
|
+
EditorState4 as EditorState,
|
|
8496
|
+
EditorView33 as EditorView,
|
|
7699
8497
|
Inline,
|
|
7700
8498
|
InputModeExtensions,
|
|
7701
8499
|
List,
|
|
@@ -7712,6 +8510,7 @@ export {
|
|
|
7712
8510
|
addStyle,
|
|
7713
8511
|
annotations,
|
|
7714
8512
|
autoScroll,
|
|
8513
|
+
autoScrollEffect,
|
|
7715
8514
|
autocomplete,
|
|
7716
8515
|
automerge,
|
|
7717
8516
|
awareness,
|
|
@@ -7725,7 +8524,11 @@ export {
|
|
|
7725
8524
|
commentClickedEffect,
|
|
7726
8525
|
comments,
|
|
7727
8526
|
commentsState,
|
|
8527
|
+
compactSlots,
|
|
7728
8528
|
convertTreeToJson,
|
|
8529
|
+
crawler,
|
|
8530
|
+
crawlerActiveEffect,
|
|
8531
|
+
crawlerLineEffect,
|
|
7729
8532
|
createBasicExtensions,
|
|
7730
8533
|
createComment,
|
|
7731
8534
|
createCrawler,
|
|
@@ -7748,12 +8551,12 @@ export {
|
|
|
7748
8551
|
defaultThemeSlots,
|
|
7749
8552
|
deleteItem,
|
|
7750
8553
|
documentId,
|
|
8554
|
+
documentSlots,
|
|
7751
8555
|
dropFile,
|
|
8556
|
+
editorClassNames,
|
|
7752
8557
|
editorInputMode,
|
|
7753
|
-
editorSlots,
|
|
7754
|
-
editorWidth,
|
|
7755
|
-
editorWithToolbarLayout,
|
|
7756
8558
|
extendedMarkdown,
|
|
8559
|
+
fader,
|
|
7757
8560
|
filterChars,
|
|
7758
8561
|
flattenRect,
|
|
7759
8562
|
focus,
|
|
@@ -7789,6 +8592,7 @@ export {
|
|
|
7789
8592
|
markdownTagsExtensions,
|
|
7790
8593
|
matchCompletion,
|
|
7791
8594
|
mention,
|
|
8595
|
+
mobileSlots,
|
|
7792
8596
|
modalStateEffect,
|
|
7793
8597
|
modalStateField,
|
|
7794
8598
|
moveItemDown,
|
|
@@ -7808,11 +8612,10 @@ export {
|
|
|
7808
8612
|
removeList,
|
|
7809
8613
|
removeStyle,
|
|
7810
8614
|
replacer,
|
|
8615
|
+
scrollPastEnd,
|
|
7811
8616
|
scrollThreadIntoView,
|
|
7812
8617
|
scrollToLine,
|
|
7813
8618
|
scroller,
|
|
7814
|
-
scrollerCrawlEffect,
|
|
7815
|
-
scrollerLineEffect,
|
|
7816
8619
|
selectionState,
|
|
7817
8620
|
setBlockquote,
|
|
7818
8621
|
setComments,
|
|
@@ -7820,9 +8623,8 @@ export {
|
|
|
7820
8623
|
setSelection,
|
|
7821
8624
|
setStyle,
|
|
7822
8625
|
singleValueFacet,
|
|
7823
|
-
|
|
8626
|
+
snippets2 as snippets,
|
|
7824
8627
|
staticCompletion,
|
|
7825
|
-
streamer,
|
|
7826
8628
|
submit,
|
|
7827
8629
|
tabbable,
|
|
7828
8630
|
table,
|
|
@@ -7841,7 +8643,12 @@ export {
|
|
|
7841
8643
|
treeFacet,
|
|
7842
8644
|
typeahead,
|
|
7843
8645
|
typewriter,
|
|
8646
|
+
typewriterBypass,
|
|
8647
|
+
typewriterDrainingEffect,
|
|
7844
8648
|
wrapWithCatch,
|
|
8649
|
+
xmlBlockDecoration,
|
|
8650
|
+
xmlElementLength,
|
|
8651
|
+
xmlFormatting,
|
|
7845
8652
|
xmlTagContextEffect,
|
|
7846
8653
|
xmlTagResetEffect,
|
|
7847
8654
|
xmlTagUpdateEffect,
|