@dxos/ui-editor 0.0.0 → 0.8.4-main.1c7ec43d41
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 +8633 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/browser/types/index.mjs +33 -0
- package/dist/lib/browser/types/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +8635 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/types/index.mjs +35 -0
- package/dist/lib/node-esm/types/index.mjs.map +7 -0
- package/dist/types/src/defaults.d.ts +6 -0
- package/dist/types/src/defaults.d.ts.map +1 -0
- package/dist/types/src/extensions/annotations.d.ts +9 -0
- package/dist/types/src/extensions/annotations.d.ts.map +1 -0
- package/dist/types/src/extensions/auto-scroll.d.ts +18 -0
- package/dist/types/src/extensions/auto-scroll.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts +17 -0
- package/dist/types/src/extensions/autocomplete/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts +5 -0
- package/dist/types/src/extensions/autocomplete/index.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts +13 -0
- package/dist/types/src/extensions/autocomplete/match.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts +23 -0
- package/dist/types/src/extensions/autocomplete/placeholder.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts +10 -0
- package/dist/types/src/extensions/autocomplete/typeahead.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts +4 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
- package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts +4 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +17 -0
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/index.d.ts +2 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/sync.d.ts +17 -0
- package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +6 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts +5 -0
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts +31 -0
- package/dist/types/src/extensions/awareness/awareness-provider.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/awareness.d.ts +46 -0
- package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness/index.d.ts +3 -0
- package/dist/types/src/extensions/awareness/index.d.ts.map +1 -0
- package/dist/types/src/extensions/blast.d.ts +25 -0
- package/dist/types/src/extensions/blast.d.ts.map +1 -0
- package/dist/types/src/extensions/blocks.d.ts +2 -0
- package/dist/types/src/extensions/blocks.d.ts.map +1 -0
- package/dist/types/src/extensions/bookmarks.d.ts +12 -0
- package/dist/types/src/extensions/bookmarks.d.ts.map +1 -0
- package/dist/types/src/extensions/comments.d.ts +90 -0
- package/dist/types/src/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/debug.d.ts +3 -0
- package/dist/types/src/extensions/debug.d.ts.map +1 -0
- package/dist/types/src/extensions/dnd.d.ts +9 -0
- package/dist/types/src/extensions/dnd.d.ts.map +1 -0
- package/dist/types/src/extensions/factories.d.ts +88 -0
- package/dist/types/src/extensions/factories.d.ts.map +1 -0
- 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 +7 -0
- package/dist/types/src/extensions/focus.d.ts.map +1 -0
- package/dist/types/src/extensions/folding.d.ts +6 -0
- package/dist/types/src/extensions/folding.d.ts.map +1 -0
- package/dist/types/src/extensions/hashtag.d.ts +3 -0
- package/dist/types/src/extensions/hashtag.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +32 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/extensions/json.d.ts +7 -0
- package/dist/types/src/extensions/json.d.ts.map +1 -0
- package/dist/types/src/extensions/listener.d.ts +13 -0
- package/dist/types/src/extensions/listener.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/action.d.ts +12 -0
- package/dist/types/src/extensions/markdown/action.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts +25 -0
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/changes.d.ts +10 -0
- package/dist/types/src/extensions/markdown/changes.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/changes.test.d.ts +2 -0
- package/dist/types/src/extensions/markdown/changes.test.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/debug.d.ts +11 -0
- package/dist/types/src/extensions/markdown/debug.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts +25 -0
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +63 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts +37 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts +7 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +10 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/link.d.ts +7 -0
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/parser.test.d.ts +2 -0
- package/dist/types/src/extensions/markdown/parser.test.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/styles.d.ts +4 -0
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts +8 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts +7 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -0
- package/dist/types/src/extensions/modal.d.ts +7 -0
- package/dist/types/src/extensions/modal.d.ts.map +1 -0
- package/dist/types/src/extensions/modes.d.ts +10 -0
- package/dist/types/src/extensions/modes.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/commands.d.ts +10 -0
- package/dist/types/src/extensions/outliner/commands.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/editor.d.ts +5 -0
- package/dist/types/src/extensions/outliner/editor.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/editor.test.d.ts +2 -0
- package/dist/types/src/extensions/outliner/editor.test.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/index.d.ts +4 -0
- package/dist/types/src/extensions/outliner/index.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/menu.d.ts +8 -0
- package/dist/types/src/extensions/outliner/menu.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/outliner.d.ts +11 -0
- package/dist/types/src/extensions/outliner/outliner.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/outliner.test.d.ts +2 -0
- package/dist/types/src/extensions/outliner/outliner.test.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/selection.d.ts +12 -0
- package/dist/types/src/extensions/outliner/selection.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/tree.d.ts +79 -0
- package/dist/types/src/extensions/outliner/tree.d.ts.map +1 -0
- package/dist/types/src/extensions/outliner/tree.test.d.ts +2 -0
- package/dist/types/src/extensions/outliner/tree.test.d.ts.map +1 -0
- package/dist/types/src/extensions/preview/index.d.ts +2 -0
- package/dist/types/src/extensions/preview/index.d.ts.map +1 -0
- package/dist/types/src/extensions/preview/preview.d.ts +34 -0
- package/dist/types/src/extensions/preview/preview.d.ts.map +1 -0
- package/dist/types/src/extensions/replacer.d.ts +21 -0
- package/dist/types/src/extensions/replacer.d.ts.map +1 -0
- package/dist/types/src/extensions/replacer.test.d.ts +2 -0
- package/dist/types/src/extensions/replacer.test.d.ts.map +1 -0
- 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 +68 -0
- package/dist/types/src/extensions/scroller.d.ts.map +1 -0
- package/dist/types/src/extensions/selection.d.ts +24 -0
- package/dist/types/src/extensions/selection.d.ts.map +1 -0
- 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/state.d.ts +2 -0
- package/dist/types/src/extensions/state.d.ts.map +1 -0
- package/dist/types/src/extensions/submit.d.ts +10 -0
- package/dist/types/src/extensions/submit.d.ts.map +1 -0
- 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/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 +7 -0
- package/dist/types/src/extensions/tags/index.d.ts.map +1 -0
- 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 +117 -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/extensions/tags/xml-util.test.d.ts +2 -0
- package/dist/types/src/extensions/tags/xml-util.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +8 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/styles/index.d.ts +2 -0
- package/dist/types/src/styles/index.d.ts.map +1 -0
- package/dist/types/src/styles/theme.d.ts +58 -0
- package/dist/types/src/styles/theme.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/types.d.ts +21 -0
- package/dist/types/src/types/types.d.ts.map +1 -0
- package/dist/types/src/util/cursor.d.ts +31 -0
- package/dist/types/src/util/cursor.d.ts.map +1 -0
- package/dist/types/src/util/debug.d.ts +17 -0
- package/dist/types/src/util/debug.d.ts.map +1 -0
- 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 +10 -0
- package/dist/types/src/util/dom.d.ts.map +1 -0
- package/dist/types/src/util/facet.d.ts +3 -0
- package/dist/types/src/util/facet.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +7 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/util.d.ts +8 -0
- package/dist/types/src/util/util.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +42 -43
- package/src/defaults.ts +33 -20
- package/src/extensions/annotations.ts +1 -1
- package/src/extensions/auto-scroll.ts +234 -0
- package/src/extensions/autocomplete/placeholder.ts +37 -18
- package/src/extensions/automerge/automerge.test.tsx +37 -11
- package/src/extensions/automerge/automerge.ts +5 -7
- package/src/extensions/blocks.ts +5 -5
- package/src/extensions/comments.ts +5 -6
- package/src/extensions/dnd.ts +2 -2
- package/src/extensions/factories.test.ts +88 -0
- package/src/extensions/factories.ts +32 -15
- package/src/extensions/folding.ts +5 -22
- package/src/extensions/index.ts +4 -3
- package/src/extensions/markdown/action.ts +0 -1
- package/src/extensions/markdown/bundle.ts +23 -9
- package/src/extensions/markdown/decorate.ts +15 -12
- package/src/extensions/markdown/formatting.ts +5 -10
- package/src/extensions/markdown/highlight.ts +15 -7
- package/src/extensions/markdown/link.ts +27 -33
- package/src/extensions/markdown/parser.test.ts +0 -1
- package/src/extensions/markdown/styles.ts +42 -9
- package/src/extensions/markdown/table.ts +24 -2
- package/src/extensions/outliner/outliner.test.ts +0 -1
- package/src/extensions/outliner/outliner.ts +3 -4
- package/src/extensions/outliner/tree.test.ts +0 -1
- package/src/extensions/preview/preview.ts +62 -15
- package/src/extensions/scroll-past-end.ts +32 -0
- package/src/extensions/scroller.ts +256 -0
- package/src/extensions/selection.ts +1 -1
- package/src/extensions/snippets.ts +67 -0
- package/src/extensions/tags/extended-markdown.test.ts +120 -2
- package/src/extensions/tags/extended-markdown.ts +80 -1
- package/src/extensions/tags/fader.ts +195 -0
- package/src/extensions/tags/index.ts +4 -1
- package/src/extensions/tags/testing/text.md +36 -0
- package/src/extensions/tags/testing/text.txt +35 -0
- package/src/extensions/tags/typewriter.test.ts +65 -0
- package/src/extensions/tags/typewriter.ts +594 -0
- package/src/extensions/tags/xml-block-decoration.ts +123 -0
- package/src/extensions/tags/xml-formatting.ts +125 -0
- package/src/extensions/tags/xml-tags.ts +186 -35
- package/src/extensions/tags/xml-util.test.ts +199 -24
- package/src/extensions/tags/xml-util.ts +62 -5
- package/src/index.ts +0 -1
- package/src/styles/index.ts +0 -2
- package/src/styles/theme.ts +124 -33
- package/src/types/types.ts +10 -2
- package/src/typings.d.ts +8 -0
- package/src/util/cursor.ts +1 -2
- package/src/extensions/autoscroll.ts +0 -165
- package/src/extensions/scrolling.ts +0 -189
- package/src/extensions/tags/streamer.ts +0 -243
- package/src/extensions/typewriter.ts +0 -68
- package/src/styles/markdown.ts +0 -26
- package/src/styles/tokens.ts +0 -17
|
@@ -2,47 +2,222 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { syntaxTree } from '@codemirror/language';
|
|
5
|
+
import { ensureSyntaxTree, syntaxTree } from '@codemirror/language';
|
|
6
6
|
import { EditorState } from '@codemirror/state';
|
|
7
|
-
import { describe,
|
|
7
|
+
import { describe, test } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { Trigger } from '@dxos/async';
|
|
10
9
|
import { trim } from '@dxos/util';
|
|
11
10
|
|
|
12
11
|
import { extendedMarkdown } from './extended-markdown';
|
|
12
|
+
import TEXT from './testing/text.md?raw';
|
|
13
13
|
import { xmlTags } from './xml-tags';
|
|
14
|
-
import { nodeToJson } from './xml-util';
|
|
14
|
+
import { nodeToJson, type Tag } from './xml-util';
|
|
15
|
+
|
|
16
|
+
type ParsedElement = Tag & {
|
|
17
|
+
/** Element spans the entire document (opening through closing tag). */
|
|
18
|
+
complete: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Helper to extract all parsed XML elements from a document.
|
|
23
|
+
* Checks completeness by verifying the Element node has a CloseTag child.
|
|
24
|
+
*/
|
|
25
|
+
const parseElements = (doc: string, registry: Record<string, any> = {}): ParsedElement[] => {
|
|
26
|
+
const state = EditorState.create({
|
|
27
|
+
doc,
|
|
28
|
+
extensions: [extendedMarkdown({ registry }), xmlTags({ registry })],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const tree = ensureSyntaxTree(state, doc.length, 5000) ?? syntaxTree(state);
|
|
32
|
+
const elements: ParsedElement[] = [];
|
|
33
|
+
tree.iterate({
|
|
34
|
+
enter: (node) => {
|
|
35
|
+
if (node.type.name === 'Element') {
|
|
36
|
+
const tag = nodeToJson(state, node.node);
|
|
37
|
+
if (tag) {
|
|
38
|
+
const hasCloseTag = !!node.node.getChild('CloseTag');
|
|
39
|
+
const hasSelfClose = !!node.node.getChild('SelfClosingTag');
|
|
40
|
+
elements.push({
|
|
41
|
+
...tag,
|
|
42
|
+
complete: hasCloseTag || hasSelfClose,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return elements;
|
|
51
|
+
};
|
|
15
52
|
|
|
16
53
|
describe('nodeToJson', () => {
|
|
17
|
-
|
|
54
|
+
test('should parse a simple element', ({ expect }) => {
|
|
18
55
|
const xml = trim`
|
|
19
56
|
# Test
|
|
20
57
|
|
|
21
58
|
<test id="123" foo="100" />
|
|
22
59
|
`;
|
|
23
60
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const value = new Trigger<any>();
|
|
30
|
-
syntaxTree(state).iterate({
|
|
31
|
-
enter: (node) => {
|
|
32
|
-
switch (node.type.name) {
|
|
33
|
-
case 'Element': {
|
|
34
|
-
const args = nodeToJson(state, node.node);
|
|
35
|
-
value.wake(args);
|
|
36
|
-
break;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
expect(await value.wait()).toEqual({
|
|
61
|
+
const elements = parseElements(xml);
|
|
62
|
+
expect(elements).toHaveLength(1);
|
|
63
|
+
expect(elements[0]).toMatchObject({
|
|
43
64
|
_tag: 'test',
|
|
44
65
|
id: '123',
|
|
45
66
|
foo: '100',
|
|
46
67
|
});
|
|
47
68
|
});
|
|
69
|
+
|
|
70
|
+
test('should parse tag with single-line content', ({ expect }) => {
|
|
71
|
+
const xml = trim`
|
|
72
|
+
<reasoning>The user is asking about markdown.</reasoning>
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
const registry = { reasoning: { block: true } };
|
|
76
|
+
const elements = parseElements(xml, registry);
|
|
77
|
+
expect(elements).toHaveLength(1);
|
|
78
|
+
expect(elements[0]._tag).toBe('reasoning');
|
|
79
|
+
expect(elements[0].complete).toBe(true);
|
|
80
|
+
expect(elements[0].children).toEqual(['The user is asking about markdown.']);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('should parse tag with multi-line content without blank lines', ({ expect }) => {
|
|
84
|
+
const xml = trim`
|
|
85
|
+
<reasoning>
|
|
86
|
+
The user is asking about markdown.
|
|
87
|
+
This is a follow-up thought.
|
|
88
|
+
</reasoning>
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
const registry = { reasoning: { block: true } };
|
|
92
|
+
const elements = parseElements(xml, registry);
|
|
93
|
+
expect(elements).toHaveLength(1);
|
|
94
|
+
expect(elements[0]._tag).toBe('reasoning');
|
|
95
|
+
expect(elements[0].complete).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// BUG: Blank lines inside XML tags cause the markdown parser to split the content
|
|
99
|
+
// into multiple blocks (HTMLBlock + Paragraph), preventing the XML mixed parser from
|
|
100
|
+
// seeing the full element. The first HTMLBlock gets an incomplete Element (no CloseTag),
|
|
101
|
+
// and the closing tag ends up in a Paragraph that's never parsed as XML.
|
|
102
|
+
//
|
|
103
|
+
// Syntax tree with blank lines:
|
|
104
|
+
// Document [0-28] → Element (incomplete: OpenTag + Text + ⚠ — no CloseTag)
|
|
105
|
+
// Paragraph [30-60] → "Second paragraph.\n</reasoning>"
|
|
106
|
+
|
|
107
|
+
test('should parse tag with blank lines in content', ({ expect }) => {
|
|
108
|
+
const xml = trim`
|
|
109
|
+
<reasoning>
|
|
110
|
+
The user is asking me to think deeply about what markdown is.
|
|
111
|
+
|
|
112
|
+
But given the context of our conversation - we've been trying to scrape slab data from a website - I think they might be hinting at something specific.
|
|
113
|
+
</reasoning>
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
const registry = { reasoning: { block: true } };
|
|
117
|
+
const elements = parseElements(xml, registry);
|
|
118
|
+
expect(elements).toHaveLength(1);
|
|
119
|
+
expect(elements[0]._tag).toBe('reasoning');
|
|
120
|
+
expect(elements[0].complete).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Regression: when reasoning text contains escaped XML (e.g. `<foo>`), Lezer XML
|
|
124
|
+
// splits the inline content into Text + EntityReference + Text + EntityReference + Text
|
|
125
|
+
// siblings. The walker used to skip entity references and push each text segment as a
|
|
126
|
+
// separate child, so `getXmlTextChild(children)` only saw the prefix before the first
|
|
127
|
+
// `<` (e.g. ``"The user sent `"``).
|
|
128
|
+
test('should preserve text containing entity references as a single child', ({ expect }) => {
|
|
129
|
+
const xml = trim`
|
|
130
|
+
<reasoning>The user sent \`<foo>\`, which appears to be an XML-like tag.</reasoning>
|
|
131
|
+
`;
|
|
132
|
+
|
|
133
|
+
const registry = { reasoning: { block: true } };
|
|
134
|
+
const elements = parseElements(xml, registry);
|
|
135
|
+
expect(elements).toHaveLength(1);
|
|
136
|
+
expect(elements[0]._tag).toBe('reasoning');
|
|
137
|
+
expect(elements[0].children).toEqual(['The user sent `<foo>`, which appears to be an XML-like tag.']);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('should decode numeric character references', ({ expect }) => {
|
|
141
|
+
const xml = trim`
|
|
142
|
+
<reasoning>arrow → and hex →</reasoning>
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
const registry = { reasoning: { block: true } };
|
|
146
|
+
const elements = parseElements(xml, registry);
|
|
147
|
+
expect(elements).toHaveLength(1);
|
|
148
|
+
expect(elements[0].children).toEqual(['arrow → and hex →']);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('should parse tag with multiple blank lines in content', ({ expect }) => {
|
|
152
|
+
const xml = trim`
|
|
153
|
+
<reasoning>
|
|
154
|
+
First paragraph.
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
Second paragraph after two blank lines.
|
|
158
|
+
</reasoning>
|
|
159
|
+
`;
|
|
160
|
+
|
|
161
|
+
const registry = { reasoning: { block: true } };
|
|
162
|
+
const elements = parseElements(xml, registry);
|
|
163
|
+
expect(elements).toHaveLength(1);
|
|
164
|
+
expect(elements[0]._tag).toBe('reasoning');
|
|
165
|
+
expect(elements[0].complete).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Regression: when an unregistered XML tag like `<prompt>` appears earlier in the doc,
|
|
169
|
+
// the markdown parser treats it as a paragraph that lazy-continues into subsequent lines,
|
|
170
|
+
// and a later multi-line tag (e.g. `<reasoning>` whose body contains an ordered list) gets
|
|
171
|
+
// its HTMLBlock truncated to its first line — losing the closing tag and breaking widget
|
|
172
|
+
// rendering. Including the surrounding tag in the registry as a block-only entry (no
|
|
173
|
+
// factory/Component) lets `xmlBlockParsers` keep each tag as its own block.
|
|
174
|
+
test('multi-line reasoning is complete when preceded by a registered prompt block', ({ expect }) => {
|
|
175
|
+
const xml = [
|
|
176
|
+
'<prompt>summarize the posts</prompt>',
|
|
177
|
+
'<toolCall id="x" />',
|
|
178
|
+
'<reasoning>multi line content',
|
|
179
|
+
'1. "First" - desc',
|
|
180
|
+
'5. "Last" - desc</reasoning>',
|
|
181
|
+
].join('\n');
|
|
182
|
+
const registry = {
|
|
183
|
+
prompt: { block: true },
|
|
184
|
+
reasoning: { block: true },
|
|
185
|
+
toolCall: { block: true },
|
|
186
|
+
};
|
|
187
|
+
const elements = parseElements(xml, registry);
|
|
188
|
+
expect(elements.map((e) => `${e._tag}${e.complete ? '' : '!'}`)).toEqual(['prompt', 'toolCall', 'reasoning']);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('should parse text.md', ({ expect }) => {
|
|
192
|
+
// Mirror the live ChatThread registry, including `prompt` as a block-only entry so
|
|
193
|
+
// unregistered-paragraph lazy-continuation does not break later multi-line tags.
|
|
194
|
+
const registry = {
|
|
195
|
+
prompt: { block: true },
|
|
196
|
+
reasoning: { block: true },
|
|
197
|
+
status: { block: true },
|
|
198
|
+
toolCall: { block: true },
|
|
199
|
+
name: { block: true },
|
|
200
|
+
};
|
|
201
|
+
const elements = parseElements(TEXT, registry);
|
|
202
|
+
const tags = elements.map((element) => element._tag);
|
|
203
|
+
expect(tags).toEqual([
|
|
204
|
+
'prompt',
|
|
205
|
+
'reasoning',
|
|
206
|
+
'status',
|
|
207
|
+
'toolCall',
|
|
208
|
+
'toolCall',
|
|
209
|
+
'reasoning',
|
|
210
|
+
'status',
|
|
211
|
+
'toolCall',
|
|
212
|
+
'reasoning',
|
|
213
|
+
'prompt',
|
|
214
|
+
'reasoning',
|
|
215
|
+
'prompt',
|
|
216
|
+
'name',
|
|
217
|
+
]);
|
|
218
|
+
// Every element must be `complete` so the widget renderer wraps it. The bug we fixed:
|
|
219
|
+
// third multi-line `<reasoning>` (lines 9-14) used to be truncated by markdown's
|
|
220
|
+
// OrderedList parser breaking the HTMLBlock, leaving an Element node with no CloseTag.
|
|
221
|
+
expect(elements.filter((e) => !e.complete)).toEqual([]);
|
|
222
|
+
});
|
|
48
223
|
});
|
|
@@ -65,14 +65,25 @@ export const nodeToJson = (state: EditorState, node: SyntaxNode): Tag | undefine
|
|
|
65
65
|
const children: any[] = [];
|
|
66
66
|
let child = node.node.firstChild;
|
|
67
67
|
|
|
68
|
+
const appendText = (raw: string) => {
|
|
69
|
+
if (raw.length === 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const last = children[children.length - 1];
|
|
73
|
+
if (typeof last === 'string') {
|
|
74
|
+
children[children.length - 1] = last + raw;
|
|
75
|
+
} else {
|
|
76
|
+
children.push(raw);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
68
80
|
while (child) {
|
|
69
81
|
// Skip the opening and closing tags.
|
|
70
82
|
if (child.type.name !== 'OpenTag' && child.type.name !== 'CloseTag') {
|
|
71
83
|
if (child.type.name === 'Text') {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
84
|
+
appendText(state.doc.sliceString(child.from, child.to));
|
|
85
|
+
} else if (child.type.name === 'EntityReference' || child.type.name === 'CharacterReference') {
|
|
86
|
+
appendText(decodeXmlEntity(state.doc.sliceString(child.from, child.to)));
|
|
76
87
|
} else if (child.type.name === 'Element') {
|
|
77
88
|
const data = nodeToJson(state, child);
|
|
78
89
|
if (data) {
|
|
@@ -83,11 +94,57 @@ export const nodeToJson = (state: EditorState, node: SyntaxNode): Tag | undefine
|
|
|
83
94
|
child = child.nextSibling;
|
|
84
95
|
}
|
|
85
96
|
|
|
97
|
+
// Trim only leading/trailing whitespace on the outer-boundary string segments —
|
|
98
|
+
// interior strings are preserved verbatim so meaningful whitespace around inline
|
|
99
|
+
// child elements (e.g. `<reasoning>foo <ref/> bar</reasoning>`) is not collapsed.
|
|
100
|
+
if (children.length > 0 && typeof children[0] === 'string') {
|
|
101
|
+
children[0] = children[0].trimStart();
|
|
102
|
+
}
|
|
86
103
|
if (children.length > 0) {
|
|
87
|
-
|
|
104
|
+
const lastIndex = children.length - 1;
|
|
105
|
+
const last = children[lastIndex];
|
|
106
|
+
if (typeof last === 'string') {
|
|
107
|
+
children[lastIndex] = last.trimEnd();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const trimmed = children.filter((value) => typeof value !== 'string' || value.length > 0);
|
|
111
|
+
|
|
112
|
+
if (trimmed.length > 0) {
|
|
113
|
+
tag.children = trimmed;
|
|
88
114
|
}
|
|
89
115
|
}
|
|
90
116
|
|
|
91
117
|
return tag;
|
|
92
118
|
}
|
|
93
119
|
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Decode the common XML named entities and numeric character references that
|
|
123
|
+
* Lezer XML produces as `EntityReference` / `CharacterReference` nodes.
|
|
124
|
+
*/
|
|
125
|
+
const XML_NAMED_ENTITIES: Record<string, string> = {
|
|
126
|
+
'<': '<',
|
|
127
|
+
'>': '>',
|
|
128
|
+
'&': '&',
|
|
129
|
+
'"': '"',
|
|
130
|
+
''': "'",
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const decodeXmlEntity = (raw: string): string => {
|
|
134
|
+
const named = XML_NAMED_ENTITIES[raw];
|
|
135
|
+
if (named !== undefined) {
|
|
136
|
+
return named;
|
|
137
|
+
}
|
|
138
|
+
const numeric = /^&#(x?)([0-9a-fA-F]+);$/.exec(raw);
|
|
139
|
+
if (numeric) {
|
|
140
|
+
const code = parseInt(numeric[2], numeric[1] ? 16 : 10);
|
|
141
|
+
if (Number.isFinite(code)) {
|
|
142
|
+
try {
|
|
143
|
+
return String.fromCodePoint(code);
|
|
144
|
+
} catch {
|
|
145
|
+
// Fall through and return the raw text on out-of-range code points.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return raw;
|
|
150
|
+
};
|
package/src/index.ts
CHANGED
package/src/styles/index.ts
CHANGED
package/src/styles/theme.ts
CHANGED
|
@@ -5,7 +5,60 @@
|
|
|
5
5
|
import { type Extension } from '@codemirror/state';
|
|
6
6
|
import { EditorView } from '@codemirror/view';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { mx } from '@dxos/ui-theme';
|
|
9
|
+
|
|
10
|
+
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
11
|
+
|
|
12
|
+
// https://tailwindcss.com/docs/font-weight
|
|
13
|
+
const headings: Record<HeadingLevel, { className: string; fontSize: string; lineHeight: string }> = {
|
|
14
|
+
1: {
|
|
15
|
+
className: 'text-3xl',
|
|
16
|
+
fontSize: 'var(--text-3xl)',
|
|
17
|
+
lineHeight: 'var(--text-4xl--line-height)',
|
|
18
|
+
},
|
|
19
|
+
2: {
|
|
20
|
+
className: 'text-2xl',
|
|
21
|
+
fontSize: 'var(--text-2xl)',
|
|
22
|
+
lineHeight: 'var(--text-3xl--line-height)',
|
|
23
|
+
},
|
|
24
|
+
3: {
|
|
25
|
+
className: 'text-xl',
|
|
26
|
+
fontSize: 'var(--text-xl)',
|
|
27
|
+
lineHeight: 'var(--text-2xl--line-height)',
|
|
28
|
+
},
|
|
29
|
+
4: {
|
|
30
|
+
className: 'text-lg',
|
|
31
|
+
fontSize: 'var(--text-lg)',
|
|
32
|
+
lineHeight: 'var(--text-xl--line-height)',
|
|
33
|
+
},
|
|
34
|
+
5: {
|
|
35
|
+
className: 'text-base',
|
|
36
|
+
fontSize: 'var(--text-base)',
|
|
37
|
+
lineHeight: 'var(--text-lg--line-height)',
|
|
38
|
+
},
|
|
39
|
+
6: {
|
|
40
|
+
className: 'text-base',
|
|
41
|
+
fontSize: 'var(--text-base)',
|
|
42
|
+
lineHeight: 'var(--text-base--line-height)',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Font families matching --font-body and --font-mono in theme.css.
|
|
47
|
+
export const fontBody = '"Inter Variable", ui-sans-serif, system-ui, sans-serif';
|
|
48
|
+
export const fontMono = '"JetBrains Mono Variable", ui-monospace, "Cascadia Code", "Source Code Pro", monospace';
|
|
49
|
+
|
|
50
|
+
export const markdownTheme = {
|
|
51
|
+
code: 'font-mono! cm-code-inline',
|
|
52
|
+
codeMark: 'font-mono! cm-code-mark',
|
|
53
|
+
mark: 'font-mono!',
|
|
54
|
+
heading: (level: HeadingLevel) => ({
|
|
55
|
+
className: mx(headings[level].className, 'font-light text-(--color-cm-heading-number)'),
|
|
56
|
+
color: 'var(--color-cm-heading) !important',
|
|
57
|
+
lineHeight: headings[level].lineHeight,
|
|
58
|
+
fontSize: headings[level].fontSize,
|
|
59
|
+
fontWeight: '100 !important',
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
9
62
|
|
|
10
63
|
/**
|
|
11
64
|
* Global base theme.
|
|
@@ -43,6 +96,9 @@ import { fontBody, fontMono } from './tokens';
|
|
|
43
96
|
* </div>
|
|
44
97
|
*/
|
|
45
98
|
export const baseTheme = EditorView.baseTheme({
|
|
99
|
+
/**
|
|
100
|
+
* Outer frame.
|
|
101
|
+
*/
|
|
46
102
|
'&': {},
|
|
47
103
|
'&.cm-focused': {
|
|
48
104
|
outline: 'none',
|
|
@@ -52,7 +108,27 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
52
108
|
* Scroller
|
|
53
109
|
*/
|
|
54
110
|
'.cm-scroller': {
|
|
55
|
-
|
|
111
|
+
// Browser scroll-anchoring: see comment in `scroller.ts`. `auto` lets the browser pin a
|
|
112
|
+
// stable element near the viewport top so widget resizes (e.g. tool-block TogglePanel
|
|
113
|
+
// open/close) don't jump the user's view.
|
|
114
|
+
overflowAnchor: 'auto',
|
|
115
|
+
},
|
|
116
|
+
'.cm-scroller::-webkit-scrollbar': {
|
|
117
|
+
width: 'var(--scrollbar-size,8px)',
|
|
118
|
+
height: 'var(--scrollbar-size,8px)',
|
|
119
|
+
},
|
|
120
|
+
'.cm-scroller::-webkit-scrollbar-corner': {
|
|
121
|
+
background: 'transparent',
|
|
122
|
+
},
|
|
123
|
+
'.cm-scroller::-webkit-scrollbar-track': {
|
|
124
|
+
background: 'transparent',
|
|
125
|
+
},
|
|
126
|
+
'.cm-scroller::-webkit-scrollbar-thumb': {
|
|
127
|
+
background: 'transparent',
|
|
128
|
+
transition: 'background 0.15s',
|
|
129
|
+
},
|
|
130
|
+
'&:hover .cm-scroller::-webkit-scrollbar-thumb': {
|
|
131
|
+
background: 'var(--color-scrollbar-thumb)',
|
|
56
132
|
},
|
|
57
133
|
|
|
58
134
|
/**
|
|
@@ -61,7 +137,6 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
61
137
|
*/
|
|
62
138
|
'.cm-content': {
|
|
63
139
|
padding: 'unset',
|
|
64
|
-
lineHeight: '24px',
|
|
65
140
|
color: 'unset',
|
|
66
141
|
},
|
|
67
142
|
|
|
@@ -76,8 +151,8 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
76
151
|
'.cm-gutter': {},
|
|
77
152
|
'.cm-gutter.cm-lineNumbers': {
|
|
78
153
|
paddingRight: '4px',
|
|
79
|
-
borderRight: '1px solid var(--
|
|
80
|
-
color: 'var(--
|
|
154
|
+
borderRight: '1px solid var(--color-subdued-separator)',
|
|
155
|
+
color: 'var(--color-subdued)',
|
|
81
156
|
},
|
|
82
157
|
'.cm-gutter.cm-lineNumbers .cm-gutterElement': {
|
|
83
158
|
minWidth: '40px',
|
|
@@ -94,31 +169,38 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
94
169
|
* Line.
|
|
95
170
|
*/
|
|
96
171
|
'.cm-line': {
|
|
97
|
-
lineHeight:
|
|
172
|
+
lineHeight: 1.5,
|
|
98
173
|
paddingInline: 0,
|
|
99
174
|
},
|
|
175
|
+
/**
|
|
176
|
+
* Force all inline children to inherit line-height to prevent monospace font metrics
|
|
177
|
+
* (JetBrains Mono ascent/descent) from inflating the line box beyond 24px.
|
|
178
|
+
*/
|
|
179
|
+
'.cm-line *': {
|
|
180
|
+
lineHeight: 'inherit',
|
|
181
|
+
},
|
|
100
182
|
'.cm-activeLine': {
|
|
101
|
-
background: 'var(--
|
|
183
|
+
background: 'var(--color-cm-active-line)',
|
|
102
184
|
},
|
|
103
185
|
|
|
104
186
|
/**
|
|
105
187
|
* Cursor (layer).
|
|
106
188
|
*/
|
|
107
189
|
'.cm-cursor, .cm-dropCursor': {
|
|
108
|
-
borderLeft: '2px solid var(--
|
|
190
|
+
borderLeft: '2px solid var(--color-cm-cursor)',
|
|
109
191
|
},
|
|
110
192
|
'.cm-placeholder': {
|
|
111
|
-
color: 'var(--
|
|
193
|
+
color: 'var(--color-placeholder)',
|
|
112
194
|
},
|
|
113
195
|
|
|
114
196
|
/**
|
|
115
197
|
* Selection (layer).
|
|
116
198
|
*/
|
|
117
199
|
'.cm-selectionBackground': {
|
|
118
|
-
background: 'var(--
|
|
200
|
+
background: 'var(--color-cm-selection)',
|
|
119
201
|
},
|
|
120
202
|
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
|
|
121
|
-
background: 'var(--
|
|
203
|
+
background: 'var(--color-cm-focused-selection)',
|
|
122
204
|
},
|
|
123
205
|
|
|
124
206
|
/**
|
|
@@ -129,8 +211,8 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
129
211
|
margin: '0 -3px',
|
|
130
212
|
padding: '3px',
|
|
131
213
|
borderRadius: '3px',
|
|
132
|
-
background: 'var(--
|
|
133
|
-
color: 'var(--
|
|
214
|
+
background: 'var(--color-cm-highlight-surface)',
|
|
215
|
+
color: 'var(--color-cm-highlight)',
|
|
134
216
|
},
|
|
135
217
|
'.cm-searchMatch-selected': {
|
|
136
218
|
textDecoration: 'underline',
|
|
@@ -142,21 +224,30 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
142
224
|
'.cm-link': {
|
|
143
225
|
textDecorationLine: 'underline',
|
|
144
226
|
textDecorationThickness: '1px',
|
|
145
|
-
textDecorationColor: 'var(--
|
|
227
|
+
textDecorationColor: 'var(--color-separator)',
|
|
146
228
|
textUnderlineOffset: '2px',
|
|
147
229
|
borderRadius: '.125rem',
|
|
148
230
|
},
|
|
149
231
|
'.cm-link > span': {
|
|
150
|
-
color: 'var(--
|
|
232
|
+
color: 'var(--color-accent-text)',
|
|
233
|
+
},
|
|
234
|
+
'.cm-link > span:hover': {
|
|
235
|
+
color: 'var(--color-accent-text-hover)',
|
|
151
236
|
},
|
|
152
237
|
|
|
153
238
|
/**
|
|
154
239
|
* Tooltip.
|
|
155
240
|
*/
|
|
156
241
|
'.cm-tooltip': {
|
|
157
|
-
background: 'var(--
|
|
242
|
+
background: 'var(--color-modal-surface)',
|
|
158
243
|
},
|
|
159
244
|
'.cm-tooltip-below': {},
|
|
245
|
+
'.cm-tooltip-hover': {
|
|
246
|
+
background: 'var(--color-modal-surface)',
|
|
247
|
+
border: '1px solid var(--color-separator)',
|
|
248
|
+
borderRadius: '4px',
|
|
249
|
+
overflow: 'hidden',
|
|
250
|
+
},
|
|
160
251
|
|
|
161
252
|
/**
|
|
162
253
|
* Autocomplete.
|
|
@@ -165,7 +256,7 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
165
256
|
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
166
257
|
marginTop: '6px',
|
|
167
258
|
marginLeft: '-10px',
|
|
168
|
-
border: '2px solid var(--
|
|
259
|
+
border: '2px solid var(--color-separator)',
|
|
169
260
|
borderRadius: '4px',
|
|
170
261
|
},
|
|
171
262
|
'.cm-tooltip.cm-tooltip-autocomplete > ul': {
|
|
@@ -175,12 +266,12 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
175
266
|
padding: '4px',
|
|
176
267
|
},
|
|
177
268
|
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
178
|
-
background: 'var(--
|
|
179
|
-
color: 'var(--
|
|
269
|
+
background: 'var(--color-active-surface)',
|
|
270
|
+
color: 'var(--color-base-surface-text)',
|
|
180
271
|
},
|
|
181
272
|
'.cm-tooltip.cm-tooltip-autocomplete > ul > completion-section': {
|
|
182
273
|
paddingLeft: '4px !important',
|
|
183
|
-
color: 'var(--
|
|
274
|
+
color: 'var(--color-base-surface-text)',
|
|
184
275
|
},
|
|
185
276
|
|
|
186
277
|
/**
|
|
@@ -190,17 +281,17 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
190
281
|
width: '360px !important',
|
|
191
282
|
margin: '-10px 1px 0 1px',
|
|
192
283
|
padding: '8px !important',
|
|
193
|
-
borderColor: 'var(--
|
|
284
|
+
borderColor: 'var(--color-separator)',
|
|
194
285
|
},
|
|
195
286
|
'.cm-completionIcon': {
|
|
196
287
|
display: 'none',
|
|
197
288
|
},
|
|
198
289
|
'.cm-completionLabel': {
|
|
199
|
-
color: 'var(--
|
|
290
|
+
color: 'var(--color-description)',
|
|
200
291
|
padding: '0 4px',
|
|
201
292
|
},
|
|
202
293
|
'.cm-completionMatchedText': {
|
|
203
|
-
color: 'var(--
|
|
294
|
+
color: 'var(--color-base-surface-text)',
|
|
204
295
|
textDecoration: 'none !important',
|
|
205
296
|
},
|
|
206
297
|
|
|
@@ -225,7 +316,7 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
225
316
|
backgroundColor: 'var(--surface-bg)',
|
|
226
317
|
},
|
|
227
318
|
'.cm-panel input, .cm-panel button, .cm-panel label': {
|
|
228
|
-
color: 'var(--
|
|
319
|
+
color: 'var(--color-subdued)',
|
|
229
320
|
fontSize: '14px',
|
|
230
321
|
all: 'unset',
|
|
231
322
|
margin: '3px !important',
|
|
@@ -233,10 +324,10 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
233
324
|
outline: '1px solid transparent',
|
|
234
325
|
},
|
|
235
326
|
'.cm-panel input, .cm-panel button': {
|
|
236
|
-
backgroundColor: 'var(--
|
|
327
|
+
backgroundColor: 'var(--color-input-surface)',
|
|
237
328
|
},
|
|
238
329
|
'.cm-panel input:focus, .cm-panel button:focus': {
|
|
239
|
-
outline: '1px solid var(--
|
|
330
|
+
outline: '1px solid var(--color-neutral-focus-indicator)',
|
|
240
331
|
},
|
|
241
332
|
'.cm-panel label': {
|
|
242
333
|
display: 'inline-flex',
|
|
@@ -249,26 +340,27 @@ export const baseTheme = EditorView.baseTheme({
|
|
|
249
340
|
height: '8px',
|
|
250
341
|
marginRight: '6px !important',
|
|
251
342
|
padding: '2px !important',
|
|
252
|
-
color: 'var(--
|
|
343
|
+
color: 'var(--color-neutral-focus-indicator)',
|
|
253
344
|
},
|
|
254
345
|
'.cm-panel button': {
|
|
255
346
|
'&:hover': {
|
|
256
|
-
|
|
347
|
+
// TODO(burdon): Replace with layer and @apply bg-accent-surface-hover
|
|
348
|
+
backgroundColor: 'var(--color-accent-surface-hover) !important',
|
|
257
349
|
},
|
|
258
350
|
'&:active': {
|
|
259
|
-
backgroundColor: 'var(--
|
|
351
|
+
backgroundColor: 'var(--color-accent-surface-hover)',
|
|
260
352
|
},
|
|
261
353
|
},
|
|
262
354
|
'.cm-panel.cm-search': {
|
|
263
355
|
padding: '4px',
|
|
264
|
-
borderTop: '1px solid var(--
|
|
356
|
+
borderTop: '1px solid var(--color-separator)',
|
|
265
357
|
},
|
|
266
358
|
});
|
|
267
359
|
|
|
268
360
|
export const editorGutter: Extension = EditorView.theme({
|
|
269
361
|
'.cm-gutters': {
|
|
270
362
|
// NOTE: Non-transparent background required to cover content if scrolling horizontally.
|
|
271
|
-
background: 'var(--
|
|
363
|
+
background: 'var(--color-base-surface) !important',
|
|
272
364
|
paddingRight: '1rem',
|
|
273
365
|
},
|
|
274
366
|
});
|
|
@@ -279,10 +371,9 @@ export type FontOptions = {
|
|
|
279
371
|
|
|
280
372
|
export const createFontTheme = ({ monospace }: FontOptions = {}) =>
|
|
281
373
|
EditorView.theme({
|
|
282
|
-
//
|
|
374
|
+
// Main content.
|
|
283
375
|
'.cm-scroller': {
|
|
284
376
|
fontFamily: monospace ? fontMono : fontBody,
|
|
285
|
-
fontSize: '16px',
|
|
286
377
|
},
|
|
287
378
|
|
|
288
379
|
// Maintain defaults for UI components.
|
package/src/types/types.ts
CHANGED
|
@@ -24,9 +24,17 @@ export type Comment = {
|
|
|
24
24
|
export type RenderCallback<Props extends object> = (el: HTMLElement, props: Props, view: EditorView) => void;
|
|
25
25
|
|
|
26
26
|
export const EditorViewModes = ['preview', 'readonly', 'source'] as const;
|
|
27
|
-
export const EditorViewMode = Schema.Union(
|
|
27
|
+
export const EditorViewMode = Schema.Union(
|
|
28
|
+
Schema.Literal('preview').annotations({ title: 'Preview' }),
|
|
29
|
+
Schema.Literal('readonly').annotations({ title: 'Read-only' }),
|
|
30
|
+
Schema.Literal('source').annotations({ title: 'Source' }),
|
|
31
|
+
);
|
|
28
32
|
export type EditorViewMode = Schema.Schema.Type<typeof EditorViewMode>;
|
|
29
33
|
|
|
30
34
|
export const EditorInputModes = ['default', 'vim', 'vscode'] as const;
|
|
31
|
-
export const EditorInputMode = Schema.Union(
|
|
35
|
+
export const EditorInputMode = Schema.Union(
|
|
36
|
+
Schema.Literal('default').annotations({ title: 'Default' }),
|
|
37
|
+
Schema.Literal('vim').annotations({ title: 'Vim' }),
|
|
38
|
+
Schema.Literal('vscode').annotations({ title: 'VS Code' }),
|
|
39
|
+
);
|
|
32
40
|
export type EditorInputMode = Schema.Schema.Type<typeof EditorInputMode>;
|