@dxos/react-ui-editor 0.8.4-main.b97322e → 0.8.4-main.dedc0f3
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 +2074 -888
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs.map +2 -2
- package/dist/lib/node-esm/index.mjs +2074 -888
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs.map +2 -2
- package/dist/types/src/components/Editor/Editor.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/util.d.ts +2 -2
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts +1 -1
- package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
- package/dist/types/src/components/Popover/CommandMenu.d.ts.map +1 -1
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts +2 -9
- package/dist/types/src/components/Popover/RefDropdownMenu.d.ts.map +1 -1
- package/dist/types/src/components/Popover/RefPopover.d.ts +20 -17
- package/dist/types/src/components/Popover/RefPopover.d.ts.map +1 -1
- package/dist/types/src/defaults.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts +20 -7
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts +9 -18
- package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +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/autoscroll.d.ts +10 -0
- package/dist/types/src/extensions/autoscroll.d.ts.map +1 -0
- package/dist/types/src/extensions/command/action.d.ts +1 -1
- package/dist/types/src/extensions/command/action.d.ts.map +1 -1
- package/dist/types/src/extensions/command/command-menu.d.ts +1 -1
- package/dist/types/src/extensions/command/command-menu.d.ts.map +1 -1
- package/dist/types/src/extensions/command/command.d.ts.map +1 -1
- package/dist/types/src/extensions/command/hint.d.ts +2 -7
- package/dist/types/src/extensions/command/hint.d.ts.map +1 -1
- package/dist/types/src/extensions/command/state.d.ts +1 -1
- package/dist/types/src/extensions/command/state.d.ts.map +1 -1
- package/dist/types/src/extensions/command/typeahead.d.ts.map +1 -1
- package/dist/types/src/extensions/command/useCommandMenu.d.ts +4 -4
- package/dist/types/src/extensions/command/useCommandMenu.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +1 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/dnd.d.ts.map +1 -1
- package/dist/types/src/extensions/factories.d.ts +2 -7
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/extensions/index.d.ts +2 -0
- package/dist/types/src/extensions/index.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 +8 -2
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts +1 -1
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts +9 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.test.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/outliner/outliner.d.ts +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 +2 -2
- package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -1
- package/dist/types/src/extensions/preview/preview.d.ts +3 -5
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -1
- package/dist/types/src/extensions/tags/extended-markdown.d.ts +10 -0
- package/dist/types/src/extensions/tags/extended-markdown.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts +2 -0
- package/dist/types/src/extensions/tags/extended-markdown.test.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/index.d.ts +4 -0
- package/dist/types/src/extensions/tags/index.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/streamer.d.ts +12 -0
- package/dist/types/src/extensions/tags/streamer.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts +71 -0
- package/dist/types/src/extensions/tags/xml-tags.d.ts.map +1 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts +10 -0
- package/dist/types/src/extensions/tags/xml-util.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
- package/dist/types/src/stories/Command.stories.d.ts +12 -4
- package/dist/types/src/stories/Command.stories.d.ts.map +1 -1
- package/dist/types/src/stories/CommandMenu.stories.d.ts +10 -3
- package/dist/types/src/stories/CommandMenu.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Comments.stories.d.ts +21 -9
- package/dist/types/src/stories/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/stories/EditorToolbar.stories.d.ts +39 -2
- package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Experimental.stories.d.ts +22 -12
- package/dist/types/src/stories/Experimental.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Markdown.stories.d.ts +32 -42
- package/dist/types/src/stories/Markdown.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Outliner.stories.d.ts +15 -20
- package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Preview.stories.d.ts +21 -6
- package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
- package/dist/types/src/stories/Tags.stories.d.ts +17 -0
- package/dist/types/src/stories/Tags.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TextEditor.stories.d.ts +38 -51
- package/dist/types/src/stories/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/components/EditorStory.d.ts +3 -6
- package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
- package/dist/types/src/styles/theme.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts +1 -0
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -1
- package/dist/types/src/types/types.d.ts +1 -1
- package/dist/types/src/util/cursor.d.ts.map +1 -1
- package/dist/types/src/util/debug.d.ts +1 -1
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/decorations.d.ts +4 -0
- package/dist/types/src/util/decorations.d.ts.map +1 -0
- package/dist/types/src/util/dom.d.ts +2 -12
- package/dist/types/src/util/dom.d.ts.map +1 -1
- package/dist/types/src/util/domino.d.ts +18 -0
- package/dist/types/src/util/domino.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/react.d.ts +1 -1
- package/dist/types/src/util/react.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +57 -51
- package/src/components/Editor/Editor.tsx +1 -1
- package/src/components/EditorToolbar/EditorToolbar.tsx +40 -30
- package/src/components/EditorToolbar/blocks.ts +21 -24
- package/src/components/EditorToolbar/formatting.ts +22 -25
- package/src/components/EditorToolbar/headings.ts +10 -5
- package/src/components/EditorToolbar/image.ts +8 -4
- package/src/components/EditorToolbar/lists.ts +16 -19
- package/src/components/EditorToolbar/search.ts +8 -4
- package/src/components/EditorToolbar/util.ts +16 -5
- package/src/components/EditorToolbar/view-mode.ts +11 -6
- package/src/components/Popover/CommandMenu.tsx +3 -3
- package/src/components/Popover/RefDropdownMenu.tsx +20 -16
- package/src/components/Popover/RefPopover.tsx +63 -45
- package/src/defaults.ts +5 -2
- package/src/extensions/autocomplete.ts +204 -54
- package/src/extensions/automerge/automerge.stories.tsx +25 -18
- package/src/extensions/automerge/automerge.ts +4 -3
- package/src/extensions/automerge/defs.ts +1 -1
- package/src/extensions/automerge/sync.ts +1 -1
- package/src/extensions/automerge/update-automerge.ts +1 -1
- package/src/extensions/autoscroll.ts +151 -0
- package/src/extensions/awareness/awareness.ts +2 -2
- package/src/extensions/command/action.ts +1 -1
- package/src/extensions/command/command-menu.ts +6 -5
- package/src/extensions/command/command.ts +3 -3
- package/src/extensions/command/floating-menu.ts +1 -1
- package/src/extensions/command/hint.ts +2 -1
- package/src/extensions/command/placeholder.ts +1 -1
- package/src/extensions/command/state.ts +4 -3
- package/src/extensions/command/typeahead.ts +2 -2
- package/src/extensions/command/useCommandMenu.ts +5 -4
- package/src/extensions/comments.ts +18 -13
- package/src/extensions/dnd.ts +1 -1
- package/src/extensions/factories.ts +9 -21
- package/src/extensions/folding.tsx +2 -2
- package/src/extensions/index.ts +2 -0
- package/src/extensions/markdown/action.ts +2 -1
- package/src/extensions/markdown/bundle.ts +25 -3
- package/src/extensions/markdown/changes.ts +1 -1
- package/src/extensions/markdown/decorate.ts +23 -14
- package/src/extensions/markdown/formatting.test.ts +6 -6
- package/src/extensions/markdown/formatting.ts +3 -3
- package/src/extensions/markdown/highlight.ts +1 -1
- package/src/extensions/markdown/image.ts +3 -4
- package/src/extensions/markdown/table.ts +7 -1
- package/src/extensions/mention.ts +1 -1
- package/src/extensions/outliner/outliner.test.ts +3 -2
- package/src/extensions/outliner/outliner.ts +5 -4
- package/src/extensions/outliner/selection.ts +1 -1
- package/src/extensions/outliner/tree.test.ts +2 -1
- package/src/extensions/outliner/tree.ts +2 -2
- package/src/extensions/preview/preview.ts +59 -59
- package/src/extensions/tags/extended-markdown.test.ts +261 -0
- package/src/extensions/tags/extended-markdown.ts +78 -0
- package/src/extensions/tags/index.ts +7 -0
- package/src/extensions/tags/streamer.ts +244 -0
- package/src/extensions/tags/xml-tags.ts +335 -0
- package/src/extensions/tags/xml-util.ts +94 -0
- package/src/hooks/useTextEditor.ts +3 -3
- package/src/stories/Command.stories.tsx +24 -31
- package/src/stories/CommandMenu.stories.tsx +23 -22
- package/src/stories/Comments.stories.tsx +10 -6
- package/src/stories/EditorToolbar.stories.tsx +8 -8
- package/src/stories/Experimental.stories.tsx +12 -8
- package/src/stories/Markdown.stories.tsx +21 -17
- package/src/stories/Outliner.stories.tsx +17 -14
- package/src/stories/Preview.stories.tsx +27 -26
- package/src/stories/Tags.stories.tsx +81 -0
- package/src/stories/TextEditor.stories.tsx +40 -34
- package/src/stories/components/EditorStory.tsx +9 -10
- package/src/styles/theme.ts +8 -6
- package/src/testing/util.ts +2 -0
- package/src/translations.ts +1 -1
- package/src/util/cursor.ts +2 -1
- package/src/util/debug.ts +2 -2
- package/src/util/decorations.ts +21 -0
- package/src/util/dom.ts +5 -27
- package/src/util/domino.ts +51 -0
- package/src/util/index.ts +2 -0
- package/src/util/react.tsx +1 -1
@@ -3,20 +3,21 @@
|
|
3
3
|
//
|
4
4
|
|
5
5
|
import { syntaxTree } from '@codemirror/language';
|
6
|
-
import {
|
7
|
-
import {
|
6
|
+
import { type EditorState, Prec, RangeSetBuilder, StateEffect } from '@codemirror/state';
|
7
|
+
import { Decoration, type DecorationSet, EditorView, ViewPlugin, type ViewUpdate, WidgetType } from '@codemirror/view';
|
8
8
|
import { type SyntaxNodeRef } from '@lezer/common';
|
9
9
|
|
10
10
|
import { invariant } from '@dxos/invariant';
|
11
11
|
import { mx } from '@dxos/react-ui-theme';
|
12
12
|
|
13
|
+
import { type HeadingLevel, theme } from '../../styles';
|
14
|
+
import { type RenderCallback } from '../../types';
|
15
|
+
import { wrapWithCatch } from '../../util';
|
16
|
+
|
13
17
|
import { adjustChanges } from './changes';
|
14
18
|
import { image } from './image';
|
15
|
-
import {
|
19
|
+
import { bulletListIndentationWidth, formattingStyles, orderedListIndentationWidth } from './styles';
|
16
20
|
import { table } from './table';
|
17
|
-
import { theme, type HeadingLevel } from '../../styles';
|
18
|
-
import { type RenderCallback } from '../../types';
|
19
|
-
import { wrapWithCatch } from '../../util';
|
20
21
|
|
21
22
|
/**
|
22
23
|
* Unicode characters.
|
@@ -233,7 +234,7 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
|
|
233
234
|
const mark = node.node.firstChild!;
|
234
235
|
if (mark?.name === 'HeaderMark') {
|
235
236
|
const { from, to = 6 } = options.numberedHeadings ?? {};
|
236
|
-
const text =
|
237
|
+
const text = state.sliceDoc(node.from, node.to);
|
237
238
|
const len = text.match(/[#\s]+/)![0].length;
|
238
239
|
if (!from || level < from || level > to) {
|
239
240
|
atomicDeco.add(mark.from, mark.from + len, hide);
|
@@ -426,6 +427,9 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
|
|
426
427
|
const editing = editingRange(state, node, focus);
|
427
428
|
if (urlNode && marks.length >= 2) {
|
428
429
|
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
430
|
+
if (options.skip?.({ name: 'Link', url })) {
|
431
|
+
break;
|
432
|
+
}
|
429
433
|
if (!editing) {
|
430
434
|
atomicDeco.add(node.from, marks[0].to, hide);
|
431
435
|
}
|
@@ -493,15 +497,15 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
|
|
493
497
|
tree.iterate({
|
494
498
|
from,
|
495
499
|
to,
|
496
|
-
enter: wrapWithCatch(enterNode),
|
497
|
-
leave: wrapWithCatch(leaveNode),
|
500
|
+
enter: wrapWithCatch(enterNode, 'decorate.enter'),
|
501
|
+
leave: wrapWithCatch(leaveNode, 'decorate.leave'),
|
498
502
|
});
|
499
503
|
}
|
500
504
|
} else {
|
501
505
|
// NOTE: If line numbering then we must iterate from the start of document.
|
502
506
|
tree.iterate({
|
503
|
-
enter: wrapWithCatch(enterNode),
|
504
|
-
leave: wrapWithCatch(leaveNode),
|
507
|
+
enter: wrapWithCatch(enterNode, 'decorate.enter'),
|
508
|
+
leave: wrapWithCatch(leaveNode, 'decorate.leave'),
|
505
509
|
});
|
506
510
|
}
|
507
511
|
|
@@ -513,15 +517,20 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
|
|
513
517
|
|
514
518
|
const forceUpdate = StateEffect.define<null>();
|
515
519
|
|
520
|
+
export type NodeData = { name: 'Link'; url: string } | { name: 'Image'; url: string };
|
521
|
+
|
516
522
|
export interface DecorateOptions {
|
517
523
|
/**
|
518
524
|
* Prevents triggering decorations as the cursor moves through the document.
|
519
525
|
*/
|
520
526
|
selectionChangeDelay?: number;
|
521
527
|
numberedHeadings?: { from: number; to?: number };
|
522
|
-
renderLinkButton?: RenderCallback<{ url: string }>;
|
523
528
|
// TODO(burdon): Additional padding for each line.
|
524
529
|
listPaddingLeft?: number;
|
530
|
+
// TODO(burdon): Use consistently.
|
531
|
+
skip?: (node: NodeData) => boolean;
|
532
|
+
// TODO(burdon): Remove.
|
533
|
+
renderLinkButton?: RenderCallback<{ url: string }>;
|
525
534
|
}
|
526
535
|
|
527
536
|
export const decorateMarkdown = (options: DecorateOptions = {}) => {
|
@@ -577,9 +586,9 @@ export const decorateMarkdown = (options: DecorateOptions = {}) => {
|
|
577
586
|
},
|
578
587
|
{
|
579
588
|
provide: (plugin) => [
|
580
|
-
EditorView.
|
589
|
+
Prec.low(EditorView.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration.none)),
|
581
590
|
EditorView.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration.none),
|
582
|
-
EditorView.
|
591
|
+
EditorView.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration.none),
|
583
592
|
],
|
584
593
|
},
|
585
594
|
),
|
@@ -7,21 +7,21 @@ import { EditorState, type StateCommand } from '@codemirror/state';
|
|
7
7
|
import { describe, expect, test } from 'vitest';
|
8
8
|
|
9
9
|
import {
|
10
|
+
type Formatting,
|
11
|
+
Inline,
|
12
|
+
List,
|
10
13
|
addBlockquote,
|
11
14
|
addCodeblock,
|
12
15
|
addLink,
|
13
16
|
addList,
|
14
17
|
addStyle,
|
15
18
|
getFormatting,
|
16
|
-
removeStyle,
|
17
|
-
removeLink,
|
18
|
-
removeList,
|
19
19
|
removeBlockquote,
|
20
20
|
removeCodeblock,
|
21
|
+
removeLink,
|
22
|
+
removeList,
|
23
|
+
removeStyle,
|
21
24
|
setHeading,
|
22
|
-
Inline,
|
23
|
-
List,
|
24
|
-
type Formatting,
|
25
25
|
} from './formatting';
|
26
26
|
|
27
27
|
export const emptyFormatting: Formatting = {
|
@@ -7,14 +7,14 @@ import { syntaxTree } from '@codemirror/language';
|
|
7
7
|
import {
|
8
8
|
type ChangeSpec,
|
9
9
|
EditorSelection,
|
10
|
-
type Extension,
|
11
10
|
type EditorState,
|
11
|
+
type Extension,
|
12
12
|
type Line,
|
13
13
|
type StateCommand,
|
14
14
|
type Text,
|
15
15
|
} from '@codemirror/state';
|
16
|
-
import { EditorView,
|
17
|
-
import { type
|
16
|
+
import { EditorView, type ViewUpdate, keymap } from '@codemirror/view';
|
17
|
+
import { type SyntaxNode, type SyntaxNodeRef } from '@lezer/common';
|
18
18
|
import { useCallback, useMemo } from 'react';
|
19
19
|
|
20
20
|
import { debounceAndThrottle } from '@dxos/async';
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
import { markdownLanguage } from '@codemirror/lang-markdown';
|
6
6
|
import { HighlightStyle } from '@codemirror/language';
|
7
|
-
import {
|
7
|
+
import { Tag, styleTags, tags } from '@lezer/highlight';
|
8
8
|
import { type MarkdownConfig, Table } from '@lezer/markdown';
|
9
9
|
|
10
10
|
import { fontBody, theme } from '../../styles';
|
@@ -17,8 +17,7 @@ export const image = (_options: ImageOptions = {}): Extension => {
|
|
17
17
|
return [
|
18
18
|
StateField.define<DecorationSet>({
|
19
19
|
create: (state) => {
|
20
|
-
|
21
|
-
return Decoration.set(buildDecorations(0, state.doc.length, state));
|
20
|
+
return Decoration.set(buildDecorations(state, 0, state.doc.length));
|
22
21
|
},
|
23
22
|
update: (value: DecorationSet, tr: Transaction) => {
|
24
23
|
if (!tr.docChanged && !tr.selection) {
|
@@ -43,7 +42,7 @@ export const image = (_options: ImageOptions = {}): Extension => {
|
|
43
42
|
filterFrom: from,
|
44
43
|
filterTo: to,
|
45
44
|
filter: () => false,
|
46
|
-
add: buildDecorations(from, to
|
45
|
+
add: buildDecorations(tr.state, from, to),
|
47
46
|
});
|
48
47
|
},
|
49
48
|
provide: (field) => EditorView.decorations.from(field),
|
@@ -51,7 +50,7 @@ export const image = (_options: ImageOptions = {}): Extension => {
|
|
51
50
|
];
|
52
51
|
};
|
53
52
|
|
54
|
-
const buildDecorations = (
|
53
|
+
const buildDecorations = (state: EditorState, from: number, to: number) => {
|
55
54
|
const decorations: Range<Decoration>[] = [];
|
56
55
|
const cursor = state.selection.main.head;
|
57
56
|
syntaxTree(state).iterate({
|
@@ -94,7 +94,13 @@ const update = (state: EditorState, _options: TableOptions) => {
|
|
94
94
|
} else {
|
95
95
|
// Add class for styling.
|
96
96
|
// TODO(burdon): Apply to each line?
|
97
|
-
builder.add(
|
97
|
+
builder.add(
|
98
|
+
table.from,
|
99
|
+
table.to,
|
100
|
+
Decoration.mark({
|
101
|
+
class: 'cm-table',
|
102
|
+
}),
|
103
|
+
);
|
98
104
|
}
|
99
105
|
});
|
100
106
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
// Copyright 2023 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import {
|
5
|
+
import { type CompletionContext, type CompletionResult, autocompletion } from '@codemirror/autocomplete';
|
6
6
|
import type { Extension } from '@codemirror/state';
|
7
7
|
|
8
8
|
import { log } from '@dxos/log';
|
@@ -6,11 +6,12 @@ import { EditorSelection, EditorState } from '@codemirror/state';
|
|
6
6
|
import { EditorView } from '@codemirror/view';
|
7
7
|
import { describe, test } from 'vitest';
|
8
8
|
|
9
|
-
import { indentItemLess, indentItemMore, moveItemDown, moveItemUp } from './commands';
|
10
|
-
import { listItemToString, outlinerTree, treeFacet } from './tree';
|
11
9
|
import { str } from '../../testing';
|
12
10
|
import { createMarkdownExtensions } from '../markdown';
|
13
11
|
|
12
|
+
import { indentItemLess, indentItemMore, moveItemDown, moveItemUp } from './commands';
|
13
|
+
import { listItemToString, outlinerTree, treeFacet } from './tree';
|
14
|
+
|
14
15
|
const lines = [
|
15
16
|
'- [ ] 1',
|
16
17
|
'- [ ] 2',
|
@@ -7,12 +7,13 @@ import { Decoration, type DecorationSet, EditorView, ViewPlugin, type ViewUpdate
|
|
7
7
|
|
8
8
|
import { mx } from '@dxos/react-ui-theme';
|
9
9
|
|
10
|
+
import { floatingMenu } from '../command';
|
11
|
+
import { decorateMarkdown } from '../markdown';
|
12
|
+
|
10
13
|
import { commands } from './commands';
|
11
14
|
import { editor } from './editor';
|
12
|
-
import { selectionCompartment,
|
15
|
+
import { selectionCompartment, selectionEquals, selectionFacet } from './selection';
|
13
16
|
import { outlinerTree, treeFacet } from './tree';
|
14
|
-
import { floatingMenu } from '../command';
|
15
|
-
import { decorateMarkdown } from '../markdown';
|
16
17
|
|
17
18
|
// ISSUES:
|
18
19
|
// TODO(burdon): Remove requirement for continuous lines to be indented (so that user's can't accidentally delete them and break the layout).
|
@@ -37,7 +38,7 @@ export type OutlinerProps = {};
|
|
37
38
|
* - Constrains editor to outline structure.
|
38
39
|
* - Supports smart cut-and-paste.
|
39
40
|
*/
|
40
|
-
export const outliner = (
|
41
|
+
export const outliner = (_options: OutlinerProps = {}): Extension => [
|
41
42
|
// Commands.
|
42
43
|
Prec.highest(commands()),
|
43
44
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
//
|
4
4
|
|
5
5
|
import { Compartment, type EditorState, Facet, type SelectionRange } from '@codemirror/state';
|
6
|
-
import { type
|
6
|
+
import { type Command, type EditorView } from '@codemirror/view';
|
7
7
|
|
8
8
|
import { treeFacet } from './tree';
|
9
9
|
|
@@ -6,10 +6,11 @@ import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
|
6
6
|
import { EditorState } from '@codemirror/state';
|
7
7
|
import { beforeEach, describe, test } from 'vitest';
|
8
8
|
|
9
|
-
import { outlinerTree, treeFacet, listItemToString, type Item } from './tree';
|
10
9
|
import { str } from '../../testing';
|
11
10
|
import { type Range } from '../../types';
|
12
11
|
|
12
|
+
import { type Item, listItemToString, outlinerTree, treeFacet } from './tree';
|
13
|
+
|
13
14
|
const lines = [
|
14
15
|
'- [ ] 1',
|
15
16
|
'- [ ] 2',
|
@@ -3,7 +3,7 @@
|
|
3
3
|
//
|
4
4
|
|
5
5
|
import { syntaxTree } from '@codemirror/language';
|
6
|
-
import {
|
6
|
+
import { type EditorState, type Extension, StateField, type Transaction } from '@codemirror/state';
|
7
7
|
import { Facet } from '@codemirror/state';
|
8
8
|
import { type SyntaxNode } from '@lezer/common';
|
9
9
|
|
@@ -195,7 +195,7 @@ export type TreeOptions = {};
|
|
195
195
|
* This adds overhead relative to the markdown AST, but allows for efficient traversal of the list items.
|
196
196
|
* NOTE: Requires markdown parser to be enabled.
|
197
197
|
*/
|
198
|
-
export const outlinerTree = (
|
198
|
+
export const outlinerTree = (_options: TreeOptions = {}): Extension => {
|
199
199
|
const buildTree = (state: EditorState): Tree => {
|
200
200
|
let tree: Tree | undefined;
|
201
201
|
let parent: Item | undefined;
|
@@ -2,21 +2,14 @@
|
|
2
2
|
// Copyright 2023 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import '@dxos/lit-ui/dx-ref-tag.pcss';
|
6
|
-
|
7
5
|
import { syntaxTree } from '@codemirror/language';
|
8
|
-
import {
|
9
|
-
type EditorState,
|
10
|
-
type Extension,
|
11
|
-
type RangeSet,
|
12
|
-
RangeSetBuilder,
|
13
|
-
StateField,
|
14
|
-
type Transaction,
|
15
|
-
} from '@codemirror/state';
|
6
|
+
import { type EditorState, type Extension, RangeSetBuilder, StateField } from '@codemirror/state';
|
16
7
|
import { Decoration, type DecorationSet, EditorView, WidgetType } from '@codemirror/view';
|
17
8
|
import { type SyntaxNode } from '@lezer/common';
|
18
9
|
|
19
10
|
export type PreviewLinkRef = {
|
11
|
+
/** @deprecated */
|
12
|
+
// TODO(burdon): Remove?
|
20
13
|
suggest?: boolean;
|
21
14
|
block?: boolean;
|
22
15
|
label: string;
|
@@ -30,7 +23,6 @@ export type PreviewLinkTarget = {
|
|
30
23
|
};
|
31
24
|
|
32
25
|
// TODO(wittjosiah): Remove.
|
33
|
-
// TODO(burdon): Handle error.
|
34
26
|
export type PreviewLookup = (link: PreviewLinkRef) => Promise<PreviewLinkTarget | null | undefined>;
|
35
27
|
|
36
28
|
export type PreviewOptions = {
|
@@ -44,10 +36,16 @@ export type PreviewOptions = {
|
|
44
36
|
export const preview = (options: PreviewOptions = {}): Extension => {
|
45
37
|
return [
|
46
38
|
// NOTE: Atomic block decorations must be created from a state field, now a widget, otherwise it results in the following error:
|
47
|
-
// "Block decorations may not be specified via plugins"
|
39
|
+
// "Block decorations may not be specified via plugins".
|
48
40
|
StateField.define<DecorationSet>({
|
49
41
|
create: (state) => buildDecorations(state, options),
|
50
|
-
update: (
|
42
|
+
update: (decorations, tr) => {
|
43
|
+
if (tr.docChanged) {
|
44
|
+
return buildDecorations(tr.state, options);
|
45
|
+
}
|
46
|
+
|
47
|
+
return decorations.map(tr.changes);
|
48
|
+
},
|
51
49
|
provide: (field) => [
|
52
50
|
EditorView.decorations.from(field),
|
53
51
|
EditorView.atomicRanges.of((view) => view.state.field(field)),
|
@@ -56,42 +54,19 @@ export const preview = (options: PreviewOptions = {}): Extension => {
|
|
56
54
|
];
|
57
55
|
};
|
58
56
|
|
59
|
-
/**
|
60
|
-
* Link references.
|
61
|
-
*
|
62
|
-
* [Label][dxn:echo:123] Inline reference
|
63
|
-
* ![Label][dxn:echo:123] Block reference
|
64
|
-
* ![Label][?dxn:echo:123] Suggestion
|
65
|
-
*/
|
66
|
-
export const getLinkRef = (state: EditorState, node: SyntaxNode): PreviewLinkRef | undefined => {
|
67
|
-
const mark = node.getChild('LinkMark');
|
68
|
-
const label = node.getChild('LinkLabel');
|
69
|
-
if (mark && label) {
|
70
|
-
const ref = state.sliceDoc(label.from + 1, label.to - 1);
|
71
|
-
return {
|
72
|
-
suggest: ref.startsWith('?'),
|
73
|
-
block: state.sliceDoc(mark.from, mark.from + 1) === '!',
|
74
|
-
label: state.sliceDoc(mark.to, label.from - 1),
|
75
|
-
ref: ref.startsWith('?') ? ref.slice(1) : ref,
|
76
|
-
};
|
77
|
-
}
|
78
|
-
};
|
79
|
-
|
80
57
|
/**
|
81
58
|
* Echo references are represented as markdown reference links.
|
82
59
|
* https://www.markdownguide.org/basic-syntax/#reference-style-links
|
83
|
-
* [Label|block][dxn:echo:123]
|
84
|
-
* [Label|inline][dxn:echo:123]
|
85
60
|
*/
|
86
|
-
const buildDecorations = (state: EditorState, options: PreviewOptions) => {
|
61
|
+
const buildDecorations = (state: EditorState, options: PreviewOptions): DecorationSet => {
|
87
62
|
const builder = new RangeSetBuilder<Decoration>();
|
88
63
|
|
89
64
|
syntaxTree(state).iterate({
|
90
65
|
enter: (node) => {
|
91
66
|
switch (node.name) {
|
92
67
|
//
|
93
|
-
//
|
94
|
-
// [Label]
|
68
|
+
// Inline widget.
|
69
|
+
// [Label](dxn:echo:123)
|
95
70
|
//
|
96
71
|
case 'Link': {
|
97
72
|
const link = getLinkRef(state, node.node);
|
@@ -101,29 +76,32 @@ const buildDecorations = (state: EditorState, options: PreviewOptions) => {
|
|
101
76
|
node.to,
|
102
77
|
Decoration.replace({
|
103
78
|
widget: new PreviewInlineWidget(options, link),
|
79
|
+
side: 1,
|
104
80
|
}),
|
105
81
|
);
|
106
82
|
}
|
107
|
-
|
83
|
+
return false;
|
108
84
|
}
|
85
|
+
|
109
86
|
//
|
110
|
-
// Block widget.
|
111
|
-
// ![Label]
|
87
|
+
// Block widget (transclusion).
|
88
|
+
// 
|
112
89
|
//
|
113
90
|
case 'Image': {
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
91
|
+
if (options.addBlockContainer && options.removeBlockContainer) {
|
92
|
+
const link = getLinkRef(state, node.node);
|
93
|
+
if (link) {
|
94
|
+
builder.add(
|
95
|
+
node.from,
|
96
|
+
node.to,
|
97
|
+
Decoration.replace({
|
98
|
+
block: true,
|
99
|
+
widget: new PreviewBlockWidget(options, link),
|
100
|
+
}),
|
101
|
+
);
|
102
|
+
}
|
125
103
|
}
|
126
|
-
|
104
|
+
return false;
|
127
105
|
}
|
128
106
|
}
|
129
107
|
},
|
@@ -132,9 +110,30 @@ const buildDecorations = (state: EditorState, options: PreviewOptions) => {
|
|
132
110
|
return builder.finish();
|
133
111
|
};
|
134
112
|
|
113
|
+
/**
|
114
|
+
* Link references.
|
115
|
+
* [Label](dxn:echo:123) Inline reference
|
116
|
+
*  Block reference
|
117
|
+
*/
|
118
|
+
export const getLinkRef = (state: EditorState, node: SyntaxNode): PreviewLinkRef | undefined => {
|
119
|
+
const mark = node.getChildren('LinkMark');
|
120
|
+
const urlNode = node.getChild('URL');
|
121
|
+
if (mark && urlNode) {
|
122
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
123
|
+
if (url.startsWith('dxn:')) {
|
124
|
+
const label = state.sliceDoc(mark[0].to, mark[1].from);
|
125
|
+
return {
|
126
|
+
block: state.sliceDoc(mark[0].from, mark[0].from + 1) === '!',
|
127
|
+
label,
|
128
|
+
ref: url,
|
129
|
+
};
|
130
|
+
}
|
131
|
+
}
|
132
|
+
};
|
133
|
+
|
135
134
|
/**
|
136
135
|
* Inline widget.
|
137
|
-
*
|
136
|
+
* [Label](dxn:echo:123)
|
138
137
|
*/
|
139
138
|
class PreviewInlineWidget extends WidgetType {
|
140
139
|
constructor(
|
@@ -152,8 +151,9 @@ class PreviewInlineWidget extends WidgetType {
|
|
152
151
|
return this._link.ref === other._link.ref && this._link.label === other._link.label;
|
153
152
|
}
|
154
153
|
|
155
|
-
override toDOM(
|
156
|
-
const root = document.createElement('dx-
|
154
|
+
override toDOM(_view: EditorView): HTMLElement {
|
155
|
+
const root = document.createElement('dx-anchor');
|
156
|
+
root.classList.add('dx-tag--anchor');
|
157
157
|
root.textContent = this._link.label;
|
158
158
|
root.setAttribute('refId', this._link.ref);
|
159
159
|
return root;
|
@@ -161,7 +161,7 @@ class PreviewInlineWidget extends WidgetType {
|
|
161
161
|
}
|
162
162
|
|
163
163
|
/**
|
164
|
-
* Block widget.
|
164
|
+
* Block widget (e.g., for surfaces).
|
165
165
|
* ![Label][dxn:echo:123]
|
166
166
|
*/
|
167
167
|
class PreviewBlockWidget extends WidgetType {
|
@@ -180,7 +180,7 @@ class PreviewBlockWidget extends WidgetType {
|
|
180
180
|
return this._link.ref === other._link.ref;
|
181
181
|
}
|
182
182
|
|
183
|
-
override toDOM(
|
183
|
+
override toDOM(_view: EditorView): HTMLDivElement {
|
184
184
|
const root = document.createElement('div');
|
185
185
|
root.classList.add('cm-preview-block', 'density-coarse');
|
186
186
|
this._options.addBlockContainer?.(this._link, root);
|