@dxos/ui-editor 0.8.4-main.d05673bc65 → 0.8.4-main.dfabb4ec29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +1547 -768
- 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 +1548 -768
- 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/auto-scroll.d.ts +14 -2
- package/dist/types/src/extensions/auto-scroll.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 -1
- 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/scroll-past-end.d.ts +3 -0
- package/dist/types/src/extensions/scroll-past-end.d.ts.map +1 -0
- package/dist/types/src/extensions/scroller.d.ts +12 -10
- package/dist/types/src/extensions/scroller.d.ts.map +1 -1
- 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 +34 -37
- package/src/defaults.ts +33 -20
- package/src/extensions/auto-scroll.ts +120 -12
- 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 -1
- 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 +0 -1
- package/src/extensions/outliner/tree.test.ts +0 -1
- package/src/extensions/preview/preview.ts +54 -7
- package/src/extensions/scroll-past-end.ts +32 -0
- package/src/extensions/scroller.ts +49 -25
- 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 +179 -31
- 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 +39 -25
- 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/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/tags/streamer.ts +0 -243
- package/src/extensions/typewriter.ts +0 -68
|
@@ -1,29 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EditorInputMode,
|
|
3
|
-
EditorInputModes,
|
|
4
|
-
EditorViewMode,
|
|
5
|
-
EditorViewModes
|
|
6
|
-
} from "./chunk-HL3YF6WC.mjs";
|
|
7
|
-
|
|
8
1
|
// src/index.ts
|
|
9
|
-
import { EditorState as
|
|
10
|
-
import { EditorView as
|
|
2
|
+
import { EditorState as EditorState4 } from "@codemirror/state";
|
|
3
|
+
import { EditorView as EditorView33, keymap as keymap15 } from "@codemirror/view";
|
|
11
4
|
import { tags as tags2 } from "@lezer/highlight";
|
|
12
5
|
import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
|
|
13
6
|
|
|
14
7
|
// src/defaults.ts
|
|
15
8
|
import { mx } from "@dxos/ui-theme";
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
var editorClassNames = (role) => mx("dx-attention-surface p-0.5 data-[toolbar=disabled]:pt-2 dx-focus-ring-inset", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-h-24" : "dx-container overflow-hidden");
|
|
10
|
+
var documentSlots = {
|
|
11
|
+
content: {
|
|
12
|
+
/**
|
|
13
|
+
* CodeMirror content width.
|
|
14
|
+
* 40rem = 640px. Corresponds to initial plank width (Google docs, Stashpad, etc.)
|
|
15
|
+
* 50rem = 800px. Maximum content width for solo mode.
|
|
16
|
+
* NOTE: Max width - 4rem = 2rem left/right margin (or 2rem gutter plus 1rem left/right margin).
|
|
17
|
+
*/
|
|
18
|
+
className: mx(
|
|
19
|
+
// Inline-size container for widget sizing (children use `max-w-[100cqi]`).
|
|
20
|
+
// NOTE: Use inline-size, not full size containment — `container-type: size` on the
|
|
21
|
+
// editor content breaks CodeMirror's viewport measurement, leaving blank gaps during
|
|
22
|
+
// scroll until a click forces a re-measure.
|
|
23
|
+
"dx-inline-size-container",
|
|
24
|
+
// Wider margin for web (vs. mobile).
|
|
25
|
+
"pointer-fine:max-w-[min(50rem,100%-4rem)] pointer-coarse:max-w-[min(50rem,100%-2rem)]",
|
|
26
|
+
"mx-auto! w-full"
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var compactSlots = {
|
|
31
|
+
content: {
|
|
32
|
+
className: "mx-2!"
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var mobileSlots = {
|
|
21
36
|
content: {
|
|
22
|
-
className:
|
|
37
|
+
className: "mx-2!"
|
|
23
38
|
}
|
|
24
39
|
};
|
|
25
|
-
var editorWithToolbarLayout = "grid grid-cols-1 grid-rows-[min-content_1fr] data-[toolbar=disabled]:grid-rows-[1fr] justify-center content-start overflow-hidden";
|
|
26
|
-
var stackItemContentEditorClassNames = (role) => mx("dx-attention-surface p-0.5 dx-focus-ring-inset data-[toolbar=disabled]:pt-2", role === "section" ? "[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-h-24" : "dx-container overflow-hidden");
|
|
27
40
|
|
|
28
41
|
// src/extensions/annotations.ts
|
|
29
42
|
import { RangeSetBuilder } from "@codemirror/state";
|
|
@@ -207,7 +220,7 @@ var singleValueFacet = (defaultValue) => Facet.define({
|
|
|
207
220
|
var overlap = (a, b) => a.from <= b.to && a.to >= b.from;
|
|
208
221
|
var defaultCursorConverter = {
|
|
209
222
|
toCursor: (position) => position.toString(),
|
|
210
|
-
fromCursor: (
|
|
223
|
+
fromCursor: (cursor) => parseInt(cursor)
|
|
211
224
|
};
|
|
212
225
|
var Cursor = class _Cursor {
|
|
213
226
|
static converter = singleValueFacet(defaultCursorConverter);
|
|
@@ -220,9 +233,9 @@ var Cursor = class _Cursor {
|
|
|
220
233
|
to
|
|
221
234
|
].join(":");
|
|
222
235
|
};
|
|
223
|
-
static getRangeFromCursor = (state,
|
|
236
|
+
static getRangeFromCursor = (state, cursor) => {
|
|
224
237
|
const cursorConverter2 = state.facet(_Cursor.converter);
|
|
225
|
-
const parts =
|
|
238
|
+
const parts = cursor.split(":");
|
|
226
239
|
const from = cursorConverter2.fromCursor(parts[0]);
|
|
227
240
|
const to = cursorConverter2.fromCursor(parts[1]);
|
|
228
241
|
return from !== void 0 && to !== void 0 ? {
|
|
@@ -258,12 +271,7 @@ var wrapWithCatch = (fn, label) => {
|
|
|
258
271
|
} catch (err) {
|
|
259
272
|
log.catch(err, {
|
|
260
273
|
label
|
|
261
|
-
}, {
|
|
262
|
-
F: __dxlog_file,
|
|
263
|
-
L: 20,
|
|
264
|
-
S: void 0,
|
|
265
|
-
C: (f, a) => f(...a)
|
|
266
|
-
});
|
|
274
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 13, S: void 0 });
|
|
267
275
|
}
|
|
268
276
|
};
|
|
269
277
|
};
|
|
@@ -289,12 +297,7 @@ var logChanges = (trs) => {
|
|
|
289
297
|
if (changes.length) {
|
|
290
298
|
log("changes", {
|
|
291
299
|
changes
|
|
292
|
-
}, {
|
|
293
|
-
F: __dxlog_file,
|
|
294
|
-
L: 54,
|
|
295
|
-
S: void 0,
|
|
296
|
-
C: (f, a) => f(...a)
|
|
297
|
-
});
|
|
300
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 44, S: void 0 });
|
|
298
301
|
}
|
|
299
302
|
};
|
|
300
303
|
|
|
@@ -360,30 +363,37 @@ var insertAtLineStart = (view, from, insert) => {
|
|
|
360
363
|
};
|
|
361
364
|
|
|
362
365
|
// src/extensions/autocomplete/placeholder.ts
|
|
363
|
-
var placeholder = ({ content, delay = 3e3 }) => {
|
|
366
|
+
var placeholder = ({ content, delay = 3e3, focusOnly = false }) => {
|
|
364
367
|
const plugin = ViewPlugin3.fromClass(class {
|
|
365
368
|
_timeout;
|
|
366
369
|
_decorations = Decoration3.none;
|
|
367
370
|
update(update2) {
|
|
371
|
+
if (!update2.docChanged && !update2.selectionSet && !update2.focusChanged) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
368
374
|
if (this._timeout) {
|
|
369
375
|
window.clearTimeout(this._timeout);
|
|
370
376
|
this._timeout = void 0;
|
|
371
377
|
}
|
|
378
|
+
this._decorations = Decoration3.none;
|
|
379
|
+
if (focusOnly && !update2.view.hasFocus) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
372
382
|
const activeLine = update2.view.state.doc.lineAt(update2.view.state.selection.main.head);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const lineStart = activeLine.from;
|
|
376
|
-
this._timeout = setTimeout(() => {
|
|
377
|
-
this._decorations = Decoration3.set([
|
|
378
|
-
Decoration3.widget({
|
|
379
|
-
widget: new PlaceholderWidget(content),
|
|
380
|
-
side: 1
|
|
381
|
-
}).range(lineStart)
|
|
382
|
-
]);
|
|
383
|
-
update2.view.update([]);
|
|
384
|
-
}, delay);
|
|
383
|
+
if (activeLine.text.trim() !== "") {
|
|
384
|
+
return;
|
|
385
385
|
}
|
|
386
|
-
|
|
386
|
+
const lineStart = activeLine.from;
|
|
387
|
+
const view = update2.view;
|
|
388
|
+
this._timeout = setTimeout(() => {
|
|
389
|
+
this._decorations = Decoration3.set([
|
|
390
|
+
Decoration3.widget({
|
|
391
|
+
widget: new PlaceholderWidget(content),
|
|
392
|
+
side: 1
|
|
393
|
+
}).range(lineStart)
|
|
394
|
+
]);
|
|
395
|
+
view.update([]);
|
|
396
|
+
}, delay);
|
|
387
397
|
}
|
|
388
398
|
destroy() {
|
|
389
399
|
if (this._timeout) {
|
|
@@ -502,9 +512,11 @@ var typeahead = ({ onComplete } = {}) => {
|
|
|
502
512
|
};
|
|
503
513
|
|
|
504
514
|
// src/extensions/auto-scroll.ts
|
|
515
|
+
import { StateEffect as StateEffect2 } from "@codemirror/state";
|
|
505
516
|
import { EditorView as EditorView5, ViewPlugin as ViewPlugin6 } from "@codemirror/view";
|
|
506
517
|
import { addEventListener, combine, throttle } from "@dxos/async";
|
|
507
518
|
import { Domino } from "@dxos/ui";
|
|
519
|
+
import { getSize } from "@dxos/ui-theme";
|
|
508
520
|
|
|
509
521
|
// src/extensions/scroller.ts
|
|
510
522
|
import { StateEffect } from "@codemirror/state";
|
|
@@ -561,15 +573,14 @@ var scroller = ({ overScroll = 0 } = {}) => {
|
|
|
561
573
|
}
|
|
562
574
|
requestAnimationFrame(() => {
|
|
563
575
|
this.view.scrollDOM.scrollTo({
|
|
564
|
-
top: targetScrollTop
|
|
565
|
-
behavior
|
|
576
|
+
top: targetScrollTop
|
|
566
577
|
});
|
|
567
578
|
});
|
|
568
579
|
}
|
|
569
580
|
});
|
|
570
581
|
return [
|
|
571
582
|
scrollPlugin,
|
|
572
|
-
// Listen for effect.
|
|
583
|
+
// Listen for effect.
|
|
573
584
|
EditorView4.updateListener.of((update2) => {
|
|
574
585
|
update2.transactions.forEach((transaction) => {
|
|
575
586
|
try {
|
|
@@ -584,23 +595,19 @@ var scroller = ({ overScroll = 0 } = {}) => {
|
|
|
584
595
|
}
|
|
585
596
|
}
|
|
586
597
|
} catch (err) {
|
|
587
|
-
log2.catch(err, void 0, {
|
|
588
|
-
F: __dxlog_file2,
|
|
589
|
-
L: 145,
|
|
590
|
-
S: void 0,
|
|
591
|
-
C: (f, a) => f(...a)
|
|
592
|
-
});
|
|
598
|
+
log2.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 91, S: void 0 });
|
|
593
599
|
}
|
|
594
600
|
});
|
|
595
601
|
}),
|
|
596
602
|
// Styles.
|
|
597
603
|
EditorView4.theme({
|
|
598
|
-
".cm-content": {
|
|
599
|
-
paddingBottom: `${overScroll}px`
|
|
600
|
-
},
|
|
601
604
|
".cm-scroller": {
|
|
602
|
-
|
|
603
|
-
|
|
605
|
+
overflowY: "scroll",
|
|
606
|
+
// Browser scroll-anchoring: when widgets above the viewport resize (e.g. tool blocks
|
|
607
|
+
// expanding their TogglePanel), the browser picks a stable element near the viewport
|
|
608
|
+
// top and adjusts `scrollTop` so the user's view doesn't jump. Auto-scroll's pinning
|
|
609
|
+
// logic still has the final word when pinned (forces scrollTop to scrollHeight).
|
|
610
|
+
overflowAnchor: "auto"
|
|
604
611
|
},
|
|
605
612
|
".cm-scroller.cm-hide-scrollbar::-webkit-scrollbar": {
|
|
606
613
|
display: "none"
|
|
@@ -612,6 +619,16 @@ var scroller = ({ overScroll = 0 } = {}) => {
|
|
|
612
619
|
"&:hover .cm-scroller::-webkit-scrollbar-thumb": {
|
|
613
620
|
background: "var(--color-scrollbar-thumb)"
|
|
614
621
|
},
|
|
622
|
+
// Spacer below the last text line. Implemented as a real block pseudo-element
|
|
623
|
+
// (rather than `padding-bottom` on `.cm-content`) so it materializes in the
|
|
624
|
+
// scroller's `scrollHeight` regardless of how `padding` is reset by the base
|
|
625
|
+
// theme or downstream classes — this is what gives auto-scroll its head-room
|
|
626
|
+
// so the last line stays `overScroll` px above the viewport bottom.
|
|
627
|
+
".cm-content::after": {
|
|
628
|
+
content: '""',
|
|
629
|
+
display: "block",
|
|
630
|
+
height: `${overScroll}px`
|
|
631
|
+
},
|
|
615
632
|
".cm-scroll-button": {
|
|
616
633
|
position: "absolute",
|
|
617
634
|
bottom: "0.5rem",
|
|
@@ -620,22 +637,28 @@ var scroller = ({ overScroll = 0 } = {}) => {
|
|
|
620
637
|
})
|
|
621
638
|
];
|
|
622
639
|
};
|
|
623
|
-
function createCrawler(view,
|
|
640
|
+
function createCrawler(view, omega = 5, snapThreshold = 5, snapVelocity = 50) {
|
|
624
641
|
const el = view.scrollDOM;
|
|
625
642
|
let currentTop = 0;
|
|
643
|
+
let velocity = 0;
|
|
626
644
|
let rafId = null;
|
|
627
|
-
|
|
645
|
+
let lastTime = 0;
|
|
646
|
+
function frame(now) {
|
|
647
|
+
const dt = lastTime === 0 ? 1 / 60 : Math.min(0.1, (now - lastTime) / 1e3);
|
|
648
|
+
lastTime = now;
|
|
628
649
|
const targetTop = el.scrollHeight - el.clientHeight;
|
|
629
650
|
const delta = targetTop - currentTop;
|
|
630
|
-
|
|
631
|
-
if (absDelta < targetDelta) {
|
|
651
|
+
if (Math.abs(delta) < snapThreshold && Math.abs(velocity) < snapVelocity) {
|
|
632
652
|
el.scrollTop = targetTop;
|
|
633
653
|
currentTop = targetTop;
|
|
654
|
+
velocity = 0;
|
|
634
655
|
rafId = null;
|
|
656
|
+
lastTime = 0;
|
|
635
657
|
return;
|
|
636
658
|
}
|
|
637
|
-
const
|
|
638
|
-
|
|
659
|
+
const accel = omega * omega * delta - 2 * omega * velocity;
|
|
660
|
+
velocity += accel * dt;
|
|
661
|
+
currentTop += velocity * dt;
|
|
639
662
|
el.scrollTop = currentTop;
|
|
640
663
|
rafId = requestAnimationFrame(frame);
|
|
641
664
|
}
|
|
@@ -643,12 +666,15 @@ function createCrawler(view, k = 0.3, maxStep = 2, targetDelta = 0.5) {
|
|
|
643
666
|
scroll: () => {
|
|
644
667
|
if (rafId === null) {
|
|
645
668
|
currentTop = el.scrollTop;
|
|
669
|
+
lastTime = 0;
|
|
646
670
|
rafId = requestAnimationFrame(frame);
|
|
647
671
|
}
|
|
648
672
|
},
|
|
649
673
|
cancel: () => {
|
|
650
674
|
if (rafId !== null) {
|
|
651
675
|
cancelAnimationFrame(rafId);
|
|
676
|
+
velocity = 0;
|
|
677
|
+
lastTime = 0;
|
|
652
678
|
rafId = null;
|
|
653
679
|
}
|
|
654
680
|
}
|
|
@@ -656,26 +682,64 @@ function createCrawler(view, k = 0.3, maxStep = 2, targetDelta = 0.5) {
|
|
|
656
682
|
}
|
|
657
683
|
|
|
658
684
|
// src/extensions/auto-scroll.ts
|
|
659
|
-
var
|
|
685
|
+
var autoScrollEffect = StateEffect2.define();
|
|
686
|
+
var autoScroll = ({ scrollOnResize = true } = {}) => {
|
|
660
687
|
let buttonContainer;
|
|
661
688
|
let isPinned = true;
|
|
689
|
+
let jumpPending = false;
|
|
690
|
+
let enabled = true;
|
|
691
|
+
let firstUpdate = true;
|
|
662
692
|
const setPinned = (pinned) => {
|
|
663
693
|
buttonContainer?.classList.toggle("opacity-0", pinned);
|
|
664
694
|
isPinned = pinned;
|
|
665
695
|
};
|
|
666
696
|
return [
|
|
667
|
-
// Update listener for
|
|
668
|
-
EditorView5.updateListener.of((
|
|
697
|
+
// Update listener for scrolling when content changes.
|
|
698
|
+
EditorView5.updateListener.of((update2) => {
|
|
699
|
+
const { view, heightChanged, state, startState } = update2;
|
|
700
|
+
for (const tr of update2.transactions) {
|
|
701
|
+
for (const effect of tr.effects) {
|
|
702
|
+
if (effect.is(autoScrollEffect)) {
|
|
703
|
+
enabled = effect.value;
|
|
704
|
+
if (enabled) {
|
|
705
|
+
setPinned(true);
|
|
706
|
+
view.dispatch({
|
|
707
|
+
effects: scrollerCrawlEffect.of(true)
|
|
708
|
+
});
|
|
709
|
+
} else {
|
|
710
|
+
view.dispatch({
|
|
711
|
+
effects: scrollerCrawlEffect.of(false)
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (!enabled) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (isPinned && (firstUpdate || startState.doc.length === 0) && state.doc.length > 0) {
|
|
721
|
+
firstUpdate = false;
|
|
722
|
+
jumpPending = true;
|
|
723
|
+
requestAnimationFrame(() => {
|
|
724
|
+
view.scrollDOM.scrollTop = view.scrollDOM.scrollHeight;
|
|
725
|
+
jumpPending = false;
|
|
726
|
+
});
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
firstUpdate = false;
|
|
730
|
+
if (jumpPending) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
669
733
|
if (heightChanged) {
|
|
670
734
|
if (isPinned) {
|
|
671
735
|
const { scrollTop, scrollHeight, clientHeight } = view.scrollDOM;
|
|
672
736
|
const delta = scrollHeight - scrollTop - clientHeight;
|
|
673
|
-
if (delta > 0
|
|
737
|
+
if (delta > 0) {
|
|
674
738
|
setPinned(true);
|
|
675
739
|
view.dispatch({
|
|
676
740
|
effects: scrollerCrawlEffect.of(true)
|
|
677
741
|
});
|
|
678
|
-
} else if (delta <
|
|
742
|
+
} else if (delta < -1) {
|
|
679
743
|
setPinned(false);
|
|
680
744
|
}
|
|
681
745
|
} else {
|
|
@@ -685,6 +749,46 @@ var autoScroll = (_ = {}) => {
|
|
|
685
749
|
}
|
|
686
750
|
}
|
|
687
751
|
}),
|
|
752
|
+
// Re-pin and jump to bottom when the scroll container itself resizes (e.g. sidebar toggle,
|
|
753
|
+
// window resize). Doc-driven height changes are handled by the updateListener above; this
|
|
754
|
+
// observer covers the case where the viewport changes while the doc length is unchanged.
|
|
755
|
+
scrollOnResize ? ViewPlugin6.fromClass(class {
|
|
756
|
+
observer;
|
|
757
|
+
firstObservation = true;
|
|
758
|
+
destroyed = false;
|
|
759
|
+
constructor(view) {
|
|
760
|
+
const onResize = throttle(() => {
|
|
761
|
+
if (this.destroyed || !enabled) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
setPinned(true);
|
|
765
|
+
requestAnimationFrame(() => {
|
|
766
|
+
if (this.destroyed) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
view.scrollDOM.scrollTo({
|
|
770
|
+
top: view.scrollDOM.scrollHeight,
|
|
771
|
+
behavior: "instant"
|
|
772
|
+
});
|
|
773
|
+
view.dispatch({
|
|
774
|
+
effects: scrollerCrawlEffect.of(false)
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
}, 50);
|
|
778
|
+
this.observer = new ResizeObserver(() => {
|
|
779
|
+
if (this.firstObservation) {
|
|
780
|
+
this.firstObservation = false;
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
onResize();
|
|
784
|
+
});
|
|
785
|
+
this.observer.observe(view.scrollDOM);
|
|
786
|
+
}
|
|
787
|
+
destroy() {
|
|
788
|
+
this.destroyed = true;
|
|
789
|
+
this.observer.disconnect();
|
|
790
|
+
}
|
|
791
|
+
}) : [],
|
|
688
792
|
// Detect user scroll and unpin (or re-pin if scrolled to the bottom).
|
|
689
793
|
ViewPlugin6.fromClass(class {
|
|
690
794
|
cleanup;
|
|
@@ -710,12 +814,12 @@ var autoScroll = (_ = {}) => {
|
|
|
710
814
|
// Scroll button.
|
|
711
815
|
ViewPlugin6.fromClass(class {
|
|
712
816
|
constructor(view) {
|
|
713
|
-
const icon = Domino.of("dx-icon").attributes({
|
|
817
|
+
const icon = Domino.of("dx-icon").classNames(getSize(4)).attributes({
|
|
714
818
|
icon: "ph--arrow-down--regular"
|
|
715
819
|
});
|
|
716
820
|
const button = Domino.of("button").classNames("dx-button bg-accent-surface").attributes({
|
|
717
821
|
"data-density": "fine"
|
|
718
|
-
}).
|
|
822
|
+
}).append(icon).on("click", () => {
|
|
719
823
|
setPinned(true);
|
|
720
824
|
view.dispatch({
|
|
721
825
|
effects: scrollerLineEffect.of({
|
|
@@ -725,7 +829,7 @@ var autoScroll = (_ = {}) => {
|
|
|
725
829
|
})
|
|
726
830
|
});
|
|
727
831
|
});
|
|
728
|
-
buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").
|
|
832
|
+
buttonContainer = Domino.of("div").classNames("cm-scroll-button transition-opacity duration-300 opacity-0").append(button).root;
|
|
729
833
|
view.scrollDOM.parentElement.appendChild(buttonContainer);
|
|
730
834
|
}
|
|
731
835
|
})
|
|
@@ -760,35 +864,25 @@ var cursorConverter = (accessor) => ({
|
|
|
760
864
|
try {
|
|
761
865
|
return toCursor(accessor, pos, assoc);
|
|
762
866
|
} catch (err) {
|
|
763
|
-
log3.catch(err, void 0, {
|
|
764
|
-
F: __dxlog_file3,
|
|
765
|
-
L: 15,
|
|
766
|
-
S: void 0,
|
|
767
|
-
C: (f, a) => f(...a)
|
|
768
|
-
});
|
|
867
|
+
log3.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 11, S: void 0 });
|
|
769
868
|
return "";
|
|
770
869
|
}
|
|
771
870
|
},
|
|
772
|
-
fromCursor: (
|
|
871
|
+
fromCursor: (cursor) => {
|
|
773
872
|
try {
|
|
774
|
-
return fromCursor(accessor,
|
|
873
|
+
return fromCursor(accessor, cursor);
|
|
775
874
|
} catch (err) {
|
|
776
|
-
log3.catch(err, void 0, {
|
|
777
|
-
F: __dxlog_file3,
|
|
778
|
-
L: 24,
|
|
779
|
-
S: void 0,
|
|
780
|
-
C: (f, a) => f(...a)
|
|
781
|
-
});
|
|
875
|
+
log3.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 19, S: void 0 });
|
|
782
876
|
return 0;
|
|
783
877
|
}
|
|
784
878
|
}
|
|
785
879
|
});
|
|
786
880
|
|
|
787
881
|
// src/extensions/automerge/defs.ts
|
|
788
|
-
import { Annotation, StateEffect as
|
|
882
|
+
import { Annotation, StateEffect as StateEffect3 } from "@codemirror/state";
|
|
789
883
|
var getPath = (state, field) => state.field(field).path;
|
|
790
884
|
var getLastHeads = (state, field) => state.field(field).lastHeads;
|
|
791
|
-
var updateHeadsEffect =
|
|
885
|
+
var updateHeadsEffect = StateEffect3.define({});
|
|
792
886
|
var updateHeads = (newHeads) => updateHeadsEffect.of({
|
|
793
887
|
newHeads
|
|
794
888
|
});
|
|
@@ -963,12 +1057,7 @@ var Syncer = class {
|
|
|
963
1057
|
this._pending = false;
|
|
964
1058
|
}
|
|
965
1059
|
onEditorChange(view) {
|
|
966
|
-
log4("onEditorChange", void 0, {
|
|
967
|
-
F: __dxlog_file4,
|
|
968
|
-
L: 45,
|
|
969
|
-
S: this,
|
|
970
|
-
C: (f, a) => f(...a)
|
|
971
|
-
});
|
|
1060
|
+
log4("onEditorChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 35, S: this });
|
|
972
1061
|
const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
|
|
973
1062
|
const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
|
|
974
1063
|
if (newHeads) {
|
|
@@ -979,12 +1068,7 @@ var Syncer = class {
|
|
|
979
1068
|
}
|
|
980
1069
|
}
|
|
981
1070
|
onAutomergeChange(view) {
|
|
982
|
-
log4("onAutomergeChange", void 0, {
|
|
983
|
-
F: __dxlog_file4,
|
|
984
|
-
L: 60,
|
|
985
|
-
S: this,
|
|
986
|
-
C: (f, a) => f(...a)
|
|
987
|
-
});
|
|
1071
|
+
log4("onAutomergeChange", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 47, S: this });
|
|
988
1072
|
const oldHeads = getLastHeads(view.state, this._state);
|
|
989
1073
|
const newHeads = A2.getHeads(this._handle.doc());
|
|
990
1074
|
const diff = A2.equals(oldHeads, newHeads) ? [] : A2.diff(this._handle.doc(), oldHeads, newHeads);
|
|
@@ -1046,14 +1130,16 @@ var automerge = (accessor) => {
|
|
|
1046
1130
|
const value = DocAccessor.getValue(accessor);
|
|
1047
1131
|
const current = this._view.state.doc.toString();
|
|
1048
1132
|
if (value !== current) {
|
|
1049
|
-
console.warn("ENABLING INITIAL SYNC -- THIS MAY BE A REGRESSION");
|
|
1050
1133
|
this._view.dispatch({
|
|
1051
1134
|
changes: {
|
|
1052
1135
|
from: 0,
|
|
1053
1136
|
to: this._view.state.doc.length,
|
|
1054
1137
|
insert: value
|
|
1055
1138
|
},
|
|
1056
|
-
annotations:
|
|
1139
|
+
annotations: [
|
|
1140
|
+
initialSync,
|
|
1141
|
+
reconcileAnnotation.of(true)
|
|
1142
|
+
]
|
|
1057
1143
|
});
|
|
1058
1144
|
}
|
|
1059
1145
|
});
|
|
@@ -1105,10 +1191,7 @@ var awareness = (provider = dummyProvider) => {
|
|
|
1105
1191
|
];
|
|
1106
1192
|
};
|
|
1107
1193
|
var RemoteSelectionsDecorator = class {
|
|
1108
|
-
_ctx = new Context(void 0, {
|
|
1109
|
-
F: __dxlog_file5,
|
|
1110
|
-
L: 80
|
|
1111
|
-
});
|
|
1194
|
+
_ctx = new Context(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 33 });
|
|
1112
1195
|
_cursorConverter;
|
|
1113
1196
|
_provider;
|
|
1114
1197
|
_lastAnchor;
|
|
@@ -1339,10 +1422,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1339
1422
|
this._info = info;
|
|
1340
1423
|
}
|
|
1341
1424
|
open() {
|
|
1342
|
-
this._ctx = new Context2(void 0, {
|
|
1343
|
-
F: __dxlog_file6,
|
|
1344
|
-
L: 57
|
|
1345
|
-
});
|
|
1425
|
+
this._ctx = new Context2(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 28 });
|
|
1346
1426
|
this._postTask = new DeferredTask(this._ctx, async () => {
|
|
1347
1427
|
if (this._localState) {
|
|
1348
1428
|
await this._messenger.postMessage(this._channel, {
|
|
@@ -1369,12 +1449,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1369
1449
|
}).catch((err) => {
|
|
1370
1450
|
log5.debug("failed to query awareness", {
|
|
1371
1451
|
err
|
|
1372
|
-
}, {
|
|
1373
|
-
F: __dxlog_file6,
|
|
1374
|
-
L: 91,
|
|
1375
|
-
S: this,
|
|
1376
|
-
C: (f, a) => f(...a)
|
|
1377
|
-
});
|
|
1452
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 57, S: this });
|
|
1378
1453
|
});
|
|
1379
1454
|
}
|
|
1380
1455
|
close() {
|
|
@@ -1386,15 +1461,7 @@ var SpaceAwarenessProvider = class {
|
|
|
1386
1461
|
return Array.from(this._remoteStates.values());
|
|
1387
1462
|
}
|
|
1388
1463
|
update(position) {
|
|
1389
|
-
invariant(this._postTask, void 0, {
|
|
1390
|
-
F: __dxlog_file6,
|
|
1391
|
-
L: 106,
|
|
1392
|
-
S: this,
|
|
1393
|
-
A: [
|
|
1394
|
-
"this._postTask",
|
|
1395
|
-
""
|
|
1396
|
-
]
|
|
1397
|
-
});
|
|
1464
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 71, S: this, A: ["this._postTask", ""] });
|
|
1398
1465
|
this._localState = {
|
|
1399
1466
|
peerId: this._peerId,
|
|
1400
1467
|
position,
|
|
@@ -1403,27 +1470,11 @@ var SpaceAwarenessProvider = class {
|
|
|
1403
1470
|
this._postTask.schedule();
|
|
1404
1471
|
}
|
|
1405
1472
|
_handleQueryMessage() {
|
|
1406
|
-
invariant(this._postTask, void 0, {
|
|
1407
|
-
F: __dxlog_file6,
|
|
1408
|
-
L: 117,
|
|
1409
|
-
S: this,
|
|
1410
|
-
A: [
|
|
1411
|
-
"this._postTask",
|
|
1412
|
-
""
|
|
1413
|
-
]
|
|
1414
|
-
});
|
|
1473
|
+
invariant(this._postTask, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 80, S: this, A: ["this._postTask", ""] });
|
|
1415
1474
|
this._postTask.schedule();
|
|
1416
1475
|
}
|
|
1417
1476
|
_handlePostMessage(message) {
|
|
1418
|
-
invariant(message.kind === "post", void 0, {
|
|
1419
|
-
F: __dxlog_file6,
|
|
1420
|
-
L: 122,
|
|
1421
|
-
S: this,
|
|
1422
|
-
A: [
|
|
1423
|
-
"message.kind === 'post'",
|
|
1424
|
-
""
|
|
1425
|
-
]
|
|
1426
|
-
});
|
|
1477
|
+
invariant(message.kind === "post", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file6, L: 84, S: this, A: ["message.kind === 'post'", ""] });
|
|
1427
1478
|
this._remoteStates.set(message.state.peerId, message.state);
|
|
1428
1479
|
this.remoteStateChange.emit();
|
|
1429
1480
|
}
|
|
@@ -1552,15 +1603,7 @@ var Blaster = class {
|
|
|
1552
1603
|
return this._node;
|
|
1553
1604
|
}
|
|
1554
1605
|
initialize() {
|
|
1555
|
-
invariant2(!this._canvas && !this._ctx, void 0, {
|
|
1556
|
-
F: __dxlog_file7,
|
|
1557
|
-
L: 142,
|
|
1558
|
-
S: this,
|
|
1559
|
-
A: [
|
|
1560
|
-
"!this._canvas && !this._ctx",
|
|
1561
|
-
""
|
|
1562
|
-
]
|
|
1563
|
-
});
|
|
1606
|
+
invariant2(!this._canvas && !this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 134, S: this, A: ["!this._canvas && !this._ctx", ""] });
|
|
1564
1607
|
this._canvas = document.createElement("canvas");
|
|
1565
1608
|
this._canvas.id = "code-blast-canvas";
|
|
1566
1609
|
this._canvas.style.position = "absolute";
|
|
@@ -1589,15 +1632,7 @@ var Blaster = class {
|
|
|
1589
1632
|
}
|
|
1590
1633
|
}
|
|
1591
1634
|
start() {
|
|
1592
|
-
invariant2(this._canvas && this._ctx, void 0, {
|
|
1593
|
-
F: __dxlog_file7,
|
|
1594
|
-
L: 181,
|
|
1595
|
-
S: this,
|
|
1596
|
-
A: [
|
|
1597
|
-
"this._canvas && this._ctx",
|
|
1598
|
-
""
|
|
1599
|
-
]
|
|
1600
|
-
});
|
|
1635
|
+
invariant2(this._canvas && this._ctx, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file7, L: 166, S: this, A: ["this._canvas && this._ctx", ""] });
|
|
1601
1636
|
this._running = true;
|
|
1602
1637
|
this.loop();
|
|
1603
1638
|
}
|
|
@@ -1832,13 +1867,13 @@ var blocks = () => [
|
|
|
1832
1867
|
];
|
|
1833
1868
|
|
|
1834
1869
|
// src/extensions/bookmarks.ts
|
|
1835
|
-
import { Prec as Prec3, StateEffect as
|
|
1870
|
+
import { Prec as Prec3, StateEffect as StateEffect4, StateField as StateField2 } from "@codemirror/state";
|
|
1836
1871
|
import { keymap as keymap4 } from "@codemirror/view";
|
|
1837
1872
|
import { log as log6 } from "@dxos/log";
|
|
1838
1873
|
var __dxlog_file8 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/bookmarks.ts";
|
|
1839
|
-
var addBookmark =
|
|
1840
|
-
var removeBookmark =
|
|
1841
|
-
var clearBookmarks =
|
|
1874
|
+
var addBookmark = StateEffect4.define();
|
|
1875
|
+
var removeBookmark = StateEffect4.define();
|
|
1876
|
+
var clearBookmarks = StateEffect4.define();
|
|
1842
1877
|
var bookmarks = () => {
|
|
1843
1878
|
return [
|
|
1844
1879
|
bookmarksField,
|
|
@@ -1847,12 +1882,7 @@ var bookmarks = () => {
|
|
|
1847
1882
|
key: "Mod-ArrowUp",
|
|
1848
1883
|
run: (view) => {
|
|
1849
1884
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1850
|
-
log6("up", bookmarks2, {
|
|
1851
|
-
F: __dxlog_file8,
|
|
1852
|
-
L: 29,
|
|
1853
|
-
S: void 0,
|
|
1854
|
-
C: (f, a) => f(...a)
|
|
1855
|
-
});
|
|
1885
|
+
log6("up", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 18, S: void 0 });
|
|
1856
1886
|
return true;
|
|
1857
1887
|
}
|
|
1858
1888
|
},
|
|
@@ -1860,12 +1890,7 @@ var bookmarks = () => {
|
|
|
1860
1890
|
key: "Mod-ArrowDown",
|
|
1861
1891
|
run: (view) => {
|
|
1862
1892
|
const bookmarks2 = view.state.field(bookmarksField);
|
|
1863
|
-
log6("down", bookmarks2, {
|
|
1864
|
-
F: __dxlog_file8,
|
|
1865
|
-
L: 37,
|
|
1866
|
-
S: void 0,
|
|
1867
|
-
C: (f, a) => f(...a)
|
|
1868
|
-
});
|
|
1893
|
+
log6("down", bookmarks2, { "~LogMeta": "~LogMeta", F: __dxlog_file8, L: 26, S: void 0 });
|
|
1869
1894
|
return true;
|
|
1870
1895
|
}
|
|
1871
1896
|
}
|
|
@@ -1902,7 +1927,7 @@ var bookmarksField = StateField2.define({
|
|
|
1902
1927
|
|
|
1903
1928
|
// src/extensions/comments.ts
|
|
1904
1929
|
import { invertedEffects } from "@codemirror/commands";
|
|
1905
|
-
import { StateEffect as
|
|
1930
|
+
import { StateEffect as StateEffect5, StateField as StateField3 } from "@codemirror/state";
|
|
1906
1931
|
import { Decoration as Decoration7, EditorView as EditorView11, ViewPlugin as ViewPlugin10, hoverTooltip, keymap as keymap6 } from "@codemirror/view";
|
|
1907
1932
|
import sortBy from "lodash.sortby";
|
|
1908
1933
|
import { debounce as debounce2 } from "@dxos/async";
|
|
@@ -1930,28 +1955,12 @@ var createEditorStateTransaction = ({ scrollTo, selection }) => {
|
|
|
1930
1955
|
};
|
|
1931
1956
|
var createEditorStateStore = (keyPrefix) => ({
|
|
1932
1957
|
getState: (id) => {
|
|
1933
|
-
invariant3(id, void 0, {
|
|
1934
|
-
F: __dxlog_file9,
|
|
1935
|
-
L: 47,
|
|
1936
|
-
S: void 0,
|
|
1937
|
-
A: [
|
|
1938
|
-
"id",
|
|
1939
|
-
""
|
|
1940
|
-
]
|
|
1941
|
-
});
|
|
1958
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file9, L: 26, S: void 0, A: ["id", ""] });
|
|
1942
1959
|
const state = localStorage.getItem(`${keyPrefix}/${id}`);
|
|
1943
1960
|
return state ? JSON.parse(state) : void 0;
|
|
1944
1961
|
},
|
|
1945
1962
|
setState: (id, state) => {
|
|
1946
|
-
invariant3(id, void 0, {
|
|
1947
|
-
F: __dxlog_file9,
|
|
1948
|
-
L: 53,
|
|
1949
|
-
S: void 0,
|
|
1950
|
-
A: [
|
|
1951
|
-
"id",
|
|
1952
|
-
""
|
|
1953
|
-
]
|
|
1954
|
-
});
|
|
1963
|
+
invariant3(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file9, L: 31, S: void 0, A: ["id", ""] });
|
|
1955
1964
|
localStorage.setItem(`${keyPrefix}/${id}`, JSON.stringify(state));
|
|
1956
1965
|
}
|
|
1957
1966
|
});
|
|
@@ -2004,9 +2013,9 @@ var selectionState = ({ getState, setState } = {}) => {
|
|
|
2004
2013
|
|
|
2005
2014
|
// src/extensions/comments.ts
|
|
2006
2015
|
var __dxlog_file10 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/comments.ts";
|
|
2007
|
-
var setComments =
|
|
2008
|
-
var setSelection =
|
|
2009
|
-
var setCommentState =
|
|
2016
|
+
var setComments = StateEffect5.define();
|
|
2017
|
+
var setSelection = StateEffect5.define();
|
|
2018
|
+
var setCommentState = StateEffect5.define();
|
|
2010
2019
|
var commentsState = StateField3.define({
|
|
2011
2020
|
create: (state) => ({
|
|
2012
2021
|
id: state.facet(documentId),
|
|
@@ -2073,12 +2082,7 @@ var commentsDecorations = EditorView11.decorations.compute([
|
|
|
2073
2082
|
const decorations2 = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
|
|
2074
2083
|
const range = comment.range;
|
|
2075
2084
|
if (!range) {
|
|
2076
|
-
log7.warn("Invalid range:", range, {
|
|
2077
|
-
F: __dxlog_file10,
|
|
2078
|
-
L: 140,
|
|
2079
|
-
S: void 0,
|
|
2080
|
-
C: (f, a) => f(...a)
|
|
2081
|
-
});
|
|
2085
|
+
log7.warn("Invalid range:", range, { "~LogMeta": "~LogMeta", F: __dxlog_file10, L: 93, S: void 0 });
|
|
2082
2086
|
return void 0;
|
|
2083
2087
|
} else if (range.from === range.to) {
|
|
2084
2088
|
return void 0;
|
|
@@ -2088,7 +2092,7 @@ var commentsDecorations = EditorView11.decorations.compute([
|
|
|
2088
2092
|
}).filter(isNonNullable);
|
|
2089
2093
|
return Decoration7.set(decorations2);
|
|
2090
2094
|
});
|
|
2091
|
-
var commentClickedEffect =
|
|
2095
|
+
var commentClickedEffect = StateEffect5.define();
|
|
2092
2096
|
var handleCommentClick = EditorView11.domEventHandlers({
|
|
2093
2097
|
click: (event, view) => {
|
|
2094
2098
|
let target = event.target;
|
|
@@ -2191,10 +2195,10 @@ var trackPastedComments = (onUpdate) => {
|
|
|
2191
2195
|
const { comments: comments2 } = update2.startState.field(commentsState);
|
|
2192
2196
|
const exists = comments2.some((c) => c.comment.id === comment.id && c.range.from < c.range.to);
|
|
2193
2197
|
if (!exists) {
|
|
2194
|
-
const
|
|
2198
|
+
const cursor = Cursor.getCursorFromRange(update2.state, comment);
|
|
2195
2199
|
onUpdate({
|
|
2196
2200
|
id: comment.id,
|
|
2197
|
-
cursor
|
|
2201
|
+
cursor
|
|
2198
2202
|
});
|
|
2199
2203
|
}
|
|
2200
2204
|
}
|
|
@@ -2206,7 +2210,7 @@ var mapTrackedComment = (comment, changes) => ({
|
|
|
2206
2210
|
from: changes.mapPos(comment.from, 1),
|
|
2207
2211
|
to: changes.mapPos(comment.to, 1)
|
|
2208
2212
|
});
|
|
2209
|
-
var restoreCommentEffect =
|
|
2213
|
+
var restoreCommentEffect = StateEffect5.define({
|
|
2210
2214
|
map: mapTrackedComment
|
|
2211
2215
|
});
|
|
2212
2216
|
var createComment = (view) => {
|
|
@@ -2223,13 +2227,13 @@ var createComment = (view) => {
|
|
|
2223
2227
|
}
|
|
2224
2228
|
});
|
|
2225
2229
|
}
|
|
2226
|
-
const
|
|
2230
|
+
const cursor = Cursor.getCursorFromRange(view.state, {
|
|
2227
2231
|
from,
|
|
2228
2232
|
to
|
|
2229
2233
|
});
|
|
2230
|
-
if (
|
|
2234
|
+
if (cursor) {
|
|
2231
2235
|
options.onCreate?.({
|
|
2232
|
-
cursor
|
|
2236
|
+
cursor,
|
|
2233
2237
|
from,
|
|
2234
2238
|
location: view.coordsAtPos(from)
|
|
2235
2239
|
});
|
|
@@ -2470,7 +2474,7 @@ import { defaultKeymap, history, historyKeymap, indentWithTab, standardKeymap }
|
|
|
2470
2474
|
import { HighlightStyle, bracketMatching, syntaxHighlighting } from "@codemirror/language";
|
|
2471
2475
|
import { searchKeymap } from "@codemirror/search";
|
|
2472
2476
|
import { EditorState } from "@codemirror/state";
|
|
2473
|
-
import { EditorView as
|
|
2477
|
+
import { EditorView as EditorView16, ViewPlugin as ViewPlugin12, drawSelection, dropCursor as dropCursor2, highlightActiveLine, keymap as keymap7, lineNumbers, placeholder as placeholder2 } from "@codemirror/view";
|
|
2474
2478
|
import { vscodeDarkStyle, vscodeLightStyle } from "@uiw/codemirror-theme-vscode";
|
|
2475
2479
|
import defaultsDeep2 from "lodash.defaultsdeep";
|
|
2476
2480
|
import { generateName } from "@dxos/display-name";
|
|
@@ -2482,28 +2486,28 @@ import { EditorView as EditorView13 } from "@codemirror/view";
|
|
|
2482
2486
|
import { mx as mx3 } from "@dxos/ui-theme";
|
|
2483
2487
|
var headings = {
|
|
2484
2488
|
1: {
|
|
2485
|
-
className: "text-
|
|
2486
|
-
fontSize: "var(--text-
|
|
2489
|
+
className: "text-3xl",
|
|
2490
|
+
fontSize: "var(--text-3xl)",
|
|
2487
2491
|
lineHeight: "var(--text-4xl--line-height)"
|
|
2488
2492
|
},
|
|
2489
2493
|
2: {
|
|
2490
|
-
className: "text-
|
|
2491
|
-
fontSize: "var(--text-
|
|
2494
|
+
className: "text-2xl",
|
|
2495
|
+
fontSize: "var(--text-2xl)",
|
|
2492
2496
|
lineHeight: "var(--text-3xl--line-height)"
|
|
2493
2497
|
},
|
|
2494
2498
|
3: {
|
|
2495
|
-
className: "text-
|
|
2496
|
-
fontSize: "var(--text-
|
|
2499
|
+
className: "text-xl",
|
|
2500
|
+
fontSize: "var(--text-xl)",
|
|
2497
2501
|
lineHeight: "var(--text-2xl--line-height)"
|
|
2498
2502
|
},
|
|
2499
2503
|
4: {
|
|
2500
|
-
className: "text-
|
|
2501
|
-
fontSize: "var(--text-
|
|
2504
|
+
className: "text-lg",
|
|
2505
|
+
fontSize: "var(--text-lg)",
|
|
2502
2506
|
lineHeight: "var(--text-xl--line-height)"
|
|
2503
2507
|
},
|
|
2504
2508
|
5: {
|
|
2505
|
-
className: "text-
|
|
2506
|
-
fontSize: "var(--text-
|
|
2509
|
+
className: "text-base",
|
|
2510
|
+
fontSize: "var(--text-base)",
|
|
2507
2511
|
lineHeight: "var(--text-lg--line-height)"
|
|
2508
2512
|
},
|
|
2509
2513
|
6: {
|
|
@@ -2512,20 +2516,20 @@ var headings = {
|
|
|
2512
2516
|
lineHeight: "var(--text-base--line-height)"
|
|
2513
2517
|
}
|
|
2514
2518
|
};
|
|
2519
|
+
var fontBody = '"Inter Variable", ui-sans-serif, system-ui, sans-serif';
|
|
2520
|
+
var fontMono = '"JetBrains Mono Variable", ui-monospace, "Cascadia Code", "Source Code Pro", monospace';
|
|
2515
2521
|
var markdownTheme = {
|
|
2516
|
-
code: "font-mono
|
|
2517
|
-
codeMark: "font-mono
|
|
2518
|
-
mark: "
|
|
2522
|
+
code: "font-mono! cm-code-inline",
|
|
2523
|
+
codeMark: "font-mono! cm-code-mark",
|
|
2524
|
+
mark: "font-mono!",
|
|
2519
2525
|
heading: (level) => ({
|
|
2520
|
-
className: mx3(headings[level].className, "font-light text-cm-heading"),
|
|
2526
|
+
className: mx3(headings[level].className, "font-light text-(--color-cm-heading-number)"),
|
|
2521
2527
|
color: "var(--color-cm-heading) !important",
|
|
2522
2528
|
lineHeight: headings[level].lineHeight,
|
|
2523
2529
|
fontSize: headings[level].fontSize,
|
|
2524
2530
|
fontWeight: "100 !important"
|
|
2525
2531
|
})
|
|
2526
2532
|
};
|
|
2527
|
-
var fontBody = "Inter Variable, ui-sans-serif, system-ui, sans-serif";
|
|
2528
|
-
var fontMono = "JetBrains Mono Variable, ui-monospace, Cascadia Code, Source Code Pro, monospace";
|
|
2529
2533
|
var baseTheme = EditorView13.baseTheme({
|
|
2530
2534
|
/**
|
|
2531
2535
|
* Outer frame.
|
|
@@ -2538,12 +2542,21 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2538
2542
|
* Scroller
|
|
2539
2543
|
*/
|
|
2540
2544
|
".cm-scroller": {
|
|
2541
|
-
|
|
2545
|
+
// Browser scroll-anchoring: see comment in `scroller.ts`. `auto` lets the browser pin a
|
|
2546
|
+
// stable element near the viewport top so widget resizes (e.g. tool-block TogglePanel
|
|
2547
|
+
// open/close) don't jump the user's view.
|
|
2548
|
+
overflowAnchor: "auto"
|
|
2542
2549
|
},
|
|
2543
2550
|
".cm-scroller::-webkit-scrollbar": {
|
|
2544
|
-
width: "8px"
|
|
2551
|
+
width: "var(--scrollbar-size,8px)",
|
|
2552
|
+
height: "var(--scrollbar-size,8px)"
|
|
2553
|
+
},
|
|
2554
|
+
".cm-scroller::-webkit-scrollbar-corner": {
|
|
2555
|
+
background: "transparent"
|
|
2556
|
+
},
|
|
2557
|
+
".cm-scroller::-webkit-scrollbar-track": {
|
|
2558
|
+
background: "transparent"
|
|
2545
2559
|
},
|
|
2546
|
-
".cm-scroller::-webkit-scrollbar-track": {},
|
|
2547
2560
|
".cm-scroller::-webkit-scrollbar-thumb": {
|
|
2548
2561
|
background: "transparent",
|
|
2549
2562
|
transition: "background 0.15s"
|
|
@@ -2557,7 +2570,6 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2557
2570
|
*/
|
|
2558
2571
|
".cm-content": {
|
|
2559
2572
|
padding: "unset",
|
|
2560
|
-
lineHeight: "24px",
|
|
2561
2573
|
color: "unset"
|
|
2562
2574
|
},
|
|
2563
2575
|
/**
|
|
@@ -2588,9 +2600,16 @@ var baseTheme = EditorView13.baseTheme({
|
|
|
2588
2600
|
* Line.
|
|
2589
2601
|
*/
|
|
2590
2602
|
".cm-line": {
|
|
2591
|
-
lineHeight:
|
|
2603
|
+
lineHeight: 1.5,
|
|
2592
2604
|
paddingInline: 0
|
|
2593
2605
|
},
|
|
2606
|
+
/**
|
|
2607
|
+
* Force all inline children to inherit line-height to prevent monospace font metrics
|
|
2608
|
+
* (JetBrains Mono ascent/descent) from inflating the line box beyond 24px.
|
|
2609
|
+
*/
|
|
2610
|
+
".cm-line *": {
|
|
2611
|
+
lineHeight: "inherit"
|
|
2612
|
+
},
|
|
2594
2613
|
".cm-activeLine": {
|
|
2595
2614
|
background: "var(--color-cm-active-line)"
|
|
2596
2615
|
},
|
|
@@ -2768,10 +2787,9 @@ var editorGutter = EditorView13.theme({
|
|
|
2768
2787
|
}
|
|
2769
2788
|
});
|
|
2770
2789
|
var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
|
|
2771
|
-
//
|
|
2790
|
+
// Main content.
|
|
2772
2791
|
".cm-scroller": {
|
|
2773
|
-
fontFamily: monospace ? fontMono : fontBody
|
|
2774
|
-
fontSize: "16px"
|
|
2792
|
+
fontFamily: monospace ? fontMono : fontBody
|
|
2775
2793
|
},
|
|
2776
2794
|
// Maintain defaults for UI components.
|
|
2777
2795
|
".cm-content, .cm-gutters, .cm-panel": {
|
|
@@ -2781,9 +2799,9 @@ var createFontTheme = ({ monospace } = {}) => EditorView13.theme({
|
|
|
2781
2799
|
});
|
|
2782
2800
|
|
|
2783
2801
|
// src/extensions/focus.ts
|
|
2784
|
-
import { StateEffect as
|
|
2802
|
+
import { StateEffect as StateEffect6, StateField as StateField5 } from "@codemirror/state";
|
|
2785
2803
|
import { EditorView as EditorView14 } from "@codemirror/view";
|
|
2786
|
-
var focusEffect =
|
|
2804
|
+
var focusEffect = StateEffect6.define();
|
|
2787
2805
|
var focusField = StateField5.define({
|
|
2788
2806
|
create: () => false,
|
|
2789
2807
|
update: (value, tr) => {
|
|
@@ -2811,9 +2829,32 @@ var focus = [
|
|
|
2811
2829
|
})
|
|
2812
2830
|
];
|
|
2813
2831
|
|
|
2832
|
+
// src/extensions/scroll-past-end.ts
|
|
2833
|
+
import { EditorView as EditorView15, ViewPlugin as ViewPlugin11 } from "@codemirror/view";
|
|
2834
|
+
var scrollPastEndPlugin = ViewPlugin11.fromClass(class {
|
|
2835
|
+
height = 1e3;
|
|
2836
|
+
attrs = {
|
|
2837
|
+
style: "padding-bottom: 1000px"
|
|
2838
|
+
};
|
|
2839
|
+
update({ view }) {
|
|
2840
|
+
const lastLineBlock = view.lineBlockAt(view.state.doc.length);
|
|
2841
|
+
const height = view.dom.clientHeight - lastLineBlock.height - view.documentPadding.top - 0.5;
|
|
2842
|
+
if (height >= 0 && height !== this.height) {
|
|
2843
|
+
this.height = height;
|
|
2844
|
+
this.attrs = {
|
|
2845
|
+
style: `padding-bottom: ${height}px`
|
|
2846
|
+
};
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
});
|
|
2850
|
+
var scrollPastEnd = () => [
|
|
2851
|
+
scrollPastEndPlugin,
|
|
2852
|
+
EditorView15.contentAttributes.of((view) => view.plugin(scrollPastEndPlugin)?.attrs ?? null)
|
|
2853
|
+
];
|
|
2854
|
+
|
|
2814
2855
|
// src/extensions/factories.ts
|
|
2815
2856
|
var __dxlog_file11 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/factories.ts";
|
|
2816
|
-
var tabbable =
|
|
2857
|
+
var tabbable = EditorView16.contentAttributes.of({
|
|
2817
2858
|
tabindex: "0"
|
|
2818
2859
|
});
|
|
2819
2860
|
var filterChars = (chars) => {
|
|
@@ -2866,13 +2907,8 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2866
2907
|
const props = defaultsDeep2({}, propsProp, defaultBasicOptions);
|
|
2867
2908
|
return [
|
|
2868
2909
|
// NOTE: Doesn't catch errors in keymap functions.
|
|
2869
|
-
|
|
2870
|
-
log8.catch(err, void 0, {
|
|
2871
|
-
F: __dxlog_file11,
|
|
2872
|
-
L: 131,
|
|
2873
|
-
S: void 0,
|
|
2874
|
-
C: (f, a) => f(...a)
|
|
2875
|
-
});
|
|
2910
|
+
EditorView16.exceptionSink.of((err) => {
|
|
2911
|
+
log8.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file11, L: 79, S: void 0 });
|
|
2876
2912
|
}),
|
|
2877
2913
|
props.allowMultipleSelections && EditorState.allowMultipleSelections.of(true),
|
|
2878
2914
|
props.bracketMatching && bracketMatching(),
|
|
@@ -2881,7 +2917,7 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2881
2917
|
props.drawSelection && drawSelection({
|
|
2882
2918
|
cursorBlinkRate: 1200
|
|
2883
2919
|
}),
|
|
2884
|
-
props.editable !== void 0 &&
|
|
2920
|
+
props.editable !== void 0 && EditorView16.editable.of(props.editable),
|
|
2885
2921
|
props.focus && focus,
|
|
2886
2922
|
props.highlightActiveLine && highlightActiveLine(),
|
|
2887
2923
|
props.history && history(),
|
|
@@ -2889,9 +2925,16 @@ var createBasicExtensions = (propsProp) => {
|
|
|
2889
2925
|
lineNumbers(),
|
|
2890
2926
|
editorGutter
|
|
2891
2927
|
],
|
|
2892
|
-
props.lineWrapping &&
|
|
2928
|
+
props.lineWrapping && EditorView16.lineWrapping,
|
|
2893
2929
|
props.placeholder && placeholder2(props.placeholder),
|
|
2894
2930
|
props.readOnly !== void 0 && EditorState.readOnly.of(props.readOnly),
|
|
2931
|
+
// `EditorState.readOnly` is advisory — CodeMirror doesn't auto-reject doc-changing
|
|
2932
|
+
// transactions. Some extensions (e.g. `@codemirror/lang-markdown`'s Enter handler that
|
|
2933
|
+
// continues a list) dispatch programmatic edits regardless. Drop user-initiated edits
|
|
2934
|
+
// (`input` / `delete` keymap dispatches plus `undo` / `redo` from the history extension)
|
|
2935
|
+
// but pass programmatic dispatches — streaming `MarkdownStream` and similar consumers
|
|
2936
|
+
// depend on being able to populate the doc themselves.
|
|
2937
|
+
props.readOnly && EditorState.transactionFilter.of((tr) => tr.docChanged && (tr.isUserEvent("input") || tr.isUserEvent("delete") || tr.isUserEvent("undo") || tr.isUserEvent("redo")) ? [] : tr),
|
|
2895
2938
|
props.scrollPastEnd && scrollPastEnd(),
|
|
2896
2939
|
props.tabbable && tabbable,
|
|
2897
2940
|
props.tabSize && EditorState.tabSize.of(props.tabSize),
|
|
@@ -2934,24 +2977,29 @@ var defaultStyles = {
|
|
|
2934
2977
|
dark: vscodeDarkStyle,
|
|
2935
2978
|
light: vscodeLightStyle
|
|
2936
2979
|
};
|
|
2937
|
-
var createThemeExtensions = ({ monospace,
|
|
2980
|
+
var createThemeExtensions = ({ monospace, scrollbarThin, slots: slotsProp, syntaxHighlighting: syntaxHighlightingProp, themeMode } = {}) => {
|
|
2938
2981
|
const slots = defaultsDeep2({}, slotsProp, defaultThemeSlots);
|
|
2939
2982
|
return [
|
|
2940
2983
|
baseTheme,
|
|
2941
|
-
|
|
2984
|
+
EditorView16.darkTheme.of(themeMode === "dark"),
|
|
2942
2985
|
createFontTheme({
|
|
2943
2986
|
monospace
|
|
2944
2987
|
}),
|
|
2945
2988
|
syntaxHighlightingProp && syntaxHighlighting(HighlightStyle.define(themeMode === "dark" ? defaultStyles.dark : defaultStyles.light)),
|
|
2946
|
-
slots.editor?.className &&
|
|
2989
|
+
slots.editor?.className && EditorView16.editorAttributes.of({
|
|
2947
2990
|
class: slots.editor.className
|
|
2948
2991
|
}),
|
|
2949
|
-
slots.content?.className &&
|
|
2992
|
+
slots.content?.className && EditorView16.contentAttributes.of({
|
|
2950
2993
|
class: slots.content.className
|
|
2951
2994
|
}),
|
|
2952
|
-
slots.
|
|
2995
|
+
(slots.scroller?.className || scrollbarThin) && ViewPlugin12.fromClass(class {
|
|
2953
2996
|
constructor(view) {
|
|
2954
|
-
|
|
2997
|
+
if (slots.scroller?.className) {
|
|
2998
|
+
view.scrollDOM.classList.add(...slots.scroller.className.split(/\s+/));
|
|
2999
|
+
}
|
|
3000
|
+
if (scrollbarThin) {
|
|
3001
|
+
view.scrollDOM.style.setProperty("--scrollbar-size", "4px");
|
|
3002
|
+
}
|
|
2955
3003
|
}
|
|
2956
3004
|
})
|
|
2957
3005
|
].filter(isTruthy2);
|
|
@@ -2980,7 +3028,7 @@ var createDataExtensions = ({ id, text, messenger, identity }) => {
|
|
|
2980
3028
|
|
|
2981
3029
|
// src/extensions/folding.ts
|
|
2982
3030
|
import { codeFolding, foldGutter } from "@codemirror/language";
|
|
2983
|
-
import { EditorView as
|
|
3031
|
+
import { EditorView as EditorView17 } from "@codemirror/view";
|
|
2984
3032
|
import { Domino as Domino2, mx as mx4 } from "@dxos/ui";
|
|
2985
3033
|
var folding = () => {
|
|
2986
3034
|
return [
|
|
@@ -2988,13 +3036,14 @@ var folding = () => {
|
|
|
2988
3036
|
placeholderDOM: () => Domino2.of("span").root
|
|
2989
3037
|
}),
|
|
2990
3038
|
foldGutter({
|
|
3039
|
+
// NOTE: We can't animate since the element is remounted on state change.
|
|
2991
3040
|
markerDOM: (open) => {
|
|
2992
|
-
return Domino2.of("div").classNames("flex h-full justify-center items-center").
|
|
3041
|
+
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({
|
|
2993
3042
|
href: Domino2.icon("ph--caret-right--regular")
|
|
2994
3043
|
}))).root;
|
|
2995
3044
|
}
|
|
2996
3045
|
}),
|
|
2997
|
-
|
|
3046
|
+
EditorView17.theme({
|
|
2998
3047
|
".cm-foldGutter": {
|
|
2999
3048
|
opacity: 0.3,
|
|
3000
3049
|
transition: "opacity 0.3s",
|
|
@@ -3008,7 +3057,7 @@ var folding = () => {
|
|
|
3008
3057
|
};
|
|
3009
3058
|
|
|
3010
3059
|
// src/extensions/hashtag.ts
|
|
3011
|
-
import { Decoration as Decoration8, EditorView as
|
|
3060
|
+
import { Decoration as Decoration8, EditorView as EditorView18, MatchDecorator, ViewPlugin as ViewPlugin13, WidgetType as WidgetType4 } from "@codemirror/view";
|
|
3012
3061
|
import { getHashStyles, mx as mx5 } from "@dxos/ui-theme";
|
|
3013
3062
|
var TagWidget = class extends WidgetType4 {
|
|
3014
3063
|
_text;
|
|
@@ -3029,7 +3078,7 @@ var tagMatcher = new MatchDecorator({
|
|
|
3029
3078
|
})
|
|
3030
3079
|
});
|
|
3031
3080
|
var hashtag = () => [
|
|
3032
|
-
|
|
3081
|
+
ViewPlugin13.fromClass(class {
|
|
3033
3082
|
tags;
|
|
3034
3083
|
constructor(view) {
|
|
3035
3084
|
this.tags = tagMatcher.createDeco(view);
|
|
@@ -3039,11 +3088,11 @@ var hashtag = () => [
|
|
|
3039
3088
|
}
|
|
3040
3089
|
}, {
|
|
3041
3090
|
decorations: (instance) => instance.tags,
|
|
3042
|
-
provide: (plugin) =>
|
|
3091
|
+
provide: (plugin) => EditorView18.atomicRanges.of((view) => {
|
|
3043
3092
|
return view.plugin(plugin)?.tags || Decoration8.none;
|
|
3044
3093
|
})
|
|
3045
3094
|
}),
|
|
3046
|
-
|
|
3095
|
+
EditorView18.theme({
|
|
3047
3096
|
".cm-tag": {
|
|
3048
3097
|
borderRadius: "4px",
|
|
3049
3098
|
marginRight: "6px",
|
|
@@ -3098,18 +3147,18 @@ var schemaLinter = (validate) => (view) => {
|
|
|
3098
3147
|
};
|
|
3099
3148
|
|
|
3100
3149
|
// src/extensions/listener.ts
|
|
3101
|
-
import { EditorView as
|
|
3150
|
+
import { EditorView as EditorView19 } from "@codemirror/view";
|
|
3102
3151
|
import { isNonNullable as isNonNullable2 } from "@dxos/util";
|
|
3103
3152
|
var listener = ({ onFocus, onChange }) => {
|
|
3104
3153
|
return [
|
|
3105
|
-
onFocus &&
|
|
3154
|
+
onFocus && EditorView19.focusChangeEffect.of((state, focusing) => {
|
|
3106
3155
|
onFocus({
|
|
3107
3156
|
id: state.facet(documentId),
|
|
3108
3157
|
focusing
|
|
3109
3158
|
});
|
|
3110
3159
|
return null;
|
|
3111
3160
|
}),
|
|
3112
|
-
onChange &&
|
|
3161
|
+
onChange && EditorView19.updateListener.of(({ state, docChanged }) => {
|
|
3113
3162
|
if (docChanged) {
|
|
3114
3163
|
onChange({
|
|
3115
3164
|
id: state.facet(documentId),
|
|
@@ -3124,7 +3173,7 @@ var listener = ({ onFocus, onChange }) => {
|
|
|
3124
3173
|
import { snippet } from "@codemirror/autocomplete";
|
|
3125
3174
|
import { syntaxTree as syntaxTree2 } from "@codemirror/language";
|
|
3126
3175
|
import { EditorSelection as EditorSelection2 } from "@codemirror/state";
|
|
3127
|
-
import { EditorView as
|
|
3176
|
+
import { EditorView as EditorView20, keymap as keymap8 } from "@codemirror/view";
|
|
3128
3177
|
import { debounceAndThrottle } from "@dxos/async";
|
|
3129
3178
|
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;
|
|
3130
3179
|
var Inline = /* @__PURE__ */ (function(Inline2) {
|
|
@@ -4213,7 +4262,7 @@ var getFormatting = (state) => {
|
|
|
4213
4262
|
};
|
|
4214
4263
|
};
|
|
4215
4264
|
var formattingListener = (onStateChange, delay = 100) => {
|
|
4216
|
-
return
|
|
4265
|
+
return EditorView20.updateListener.of(debounceAndThrottle((update2) => {
|
|
4217
4266
|
if (update2.docChanged || update2.selectionSet) {
|
|
4218
4267
|
onStateChange(getFormatting(update2.state));
|
|
4219
4268
|
}
|
|
@@ -4274,8 +4323,7 @@ import { completionKeymap } from "@codemirror/autocomplete";
|
|
|
4274
4323
|
import { defaultKeymap as defaultKeymap2, indentWithTab as indentWithTab2 } from "@codemirror/commands";
|
|
4275
4324
|
import { jsonLanguage } from "@codemirror/lang-json";
|
|
4276
4325
|
import { markdown, markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
|
|
4277
|
-
import {
|
|
4278
|
-
import { LanguageDescription, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4326
|
+
import { foldNodeProp, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
|
|
4279
4327
|
import { languages } from "@codemirror/language-data";
|
|
4280
4328
|
import { keymap as keymap9 } from "@codemirror/view";
|
|
4281
4329
|
import { isTruthy as isTruthy3 } from "@dxos/util";
|
|
@@ -4285,11 +4333,6 @@ import { markdownLanguage } from "@codemirror/lang-markdown";
|
|
|
4285
4333
|
import { HighlightStyle as HighlightStyle2 } from "@codemirror/language";
|
|
4286
4334
|
import { Tag, styleTags, tags } from "@lezer/highlight";
|
|
4287
4335
|
import { Table } from "@lezer/markdown";
|
|
4288
|
-
var styles4 = {
|
|
4289
|
-
code: "font-mono no-underline! text-cm-code",
|
|
4290
|
-
codeMark: "font-mono text-cm-code-mark",
|
|
4291
|
-
mark: "opacity-50"
|
|
4292
|
-
};
|
|
4293
4336
|
var markdownTags = {
|
|
4294
4337
|
Blockquote: Tag.define(),
|
|
4295
4338
|
CodeMark: Tag.define(),
|
|
@@ -4371,7 +4414,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4371
4414
|
markdownTags.LinkReference,
|
|
4372
4415
|
markdownTags.ListMark
|
|
4373
4416
|
],
|
|
4374
|
-
class:
|
|
4417
|
+
class: markdownTheme.mark
|
|
4375
4418
|
},
|
|
4376
4419
|
// Markdown marks.
|
|
4377
4420
|
{
|
|
@@ -4382,7 +4425,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4382
4425
|
markdownTags.QuoteMark,
|
|
4383
4426
|
markdownTags.EmphasisMark
|
|
4384
4427
|
],
|
|
4385
|
-
class:
|
|
4428
|
+
class: markdownTheme.mark
|
|
4386
4429
|
},
|
|
4387
4430
|
// E.g., code block language (after ```).
|
|
4388
4431
|
{
|
|
@@ -4391,7 +4434,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4391
4434
|
tags.function(tags.variableName),
|
|
4392
4435
|
tags.labelName
|
|
4393
4436
|
],
|
|
4394
|
-
class:
|
|
4437
|
+
class: markdownTheme.codeMark
|
|
4395
4438
|
},
|
|
4396
4439
|
// Fonts.
|
|
4397
4440
|
{
|
|
@@ -4457,7 +4500,7 @@ var markdownHighlightStyle = (_options = {}) => {
|
|
|
4457
4500
|
markdownTags.CodeText,
|
|
4458
4501
|
markdownTags.InlineCode
|
|
4459
4502
|
],
|
|
4460
|
-
class:
|
|
4503
|
+
class: markdownTheme.code
|
|
4461
4504
|
},
|
|
4462
4505
|
{
|
|
4463
4506
|
tag: [
|
|
@@ -4487,15 +4530,23 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4487
4530
|
// https://github.com/lezer-parser/markdown?tab=readme-ov-file#github-flavored-markdown
|
|
4488
4531
|
base: markdownLanguage2,
|
|
4489
4532
|
// Languages for syntax highlighting fenced code blocks.
|
|
4533
|
+
// Caller-supplied languages are checked first so they can override defaults.
|
|
4490
4534
|
defaultCodeLanguage: jsonLanguage,
|
|
4491
|
-
codeLanguages:
|
|
4535
|
+
codeLanguages: [
|
|
4536
|
+
...options.codeLanguages ?? [],
|
|
4537
|
+
...languages
|
|
4538
|
+
],
|
|
4492
4539
|
// Don't complete HTML tags.
|
|
4493
4540
|
completeHTMLTags: false,
|
|
4494
4541
|
// Parser extensions.
|
|
4495
4542
|
extensions: [
|
|
4496
4543
|
// GFM provided by default.
|
|
4497
4544
|
markdownTagsExtensions,
|
|
4498
|
-
...options.extensions ?? defaultExtensions()
|
|
4545
|
+
...options.extensions ?? defaultExtensions(),
|
|
4546
|
+
// Disable folding for fenced code blocks by overriding foldNodeProp.
|
|
4547
|
+
// Note: returning null from foldService does not prevent syntaxFolding fallback,
|
|
4548
|
+
// so we must override the node prop directly on the FencedCode node type.
|
|
4549
|
+
noFencedCodeFolding
|
|
4499
4550
|
]
|
|
4500
4551
|
}),
|
|
4501
4552
|
// Custom styles.
|
|
@@ -4510,18 +4561,13 @@ var createMarkdownExtensions = (options = {}) => {
|
|
|
4510
4561
|
].filter(isTruthy3))
|
|
4511
4562
|
];
|
|
4512
4563
|
};
|
|
4513
|
-
var
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
]
|
|
4519
|
-
|
|
4520
|
-
"xml",
|
|
4521
|
-
"xhtml"
|
|
4522
|
-
],
|
|
4523
|
-
load: async () => xml()
|
|
4524
|
-
});
|
|
4564
|
+
var noFencedCodeFolding = {
|
|
4565
|
+
props: [
|
|
4566
|
+
foldNodeProp.add({
|
|
4567
|
+
FencedCode: () => null
|
|
4568
|
+
})
|
|
4569
|
+
]
|
|
4570
|
+
};
|
|
4525
4571
|
var defaultExtensions = () => [
|
|
4526
4572
|
noSetExtHeading,
|
|
4527
4573
|
noHtml
|
|
@@ -4541,19 +4587,19 @@ var debugTree = (cb) => StateField6.define({
|
|
|
4541
4587
|
update: (value, tr) => cb(convertTreeToJson(tr.state))
|
|
4542
4588
|
});
|
|
4543
4589
|
var convertTreeToJson = (state) => {
|
|
4544
|
-
const treeToJson = (
|
|
4590
|
+
const treeToJson = (cursor) => {
|
|
4545
4591
|
const node = {
|
|
4546
|
-
type:
|
|
4547
|
-
from:
|
|
4548
|
-
to:
|
|
4549
|
-
text: state.doc.slice(
|
|
4592
|
+
type: cursor.type.name,
|
|
4593
|
+
from: cursor.from,
|
|
4594
|
+
to: cursor.to,
|
|
4595
|
+
text: state.doc.slice(cursor.from, cursor.to).toString(),
|
|
4550
4596
|
children: []
|
|
4551
4597
|
};
|
|
4552
|
-
if (
|
|
4598
|
+
if (cursor.firstChild()) {
|
|
4553
4599
|
do {
|
|
4554
|
-
node.children.push(treeToJson(
|
|
4555
|
-
} while (
|
|
4556
|
-
|
|
4600
|
+
node.children.push(treeToJson(cursor));
|
|
4601
|
+
} while (cursor.nextSibling());
|
|
4602
|
+
cursor.parent();
|
|
4557
4603
|
}
|
|
4558
4604
|
return node;
|
|
4559
4605
|
};
|
|
@@ -4562,17 +4608,16 @@ var convertTreeToJson = (state) => {
|
|
|
4562
4608
|
|
|
4563
4609
|
// src/extensions/markdown/decorate.ts
|
|
4564
4610
|
import { syntaxTree as syntaxTree7 } from "@codemirror/language";
|
|
4565
|
-
import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as
|
|
4566
|
-
import { Decoration as Decoration11, EditorView as
|
|
4611
|
+
import { Prec as Prec4, RangeSetBuilder as RangeSetBuilder5, StateEffect as StateEffect7 } from "@codemirror/state";
|
|
4612
|
+
import { Decoration as Decoration11, EditorView as EditorView24, ViewPlugin as ViewPlugin15, WidgetType as WidgetType7 } from "@codemirror/view";
|
|
4567
4613
|
import { invariant as invariant4 } from "@dxos/invariant";
|
|
4568
|
-
import { mx as mx6 } from "@dxos/ui-theme";
|
|
4569
4614
|
|
|
4570
4615
|
// src/extensions/markdown/changes.ts
|
|
4571
4616
|
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
4572
4617
|
import { Transaction as Transaction4 } from "@codemirror/state";
|
|
4573
|
-
import { ViewPlugin as
|
|
4618
|
+
import { ViewPlugin as ViewPlugin14 } from "@codemirror/view";
|
|
4574
4619
|
var adjustChanges = () => {
|
|
4575
|
-
return
|
|
4620
|
+
return ViewPlugin14.fromClass(class {
|
|
4576
4621
|
update(update2) {
|
|
4577
4622
|
const tree = syntaxTree4(update2.state);
|
|
4578
4623
|
const adjustments = [];
|
|
@@ -4714,7 +4759,7 @@ var getValidUrl = (str) => {
|
|
|
4714
4759
|
// src/extensions/markdown/image.ts
|
|
4715
4760
|
import { syntaxTree as syntaxTree5 } from "@codemirror/language";
|
|
4716
4761
|
import { StateField as StateField7 } from "@codemirror/state";
|
|
4717
|
-
import { Decoration as Decoration9, EditorView as
|
|
4762
|
+
import { Decoration as Decoration9, EditorView as EditorView21, WidgetType as WidgetType5 } from "@codemirror/view";
|
|
4718
4763
|
var image = (_options = {}) => {
|
|
4719
4764
|
return [
|
|
4720
4765
|
StateField7.define({
|
|
@@ -4725,10 +4770,10 @@ var image = (_options = {}) => {
|
|
|
4725
4770
|
if (!tr.docChanged && !tr.selection) {
|
|
4726
4771
|
return value;
|
|
4727
4772
|
}
|
|
4728
|
-
const
|
|
4773
|
+
const cursor = tr.state.selection.main.head;
|
|
4729
4774
|
const oldCursor = tr.changes.mapPos(tr.startState.selection.main.head);
|
|
4730
|
-
let from = Math.min(
|
|
4731
|
-
let to = Math.max(
|
|
4775
|
+
let from = Math.min(cursor, oldCursor);
|
|
4776
|
+
let to = Math.max(cursor, oldCursor);
|
|
4732
4777
|
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
4733
4778
|
from = Math.min(from, fromB);
|
|
4734
4779
|
to = Math.max(to, toB);
|
|
@@ -4742,19 +4787,19 @@ var image = (_options = {}) => {
|
|
|
4742
4787
|
add: buildDecorations(tr.state, from, to)
|
|
4743
4788
|
});
|
|
4744
4789
|
},
|
|
4745
|
-
provide: (field) =>
|
|
4790
|
+
provide: (field) => EditorView21.decorations.from(field)
|
|
4746
4791
|
})
|
|
4747
4792
|
];
|
|
4748
4793
|
};
|
|
4749
4794
|
var buildDecorations = (state, from, to) => {
|
|
4750
4795
|
const decorations2 = [];
|
|
4751
|
-
const
|
|
4796
|
+
const cursor = state.selection.main.head;
|
|
4752
4797
|
syntaxTree5(state).iterate({
|
|
4753
4798
|
enter: (node) => {
|
|
4754
4799
|
if (node.name === "Image") {
|
|
4755
4800
|
const urlNode = node.node.getChild("URL");
|
|
4756
4801
|
if (urlNode) {
|
|
4757
|
-
const hide2 = state.readOnly ||
|
|
4802
|
+
const hide2 = state.readOnly || cursor < node.from || cursor > node.to || !state.field(focusField);
|
|
4758
4803
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
4759
4804
|
if (url.match(/^https?:\/\//) === null && url.match(/^file?:\/\//) === null) {
|
|
4760
4805
|
return;
|
|
@@ -4802,10 +4847,10 @@ var ImageWidget = class extends WidgetType5 {
|
|
|
4802
4847
|
};
|
|
4803
4848
|
|
|
4804
4849
|
// src/extensions/markdown/styles.ts
|
|
4805
|
-
import { EditorView as
|
|
4850
|
+
import { EditorView as EditorView22 } from "@codemirror/view";
|
|
4806
4851
|
var bulletListIndentationWidth = 24;
|
|
4807
4852
|
var orderedListIndentationWidth = 36;
|
|
4808
|
-
var formattingStyles =
|
|
4853
|
+
var formattingStyles = EditorView22.theme({
|
|
4809
4854
|
/**
|
|
4810
4855
|
* Horizontal rule.
|
|
4811
4856
|
*/
|
|
@@ -4840,13 +4885,38 @@ var formattingStyles = EditorView21.theme({
|
|
|
4840
4885
|
background: "var(--color-cm-codeblock)",
|
|
4841
4886
|
borderLeft: "2px solid var(--color-cm-separator)",
|
|
4842
4887
|
paddingLeft: "1rem",
|
|
4843
|
-
margin:
|
|
4888
|
+
margin: 0
|
|
4844
4889
|
},
|
|
4845
4890
|
/**
|
|
4846
4891
|
* Code and codeblocks.
|
|
4847
4892
|
*/
|
|
4893
|
+
"& code": {
|
|
4894
|
+
fontFamily: fontMono,
|
|
4895
|
+
color: "var(--color-cm-code)",
|
|
4896
|
+
whiteSpace: "nowrap"
|
|
4897
|
+
},
|
|
4848
4898
|
"& .cm-code": {
|
|
4849
|
-
fontFamily: fontMono
|
|
4899
|
+
fontFamily: fontMono,
|
|
4900
|
+
color: "var(--color-cm-code)"
|
|
4901
|
+
},
|
|
4902
|
+
// Inline code spans (triggered by backticks) use `cm-code-inline` + `font-mono`.
|
|
4903
|
+
// Different monospace font metrics can slightly overflow the fixed CodeMirror line box,
|
|
4904
|
+
// so constrain them to the target 24px height.
|
|
4905
|
+
"& .cm-code-inline": {
|
|
4906
|
+
fontFamily: fontMono,
|
|
4907
|
+
height: "24px",
|
|
4908
|
+
// display: 'inline-flex',
|
|
4909
|
+
alignItems: "center",
|
|
4910
|
+
overflow: "hidden",
|
|
4911
|
+
whiteSpace: "nowrap",
|
|
4912
|
+
color: "var(--color-cm-code-inline)"
|
|
4913
|
+
},
|
|
4914
|
+
"& .cm-code-mark": {
|
|
4915
|
+
fontFamily: fontMono,
|
|
4916
|
+
height: "24px",
|
|
4917
|
+
display: "inline-flex",
|
|
4918
|
+
alignItems: "center",
|
|
4919
|
+
overflow: "hidden"
|
|
4850
4920
|
},
|
|
4851
4921
|
"& .cm-codeblock-line": {
|
|
4852
4922
|
background: "var(--color-cm-codeblock)",
|
|
@@ -4878,16 +4948,24 @@ var formattingStyles = EditorView21.theme({
|
|
|
4878
4948
|
*/
|
|
4879
4949
|
".cm-table *": {
|
|
4880
4950
|
fontFamily: fontMono,
|
|
4951
|
+
lineHeight: 1.5,
|
|
4881
4952
|
textDecoration: "none !important"
|
|
4882
4953
|
},
|
|
4883
4954
|
".cm-table-head": {
|
|
4884
4955
|
padding: "2px 16px 2px 0px",
|
|
4956
|
+
overflowWrap: "break-word",
|
|
4957
|
+
whiteSpace: "pre-wrap",
|
|
4958
|
+
wordBreak: "keep-all",
|
|
4885
4959
|
textAlign: "left",
|
|
4886
|
-
|
|
4887
|
-
|
|
4960
|
+
color: "var(--color-subdued)",
|
|
4961
|
+
borderBottom: "1px solid var(--color-cm-separator)"
|
|
4888
4962
|
},
|
|
4889
4963
|
".cm-table-cell": {
|
|
4890
|
-
padding: "2px 16px 2px 0px"
|
|
4964
|
+
padding: "2px 16px 2px 0px",
|
|
4965
|
+
overflowWrap: "break-word",
|
|
4966
|
+
whiteSpace: "pre-wrap",
|
|
4967
|
+
wordBreak: "keep-all",
|
|
4968
|
+
verticalAlign: "top"
|
|
4891
4969
|
},
|
|
4892
4970
|
/**
|
|
4893
4971
|
* Image.
|
|
@@ -4903,12 +4981,12 @@ var formattingStyles = EditorView21.theme({
|
|
|
4903
4981
|
},
|
|
4904
4982
|
".cm-image-with-loader": {
|
|
4905
4983
|
display: "block",
|
|
4906
|
-
opacity:
|
|
4984
|
+
opacity: 0,
|
|
4907
4985
|
transitionDuration: "350ms",
|
|
4908
4986
|
transitionProperty: "opacity"
|
|
4909
4987
|
},
|
|
4910
4988
|
".cm-image-with-loader.cm-loaded-image": {
|
|
4911
|
-
opacity:
|
|
4989
|
+
opacity: 1
|
|
4912
4990
|
},
|
|
4913
4991
|
".cm-image-wrapper": {
|
|
4914
4992
|
"grid-template-columns": "1fr",
|
|
@@ -4927,17 +5005,17 @@ var formattingStyles = EditorView21.theme({
|
|
|
4927
5005
|
// src/extensions/markdown/table.ts
|
|
4928
5006
|
import { syntaxTree as syntaxTree6 } from "@codemirror/language";
|
|
4929
5007
|
import { RangeSetBuilder as RangeSetBuilder4, StateField as StateField8 } from "@codemirror/state";
|
|
4930
|
-
import { Decoration as Decoration10, EditorView as
|
|
5008
|
+
import { Decoration as Decoration10, EditorView as EditorView23, WidgetType as WidgetType6 } from "@codemirror/view";
|
|
4931
5009
|
var table = (options = {}) => {
|
|
4932
5010
|
return StateField8.define({
|
|
4933
5011
|
create: (state) => update(state, options),
|
|
4934
5012
|
update: (_, tr) => update(tr.state, options),
|
|
4935
|
-
provide: (field) =>
|
|
5013
|
+
provide: (field) => EditorView23.decorations.from(field)
|
|
4936
5014
|
});
|
|
4937
5015
|
};
|
|
4938
5016
|
var update = (state, _options) => {
|
|
4939
5017
|
const builder = new RangeSetBuilder4();
|
|
4940
|
-
const
|
|
5018
|
+
const cursor = state.selection.main.head;
|
|
4941
5019
|
const tables = [];
|
|
4942
5020
|
const getTable = () => tables[tables.length - 1];
|
|
4943
5021
|
const getRow = () => {
|
|
@@ -4975,7 +5053,7 @@ var update = (state, _options) => {
|
|
|
4975
5053
|
}
|
|
4976
5054
|
});
|
|
4977
5055
|
tables.forEach((table2) => {
|
|
4978
|
-
const replace = state.readOnly ||
|
|
5056
|
+
const replace = state.readOnly || cursor < table2.from || cursor > table2.to;
|
|
4979
5057
|
if (replace) {
|
|
4980
5058
|
builder.add(table2.from, table2.to, Decoration10.replace({
|
|
4981
5059
|
block: true,
|
|
@@ -4989,6 +5067,26 @@ var update = (state, _options) => {
|
|
|
4989
5067
|
});
|
|
4990
5068
|
return builder.finish();
|
|
4991
5069
|
};
|
|
5070
|
+
var renderCellContent = (el, text) => {
|
|
5071
|
+
const parts = text.split(/(`[^`\n]+`|\*\*[^*\n]+\*\*|__[^_\n]+__|\*[^*\n]+\*|_[^_\n]+_)/);
|
|
5072
|
+
for (const part of parts) {
|
|
5073
|
+
if (part.length > 2 && part.startsWith("`") && part.endsWith("`")) {
|
|
5074
|
+
const code = document.createElement("code");
|
|
5075
|
+
code.textContent = part.slice(1, -1);
|
|
5076
|
+
el.appendChild(code);
|
|
5077
|
+
} else if (part.startsWith("**") && part.endsWith("**") || part.startsWith("__") && part.endsWith("__")) {
|
|
5078
|
+
const strong = document.createElement("strong");
|
|
5079
|
+
strong.textContent = part.slice(2, -2);
|
|
5080
|
+
el.appendChild(strong);
|
|
5081
|
+
} else if (part.startsWith("*") && part.endsWith("*") || part.startsWith("_") && part.endsWith("_")) {
|
|
5082
|
+
const em = document.createElement("em");
|
|
5083
|
+
em.textContent = part.slice(1, -1);
|
|
5084
|
+
el.appendChild(em);
|
|
5085
|
+
} else {
|
|
5086
|
+
el.appendChild(document.createTextNode(part));
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
};
|
|
4992
5090
|
var TableWidget = class extends WidgetType6 {
|
|
4993
5091
|
_table;
|
|
4994
5092
|
constructor(_table) {
|
|
@@ -5008,7 +5106,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
5008
5106
|
this._table.header?.forEach((cell) => {
|
|
5009
5107
|
const th = document.createElement("th");
|
|
5010
5108
|
th.setAttribute("class", "cm-table-head");
|
|
5011
|
-
tr.appendChild(th)
|
|
5109
|
+
renderCellContent(tr.appendChild(th), cell);
|
|
5012
5110
|
});
|
|
5013
5111
|
const body = table2.appendChild(document.createElement("tbody"));
|
|
5014
5112
|
this._table.rows?.forEach((row) => {
|
|
@@ -5016,7 +5114,7 @@ var TableWidget = class extends WidgetType6 {
|
|
|
5016
5114
|
row.forEach((cell) => {
|
|
5017
5115
|
const td = document.createElement("td");
|
|
5018
5116
|
td.setAttribute("class", "cm-table-cell");
|
|
5019
|
-
tr2.appendChild(td)
|
|
5117
|
+
renderCellContent(tr2.appendChild(td), cell);
|
|
5020
5118
|
});
|
|
5021
5119
|
});
|
|
5022
5120
|
return div;
|
|
@@ -5123,10 +5221,10 @@ var fencedCodeLine = Decoration11.line({
|
|
|
5123
5221
|
class: "cm-code cm-codeblock-line"
|
|
5124
5222
|
});
|
|
5125
5223
|
var fencedCodeLineFirst = Decoration11.line({
|
|
5126
|
-
class:
|
|
5224
|
+
class: "cm-code cm-codeblock-line cm-codeblock-start"
|
|
5127
5225
|
});
|
|
5128
5226
|
var fencedCodeLineLast = Decoration11.line({
|
|
5129
|
-
class:
|
|
5227
|
+
class: "cm-code cm-codeblock-line cm-codeblock-end"
|
|
5130
5228
|
});
|
|
5131
5229
|
var commentBlockLine = fencedCodeLine;
|
|
5132
5230
|
var commentBlockLineFirst = fencedCodeLineFirst;
|
|
@@ -5158,15 +5256,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5158
5256
|
const { state } = view;
|
|
5159
5257
|
const headerLevels = [];
|
|
5160
5258
|
const getHeaderLevels = (node, level) => {
|
|
5161
|
-
invariant4(level > 0, void 0, {
|
|
5162
|
-
F: __dxlog_file12,
|
|
5163
|
-
L: 179,
|
|
5164
|
-
S: void 0,
|
|
5165
|
-
A: [
|
|
5166
|
-
"level > 0",
|
|
5167
|
-
""
|
|
5168
|
-
]
|
|
5169
|
-
});
|
|
5259
|
+
invariant4(level > 0, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 160, S: void 0, A: ["level > 0", ""] });
|
|
5170
5260
|
if (level > headerLevels.length) {
|
|
5171
5261
|
const len = headerLevels.length;
|
|
5172
5262
|
headerLevels.length = level;
|
|
@@ -5197,15 +5287,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5197
5287
|
listLevels.pop();
|
|
5198
5288
|
};
|
|
5199
5289
|
const getCurrentListLevel = () => {
|
|
5200
|
-
invariant4(listLevels.length, void 0, {
|
|
5201
|
-
F: __dxlog_file12,
|
|
5202
|
-
L: 201,
|
|
5203
|
-
S: void 0,
|
|
5204
|
-
A: [
|
|
5205
|
-
"listLevels.length",
|
|
5206
|
-
""
|
|
5207
|
-
]
|
|
5208
|
-
});
|
|
5290
|
+
invariant4(listLevels.length, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file12, L: 192, S: void 0, A: ["listLevels.length", ""] });
|
|
5209
5291
|
return listLevels[listLevels.length - 1];
|
|
5210
5292
|
};
|
|
5211
5293
|
const enterNode = (node) => {
|
|
@@ -5243,7 +5325,7 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5243
5325
|
deco: hide
|
|
5244
5326
|
});
|
|
5245
5327
|
} else {
|
|
5246
|
-
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + " ";
|
|
5328
|
+
const num = headers.slice(from - 1).map((level2) => level2?.number ?? 0).join(".") + "). ";
|
|
5247
5329
|
if (num.length) {
|
|
5248
5330
|
atomicDecoRanges.push({
|
|
5249
5331
|
from: mark.from,
|
|
@@ -5426,11 +5508,11 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5426
5508
|
}
|
|
5427
5509
|
decoRanges.push({
|
|
5428
5510
|
from: marks[0].to,
|
|
5429
|
-
to: marks[1].from,
|
|
5511
|
+
to: !editing && options.renderLinkButton ? node.to : marks[1].from,
|
|
5430
5512
|
deco: Decoration11.mark({
|
|
5431
5513
|
tagName: "a",
|
|
5432
5514
|
attributes: {
|
|
5433
|
-
class: "cm-link",
|
|
5515
|
+
class: options.renderLinkButton ? "cm-link cm-link-with-button" : "cm-link",
|
|
5434
5516
|
href: url,
|
|
5435
5517
|
rel: "noreferrer",
|
|
5436
5518
|
target: "_blank"
|
|
@@ -5508,18 +5590,21 @@ var buildDecorations2 = (view, options, focus2) => {
|
|
|
5508
5590
|
deco.add(from, to, d);
|
|
5509
5591
|
}
|
|
5510
5592
|
const atomicDeco = new RangeSetBuilder5();
|
|
5511
|
-
for (const { from, to, deco:
|
|
5512
|
-
|
|
5593
|
+
for (const { from, to, deco: deco2 } of atomicDecoRanges) {
|
|
5594
|
+
if (from < to && state.doc.lineAt(from).number !== state.doc.lineAt(to).number) {
|
|
5595
|
+
continue;
|
|
5596
|
+
}
|
|
5597
|
+
atomicDeco.add(from, to, deco2);
|
|
5513
5598
|
}
|
|
5514
5599
|
return {
|
|
5515
5600
|
deco: deco.finish(),
|
|
5516
5601
|
atomicDeco: atomicDeco.finish()
|
|
5517
5602
|
};
|
|
5518
5603
|
};
|
|
5519
|
-
var forceUpdate =
|
|
5604
|
+
var forceUpdate = StateEffect7.define();
|
|
5520
5605
|
var decorateMarkdown = (options = {}) => {
|
|
5521
5606
|
return [
|
|
5522
|
-
|
|
5607
|
+
ViewPlugin15.fromClass(class {
|
|
5523
5608
|
deco;
|
|
5524
5609
|
atomicDeco;
|
|
5525
5610
|
pendingUpdate;
|
|
@@ -5554,9 +5639,9 @@ var decorateMarkdown = (options = {}) => {
|
|
|
5554
5639
|
}
|
|
5555
5640
|
}, {
|
|
5556
5641
|
provide: (plugin) => [
|
|
5557
|
-
Prec4.low(
|
|
5558
|
-
|
|
5559
|
-
|
|
5642
|
+
Prec4.low(EditorView24.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration11.none)),
|
|
5643
|
+
EditorView24.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none),
|
|
5644
|
+
EditorView24.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration11.none)
|
|
5560
5645
|
]
|
|
5561
5646
|
}),
|
|
5562
5647
|
image(),
|
|
@@ -5624,12 +5709,7 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5624
5709
|
(context) => {
|
|
5625
5710
|
log9.info("completion context", {
|
|
5626
5711
|
context
|
|
5627
|
-
}, {
|
|
5628
|
-
F: __dxlog_file13,
|
|
5629
|
-
L: 27,
|
|
5630
|
-
S: void 0,
|
|
5631
|
-
C: (f, a) => f(...a)
|
|
5632
|
-
});
|
|
5712
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file13, L: 18, S: void 0 });
|
|
5633
5713
|
const match = context.matchBefore(/@(\w+)?/);
|
|
5634
5714
|
if (!match || match.from === match.to && !context.explicit) {
|
|
5635
5715
|
return null;
|
|
@@ -5646,8 +5726,8 @@ var mention = ({ debug, onSearch }) => {
|
|
|
5646
5726
|
};
|
|
5647
5727
|
|
|
5648
5728
|
// src/extensions/modal.ts
|
|
5649
|
-
import { StateEffect as
|
|
5650
|
-
var modalStateEffect =
|
|
5729
|
+
import { StateEffect as StateEffect8, StateField as StateField9 } from "@codemirror/state";
|
|
5730
|
+
var modalStateEffect = StateEffect8.define();
|
|
5651
5731
|
var modalStateField = StateField9.define({
|
|
5652
5732
|
create: () => false,
|
|
5653
5733
|
update: (value, tr) => {
|
|
@@ -5862,15 +5942,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5862
5942
|
break;
|
|
5863
5943
|
}
|
|
5864
5944
|
case "BulletList": {
|
|
5865
|
-
invariant5(current, void 0, {
|
|
5866
|
-
F: __dxlog_file14,
|
|
5867
|
-
L: 219,
|
|
5868
|
-
S: void 0,
|
|
5869
|
-
A: [
|
|
5870
|
-
"current",
|
|
5871
|
-
""
|
|
5872
|
-
]
|
|
5873
|
-
});
|
|
5945
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 169, S: void 0, A: ["current", ""] });
|
|
5874
5946
|
parent = current;
|
|
5875
5947
|
if (current) {
|
|
5876
5948
|
current.lineRange.to = current.node.from;
|
|
@@ -5879,15 +5951,7 @@ var outlinerTree = (_options = {}) => {
|
|
|
5879
5951
|
break;
|
|
5880
5952
|
}
|
|
5881
5953
|
case "ListItem": {
|
|
5882
|
-
invariant5(parent, void 0, {
|
|
5883
|
-
F: __dxlog_file14,
|
|
5884
|
-
L: 228,
|
|
5885
|
-
S: void 0,
|
|
5886
|
-
A: [
|
|
5887
|
-
"parent",
|
|
5888
|
-
""
|
|
5889
|
-
]
|
|
5890
|
-
});
|
|
5954
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 179, S: void 0, A: ["parent", ""] });
|
|
5891
5955
|
const nextSibling = node.node.nextSibling ?? node.node.parent?.nextSibling;
|
|
5892
5956
|
const docRange = {
|
|
5893
5957
|
from: state.doc.lineAt(node.from).from,
|
|
@@ -5921,42 +5985,18 @@ var outlinerTree = (_options = {}) => {
|
|
|
5921
5985
|
break;
|
|
5922
5986
|
}
|
|
5923
5987
|
case "ListMark": {
|
|
5924
|
-
invariant5(current, void 0, {
|
|
5925
|
-
F: __dxlog_file14,
|
|
5926
|
-
L: 272,
|
|
5927
|
-
S: void 0,
|
|
5928
|
-
A: [
|
|
5929
|
-
"current",
|
|
5930
|
-
""
|
|
5931
|
-
]
|
|
5932
|
-
});
|
|
5988
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 219, S: void 0, A: ["current", ""] });
|
|
5933
5989
|
current.type = "bullet";
|
|
5934
5990
|
current.contentRange.from = node.from + "- ".length;
|
|
5935
5991
|
break;
|
|
5936
5992
|
}
|
|
5937
5993
|
case "Task": {
|
|
5938
|
-
invariant5(current, void 0, {
|
|
5939
|
-
F: __dxlog_file14,
|
|
5940
|
-
L: 278,
|
|
5941
|
-
S: void 0,
|
|
5942
|
-
A: [
|
|
5943
|
-
"current",
|
|
5944
|
-
""
|
|
5945
|
-
]
|
|
5946
|
-
});
|
|
5994
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 226, S: void 0, A: ["current", ""] });
|
|
5947
5995
|
current.type = "task";
|
|
5948
5996
|
break;
|
|
5949
5997
|
}
|
|
5950
5998
|
case "TaskMarker": {
|
|
5951
|
-
invariant5(current, void 0, {
|
|
5952
|
-
F: __dxlog_file14,
|
|
5953
|
-
L: 283,
|
|
5954
|
-
S: void 0,
|
|
5955
|
-
A: [
|
|
5956
|
-
"current",
|
|
5957
|
-
""
|
|
5958
|
-
]
|
|
5959
|
-
});
|
|
5999
|
+
invariant5(current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 232, S: void 0, A: ["current", ""] });
|
|
5960
6000
|
current.contentRange.from = node.from + "[ ] ".length;
|
|
5961
6001
|
break;
|
|
5962
6002
|
}
|
|
@@ -5964,29 +6004,13 @@ var outlinerTree = (_options = {}) => {
|
|
|
5964
6004
|
},
|
|
5965
6005
|
leave: (node) => {
|
|
5966
6006
|
if (node.name === "BulletList") {
|
|
5967
|
-
invariant5(parent, void 0, {
|
|
5968
|
-
F: __dxlog_file14,
|
|
5969
|
-
L: 291,
|
|
5970
|
-
S: void 0,
|
|
5971
|
-
A: [
|
|
5972
|
-
"parent",
|
|
5973
|
-
""
|
|
5974
|
-
]
|
|
5975
|
-
});
|
|
6007
|
+
invariant5(parent, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 240, S: void 0, A: ["parent", ""] });
|
|
5976
6008
|
prevSiblings[level--] = void 0;
|
|
5977
6009
|
parent = parent.parent;
|
|
5978
6010
|
}
|
|
5979
6011
|
}
|
|
5980
6012
|
});
|
|
5981
|
-
invariant5(tree, void 0, {
|
|
5982
|
-
F: __dxlog_file14,
|
|
5983
|
-
L: 298,
|
|
5984
|
-
S: void 0,
|
|
5985
|
-
A: [
|
|
5986
|
-
"tree",
|
|
5987
|
-
""
|
|
5988
|
-
]
|
|
5989
|
-
});
|
|
6013
|
+
invariant5(tree, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file14, L: 246, S: void 0, A: ["tree", ""] });
|
|
5990
6014
|
return tree;
|
|
5991
6015
|
};
|
|
5992
6016
|
return [
|
|
@@ -6271,17 +6295,17 @@ var commands = () => keymap11.of([
|
|
|
6271
6295
|
|
|
6272
6296
|
// src/extensions/outliner/outliner.ts
|
|
6273
6297
|
import { Prec as Prec5 } from "@codemirror/state";
|
|
6274
|
-
import { Decoration as Decoration12, EditorView as
|
|
6275
|
-
import { mx as
|
|
6298
|
+
import { Decoration as Decoration12, EditorView as EditorView26, ViewPlugin as ViewPlugin18 } from "@codemirror/view";
|
|
6299
|
+
import { mx as mx6 } from "@dxos/ui-theme";
|
|
6276
6300
|
|
|
6277
6301
|
// src/extensions/outliner/editor.ts
|
|
6278
6302
|
import { EditorSelection as EditorSelection4, EditorState as EditorState2 } from "@codemirror/state";
|
|
6279
|
-
import { ViewPlugin as
|
|
6303
|
+
import { ViewPlugin as ViewPlugin16 } from "@codemirror/view";
|
|
6280
6304
|
import { log as log10 } from "@dxos/log";
|
|
6281
6305
|
var __dxlog_file15 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/outliner/editor.ts";
|
|
6282
6306
|
var LIST_ITEM_REGEX = /^\s*- (\[ \]|\[x\])? /;
|
|
6283
6307
|
var initialize = () => {
|
|
6284
|
-
return
|
|
6308
|
+
return ViewPlugin16.fromClass(class {
|
|
6285
6309
|
constructor(view) {
|
|
6286
6310
|
const first = view.state.doc.lineAt(0);
|
|
6287
6311
|
const text = view.state.sliceDoc(first.from, first.to);
|
|
@@ -6428,35 +6452,20 @@ var editor = () => [
|
|
|
6428
6452
|
text: insert.toString(),
|
|
6429
6453
|
length: insert.length
|
|
6430
6454
|
}
|
|
6431
|
-
}, {
|
|
6432
|
-
F: __dxlog_file15,
|
|
6433
|
-
L: 164,
|
|
6434
|
-
S: void 0,
|
|
6435
|
-
C: (f, a) => f(...a)
|
|
6436
|
-
});
|
|
6455
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 174, S: void 0 });
|
|
6437
6456
|
}
|
|
6438
6457
|
});
|
|
6439
6458
|
if (changes.length > 0) {
|
|
6440
6459
|
log10("modified,", {
|
|
6441
6460
|
changes
|
|
6442
|
-
}, {
|
|
6443
|
-
F: __dxlog_file15,
|
|
6444
|
-
L: 175,
|
|
6445
|
-
S: void 0,
|
|
6446
|
-
C: (f, a) => f(...a)
|
|
6447
|
-
});
|
|
6461
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 196, S: void 0 });
|
|
6448
6462
|
return [
|
|
6449
6463
|
{
|
|
6450
6464
|
changes
|
|
6451
6465
|
}
|
|
6452
6466
|
];
|
|
6453
6467
|
} else if (cancel) {
|
|
6454
|
-
log10("cancel", void 0, {
|
|
6455
|
-
F: __dxlog_file15,
|
|
6456
|
-
L: 178,
|
|
6457
|
-
S: void 0,
|
|
6458
|
-
C: (f, a) => f(...a)
|
|
6459
|
-
});
|
|
6468
|
+
log10("cancel", void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file15, L: 205, S: void 0 });
|
|
6460
6469
|
return [];
|
|
6461
6470
|
}
|
|
6462
6471
|
return tr;
|
|
@@ -6464,10 +6473,10 @@ var editor = () => [
|
|
|
6464
6473
|
];
|
|
6465
6474
|
|
|
6466
6475
|
// src/extensions/outliner/menu.ts
|
|
6467
|
-
import { EditorView as
|
|
6476
|
+
import { EditorView as EditorView25, ViewPlugin as ViewPlugin17 } from "@codemirror/view";
|
|
6468
6477
|
import { addEventListener as addEventListener2 } from "@dxos/async";
|
|
6469
6478
|
var menu = (options = {}) => [
|
|
6470
|
-
|
|
6479
|
+
ViewPlugin17.fromClass(class {
|
|
6471
6480
|
view;
|
|
6472
6481
|
tag;
|
|
6473
6482
|
rafId;
|
|
@@ -6529,7 +6538,7 @@ var menu = (options = {}) => [
|
|
|
6529
6538
|
this.rafId = requestAnimationFrame(this.updateButtonPosition.bind(this));
|
|
6530
6539
|
}
|
|
6531
6540
|
}),
|
|
6532
|
-
|
|
6541
|
+
EditorView25.theme({
|
|
6533
6542
|
".cm-popover-trigger": {
|
|
6534
6543
|
position: "fixed",
|
|
6535
6544
|
padding: "0",
|
|
@@ -6565,12 +6574,12 @@ var outliner = (_options = {}) => [
|
|
|
6565
6574
|
listPaddingLeft: 8
|
|
6566
6575
|
}),
|
|
6567
6576
|
// Researve space for menu.
|
|
6568
|
-
|
|
6577
|
+
EditorView26.contentAttributes.of({
|
|
6569
6578
|
class: "w-full !mr-[3rem]"
|
|
6570
6579
|
})
|
|
6571
6580
|
];
|
|
6572
6581
|
var decorations = () => [
|
|
6573
|
-
|
|
6582
|
+
ViewPlugin18.fromClass(class {
|
|
6574
6583
|
decorations = Decoration12.none;
|
|
6575
6584
|
constructor(view) {
|
|
6576
6585
|
this.updateDecorations(view.state, view);
|
|
@@ -6595,7 +6604,7 @@ var decorations = () => [
|
|
|
6595
6604
|
const lineTo = doc.lineAt(item.contentRange.to);
|
|
6596
6605
|
const isSelected = selection.includes(item.index) || item === current;
|
|
6597
6606
|
decorations2.push(Decoration12.line({
|
|
6598
|
-
class:
|
|
6607
|
+
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"))
|
|
6599
6608
|
}).range(line.from, line.from));
|
|
6600
6609
|
}
|
|
6601
6610
|
}
|
|
@@ -6605,7 +6614,7 @@ var decorations = () => [
|
|
|
6605
6614
|
decorations: (v) => v.decorations
|
|
6606
6615
|
}),
|
|
6607
6616
|
// Theme.
|
|
6608
|
-
|
|
6617
|
+
EditorView26.theme(Object.assign({
|
|
6609
6618
|
".cm-list-item": {
|
|
6610
6619
|
borderLeftWidth: "1px",
|
|
6611
6620
|
borderRightWidth: "1px",
|
|
@@ -6640,28 +6649,57 @@ var decorations = () => [
|
|
|
6640
6649
|
|
|
6641
6650
|
// src/extensions/preview/preview.ts
|
|
6642
6651
|
import { syntaxTree as syntaxTree10 } from "@codemirror/language";
|
|
6643
|
-
import { RangeSetBuilder as RangeSetBuilder6, StateField as StateField11 } from "@codemirror/state";
|
|
6644
|
-
import { Decoration as Decoration13, EditorView as
|
|
6652
|
+
import { RangeSetBuilder as RangeSetBuilder6, StateEffect as StateEffect9, StateField as StateField11 } from "@codemirror/state";
|
|
6653
|
+
import { Decoration as Decoration13, EditorView as EditorView27, ViewPlugin as ViewPlugin19, WidgetType as WidgetType8 } from "@codemirror/view";
|
|
6654
|
+
import { DXN, Entity } from "@dxos/echo";
|
|
6655
|
+
var labelResolvedEffect = StateEffect9.define();
|
|
6645
6656
|
var preview = (options = {}) => {
|
|
6657
|
+
const viewRef = {
|
|
6658
|
+
current: void 0
|
|
6659
|
+
};
|
|
6646
6660
|
return [
|
|
6647
6661
|
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
|
6648
6662
|
// "Block decorations may not be specified via plugins".
|
|
6649
6663
|
StateField11.define({
|
|
6650
|
-
create: (state) => buildDecorations3(state, options),
|
|
6664
|
+
create: (state) => buildDecorations3(state, options, viewRef),
|
|
6651
6665
|
update: (decorations2, tr) => {
|
|
6652
|
-
if (tr.docChanged) {
|
|
6653
|
-
return buildDecorations3(tr.state, options);
|
|
6666
|
+
if (tr.docChanged || tr.effects.some((effect) => effect.is(labelResolvedEffect))) {
|
|
6667
|
+
return buildDecorations3(tr.state, options, viewRef);
|
|
6654
6668
|
}
|
|
6655
6669
|
return decorations2.map(tr.changes);
|
|
6656
6670
|
},
|
|
6657
6671
|
provide: (field) => [
|
|
6658
|
-
|
|
6659
|
-
|
|
6672
|
+
EditorView27.decorations.from(field),
|
|
6673
|
+
EditorView27.atomicRanges.of((view) => view.state.field(field))
|
|
6660
6674
|
]
|
|
6675
|
+
}),
|
|
6676
|
+
ViewPlugin19.define((view) => {
|
|
6677
|
+
viewRef.current = view;
|
|
6678
|
+
return {
|
|
6679
|
+
destroy() {
|
|
6680
|
+
viewRef.current = void 0;
|
|
6681
|
+
}
|
|
6682
|
+
};
|
|
6661
6683
|
})
|
|
6662
6684
|
];
|
|
6663
6685
|
};
|
|
6664
|
-
var
|
|
6686
|
+
var resolveLabel = (db, dxnStr, viewRef) => {
|
|
6687
|
+
const dxn = DXN.tryParse(dxnStr);
|
|
6688
|
+
if (!dxn) {
|
|
6689
|
+
return;
|
|
6690
|
+
}
|
|
6691
|
+
const ref = db.makeRef(dxn);
|
|
6692
|
+
const target = ref.target;
|
|
6693
|
+
if (target) {
|
|
6694
|
+
return Entity.getLabel(target);
|
|
6695
|
+
}
|
|
6696
|
+
void ref.tryLoad().then(() => {
|
|
6697
|
+
viewRef.current?.dispatch({
|
|
6698
|
+
effects: labelResolvedEffect.of(void 0)
|
|
6699
|
+
});
|
|
6700
|
+
});
|
|
6701
|
+
};
|
|
6702
|
+
var buildDecorations3 = (state, options, viewRef) => {
|
|
6665
6703
|
const builder = new RangeSetBuilder6();
|
|
6666
6704
|
syntaxTree10(state).iterate({
|
|
6667
6705
|
enter: (node) => {
|
|
@@ -6673,8 +6711,13 @@ var buildDecorations3 = (state, options) => {
|
|
|
6673
6711
|
case "Link": {
|
|
6674
6712
|
const link = getLinkRef(state, node.node);
|
|
6675
6713
|
if (link) {
|
|
6714
|
+
const resolved = options.db ? resolveLabel(options.db, link.dxn, viewRef) : void 0;
|
|
6715
|
+
const displayLink = resolved ? {
|
|
6716
|
+
...link,
|
|
6717
|
+
label: resolved
|
|
6718
|
+
} : link;
|
|
6676
6719
|
builder.add(node.from, node.to, Decoration13.replace({
|
|
6677
|
-
widget: new PreviewInlineWidget(options,
|
|
6720
|
+
widget: new PreviewInlineWidget(options, displayLink),
|
|
6678
6721
|
side: 1
|
|
6679
6722
|
}));
|
|
6680
6723
|
}
|
|
@@ -6766,7 +6809,7 @@ var PreviewBlockWidget = class extends WidgetType8 {
|
|
|
6766
6809
|
};
|
|
6767
6810
|
|
|
6768
6811
|
// src/extensions/replacer.ts
|
|
6769
|
-
import { EditorView as
|
|
6812
|
+
import { EditorView as EditorView28 } from "@codemirror/view";
|
|
6770
6813
|
var defaultReplacements = [
|
|
6771
6814
|
{
|
|
6772
6815
|
input: "--",
|
|
@@ -6829,7 +6872,7 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6829
6872
|
const sortedReplacements = [
|
|
6830
6873
|
...replacements
|
|
6831
6874
|
].sort((a, b) => b.input.length - a.input.length);
|
|
6832
|
-
return
|
|
6875
|
+
return EditorView28.inputHandler.of((view, from, to, insert) => {
|
|
6833
6876
|
if (insert.length !== 1) {
|
|
6834
6877
|
return false;
|
|
6835
6878
|
}
|
|
@@ -6863,12 +6906,69 @@ var replacer = ({ replacements = defaultReplacements } = {}) => {
|
|
|
6863
6906
|
});
|
|
6864
6907
|
};
|
|
6865
6908
|
|
|
6909
|
+
// src/extensions/snippets.ts
|
|
6910
|
+
import { keymap as keymap12 } from "@codemirror/view";
|
|
6911
|
+
var defaultItems = [
|
|
6912
|
+
"hello world!",
|
|
6913
|
+
"this is a test.",
|
|
6914
|
+
"this is [DXOS](https://dxos.org)"
|
|
6915
|
+
];
|
|
6916
|
+
var snippets2 = ({ delay = 75, items = defaultItems } = {}) => {
|
|
6917
|
+
let timer;
|
|
6918
|
+
let index = 0;
|
|
6919
|
+
return [
|
|
6920
|
+
keymap12.of([
|
|
6921
|
+
{
|
|
6922
|
+
// Reset.
|
|
6923
|
+
key: "alt-meta-'",
|
|
6924
|
+
run: () => {
|
|
6925
|
+
clearTimeout(timer);
|
|
6926
|
+
index = 0;
|
|
6927
|
+
return true;
|
|
6928
|
+
}
|
|
6929
|
+
},
|
|
6930
|
+
{
|
|
6931
|
+
// Next snippet.
|
|
6932
|
+
// TODO(burdon): Press 1-9 to select snippet?
|
|
6933
|
+
key: "Shift-Meta-'",
|
|
6934
|
+
run: (view) => {
|
|
6935
|
+
clearTimeout(timer);
|
|
6936
|
+
const text = items[index++];
|
|
6937
|
+
if (index === items?.length) {
|
|
6938
|
+
index = 0;
|
|
6939
|
+
}
|
|
6940
|
+
let offset = 0;
|
|
6941
|
+
const insert = (delayMs = 0) => {
|
|
6942
|
+
timer = setTimeout(() => {
|
|
6943
|
+
const pos = view.state.selection.main.head;
|
|
6944
|
+
view.dispatch({
|
|
6945
|
+
changes: {
|
|
6946
|
+
from: pos,
|
|
6947
|
+
insert: text[offset++]
|
|
6948
|
+
},
|
|
6949
|
+
selection: {
|
|
6950
|
+
anchor: pos + 1
|
|
6951
|
+
}
|
|
6952
|
+
});
|
|
6953
|
+
if (offset < text.length) {
|
|
6954
|
+
insert(Math.random() * delay * (text[offset] === " " ? 2 : 1));
|
|
6955
|
+
}
|
|
6956
|
+
}, delayMs);
|
|
6957
|
+
};
|
|
6958
|
+
insert();
|
|
6959
|
+
return true;
|
|
6960
|
+
}
|
|
6961
|
+
}
|
|
6962
|
+
])
|
|
6963
|
+
];
|
|
6964
|
+
};
|
|
6965
|
+
|
|
6866
6966
|
// src/extensions/submit.ts
|
|
6867
6967
|
import { Prec as Prec6 } from "@codemirror/state";
|
|
6868
|
-
import { keymap as
|
|
6968
|
+
import { keymap as keymap13 } from "@codemirror/view";
|
|
6869
6969
|
var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
6870
6970
|
return [
|
|
6871
|
-
Prec6.highest(
|
|
6971
|
+
Prec6.highest(keymap13.of([
|
|
6872
6972
|
{
|
|
6873
6973
|
key: "Enter",
|
|
6874
6974
|
preventDefault: true,
|
|
@@ -6913,6 +7013,7 @@ var submit = ({ fireIfEmpty = false, onSubmit } = {}) => {
|
|
|
6913
7013
|
// src/extensions/tags/extended-markdown.ts
|
|
6914
7014
|
import { xmlLanguage } from "@codemirror/lang-xml";
|
|
6915
7015
|
import { parseMixed } from "@lezer/common";
|
|
7016
|
+
var escapeRegExpSource = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6916
7017
|
var extendedMarkdown = ({ registry } = {}) => {
|
|
6917
7018
|
return [
|
|
6918
7019
|
createMarkdownExtensions({
|
|
@@ -6924,13 +7025,65 @@ var extendedMarkdown = ({ registry } = {}) => {
|
|
|
6924
7025
|
{
|
|
6925
7026
|
name: "SetextHeading",
|
|
6926
7027
|
parse: () => false
|
|
6927
|
-
}
|
|
7028
|
+
},
|
|
7029
|
+
// Custom XML block parser that keeps registered tags as a single HTMLBlock
|
|
7030
|
+
// even when their content contains blank lines.
|
|
7031
|
+
...xmlBlockParsers(registry)
|
|
6928
7032
|
]
|
|
6929
7033
|
}
|
|
6930
7034
|
]
|
|
6931
7035
|
})
|
|
6932
7036
|
];
|
|
6933
7037
|
};
|
|
7038
|
+
var xmlBlockParsers = (registry) => {
|
|
7039
|
+
const customTags = Object.keys(registry ?? {});
|
|
7040
|
+
if (customTags.length === 0) {
|
|
7041
|
+
return [];
|
|
7042
|
+
}
|
|
7043
|
+
const tagPattern = customTags.map(escapeRegExpSource).join("|");
|
|
7044
|
+
const selfClosePattern = new RegExp(`^\\s*<(${tagPattern})(\\s[^>]*)?\\/>\\s*$`);
|
|
7045
|
+
const openPattern = new RegExp(`^\\s*<(${tagPattern})(\\s[^>]*)?\\/?>`);
|
|
7046
|
+
return [
|
|
7047
|
+
{
|
|
7048
|
+
name: "XMLBlock",
|
|
7049
|
+
before: "HTMLBlock",
|
|
7050
|
+
parse: (cx, line) => {
|
|
7051
|
+
const match = openPattern.exec(line.text);
|
|
7052
|
+
if (!match) {
|
|
7053
|
+
return false;
|
|
7054
|
+
}
|
|
7055
|
+
if (selfClosePattern.test(line.text)) {
|
|
7056
|
+
const end2 = cx.lineStart + line.text.length;
|
|
7057
|
+
cx.addElement(cx.elt("HTMLBlock", cx.lineStart, end2));
|
|
7058
|
+
cx.nextLine();
|
|
7059
|
+
return true;
|
|
7060
|
+
}
|
|
7061
|
+
if (match[0].trimEnd().endsWith("/>")) {
|
|
7062
|
+
return false;
|
|
7063
|
+
}
|
|
7064
|
+
const tagName = match[1];
|
|
7065
|
+
const closeTag = `</${tagName}>`;
|
|
7066
|
+
const start = cx.lineStart;
|
|
7067
|
+
if (line.text.includes(closeTag)) {
|
|
7068
|
+
cx.addElement(cx.elt("HTMLBlock", start, start + line.text.length));
|
|
7069
|
+
cx.nextLine();
|
|
7070
|
+
return true;
|
|
7071
|
+
}
|
|
7072
|
+
let end = cx.lineStart + line.text.length;
|
|
7073
|
+
while (cx.nextLine()) {
|
|
7074
|
+
end = cx.lineStart + line.text.length;
|
|
7075
|
+
if (line.text.includes(closeTag)) {
|
|
7076
|
+
cx.addElement(cx.elt("HTMLBlock", start, end));
|
|
7077
|
+
cx.nextLine();
|
|
7078
|
+
return true;
|
|
7079
|
+
}
|
|
7080
|
+
}
|
|
7081
|
+
cx.addElement(cx.elt("HTMLBlock", start, end));
|
|
7082
|
+
return true;
|
|
7083
|
+
}
|
|
7084
|
+
}
|
|
7085
|
+
];
|
|
7086
|
+
};
|
|
6934
7087
|
var mixedParser = (registry) => {
|
|
6935
7088
|
const customTags = Object.keys(registry ?? {});
|
|
6936
7089
|
const tagPattern = new RegExp(`<(${customTags.join("|")})`);
|
|
@@ -6964,219 +7117,793 @@ var mixedParser = (registry) => {
|
|
|
6964
7117
|
});
|
|
6965
7118
|
};
|
|
6966
7119
|
|
|
6967
|
-
// src/extensions/tags/
|
|
6968
|
-
import { StateEffect as
|
|
6969
|
-
import { Decoration as Decoration14, EditorView as
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
var
|
|
6973
|
-
var
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
7120
|
+
// src/extensions/tags/fader.ts
|
|
7121
|
+
import { StateEffect as StateEffect10, StateField as StateField12 } from "@codemirror/state";
|
|
7122
|
+
import { Decoration as Decoration14, EditorView as EditorView29, ViewPlugin as ViewPlugin20 } from "@codemirror/view";
|
|
7123
|
+
var DEFAULT_REMOVAL_DELAY = 5e3;
|
|
7124
|
+
var DEFAULT_COALESCE_WINDOW = 100;
|
|
7125
|
+
var CLEANUP_INTERVAL = 1e3;
|
|
7126
|
+
var fader = (options = {}) => {
|
|
7127
|
+
const removalDelay = DEFAULT_REMOVAL_DELAY;
|
|
7128
|
+
const coalesceWindow = options.coalesce ?? DEFAULT_COALESCE_WINDOW;
|
|
7129
|
+
let lastCount = -1;
|
|
7130
|
+
const log12 = (expiries) => {
|
|
7131
|
+
if (expiries.length !== lastCount) {
|
|
7132
|
+
lastCount = expiries.length;
|
|
7133
|
+
}
|
|
7134
|
+
};
|
|
7135
|
+
const dequeue = StateEffect10.define();
|
|
7136
|
+
const fadeField = StateField12.define({
|
|
7137
|
+
create: () => ({
|
|
7138
|
+
decorations: Decoration14.none,
|
|
7139
|
+
expiries: [],
|
|
7140
|
+
batchStart: 0
|
|
7141
|
+
}),
|
|
7142
|
+
update: ({ decorations: decorations2, expiries, batchStart }, tr) => {
|
|
6984
7143
|
for (const effect of tr.effects) {
|
|
6985
|
-
if (effect.is(
|
|
6986
|
-
|
|
7144
|
+
if (effect.is(dequeue)) {
|
|
7145
|
+
const now2 = effect.value;
|
|
7146
|
+
let removeCount = 0;
|
|
7147
|
+
while (removeCount < expiries.length && expiries[removeCount] <= now2) {
|
|
7148
|
+
removeCount++;
|
|
7149
|
+
}
|
|
7150
|
+
if (removeCount > 0) {
|
|
7151
|
+
expiries = expiries.slice(removeCount);
|
|
7152
|
+
let skipped = 0;
|
|
7153
|
+
decorations2 = decorations2.update({
|
|
7154
|
+
filter: () => {
|
|
7155
|
+
if (skipped < removeCount) {
|
|
7156
|
+
skipped++;
|
|
7157
|
+
return false;
|
|
7158
|
+
}
|
|
7159
|
+
return true;
|
|
7160
|
+
}
|
|
7161
|
+
});
|
|
7162
|
+
}
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
7165
|
+
if (!tr.docChanged) {
|
|
7166
|
+
log12(expiries);
|
|
7167
|
+
return {
|
|
7168
|
+
decorations: decorations2,
|
|
7169
|
+
expiries,
|
|
7170
|
+
batchStart
|
|
7171
|
+
};
|
|
7172
|
+
}
|
|
7173
|
+
let isReset = tr.state.doc.length === 0;
|
|
7174
|
+
if (!isReset && tr.startState.doc.length > 0) {
|
|
7175
|
+
tr.changes.iterChanges((fromA, toA) => {
|
|
7176
|
+
if (fromA === 0 && toA === tr.startState.doc.length) {
|
|
7177
|
+
isReset = true;
|
|
7178
|
+
}
|
|
7179
|
+
});
|
|
7180
|
+
}
|
|
7181
|
+
if (isReset) {
|
|
7182
|
+
log12([]);
|
|
7183
|
+
return {
|
|
7184
|
+
decorations: Decoration14.none,
|
|
7185
|
+
expiries: [],
|
|
7186
|
+
batchStart: 0
|
|
7187
|
+
};
|
|
7188
|
+
}
|
|
7189
|
+
const now = Date.now();
|
|
7190
|
+
const add = [];
|
|
7191
|
+
tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
|
|
7192
|
+
if (toA === tr.startState.doc.length && inserted.length > 0) {
|
|
7193
|
+
add.push({
|
|
7194
|
+
from: fromB,
|
|
7195
|
+
to: toB
|
|
7196
|
+
});
|
|
7197
|
+
}
|
|
7198
|
+
});
|
|
7199
|
+
if (add.length > 0) {
|
|
7200
|
+
const canCoalesce = expiries.length > 0 && batchStart > 0 && now - batchStart < coalesceWindow;
|
|
7201
|
+
if (canCoalesce) {
|
|
7202
|
+
let lastFrom = -1;
|
|
7203
|
+
let lastTo = -1;
|
|
7204
|
+
decorations2.between(0, tr.state.doc.length, (from, to) => {
|
|
7205
|
+
lastFrom = from;
|
|
7206
|
+
lastTo = to;
|
|
7207
|
+
});
|
|
7208
|
+
if (lastFrom >= 0) {
|
|
7209
|
+
decorations2 = decorations2.update({
|
|
7210
|
+
filter: (from, to) => !(from === lastFrom && to === lastTo)
|
|
7211
|
+
});
|
|
7212
|
+
const mergedFrom = Math.min(lastFrom, add[0].from);
|
|
7213
|
+
const mergedTo = add[add.length - 1].to;
|
|
7214
|
+
decorations2 = decorations2.update({
|
|
7215
|
+
add: [
|
|
7216
|
+
Decoration14.mark({
|
|
7217
|
+
class: "cm-fader"
|
|
7218
|
+
}).range(mergedFrom, mergedTo)
|
|
7219
|
+
]
|
|
7220
|
+
});
|
|
7221
|
+
expiries = [
|
|
7222
|
+
...expiries.slice(0, -1),
|
|
7223
|
+
now + removalDelay
|
|
7224
|
+
];
|
|
7225
|
+
}
|
|
7226
|
+
} else {
|
|
7227
|
+
batchStart = now;
|
|
7228
|
+
expiries = [
|
|
7229
|
+
...expiries,
|
|
7230
|
+
now + removalDelay
|
|
7231
|
+
];
|
|
7232
|
+
decorations2 = decorations2.update({
|
|
7233
|
+
add: add.map(({ from, to }) => Decoration14.mark({
|
|
7234
|
+
class: "cm-fader"
|
|
7235
|
+
}).range(from, to))
|
|
7236
|
+
});
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
log12(expiries);
|
|
7240
|
+
return {
|
|
7241
|
+
decorations: decorations2,
|
|
7242
|
+
expiries,
|
|
7243
|
+
batchStart
|
|
7244
|
+
};
|
|
7245
|
+
},
|
|
7246
|
+
provide: (f) => EditorView29.decorations.from(f, (value) => value.decorations)
|
|
7247
|
+
});
|
|
7248
|
+
const cleanup = ViewPlugin20.fromClass(class {
|
|
7249
|
+
view;
|
|
7250
|
+
#timer;
|
|
7251
|
+
constructor(view) {
|
|
7252
|
+
this.view = view;
|
|
7253
|
+
this.#schedule();
|
|
7254
|
+
}
|
|
7255
|
+
update() {
|
|
7256
|
+
this.#schedule();
|
|
7257
|
+
}
|
|
7258
|
+
#schedule() {
|
|
7259
|
+
const { expiries } = this.view.state.field(fadeField);
|
|
7260
|
+
if (expiries.length === 0) {
|
|
7261
|
+
clearTimeout(this.#timer);
|
|
7262
|
+
this.#timer = void 0;
|
|
7263
|
+
return;
|
|
7264
|
+
}
|
|
7265
|
+
if (this.#timer !== void 0) {
|
|
7266
|
+
return;
|
|
7267
|
+
}
|
|
7268
|
+
const delay = Math.max(CLEANUP_INTERVAL, expiries[0] - Date.now());
|
|
7269
|
+
this.#timer = setTimeout(() => {
|
|
7270
|
+
this.#timer = void 0;
|
|
7271
|
+
this.view.dispatch({
|
|
7272
|
+
effects: dequeue.of(Date.now())
|
|
7273
|
+
});
|
|
7274
|
+
}, delay);
|
|
7275
|
+
}
|
|
7276
|
+
destroy() {
|
|
7277
|
+
clearTimeout(this.#timer);
|
|
7278
|
+
}
|
|
7279
|
+
});
|
|
7280
|
+
return [
|
|
7281
|
+
fadeField,
|
|
7282
|
+
cleanup,
|
|
7283
|
+
EditorView29.theme({
|
|
7284
|
+
".cm-fader": {
|
|
7285
|
+
animation: "fader 1s ease-out forwards"
|
|
7286
|
+
},
|
|
7287
|
+
"@keyframes fader": {
|
|
7288
|
+
"0%": {
|
|
7289
|
+
textShadow: "0 0 16px rgba(100, 200, 255, 1), 0 0 32px rgba(100, 200, 255, 0.6)"
|
|
7290
|
+
},
|
|
7291
|
+
"100%": {}
|
|
7292
|
+
}
|
|
7293
|
+
})
|
|
7294
|
+
];
|
|
7295
|
+
};
|
|
7296
|
+
|
|
7297
|
+
// src/extensions/tags/typewriter.ts
|
|
7298
|
+
import { Annotation as Annotation3, ChangeSet as ChangeSet2, EditorState as EditorState3, StateEffect as StateEffect11, StateField as StateField13 } from "@codemirror/state";
|
|
7299
|
+
import { Decoration as Decoration15, EditorView as EditorView30, ViewPlugin as ViewPlugin21, WidgetType as WidgetType9 } from "@codemirror/view";
|
|
7300
|
+
import { Domino as Domino3 } from "@dxos/ui";
|
|
7301
|
+
var typewriterBypass = Annotation3.define();
|
|
7302
|
+
var typewriterDrainingEffect = StateEffect11.define();
|
|
7303
|
+
var CURSOR_LINGER = 3e3;
|
|
7304
|
+
var FRAME_BUDGET_MS = 4;
|
|
7305
|
+
var CHARS_PER_FRAME = 5;
|
|
7306
|
+
var FLUSH_THRESHOLD = 2e3;
|
|
7307
|
+
var COMPACT_HEAD_THRESHOLD = 4096;
|
|
7308
|
+
var typewriter = (options = {}) => {
|
|
7309
|
+
const streamingTags = options.streamingTags ?? /* @__PURE__ */ new Set();
|
|
7310
|
+
const flushThreshold = options.flushThreshold ?? FLUSH_THRESHOLD;
|
|
7311
|
+
const frameBudgetMs = options.frameBudgetMs ?? FRAME_BUDGET_MS;
|
|
7312
|
+
const charsPerFrame = options.charsPerFrame ?? CHARS_PER_FRAME;
|
|
7313
|
+
const suppressAppend = StateEffect11.define();
|
|
7314
|
+
const insertChunk = StateEffect11.define();
|
|
7315
|
+
const bufferField = StateField13.define({
|
|
7316
|
+
create: () => ({
|
|
7317
|
+
text: "",
|
|
7318
|
+
head: 0,
|
|
7319
|
+
insertAt: 0
|
|
7320
|
+
}),
|
|
7321
|
+
update: (value, tr) => {
|
|
7322
|
+
let { text, head, insertAt } = value;
|
|
7323
|
+
for (const effect of tr.effects) {
|
|
7324
|
+
if (effect.is(suppressAppend)) {
|
|
7325
|
+
if (text.length === head) {
|
|
7326
|
+
insertAt = effect.value.from;
|
|
7327
|
+
}
|
|
7328
|
+
text += effect.value.text;
|
|
7329
|
+
}
|
|
7330
|
+
if (effect.is(insertChunk)) {
|
|
7331
|
+
head += effect.value.text.length;
|
|
7332
|
+
insertAt = effect.value.from + effect.value.text.length;
|
|
7333
|
+
if (head >= COMPACT_HEAD_THRESHOLD || head > 0 && head * 2 >= text.length) {
|
|
7334
|
+
text = text.slice(head);
|
|
7335
|
+
head = 0;
|
|
7336
|
+
}
|
|
6987
7337
|
}
|
|
6988
7338
|
}
|
|
6989
7339
|
if (tr.docChanged) {
|
|
6990
|
-
|
|
7340
|
+
let isReset = tr.state.doc.length === 0;
|
|
7341
|
+
if (!isReset && tr.startState.doc.length > 0) {
|
|
7342
|
+
tr.changes.iterChanges((fromA, toA) => {
|
|
7343
|
+
if (fromA === 0 && toA === tr.startState.doc.length) {
|
|
7344
|
+
isReset = true;
|
|
7345
|
+
}
|
|
7346
|
+
});
|
|
7347
|
+
}
|
|
7348
|
+
if (isReset) {
|
|
7349
|
+
return {
|
|
7350
|
+
text: "",
|
|
7351
|
+
head: 0,
|
|
7352
|
+
insertAt: 0
|
|
7353
|
+
};
|
|
7354
|
+
}
|
|
7355
|
+
if (!tr.effects.some((effect) => effect.is(insertChunk))) {
|
|
7356
|
+
insertAt = tr.changes.mapPos(Math.min(insertAt, tr.startState.doc.length));
|
|
7357
|
+
}
|
|
6991
7358
|
}
|
|
6992
|
-
return
|
|
7359
|
+
return {
|
|
7360
|
+
text,
|
|
7361
|
+
head,
|
|
7362
|
+
insertAt
|
|
7363
|
+
};
|
|
6993
7364
|
}
|
|
6994
7365
|
});
|
|
6995
|
-
const
|
|
7366
|
+
const filter = EditorState3.transactionFilter.of((tr) => {
|
|
7367
|
+
if (!tr.docChanged) {
|
|
7368
|
+
return tr;
|
|
7369
|
+
}
|
|
7370
|
+
if (tr.annotation(typewriterBypass) || tr.effects.some((effect) => effect.is(insertChunk))) {
|
|
7371
|
+
return tr;
|
|
7372
|
+
}
|
|
7373
|
+
let appendedText = "";
|
|
7374
|
+
let appendFrom = -1;
|
|
7375
|
+
let isAppendOnly = true;
|
|
7376
|
+
tr.changes.iterChanges((fromA, toA, _fromB, _toB, inserted) => {
|
|
7377
|
+
if (toA === tr.startState.doc.length && fromA === toA && inserted.length > 0) {
|
|
7378
|
+
appendedText += inserted.sliceString(0);
|
|
7379
|
+
if (appendFrom === -1) {
|
|
7380
|
+
appendFrom = fromA;
|
|
7381
|
+
}
|
|
7382
|
+
} else {
|
|
7383
|
+
isAppendOnly = false;
|
|
7384
|
+
}
|
|
7385
|
+
});
|
|
7386
|
+
if (!isAppendOnly || appendedText.length === 0) {
|
|
7387
|
+
return tr;
|
|
7388
|
+
}
|
|
7389
|
+
return {
|
|
7390
|
+
changes: ChangeSet2.empty(tr.startState.doc.length),
|
|
7391
|
+
effects: suppressAppend.of({
|
|
7392
|
+
from: appendFrom,
|
|
7393
|
+
text: appendedText
|
|
7394
|
+
})
|
|
7395
|
+
};
|
|
7396
|
+
});
|
|
7397
|
+
const drainPlugin = ViewPlugin21.fromClass(class {
|
|
6996
7398
|
view;
|
|
6997
|
-
|
|
7399
|
+
_raf;
|
|
7400
|
+
_activeStreamTag = null;
|
|
6998
7401
|
constructor(view) {
|
|
6999
7402
|
this.view = view;
|
|
7000
7403
|
}
|
|
7001
7404
|
update(update2) {
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7405
|
+
const { text, head } = update2.state.field(bufferField);
|
|
7406
|
+
const pending = text.length - head;
|
|
7407
|
+
if (pending === 0) {
|
|
7408
|
+
this._activeStreamTag = null;
|
|
7409
|
+
}
|
|
7410
|
+
if (pending > 0 && this._raf === void 0) {
|
|
7411
|
+
this._start();
|
|
7009
7412
|
}
|
|
7010
7413
|
}
|
|
7414
|
+
_start() {
|
|
7415
|
+
queueMicrotask(() => {
|
|
7416
|
+
this.view.dispatch({
|
|
7417
|
+
effects: typewriterDrainingEffect.of(true),
|
|
7418
|
+
annotations: typewriterBypass.of(true)
|
|
7419
|
+
});
|
|
7420
|
+
});
|
|
7421
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7422
|
+
}
|
|
7423
|
+
_tick = () => {
|
|
7424
|
+
const { text, head, insertAt } = this.view.state.field(bufferField);
|
|
7425
|
+
const pending = text.length - head;
|
|
7426
|
+
if (pending === 0) {
|
|
7427
|
+
this.view.dispatch({
|
|
7428
|
+
effects: typewriterDrainingEffect.of(false),
|
|
7429
|
+
annotations: typewriterBypass.of(true)
|
|
7430
|
+
});
|
|
7431
|
+
this._raf = void 0;
|
|
7432
|
+
return;
|
|
7433
|
+
}
|
|
7434
|
+
if (pending > flushThreshold) {
|
|
7435
|
+
const chunk = text.slice(head);
|
|
7436
|
+
this._activeStreamTag = null;
|
|
7437
|
+
this.view.dispatch({
|
|
7438
|
+
changes: {
|
|
7439
|
+
from: insertAt,
|
|
7440
|
+
insert: chunk
|
|
7441
|
+
},
|
|
7442
|
+
effects: insertChunk.of({
|
|
7443
|
+
from: insertAt,
|
|
7444
|
+
text: chunk
|
|
7445
|
+
})
|
|
7446
|
+
});
|
|
7447
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7448
|
+
return;
|
|
7449
|
+
}
|
|
7450
|
+
const startTime = performance.now();
|
|
7451
|
+
let pos = head;
|
|
7452
|
+
let activeTag = this._activeStreamTag;
|
|
7453
|
+
let charsEmitted = 0;
|
|
7454
|
+
while (pos < text.length && performance.now() - startTime < frameBudgetMs) {
|
|
7455
|
+
const result = flushable(text, pos, streamingTags, activeTag);
|
|
7456
|
+
if (result.count === 0) {
|
|
7457
|
+
break;
|
|
7458
|
+
}
|
|
7459
|
+
if (charsEmitted > 0 && charsEmitted + result.count > charsPerFrame) {
|
|
7460
|
+
break;
|
|
7461
|
+
}
|
|
7462
|
+
if (result.enterTag) {
|
|
7463
|
+
activeTag = result.enterTag;
|
|
7464
|
+
}
|
|
7465
|
+
if (result.exitTag) {
|
|
7466
|
+
activeTag = null;
|
|
7467
|
+
}
|
|
7468
|
+
pos += result.count;
|
|
7469
|
+
charsEmitted += result.count;
|
|
7470
|
+
}
|
|
7471
|
+
const totalCount = pos - head;
|
|
7472
|
+
if (totalCount > 0) {
|
|
7473
|
+
const chunk = text.slice(head, head + totalCount);
|
|
7474
|
+
this._activeStreamTag = activeTag;
|
|
7475
|
+
this.view.dispatch({
|
|
7476
|
+
changes: {
|
|
7477
|
+
from: insertAt,
|
|
7478
|
+
insert: chunk
|
|
7479
|
+
},
|
|
7480
|
+
effects: insertChunk.of({
|
|
7481
|
+
from: insertAt,
|
|
7482
|
+
text: chunk
|
|
7483
|
+
})
|
|
7484
|
+
});
|
|
7485
|
+
}
|
|
7486
|
+
this._raf = requestAnimationFrame(this._tick);
|
|
7487
|
+
};
|
|
7011
7488
|
destroy() {
|
|
7012
|
-
|
|
7489
|
+
if (this._raf !== void 0) {
|
|
7490
|
+
cancelAnimationFrame(this._raf);
|
|
7491
|
+
}
|
|
7013
7492
|
}
|
|
7014
7493
|
});
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7494
|
+
return [
|
|
7495
|
+
bufferField,
|
|
7496
|
+
filter,
|
|
7497
|
+
drainPlugin,
|
|
7498
|
+
options.cursor && typewriterCursor(bufferField)
|
|
7499
|
+
].filter(Boolean);
|
|
7500
|
+
};
|
|
7501
|
+
var typewriterCursor = (bufferField) => {
|
|
7502
|
+
const hideCursor = StateEffect11.define();
|
|
7503
|
+
const visibilityField = StateField13.define({
|
|
7504
|
+
create: () => ({
|
|
7505
|
+
visible: false,
|
|
7506
|
+
insertAt: 0,
|
|
7507
|
+
lastNonWsAt: 0
|
|
7508
|
+
}),
|
|
7509
|
+
update: (value, tr) => {
|
|
7510
|
+
const { text, head, insertAt } = tr.state.field(bufferField);
|
|
7511
|
+
const pending = text.length - head;
|
|
7512
|
+
if (pending > 0) {
|
|
7513
|
+
let lastNonWsAt = tr.changes.mapPos(Math.min(value.lastNonWsAt, tr.startState.doc.length));
|
|
7514
|
+
if (tr.docChanged) {
|
|
7515
|
+
tr.changes.iterChanges((_fromA, _toA, _fromB, _toB, inserted) => {
|
|
7516
|
+
const chunk = inserted.sliceString(0);
|
|
7517
|
+
if (chunk.trim().length > 0) {
|
|
7518
|
+
lastNonWsAt = _fromB + chunk.length;
|
|
7519
|
+
}
|
|
7520
|
+
});
|
|
7521
|
+
}
|
|
7522
|
+
return {
|
|
7523
|
+
visible: true,
|
|
7524
|
+
insertAt,
|
|
7525
|
+
lastNonWsAt
|
|
7526
|
+
};
|
|
7021
7527
|
}
|
|
7022
|
-
const
|
|
7023
|
-
|
|
7024
|
-
|
|
7528
|
+
for (const effect of tr.effects) {
|
|
7529
|
+
if (effect.is(hideCursor)) {
|
|
7530
|
+
return {
|
|
7531
|
+
...value,
|
|
7532
|
+
visible: false
|
|
7533
|
+
};
|
|
7534
|
+
}
|
|
7535
|
+
}
|
|
7536
|
+
return value;
|
|
7537
|
+
}
|
|
7538
|
+
});
|
|
7539
|
+
const decorationField = StateField13.define({
|
|
7540
|
+
create: () => Decoration15.none,
|
|
7541
|
+
update: (_decorations, tr) => {
|
|
7542
|
+
const { visible, insertAt, lastNonWsAt } = tr.state.field(visibilityField);
|
|
7543
|
+
if (!visible) {
|
|
7544
|
+
return Decoration15.none;
|
|
7545
|
+
}
|
|
7546
|
+
const { text, head } = tr.state.field(bufferField);
|
|
7547
|
+
const cursorAt = text.length > head ? insertAt : lastNonWsAt;
|
|
7548
|
+
const pos = Math.min(cursorAt, tr.state.doc.length);
|
|
7549
|
+
return Decoration15.set([
|
|
7550
|
+
Decoration15.widget({
|
|
7025
7551
|
widget: new CursorWidget(),
|
|
7026
7552
|
side: 1
|
|
7027
|
-
}).range(
|
|
7553
|
+
}).range(pos)
|
|
7028
7554
|
]);
|
|
7029
7555
|
},
|
|
7030
|
-
provide: (
|
|
7556
|
+
provide: (field) => EditorView30.decorations.from(field)
|
|
7557
|
+
});
|
|
7558
|
+
const timerPlugin = ViewPlugin21.fromClass(class {
|
|
7559
|
+
view;
|
|
7560
|
+
_timer;
|
|
7561
|
+
constructor(view) {
|
|
7562
|
+
this.view = view;
|
|
7563
|
+
}
|
|
7564
|
+
update(update2) {
|
|
7565
|
+
const { text, head } = update2.state.field(bufferField);
|
|
7566
|
+
const { visible } = update2.state.field(visibilityField);
|
|
7567
|
+
const pending = text.length - head;
|
|
7568
|
+
if (pending > 0) {
|
|
7569
|
+
clearTimeout(this._timer);
|
|
7570
|
+
this._timer = void 0;
|
|
7571
|
+
} else if (visible && this._timer === void 0) {
|
|
7572
|
+
this._timer = setTimeout(() => {
|
|
7573
|
+
this.view.dispatch({
|
|
7574
|
+
effects: hideCursor.of(null)
|
|
7575
|
+
});
|
|
7576
|
+
this._timer = void 0;
|
|
7577
|
+
}, CURSOR_LINGER);
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
destroy() {
|
|
7581
|
+
clearTimeout(this._timer);
|
|
7582
|
+
}
|
|
7031
7583
|
});
|
|
7032
7584
|
return [
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7585
|
+
visibilityField,
|
|
7586
|
+
decorationField,
|
|
7587
|
+
timerPlugin
|
|
7036
7588
|
];
|
|
7037
7589
|
};
|
|
7038
|
-
var CursorWidget = class extends WidgetType9 {
|
|
7590
|
+
var CursorWidget = class _CursorWidget extends WidgetType9 {
|
|
7591
|
+
// All instances are interchangeable — let CM reuse the existing DOM across drips so
|
|
7592
|
+
// the blink animation isn't restarted on every transaction.
|
|
7593
|
+
eq(other) {
|
|
7594
|
+
return other instanceof _CursorWidget;
|
|
7595
|
+
}
|
|
7039
7596
|
toDOM() {
|
|
7040
|
-
const inner = Domino3.of("span").text("\
|
|
7041
|
-
animation: "blink
|
|
7597
|
+
const inner = Domino3.of("span").text("\u2217").style({
|
|
7598
|
+
animation: "blink 1s infinite",
|
|
7599
|
+
animationDelay: "250ms"
|
|
7042
7600
|
});
|
|
7043
7601
|
return Domino3.of("span").style({
|
|
7044
7602
|
opacity: "0.8"
|
|
7045
|
-
}).
|
|
7603
|
+
}).append(inner).root;
|
|
7046
7604
|
}
|
|
7047
7605
|
};
|
|
7048
|
-
var
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7606
|
+
var OPENING_TAG_NAME = /^<([a-zA-Z][\w-]*)/;
|
|
7607
|
+
var TAG_NAME_PROBE = 64;
|
|
7608
|
+
var escapeRegExpSource2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7609
|
+
var flushable = (buffer, start, streamingTags, activeStreamTag) => {
|
|
7610
|
+
if (start >= buffer.length) {
|
|
7611
|
+
return {
|
|
7612
|
+
count: 0
|
|
7613
|
+
};
|
|
7614
|
+
}
|
|
7615
|
+
if (activeStreamTag) {
|
|
7616
|
+
const closeTag = `</${activeStreamTag}>`;
|
|
7617
|
+
if (buffer.startsWith(closeTag, start)) {
|
|
7618
|
+
return {
|
|
7619
|
+
count: closeTag.length,
|
|
7620
|
+
exitTag: true
|
|
7621
|
+
};
|
|
7622
|
+
}
|
|
7623
|
+
if (buffer[start] === "<") {
|
|
7624
|
+
return {
|
|
7625
|
+
count: xmlElementLength(buffer, start)
|
|
7626
|
+
};
|
|
7627
|
+
}
|
|
7628
|
+
return {
|
|
7629
|
+
count: 1
|
|
7630
|
+
};
|
|
7631
|
+
}
|
|
7632
|
+
const ch = buffer[start];
|
|
7633
|
+
if (ch === "<") {
|
|
7634
|
+
const probe = buffer.slice(start, start + TAG_NAME_PROBE);
|
|
7635
|
+
const nameMatch = probe.match(OPENING_TAG_NAME);
|
|
7636
|
+
if (nameMatch && streamingTags.has(nameMatch[1])) {
|
|
7637
|
+
const close = buffer.indexOf(">", start);
|
|
7638
|
+
if (close === -1) {
|
|
7639
|
+
return {
|
|
7640
|
+
count: 0
|
|
7641
|
+
};
|
|
7067
7642
|
}
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
isReset = true;
|
|
7073
|
-
}
|
|
7074
|
-
});
|
|
7643
|
+
if (buffer[close - 1] === "/") {
|
|
7644
|
+
return {
|
|
7645
|
+
count: close + 1 - start
|
|
7646
|
+
};
|
|
7075
7647
|
}
|
|
7076
|
-
|
|
7077
|
-
|
|
7648
|
+
return {
|
|
7649
|
+
count: close + 1 - start,
|
|
7650
|
+
enterTag: nameMatch[1]
|
|
7651
|
+
};
|
|
7652
|
+
}
|
|
7653
|
+
return {
|
|
7654
|
+
count: xmlElementLength(buffer, start)
|
|
7655
|
+
};
|
|
7656
|
+
}
|
|
7657
|
+
if (ch === "!" && buffer.length > start + 1 && buffer[start + 1] === "[") {
|
|
7658
|
+
return {
|
|
7659
|
+
count: linkLength(buffer, start, start + 1)
|
|
7660
|
+
};
|
|
7661
|
+
}
|
|
7662
|
+
if (ch === "[") {
|
|
7663
|
+
return {
|
|
7664
|
+
count: linkLength(buffer, start, start)
|
|
7665
|
+
};
|
|
7666
|
+
}
|
|
7667
|
+
return {
|
|
7668
|
+
count: 1
|
|
7669
|
+
};
|
|
7670
|
+
};
|
|
7671
|
+
var xmlElementLength = (buffer, start = 0) => {
|
|
7672
|
+
const close = buffer.indexOf(">", start);
|
|
7673
|
+
if (close === -1) {
|
|
7674
|
+
return 0;
|
|
7675
|
+
}
|
|
7676
|
+
if (buffer[close - 1] === "/") {
|
|
7677
|
+
return close + 1 - start;
|
|
7678
|
+
}
|
|
7679
|
+
if (buffer[start + 1] === "/") {
|
|
7680
|
+
return close + 1 - start;
|
|
7681
|
+
}
|
|
7682
|
+
const probe = buffer.slice(start, start + TAG_NAME_PROBE);
|
|
7683
|
+
const nameMatch = probe.match(OPENING_TAG_NAME);
|
|
7684
|
+
if (!nameMatch) {
|
|
7685
|
+
return 1;
|
|
7686
|
+
}
|
|
7687
|
+
const tagName = nameMatch[1];
|
|
7688
|
+
let depth = 0;
|
|
7689
|
+
const tagPattern = new RegExp(`<(/?)${escapeRegExpSource2(tagName)}(\\s[^>]*)?>`, "g");
|
|
7690
|
+
tagPattern.lastIndex = start;
|
|
7691
|
+
let match;
|
|
7692
|
+
while ((match = tagPattern.exec(buffer)) !== null) {
|
|
7693
|
+
const isSelfClosing = match[0].endsWith("/>");
|
|
7694
|
+
const isClosing = match[1] === "/";
|
|
7695
|
+
if (isSelfClosing) {
|
|
7696
|
+
if (depth === 0) {
|
|
7697
|
+
return match.index + match[0].length - start;
|
|
7698
|
+
}
|
|
7699
|
+
} else if (isClosing) {
|
|
7700
|
+
depth--;
|
|
7701
|
+
if (depth === 0) {
|
|
7702
|
+
return match.index + match[0].length - start;
|
|
7078
7703
|
}
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7704
|
+
} else {
|
|
7705
|
+
depth++;
|
|
7706
|
+
}
|
|
7707
|
+
}
|
|
7708
|
+
return 0;
|
|
7709
|
+
};
|
|
7710
|
+
var linkLength = (buffer, start, bracketAt) => {
|
|
7711
|
+
const bracketClose = buffer.indexOf("]", bracketAt + 1);
|
|
7712
|
+
if (bracketClose === -1) {
|
|
7713
|
+
return 0;
|
|
7714
|
+
}
|
|
7715
|
+
if (bracketClose + 1 >= buffer.length) {
|
|
7716
|
+
return 0;
|
|
7717
|
+
}
|
|
7718
|
+
if (buffer[bracketClose + 1] !== "(") {
|
|
7719
|
+
return 1;
|
|
7720
|
+
}
|
|
7721
|
+
const parenClose = buffer.indexOf(")", bracketClose + 2);
|
|
7722
|
+
if (parenClose === -1) {
|
|
7723
|
+
return 0;
|
|
7724
|
+
}
|
|
7725
|
+
return parenClose + 1 - start;
|
|
7726
|
+
};
|
|
7727
|
+
|
|
7728
|
+
// src/extensions/tags/xml-block-decoration.ts
|
|
7729
|
+
import { xmlLanguage as xmlLanguage2 } from "@codemirror/lang-xml";
|
|
7730
|
+
import { Decoration as Decoration16, ViewPlugin as ViewPlugin22 } from "@codemirror/view";
|
|
7731
|
+
var xmlBlockDecoration = ({ tag, lineClass, contentClass, hideTags }) => {
|
|
7732
|
+
const lineDecoration = lineClass ? Decoration16.line({
|
|
7733
|
+
class: lineClass
|
|
7734
|
+
}) : void 0;
|
|
7735
|
+
const contentDecoration = contentClass ? Decoration16.mark({
|
|
7736
|
+
class: contentClass
|
|
7737
|
+
}) : void 0;
|
|
7738
|
+
const hideDecoration = hideTags ? Decoration16.replace({}) : void 0;
|
|
7739
|
+
const buildDecorations5 = (view) => {
|
|
7740
|
+
const text = view.state.sliceDoc(0, view.state.doc.length);
|
|
7741
|
+
if (!text.includes(`<${tag}`)) {
|
|
7742
|
+
return Decoration16.none;
|
|
7743
|
+
}
|
|
7744
|
+
const tree = xmlLanguage2.parser.parse(text);
|
|
7745
|
+
const ranges = [];
|
|
7746
|
+
tree.iterate({
|
|
7747
|
+
enter: (node) => {
|
|
7748
|
+
if (node.type.name !== "Element") {
|
|
7082
7749
|
return;
|
|
7083
7750
|
}
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7751
|
+
const openTag = node.node.getChild("OpenTag");
|
|
7752
|
+
const closeTag = node.node.getChild("CloseTag") ?? node.node.getChild("MismatchedCloseTag");
|
|
7753
|
+
const tagNameNode = openTag?.getChild("TagName");
|
|
7754
|
+
if (!openTag || !tagNameNode) {
|
|
7755
|
+
return;
|
|
7088
7756
|
}
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7757
|
+
if (text.slice(tagNameNode.from, tagNameNode.to) !== tag) {
|
|
7758
|
+
return;
|
|
7759
|
+
}
|
|
7760
|
+
const contentFrom = openTag.to;
|
|
7761
|
+
const contentTo = closeTag?.from ?? node.node.to;
|
|
7762
|
+
if (hideDecoration) {
|
|
7763
|
+
ranges.push(hideDecoration.range(openTag.from, openTag.to));
|
|
7764
|
+
if (closeTag) {
|
|
7765
|
+
ranges.push(hideDecoration.range(closeTag.from, closeTag.to));
|
|
7766
|
+
}
|
|
7767
|
+
}
|
|
7768
|
+
if (contentDecoration && contentFrom < contentTo) {
|
|
7769
|
+
ranges.push(contentDecoration.range(contentFrom, contentTo));
|
|
7770
|
+
}
|
|
7771
|
+
if (lineDecoration && contentFrom <= view.state.doc.length) {
|
|
7772
|
+
let pos = contentFrom;
|
|
7773
|
+
while (pos <= contentTo && pos <= view.state.doc.length) {
|
|
7774
|
+
const line = view.state.doc.lineAt(pos);
|
|
7775
|
+
ranges.push(lineDecoration.range(line.from));
|
|
7776
|
+
if (line.to >= contentTo) {
|
|
7777
|
+
break;
|
|
7778
|
+
}
|
|
7779
|
+
pos = line.to + 1;
|
|
7780
|
+
}
|
|
7781
|
+
}
|
|
7782
|
+
}
|
|
7783
|
+
});
|
|
7784
|
+
return Decoration16.set(ranges, true);
|
|
7785
|
+
};
|
|
7786
|
+
return ViewPlugin22.fromClass(class {
|
|
7787
|
+
decorations;
|
|
7100
7788
|
constructor(view) {
|
|
7101
|
-
this.
|
|
7789
|
+
this.decorations = buildDecorations5(view);
|
|
7102
7790
|
}
|
|
7103
7791
|
update(update2) {
|
|
7104
|
-
if (
|
|
7105
|
-
|
|
7792
|
+
if (update2.docChanged) {
|
|
7793
|
+
this.decorations = buildDecorations5(update2.view);
|
|
7106
7794
|
}
|
|
7107
|
-
|
|
7108
|
-
|
|
7795
|
+
}
|
|
7796
|
+
}, {
|
|
7797
|
+
decorations: (instance) => instance.decorations
|
|
7798
|
+
});
|
|
7799
|
+
};
|
|
7800
|
+
|
|
7801
|
+
// src/extensions/tags/xml-formatting.ts
|
|
7802
|
+
import { xmlLanguage as xmlLanguage3 } from "@codemirror/lang-xml";
|
|
7803
|
+
import { Decoration as Decoration17, EditorView as EditorView31, ViewPlugin as ViewPlugin23 } from "@codemirror/view";
|
|
7804
|
+
var XML_TAG_NODES = /* @__PURE__ */ new Set([
|
|
7805
|
+
"OpenTag",
|
|
7806
|
+
"CloseTag",
|
|
7807
|
+
"SelfClosingTag",
|
|
7808
|
+
"MismatchedCloseTag"
|
|
7809
|
+
]);
|
|
7810
|
+
var xmlElementMark = Decoration17.mark({
|
|
7811
|
+
class: "cm-xml-element"
|
|
7812
|
+
});
|
|
7813
|
+
var xmlTagMark = Decoration17.mark({
|
|
7814
|
+
class: "cm-xml-tag"
|
|
7815
|
+
});
|
|
7816
|
+
var xmlContentMark = Decoration17.mark({
|
|
7817
|
+
class: "cm-xml-content"
|
|
7818
|
+
});
|
|
7819
|
+
var xmlFormatting = ({ skip } = {}) => {
|
|
7820
|
+
const skipSet = skip && skip.length > 0 ? new Set(skip) : void 0;
|
|
7821
|
+
const buildDecorations5 = (view) => {
|
|
7822
|
+
const text = view.state.sliceDoc(0, view.state.doc.length);
|
|
7823
|
+
if (!text.includes("<")) {
|
|
7824
|
+
return Decoration17.none;
|
|
7825
|
+
}
|
|
7826
|
+
const tagNameAt = (node) => text.slice(node.from, node.to);
|
|
7827
|
+
const tree = xmlLanguage3.parser.parse(text);
|
|
7828
|
+
const ranges = [];
|
|
7829
|
+
tree.iterate({
|
|
7830
|
+
enter: (node) => {
|
|
7831
|
+
const name = node.type.name;
|
|
7832
|
+
if (name === "SelfClosingTag" && node.from < node.to) {
|
|
7833
|
+
if (skipSet) {
|
|
7834
|
+
const tagNameNode = node.node.getChild("TagName");
|
|
7835
|
+
if (tagNameNode && skipSet.has(tagNameAt(tagNameNode))) {
|
|
7836
|
+
return false;
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7839
|
+
ranges.push(xmlElementMark.range(node.from, node.to));
|
|
7840
|
+
ranges.push(xmlTagMark.range(node.from, node.to));
|
|
7841
|
+
return;
|
|
7842
|
+
}
|
|
7843
|
+
if (XML_TAG_NODES.has(name) && node.from < node.to) {
|
|
7844
|
+
ranges.push(xmlTagMark.range(node.from, node.to));
|
|
7109
7845
|
return;
|
|
7110
7846
|
}
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7847
|
+
if (name === "Element" && node.from < node.to) {
|
|
7848
|
+
const openTag = node.node.getChild("OpenTag");
|
|
7849
|
+
if (openTag && skipSet) {
|
|
7850
|
+
const tagNameNode = openTag.getChild("TagName");
|
|
7851
|
+
if (tagNameNode && skipSet.has(tagNameAt(tagNameNode))) {
|
|
7852
|
+
return false;
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7855
|
+
const closeTag = node.node.getChild("CloseTag") ?? node.node.getChild("MismatchedCloseTag");
|
|
7856
|
+
ranges.push(xmlElementMark.range(node.from, node.to));
|
|
7857
|
+
if (openTag && closeTag && openTag.to < closeTag.from) {
|
|
7858
|
+
ranges.push(xmlContentMark.range(openTag.to, closeTag.from));
|
|
7859
|
+
}
|
|
7114
7860
|
}
|
|
7115
|
-
const totalDelay = FADE_IN_DURATION + removalDelay;
|
|
7116
|
-
const id = setTimeout(() => {
|
|
7117
|
-
this.view.dispatch({
|
|
7118
|
-
effects: removeDecoration.of({
|
|
7119
|
-
from: fromB,
|
|
7120
|
-
to: toB
|
|
7121
|
-
})
|
|
7122
|
-
});
|
|
7123
|
-
this._timers.delete(key);
|
|
7124
|
-
}, totalDelay);
|
|
7125
|
-
this._timers.set(key, id);
|
|
7126
|
-
});
|
|
7127
|
-
}
|
|
7128
|
-
destroy() {
|
|
7129
|
-
for (const id of this._timers.values()) {
|
|
7130
|
-
clearTimeout(id);
|
|
7131
7861
|
}
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
}
|
|
7862
|
+
});
|
|
7863
|
+
return Decoration17.set(ranges, true);
|
|
7864
|
+
};
|
|
7135
7865
|
return [
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
},
|
|
7145
|
-
"@keyframes fade-in": {
|
|
7146
|
-
"0%": {
|
|
7147
|
-
opacity: "0"
|
|
7148
|
-
},
|
|
7149
|
-
"80%": {
|
|
7150
|
-
opacity: "1"
|
|
7151
|
-
},
|
|
7152
|
-
"100%": {
|
|
7153
|
-
opacity: "0.8"
|
|
7866
|
+
ViewPlugin23.fromClass(class {
|
|
7867
|
+
decorations;
|
|
7868
|
+
constructor(view) {
|
|
7869
|
+
this.decorations = buildDecorations5(view);
|
|
7870
|
+
}
|
|
7871
|
+
update(update2) {
|
|
7872
|
+
if (update2.docChanged) {
|
|
7873
|
+
this.decorations = buildDecorations5(update2.view);
|
|
7154
7874
|
}
|
|
7155
7875
|
}
|
|
7876
|
+
}, {
|
|
7877
|
+
decorations: (instance) => instance.decorations
|
|
7878
|
+
}),
|
|
7879
|
+
EditorView31.baseTheme({
|
|
7880
|
+
".cm-xml-element": {
|
|
7881
|
+
backgroundColor: "var(--color-active-surface)",
|
|
7882
|
+
borderRadius: "0.25rem",
|
|
7883
|
+
padding: "0.25rem"
|
|
7884
|
+
},
|
|
7885
|
+
".cm-xml-tag": {
|
|
7886
|
+
color: "var(--color-blue-500)",
|
|
7887
|
+
fontFamily: "var(--font-mono)"
|
|
7888
|
+
},
|
|
7889
|
+
".cm-xml-content": {}
|
|
7156
7890
|
})
|
|
7157
7891
|
];
|
|
7158
7892
|
};
|
|
7159
7893
|
|
|
7160
7894
|
// src/extensions/tags/xml-tags.ts
|
|
7161
7895
|
import { syntaxTree as syntaxTree11 } from "@codemirror/language";
|
|
7162
|
-
import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as
|
|
7163
|
-
import { Decoration as
|
|
7896
|
+
import { Prec as Prec7, RangeSetBuilder as RangeSetBuilder7, StateEffect as StateEffect12, StateField as StateField14 } from "@codemirror/state";
|
|
7897
|
+
import { Decoration as Decoration18, EditorView as EditorView32, ViewPlugin as ViewPlugin24, WidgetType as WidgetType10, keymap as keymap14 } from "@codemirror/view";
|
|
7164
7898
|
import { invariant as invariant7 } from "@dxos/invariant";
|
|
7165
7899
|
import { log as log11 } from "@dxos/log";
|
|
7900
|
+
import { Domino as Domino4 } from "@dxos/ui";
|
|
7166
7901
|
|
|
7167
7902
|
// src/extensions/tags/xml-util.ts
|
|
7168
7903
|
import { invariant as invariant6 } from "@dxos/invariant";
|
|
7169
7904
|
var __dxlog_file16 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-util.ts";
|
|
7170
7905
|
var nodeToJson = (state, node) => {
|
|
7171
|
-
invariant6(node.type.name === "Element", "Node is not an Element", {
|
|
7172
|
-
F: __dxlog_file16,
|
|
7173
|
-
L: 18,
|
|
7174
|
-
S: void 0,
|
|
7175
|
-
A: [
|
|
7176
|
-
"node.type.name === 'Element'",
|
|
7177
|
-
"'Node is not an Element'"
|
|
7178
|
-
]
|
|
7179
|
-
});
|
|
7906
|
+
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'"] });
|
|
7180
7907
|
const openTag = node.node.getChild("OpenTag") || node.node.getChild("SelfClosingTag");
|
|
7181
7908
|
if (openTag) {
|
|
7182
7909
|
const tagName = openTag.getChild("TagName");
|
|
@@ -7208,13 +7935,23 @@ var nodeToJson = (state, node) => {
|
|
|
7208
7935
|
if (node.type.name === "Element" && openTag.type.name !== "SelfClosingTag") {
|
|
7209
7936
|
const children = [];
|
|
7210
7937
|
let child = node.node.firstChild;
|
|
7938
|
+
const appendText = (raw) => {
|
|
7939
|
+
if (raw.length === 0) {
|
|
7940
|
+
return;
|
|
7941
|
+
}
|
|
7942
|
+
const last = children[children.length - 1];
|
|
7943
|
+
if (typeof last === "string") {
|
|
7944
|
+
children[children.length - 1] = last + raw;
|
|
7945
|
+
} else {
|
|
7946
|
+
children.push(raw);
|
|
7947
|
+
}
|
|
7948
|
+
};
|
|
7211
7949
|
while (child) {
|
|
7212
7950
|
if (child.type.name !== "OpenTag" && child.type.name !== "CloseTag") {
|
|
7213
7951
|
if (child.type.name === "Text") {
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
}
|
|
7952
|
+
appendText(state.doc.sliceString(child.from, child.to));
|
|
7953
|
+
} else if (child.type.name === "EntityReference" || child.type.name === "CharacterReference") {
|
|
7954
|
+
appendText(decodeXmlEntity(state.doc.sliceString(child.from, child.to)));
|
|
7218
7955
|
} else if (child.type.name === "Element") {
|
|
7219
7956
|
const data = nodeToJson(state, child);
|
|
7220
7957
|
if (data) {
|
|
@@ -7224,26 +7961,63 @@ var nodeToJson = (state, node) => {
|
|
|
7224
7961
|
}
|
|
7225
7962
|
child = child.nextSibling;
|
|
7226
7963
|
}
|
|
7964
|
+
if (children.length > 0 && typeof children[0] === "string") {
|
|
7965
|
+
children[0] = children[0].trimStart();
|
|
7966
|
+
}
|
|
7227
7967
|
if (children.length > 0) {
|
|
7228
|
-
|
|
7968
|
+
const lastIndex = children.length - 1;
|
|
7969
|
+
const last = children[lastIndex];
|
|
7970
|
+
if (typeof last === "string") {
|
|
7971
|
+
children[lastIndex] = last.trimEnd();
|
|
7972
|
+
}
|
|
7973
|
+
}
|
|
7974
|
+
const trimmed = children.filter((value) => typeof value !== "string" || value.length > 0);
|
|
7975
|
+
if (trimmed.length > 0) {
|
|
7976
|
+
tag.children = trimmed;
|
|
7229
7977
|
}
|
|
7230
7978
|
}
|
|
7231
7979
|
return tag;
|
|
7232
7980
|
}
|
|
7233
7981
|
};
|
|
7982
|
+
var XML_NAMED_ENTITIES = {
|
|
7983
|
+
"<": "<",
|
|
7984
|
+
">": ">",
|
|
7985
|
+
"&": "&",
|
|
7986
|
+
""": '"',
|
|
7987
|
+
"'": "'"
|
|
7988
|
+
};
|
|
7989
|
+
var decodeXmlEntity = (raw) => {
|
|
7990
|
+
const named = XML_NAMED_ENTITIES[raw];
|
|
7991
|
+
if (named !== void 0) {
|
|
7992
|
+
return named;
|
|
7993
|
+
}
|
|
7994
|
+
const numeric = /^&#(x?)([0-9a-fA-F]+);$/.exec(raw);
|
|
7995
|
+
if (numeric) {
|
|
7996
|
+
const code = parseInt(numeric[2], numeric[1] ? 16 : 10);
|
|
7997
|
+
if (Number.isFinite(code)) {
|
|
7998
|
+
try {
|
|
7999
|
+
return String.fromCodePoint(code);
|
|
8000
|
+
} catch {
|
|
8001
|
+
}
|
|
8002
|
+
}
|
|
8003
|
+
}
|
|
8004
|
+
return raw;
|
|
8005
|
+
};
|
|
7234
8006
|
|
|
7235
8007
|
// src/extensions/tags/xml-tags.ts
|
|
7236
8008
|
var __dxlog_file17 = "/__w/dxos/dxos/packages/ui/ui-editor/src/extensions/tags/xml-tags.ts";
|
|
7237
|
-
var navigatePreviousEffect =
|
|
7238
|
-
var navigateNextEffect =
|
|
8009
|
+
var navigatePreviousEffect = StateEffect12.define();
|
|
8010
|
+
var navigateNextEffect = StateEffect12.define();
|
|
7239
8011
|
var getXmlTextChild = (children) => {
|
|
7240
8012
|
const child = children?.[0];
|
|
7241
8013
|
return typeof child === "string" ? child : null;
|
|
7242
8014
|
};
|
|
7243
|
-
var
|
|
7244
|
-
var
|
|
7245
|
-
var
|
|
7246
|
-
var
|
|
8015
|
+
var xmlWidgetId = (explicit, fallback) => typeof explicit === "string" && explicit.length > 0 ? explicit : fallback;
|
|
8016
|
+
var escapeRegExpSource3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8017
|
+
var xmlTagContextEffect = StateEffect12.define();
|
|
8018
|
+
var xmlTagResetEffect = StateEffect12.define();
|
|
8019
|
+
var xmlTagUpdateEffect = StateEffect12.define();
|
|
8020
|
+
var widgetContextStateField = StateField14.define({
|
|
7247
8021
|
create: () => void 0,
|
|
7248
8022
|
update: (value, tr) => {
|
|
7249
8023
|
for (const effect of tr.effects) {
|
|
@@ -7254,7 +8028,7 @@ var widgetContextStateField = StateField13.define({
|
|
|
7254
8028
|
return value;
|
|
7255
8029
|
}
|
|
7256
8030
|
});
|
|
7257
|
-
var widgetStateMapStateField =
|
|
8031
|
+
var widgetStateMapStateField = StateField14.define({
|
|
7258
8032
|
create: () => ({}),
|
|
7259
8033
|
update: (map, tr) => {
|
|
7260
8034
|
for (const effect of tr.effects) {
|
|
@@ -7266,12 +8040,7 @@ var widgetStateMapStateField = StateField13.define({
|
|
|
7266
8040
|
log11("widget updated", {
|
|
7267
8041
|
id,
|
|
7268
8042
|
value
|
|
7269
|
-
}, {
|
|
7270
|
-
F: __dxlog_file17,
|
|
7271
|
-
L: 153,
|
|
7272
|
-
S: void 0,
|
|
7273
|
-
C: (f, a) => f(...a)
|
|
7274
|
-
});
|
|
8043
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 59, S: void 0 });
|
|
7275
8044
|
const state = typeof value === "function" ? value(map[id]) : value;
|
|
7276
8045
|
return {
|
|
7277
8046
|
...map,
|
|
@@ -7301,12 +8070,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7301
8070
|
log11("widget mounted", {
|
|
7302
8071
|
id: state.id,
|
|
7303
8072
|
tag: state.props._tag
|
|
7304
|
-
}, {
|
|
7305
|
-
F: __dxlog_file17,
|
|
7306
|
-
L: 206,
|
|
7307
|
-
S: void 0,
|
|
7308
|
-
C: (f, a) => f(...a)
|
|
7309
|
-
});
|
|
8073
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 101, S: void 0 });
|
|
7310
8074
|
widgets.set(state.id, state);
|
|
7311
8075
|
setWidgets?.([
|
|
7312
8076
|
...widgets.values()
|
|
@@ -7317,12 +8081,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7317
8081
|
log11("widget unmounted", {
|
|
7318
8082
|
id,
|
|
7319
8083
|
tag: state?.props._tag
|
|
7320
|
-
}, {
|
|
7321
|
-
F: __dxlog_file17,
|
|
7322
|
-
L: 212,
|
|
7323
|
-
S: void 0,
|
|
7324
|
-
C: (f, a) => f(...a)
|
|
7325
|
-
});
|
|
8084
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 112, S: void 0 });
|
|
7326
8085
|
widgets.delete(id);
|
|
7327
8086
|
setWidgets?.([
|
|
7328
8087
|
...widgets.values()
|
|
@@ -7331,7 +8090,7 @@ var createWidgetMap = (setWidgets) => {
|
|
|
7331
8090
|
};
|
|
7332
8091
|
return notifier;
|
|
7333
8092
|
};
|
|
7334
|
-
var keyHandlers =
|
|
8093
|
+
var keyHandlers = keymap14.of([
|
|
7335
8094
|
{
|
|
7336
8095
|
key: "Mod-ArrowUp",
|
|
7337
8096
|
run: (view) => {
|
|
@@ -7352,7 +8111,7 @@ var keyHandlers = keymap13.of([
|
|
|
7352
8111
|
}
|
|
7353
8112
|
]);
|
|
7354
8113
|
var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
7355
|
-
return
|
|
8114
|
+
return EditorView32.updateListener.of((update2) => {
|
|
7356
8115
|
update2.transactions.forEach((transaction) => {
|
|
7357
8116
|
for (const effect of transaction.effects) {
|
|
7358
8117
|
if (effect.is(navigatePreviousEffect)) {
|
|
@@ -7437,7 +8196,7 @@ var createNavigationEffectPlugin = (widgetDecorationsField, bookmarks2) => {
|
|
|
7437
8196
|
});
|
|
7438
8197
|
});
|
|
7439
8198
|
};
|
|
7440
|
-
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) =>
|
|
8199
|
+
var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin24.fromClass(class {
|
|
7441
8200
|
update(update2) {
|
|
7442
8201
|
const widgetStateMap = update2.state.field(widgetStateMapStateField);
|
|
7443
8202
|
const { decorations: decorations2 } = update2.state.field(widgetDecorationsField);
|
|
@@ -7464,14 +8223,14 @@ var createWidgetUpdatePlugin = (widgetDecorationsField, notifier) => ViewPlugin1
|
|
|
7464
8223
|
}
|
|
7465
8224
|
}
|
|
7466
8225
|
});
|
|
7467
|
-
var createWidgetDecorationsField = (registry = {}, notifier) =>
|
|
8226
|
+
var createWidgetDecorationsField = (registry = {}, notifier) => StateField14.define({
|
|
7468
8227
|
create: (state) => {
|
|
7469
8228
|
return buildDecorations4(state, {
|
|
7470
8229
|
from: 0,
|
|
7471
8230
|
to: state.doc.length
|
|
7472
8231
|
}, registry, notifier);
|
|
7473
8232
|
},
|
|
7474
|
-
update: ({ from, decorations: decorations2 }, tr) => {
|
|
8233
|
+
update: ({ from, streamingFrom, decorations: decorations2 }, tr) => {
|
|
7475
8234
|
for (const effect of tr.effects) {
|
|
7476
8235
|
if (effect.is(xmlTagResetEffect)) {
|
|
7477
8236
|
if (tr.docChanged) {
|
|
@@ -7482,7 +8241,7 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7482
8241
|
}
|
|
7483
8242
|
return {
|
|
7484
8243
|
from: 0,
|
|
7485
|
-
decorations:
|
|
8244
|
+
decorations: Decoration18.none
|
|
7486
8245
|
};
|
|
7487
8246
|
}
|
|
7488
8247
|
}
|
|
@@ -7493,24 +8252,23 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7493
8252
|
log11("document reset", {
|
|
7494
8253
|
from,
|
|
7495
8254
|
to: state.doc.length
|
|
7496
|
-
}, {
|
|
7497
|
-
F: __dxlog_file17,
|
|
7498
|
-
L: 374,
|
|
7499
|
-
S: void 0,
|
|
7500
|
-
C: (f, a) => f(...a)
|
|
7501
|
-
});
|
|
8255
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 298, S: void 0 });
|
|
7502
8256
|
return buildDecorations4(state, {
|
|
7503
8257
|
from: 0,
|
|
7504
8258
|
to: state.doc.length
|
|
7505
8259
|
}, registry, notifier);
|
|
7506
8260
|
} else {
|
|
8261
|
+
const rebuildFrom = streamingFrom ?? from;
|
|
7507
8262
|
const result = buildDecorations4(state, {
|
|
7508
|
-
from,
|
|
8263
|
+
from: rebuildFrom,
|
|
7509
8264
|
to: state.doc.length
|
|
7510
8265
|
}, registry, notifier);
|
|
7511
8266
|
return {
|
|
7512
8267
|
from: result.from,
|
|
8268
|
+
streamingFrom: result.streamingFrom,
|
|
7513
8269
|
decorations: decorations2.update({
|
|
8270
|
+
// Remove old streaming decorations — they are rebuilt each tick.
|
|
8271
|
+
filter: (_f, _t, deco) => !deco.spec.streaming,
|
|
7514
8272
|
add: decorationSetToArray(result.decorations)
|
|
7515
8273
|
})
|
|
7516
8274
|
};
|
|
@@ -7518,12 +8276,13 @@ var createWidgetDecorationsField = (registry = {}, notifier) => StateField13.def
|
|
|
7518
8276
|
}
|
|
7519
8277
|
return {
|
|
7520
8278
|
from,
|
|
8279
|
+
streamingFrom,
|
|
7521
8280
|
decorations: decorations2
|
|
7522
8281
|
};
|
|
7523
8282
|
},
|
|
7524
8283
|
provide: (field) => [
|
|
7525
|
-
|
|
7526
|
-
|
|
8284
|
+
EditorView32.decorations.from(field, (v) => v.decorations),
|
|
8285
|
+
EditorView32.atomicRanges.of((view) => view.state.field(field).decorations || Decoration18.none)
|
|
7527
8286
|
]
|
|
7528
8287
|
});
|
|
7529
8288
|
var buildDecorations4 = (state, range, registry, notifier) => {
|
|
@@ -7534,10 +8293,11 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7534
8293
|
if (!tree || tree.type.name === "Program" && tree.length === 0) {
|
|
7535
8294
|
return {
|
|
7536
8295
|
from: range.from,
|
|
7537
|
-
decorations:
|
|
8296
|
+
decorations: Decoration18.none
|
|
7538
8297
|
};
|
|
7539
8298
|
}
|
|
7540
8299
|
let last = range.from;
|
|
8300
|
+
let streamingFrom;
|
|
7541
8301
|
tree.iterate({
|
|
7542
8302
|
from: range.from,
|
|
7543
8303
|
to: range.to,
|
|
@@ -7550,21 +8310,26 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7550
8310
|
if (args) {
|
|
7551
8311
|
const def = registry[args._tag];
|
|
7552
8312
|
if (def) {
|
|
8313
|
+
if (def.streaming && !node.node.getChild("CloseTag")) {
|
|
8314
|
+
return false;
|
|
8315
|
+
}
|
|
7553
8316
|
const { block, factory, Component } = def;
|
|
7554
|
-
const widgetState = args.id ? widgetStateMap[args.id] : void 0;
|
|
7555
8317
|
const nodeRange = {
|
|
7556
8318
|
from: node.node.from,
|
|
7557
8319
|
to: node.node.to
|
|
7558
8320
|
};
|
|
8321
|
+
const widgetId = xmlWidgetId(args.id, def.streaming ? `cm-xml-${nodeRange.from}` : `cm-xml-${nodeRange.from}-${nodeRange.to}`);
|
|
8322
|
+
const widgetState = widgetStateMap[widgetId];
|
|
7559
8323
|
const props = {
|
|
7560
|
-
|
|
8324
|
+
id: widgetId,
|
|
7561
8325
|
range: nodeRange,
|
|
8326
|
+
context,
|
|
7562
8327
|
...args,
|
|
7563
8328
|
...widgetState
|
|
7564
8329
|
};
|
|
7565
|
-
const widget = factory ? factory(props) : Component ?
|
|
8330
|
+
const widget = factory ? factory(props) ?? void 0 : Component ? new PlaceholderWidget2(widgetId, Component, props, notifier) : void 0;
|
|
7566
8331
|
if (widget) {
|
|
7567
|
-
builder.add(nodeRange.from, nodeRange.to,
|
|
8332
|
+
builder.add(nodeRange.from, nodeRange.to, Decoration18.replace({
|
|
7568
8333
|
widget,
|
|
7569
8334
|
block,
|
|
7570
8335
|
atomic: true,
|
|
@@ -7576,20 +8341,72 @@ var buildDecorations4 = (state, range, registry, notifier) => {
|
|
|
7576
8341
|
}
|
|
7577
8342
|
}
|
|
7578
8343
|
} catch (err) {
|
|
7579
|
-
log11.catch(err, void 0, {
|
|
7580
|
-
F: __dxlog_file17,
|
|
7581
|
-
L: 459,
|
|
7582
|
-
S: void 0,
|
|
7583
|
-
C: (f, a) => f(...a)
|
|
7584
|
-
});
|
|
8344
|
+
log11.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 401, S: void 0 });
|
|
7585
8345
|
}
|
|
7586
8346
|
return false;
|
|
7587
8347
|
}
|
|
7588
8348
|
}
|
|
7589
8349
|
}
|
|
7590
8350
|
});
|
|
8351
|
+
const streamingTagNames = Object.entries(registry).filter(([, def]) => def.streaming).map(([name]) => name).sort((a, b) => b.length - a.length);
|
|
8352
|
+
if (streamingTagNames.length > 0) {
|
|
8353
|
+
const tailText = state.sliceDoc(range.from, range.to);
|
|
8354
|
+
const streamingPattern = streamingTagNames.map(escapeRegExpSource3).join("|");
|
|
8355
|
+
const tagPattern = new RegExp(`<(${streamingPattern})(\\s[^>]*)?>`, "g");
|
|
8356
|
+
let match;
|
|
8357
|
+
while ((match = tagPattern.exec(tailText)) !== null) {
|
|
8358
|
+
const tagName = match[1];
|
|
8359
|
+
const closeTag = `</${tagName}>`;
|
|
8360
|
+
const afterOpen = match.index + match[0].length;
|
|
8361
|
+
if (tailText.indexOf(closeTag, afterOpen) === -1) {
|
|
8362
|
+
const absoluteFrom = range.from + match.index;
|
|
8363
|
+
const contentFrom = range.from + afterOpen;
|
|
8364
|
+
const innerText = state.sliceDoc(contentFrom, range.to).trim();
|
|
8365
|
+
const def = registry[tagName];
|
|
8366
|
+
const props = {
|
|
8367
|
+
_tag: tagName,
|
|
8368
|
+
context,
|
|
8369
|
+
range: {
|
|
8370
|
+
from: absoluteFrom,
|
|
8371
|
+
to: range.to
|
|
8372
|
+
},
|
|
8373
|
+
children: innerText ? [
|
|
8374
|
+
innerText
|
|
8375
|
+
] : void 0
|
|
8376
|
+
};
|
|
8377
|
+
const attrPattern = /(\w+)="([^"]*)"/g;
|
|
8378
|
+
let attrMatch;
|
|
8379
|
+
while ((attrMatch = attrPattern.exec(match[0])) !== null) {
|
|
8380
|
+
props[attrMatch[1]] = attrMatch[2];
|
|
8381
|
+
}
|
|
8382
|
+
const widgetId = xmlWidgetId(props.id, `cm-xml-${absoluteFrom}`);
|
|
8383
|
+
const widgetState = widgetStateMap[widgetId];
|
|
8384
|
+
const mergedProps = {
|
|
8385
|
+
...props,
|
|
8386
|
+
id: widgetId,
|
|
8387
|
+
...widgetState
|
|
8388
|
+
};
|
|
8389
|
+
const widget = def.factory ? def.factory(mergedProps) ?? void 0 : def.Component ? new PlaceholderWidget2(widgetId, def.Component, mergedProps, notifier, true) : void 0;
|
|
8390
|
+
if (widget) {
|
|
8391
|
+
builder.add(absoluteFrom, range.to, Decoration18.replace({
|
|
8392
|
+
widget,
|
|
8393
|
+
block: def.block,
|
|
8394
|
+
atomic: true,
|
|
8395
|
+
inclusive: true,
|
|
8396
|
+
tag: tagName,
|
|
8397
|
+
streaming: true,
|
|
8398
|
+
contentFrom
|
|
8399
|
+
}));
|
|
8400
|
+
streamingFrom = absoluteFrom;
|
|
8401
|
+
last = absoluteFrom;
|
|
8402
|
+
}
|
|
8403
|
+
break;
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
7591
8407
|
return {
|
|
7592
8408
|
from: last,
|
|
8409
|
+
streamingFrom,
|
|
7593
8410
|
decorations: builder.finish()
|
|
7594
8411
|
};
|
|
7595
8412
|
};
|
|
@@ -7598,108 +8415,62 @@ var PlaceholderWidget2 = class extends WidgetType10 {
|
|
|
7598
8415
|
Component;
|
|
7599
8416
|
props;
|
|
7600
8417
|
notifier;
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
S: this,
|
|
7608
|
-
A: [
|
|
7609
|
-
"id",
|
|
7610
|
-
""
|
|
7611
|
-
]
|
|
7612
|
-
});
|
|
8418
|
+
streaming;
|
|
8419
|
+
#root = null;
|
|
8420
|
+
#view;
|
|
8421
|
+
constructor(id, Component, props, notifier, streaming) {
|
|
8422
|
+
super(), this.id = id, this.Component = Component, this.props = props, this.notifier = notifier, this.streaming = streaming;
|
|
8423
|
+
invariant7(id, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file17, L: 488, S: this, A: ["id", ""] });
|
|
7613
8424
|
}
|
|
7614
8425
|
get root() {
|
|
7615
|
-
return this
|
|
8426
|
+
return this.#root;
|
|
7616
8427
|
}
|
|
7617
8428
|
eq(other) {
|
|
8429
|
+
if (this.streaming) {
|
|
8430
|
+
return false;
|
|
8431
|
+
}
|
|
7618
8432
|
return this.id === other.id;
|
|
7619
8433
|
}
|
|
7620
8434
|
ignoreEvent() {
|
|
7621
8435
|
return true;
|
|
7622
8436
|
}
|
|
7623
|
-
toDOM(
|
|
7624
|
-
this
|
|
8437
|
+
toDOM(view) {
|
|
8438
|
+
this.#view = view;
|
|
8439
|
+
this.#root = Domino4.of("div").classNames("min-h-[24px]").root;
|
|
8440
|
+
const props = Object.assign({}, this.props, {
|
|
8441
|
+
view
|
|
8442
|
+
});
|
|
8443
|
+
this.notifier.mounted({
|
|
8444
|
+
id: this.id,
|
|
8445
|
+
root: this.#root,
|
|
8446
|
+
props,
|
|
8447
|
+
Component: this.Component
|
|
8448
|
+
});
|
|
8449
|
+
return this.#root;
|
|
8450
|
+
}
|
|
8451
|
+
updateDOM(dom) {
|
|
8452
|
+
this.#root = dom;
|
|
8453
|
+
const props = Object.assign({}, this.props, {
|
|
8454
|
+
view: this.#view
|
|
8455
|
+
});
|
|
7625
8456
|
this.notifier.mounted({
|
|
7626
8457
|
id: this.id,
|
|
7627
|
-
root: this
|
|
7628
|
-
props
|
|
8458
|
+
root: this.#root,
|
|
8459
|
+
props,
|
|
7629
8460
|
Component: this.Component
|
|
7630
8461
|
});
|
|
7631
|
-
return
|
|
8462
|
+
return true;
|
|
7632
8463
|
}
|
|
7633
8464
|
destroy(_dom) {
|
|
7634
8465
|
this.notifier.unmounted(this.id);
|
|
7635
|
-
this
|
|
8466
|
+
this.#root = null;
|
|
8467
|
+
this.#view = void 0;
|
|
7636
8468
|
}
|
|
7637
8469
|
};
|
|
7638
|
-
|
|
7639
|
-
// src/extensions/typewriter.ts
|
|
7640
|
-
import { keymap as keymap14 } from "@codemirror/view";
|
|
7641
|
-
var defaultItems = [
|
|
7642
|
-
"hello world!",
|
|
7643
|
-
"this is a test.",
|
|
7644
|
-
"this is [DXOS](https://dxos.org)"
|
|
7645
|
-
];
|
|
7646
|
-
var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
|
|
7647
|
-
let t;
|
|
7648
|
-
let idx = 0;
|
|
7649
|
-
return [
|
|
7650
|
-
keymap14.of([
|
|
7651
|
-
{
|
|
7652
|
-
// Reset.
|
|
7653
|
-
key: "alt-meta-'",
|
|
7654
|
-
run: () => {
|
|
7655
|
-
clearTimeout(t);
|
|
7656
|
-
idx = 0;
|
|
7657
|
-
return true;
|
|
7658
|
-
}
|
|
7659
|
-
},
|
|
7660
|
-
{
|
|
7661
|
-
// Next prompt.
|
|
7662
|
-
// TODO(burdon): Press 1-9 to select prompt?
|
|
7663
|
-
key: "Shift-Meta-'",
|
|
7664
|
-
run: (view) => {
|
|
7665
|
-
clearTimeout(t);
|
|
7666
|
-
const text = items[idx++];
|
|
7667
|
-
if (idx === items?.length) {
|
|
7668
|
-
idx = 0;
|
|
7669
|
-
}
|
|
7670
|
-
let i = 0;
|
|
7671
|
-
const insert = (d = 0) => {
|
|
7672
|
-
t = setTimeout(() => {
|
|
7673
|
-
const pos = view.state.selection.main.head;
|
|
7674
|
-
view.dispatch({
|
|
7675
|
-
changes: {
|
|
7676
|
-
from: pos,
|
|
7677
|
-
insert: text[i++]
|
|
7678
|
-
},
|
|
7679
|
-
selection: {
|
|
7680
|
-
anchor: pos + 1
|
|
7681
|
-
}
|
|
7682
|
-
});
|
|
7683
|
-
if (i < text.length) {
|
|
7684
|
-
insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
|
|
7685
|
-
}
|
|
7686
|
-
}, d);
|
|
7687
|
-
};
|
|
7688
|
-
insert();
|
|
7689
|
-
return true;
|
|
7690
|
-
}
|
|
7691
|
-
}
|
|
7692
|
-
])
|
|
7693
|
-
];
|
|
7694
|
-
};
|
|
7695
8470
|
export {
|
|
7696
8471
|
Cursor,
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
EditorState3 as EditorState,
|
|
7700
|
-
EditorView30 as EditorView,
|
|
7701
|
-
EditorViewMode,
|
|
7702
|
-
EditorViewModes,
|
|
8472
|
+
EditorState4 as EditorState,
|
|
8473
|
+
EditorView33 as EditorView,
|
|
7703
8474
|
Inline,
|
|
7704
8475
|
InputModeExtensions,
|
|
7705
8476
|
List,
|
|
@@ -7716,6 +8487,7 @@ export {
|
|
|
7716
8487
|
addStyle,
|
|
7717
8488
|
annotations,
|
|
7718
8489
|
autoScroll,
|
|
8490
|
+
autoScrollEffect,
|
|
7719
8491
|
autocomplete,
|
|
7720
8492
|
automerge,
|
|
7721
8493
|
awareness,
|
|
@@ -7729,6 +8501,7 @@ export {
|
|
|
7729
8501
|
commentClickedEffect,
|
|
7730
8502
|
comments,
|
|
7731
8503
|
commentsState,
|
|
8504
|
+
compactSlots,
|
|
7732
8505
|
convertTreeToJson,
|
|
7733
8506
|
createBasicExtensions,
|
|
7734
8507
|
createComment,
|
|
@@ -7752,12 +8525,12 @@ export {
|
|
|
7752
8525
|
defaultThemeSlots,
|
|
7753
8526
|
deleteItem,
|
|
7754
8527
|
documentId,
|
|
8528
|
+
documentSlots,
|
|
7755
8529
|
dropFile,
|
|
8530
|
+
editorClassNames,
|
|
7756
8531
|
editorInputMode,
|
|
7757
|
-
editorSlots,
|
|
7758
|
-
editorWidth,
|
|
7759
|
-
editorWithToolbarLayout,
|
|
7760
8532
|
extendedMarkdown,
|
|
8533
|
+
fader,
|
|
7761
8534
|
filterChars,
|
|
7762
8535
|
flattenRect,
|
|
7763
8536
|
focus,
|
|
@@ -7793,6 +8566,7 @@ export {
|
|
|
7793
8566
|
markdownTagsExtensions,
|
|
7794
8567
|
matchCompletion,
|
|
7795
8568
|
mention,
|
|
8569
|
+
mobileSlots,
|
|
7796
8570
|
modalStateEffect,
|
|
7797
8571
|
modalStateField,
|
|
7798
8572
|
moveItemDown,
|
|
@@ -7812,6 +8586,7 @@ export {
|
|
|
7812
8586
|
removeList,
|
|
7813
8587
|
removeStyle,
|
|
7814
8588
|
replacer,
|
|
8589
|
+
scrollPastEnd,
|
|
7815
8590
|
scrollThreadIntoView,
|
|
7816
8591
|
scrollToLine,
|
|
7817
8592
|
scroller,
|
|
@@ -7824,9 +8599,8 @@ export {
|
|
|
7824
8599
|
setSelection,
|
|
7825
8600
|
setStyle,
|
|
7826
8601
|
singleValueFacet,
|
|
7827
|
-
|
|
8602
|
+
snippets2 as snippets,
|
|
7828
8603
|
staticCompletion,
|
|
7829
|
-
streamer,
|
|
7830
8604
|
submit,
|
|
7831
8605
|
tabbable,
|
|
7832
8606
|
table,
|
|
@@ -7845,7 +8619,12 @@ export {
|
|
|
7845
8619
|
treeFacet,
|
|
7846
8620
|
typeahead,
|
|
7847
8621
|
typewriter,
|
|
8622
|
+
typewriterBypass,
|
|
8623
|
+
typewriterDrainingEffect,
|
|
7848
8624
|
wrapWithCatch,
|
|
8625
|
+
xmlBlockDecoration,
|
|
8626
|
+
xmlElementLength,
|
|
8627
|
+
xmlFormatting,
|
|
7849
8628
|
xmlTagContextEffect,
|
|
7850
8629
|
xmlTagResetEffect,
|
|
7851
8630
|
xmlTagUpdateEffect,
|