@react-x11/components 0.8.0 → 0.9.0
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/README.md +95 -34
- package/dist/charts/node.d.ts +1 -1
- package/dist/charts/node.d.ts.map +1 -1
- package/dist/charts/node.js +6 -2
- package/dist/charts/node.js.map +1 -1
- package/dist/embed/client.d.ts +48 -3
- package/dist/embed/client.d.ts.map +1 -1
- package/dist/embed/client.js +79 -5
- package/dist/embed/client.js.map +1 -1
- package/dist/embed/index.d.ts +1 -1
- package/dist/embed/index.d.ts.map +1 -1
- package/dist/embed/index.js +1 -1
- package/dist/embed/index.js.map +1 -1
- package/dist/html/node.d.ts +3 -1
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +7 -5
- package/dist/html/node.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{markdown → internal/markdown}/ast.d.ts +12 -0
- package/dist/internal/markdown/ast.d.ts.map +1 -0
- package/dist/internal/markdown/ast.js +22 -0
- package/dist/internal/markdown/ast.js.map +1 -0
- package/dist/internal/markdown/parse.d.ts.map +1 -0
- package/dist/{markdown → internal/markdown}/parse.js +112 -22
- package/dist/internal/markdown/parse.js.map +1 -0
- package/dist/internal/markdown/stringify.d.ts +4 -0
- package/dist/internal/markdown/stringify.d.ts.map +1 -0
- package/dist/internal/markdown/stringify.js +684 -0
- package/dist/internal/markdown/stringify.js.map +1 -0
- package/dist/internal/markdown/tags.d.ts.map +1 -0
- package/dist/internal/markdown/tags.js.map +1 -0
- package/dist/internal/scroll.d.ts +3 -2
- package/dist/internal/scroll.d.ts.map +1 -1
- package/dist/internal/scroll.js +1 -0
- package/dist/internal/scroll.js.map +1 -1
- package/dist/maps/anchors.d.ts +98 -0
- package/dist/maps/anchors.d.ts.map +1 -0
- package/dist/maps/anchors.js +531 -0
- package/dist/maps/anchors.js.map +1 -0
- package/dist/maps/controller.d.ts +283 -0
- package/dist/maps/controller.d.ts.map +1 -0
- package/dist/maps/controller.js +743 -0
- package/dist/maps/controller.js.map +1 -0
- package/dist/maps/gl/buckets.d.ts +95 -0
- package/dist/maps/gl/buckets.d.ts.map +1 -0
- package/dist/maps/gl/buckets.js +362 -0
- package/dist/maps/gl/buckets.js.map +1 -0
- package/dist/maps/gl/build-worker.d.ts +13 -0
- package/dist/maps/gl/build-worker.d.ts.map +1 -0
- package/dist/maps/gl/build-worker.js +44 -0
- package/dist/maps/gl/build-worker.js.map +1 -0
- package/dist/maps/gl/color.d.ts +8 -0
- package/dist/maps/gl/color.d.ts.map +1 -0
- package/dist/maps/gl/color.js +57 -0
- package/dist/maps/gl/color.js.map +1 -0
- package/dist/maps/gl/cover.d.ts +51 -0
- package/dist/maps/gl/cover.d.ts.map +1 -0
- package/dist/maps/gl/cover.js +124 -0
- package/dist/maps/gl/cover.js.map +1 -0
- package/dist/maps/gl/index.d.ts +3 -0
- package/dist/maps/gl/index.d.ts.map +1 -0
- package/dist/maps/gl/index.js +20 -0
- package/dist/maps/gl/index.js.map +1 -0
- package/dist/maps/gl/markers.d.ts +28 -0
- package/dist/maps/gl/markers.d.ts.map +1 -0
- package/dist/maps/gl/markers.js +60 -0
- package/dist/maps/gl/markers.js.map +1 -0
- package/dist/maps/gl/overlays.d.ts +68 -0
- package/dist/maps/gl/overlays.d.ts.map +1 -0
- package/dist/maps/gl/overlays.js +300 -0
- package/dist/maps/gl/overlays.js.map +1 -0
- package/dist/maps/gl/pane.d.ts +12 -0
- package/dist/maps/gl/pane.d.ts.map +1 -0
- package/dist/maps/gl/pane.js +37 -0
- package/dist/maps/gl/pane.js.map +1 -0
- package/dist/maps/gl/placement.d.ts +111 -0
- package/dist/maps/gl/placement.d.ts.map +1 -0
- package/dist/maps/gl/placement.js +567 -0
- package/dist/maps/gl/placement.js.map +1 -0
- package/dist/maps/gl/renderer.d.ts +352 -0
- package/dist/maps/gl/renderer.d.ts.map +1 -0
- package/dist/maps/gl/renderer.js +1127 -0
- package/dist/maps/gl/renderer.js.map +1 -0
- package/dist/maps/gl/shaders.d.ts +120 -0
- package/dist/maps/gl/shaders.d.ts.map +1 -0
- package/dist/maps/gl/shaders.js +451 -0
- package/dist/maps/gl/shaders.js.map +1 -0
- package/dist/maps/gl/store.d.ts +115 -0
- package/dist/maps/gl/store.d.ts.map +1 -0
- package/dist/maps/gl/store.js +469 -0
- package/dist/maps/gl/store.js.map +1 -0
- package/dist/maps/gl/text.d.ts +154 -0
- package/dist/maps/gl/text.d.ts.map +1 -0
- package/dist/maps/gl/text.js +382 -0
- package/dist/maps/gl/text.js.map +1 -0
- package/dist/maps/gl/view.d.ts +54 -0
- package/dist/maps/gl/view.d.ts.map +1 -0
- package/dist/maps/gl/view.js +974 -0
- package/dist/maps/gl/view.js.map +1 -0
- package/dist/maps/index.d.ts +1 -1
- package/dist/maps/index.d.ts.map +1 -1
- package/dist/maps/index.js +216 -52
- package/dist/maps/index.js.map +1 -1
- package/dist/maps/labels.d.ts +37 -16
- package/dist/maps/labels.d.ts.map +1 -1
- package/dist/maps/labels.js +188 -119
- package/dist/maps/labels.js.map +1 -1
- package/dist/maps/node.d.ts +162 -56
- package/dist/maps/node.d.ts.map +1 -1
- package/dist/maps/node.js +607 -515
- package/dist/maps/node.js.map +1 -1
- package/dist/maps/overlay.d.ts +72 -9
- package/dist/maps/overlay.d.ts.map +1 -1
- package/dist/maps/overlay.js +108 -28
- package/dist/maps/overlay.js.map +1 -1
- package/dist/maps/paint.d.ts +3 -0
- package/dist/maps/paint.d.ts.map +1 -1
- package/dist/maps/paint.js.map +1 -1
- package/dist/maps/proj.d.ts +14 -0
- package/dist/maps/proj.d.ts.map +1 -1
- package/dist/maps/proj.js +28 -0
- package/dist/maps/proj.js.map +1 -1
- package/dist/maps/renderer.d.ts +69 -0
- package/dist/maps/renderer.d.ts.map +1 -0
- package/dist/maps/renderer.js +66 -0
- package/dist/maps/renderer.js.map +1 -0
- package/dist/maps/sources.d.ts +25 -3
- package/dist/maps/sources.d.ts.map +1 -1
- package/dist/maps/sources.js +17 -0
- package/dist/maps/sources.js.map +1 -1
- package/dist/maps/theme.d.ts +19 -0
- package/dist/maps/theme.d.ts.map +1 -0
- package/dist/maps/theme.js +44 -0
- package/dist/maps/theme.js.map +1 -0
- package/dist/maps/tiles.d.ts +117 -17
- package/dist/maps/tiles.d.ts.map +1 -1
- package/dist/maps/tiles.js +163 -30
- package/dist/maps/tiles.js.map +1 -1
- package/dist/maps/types.d.ts +188 -20
- package/dist/maps/types.d.ts.map +1 -1
- package/dist/markdown/expressions.d.ts +1 -1
- package/dist/markdown/expressions.d.ts.map +1 -1
- package/dist/markdown/expressions.js.map +1 -1
- package/dist/markdown/index.d.ts +7 -6
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +9 -7
- package/dist/markdown/index.js.map +1 -1
- package/dist/markdown/spans.d.ts +1 -1
- package/dist/markdown/spans.d.ts.map +1 -1
- package/dist/media-player/index.d.ts +11 -3
- package/dist/media-player/index.d.ts.map +1 -1
- package/dist/media-player/index.js +13 -2
- package/dist/media-player/index.js.map +1 -1
- package/dist/rich-text-editor/clipboard.d.ts +23 -0
- package/dist/rich-text-editor/clipboard.d.ts.map +1 -0
- package/dist/rich-text-editor/clipboard.js +307 -0
- package/dist/rich-text-editor/clipboard.js.map +1 -0
- package/dist/rich-text-editor/collab.d.ts +32 -0
- package/dist/rich-text-editor/collab.d.ts.map +1 -0
- package/dist/rich-text-editor/collab.js +55 -0
- package/dist/rich-text-editor/collab.js.map +1 -0
- package/dist/rich-text-editor/commands.d.ts +50 -0
- package/dist/rich-text-editor/commands.d.ts.map +1 -0
- package/dist/rich-text-editor/commands.js +376 -0
- package/dist/rich-text-editor/commands.js.map +1 -0
- package/dist/rich-text-editor/drag.d.ts +68 -0
- package/dist/rich-text-editor/drag.d.ts.map +1 -0
- package/dist/rich-text-editor/drag.js +148 -0
- package/dist/rich-text-editor/drag.js.map +1 -0
- package/dist/rich-text-editor/html.d.ts +145 -0
- package/dist/rich-text-editor/html.d.ts.map +1 -0
- package/dist/rich-text-editor/html.js +516 -0
- package/dist/rich-text-editor/html.js.map +1 -0
- package/dist/rich-text-editor/index.d.ts +263 -0
- package/dist/rich-text-editor/index.d.ts.map +1 -0
- package/dist/rich-text-editor/index.js +822 -0
- package/dist/rich-text-editor/index.js.map +1 -0
- package/dist/rich-text-editor/inline.d.ts +94 -0
- package/dist/rich-text-editor/inline.d.ts.map +1 -0
- package/dist/rich-text-editor/inline.js +252 -0
- package/dist/rich-text-editor/inline.js.map +1 -0
- package/dist/rich-text-editor/keymap.d.ts +71 -0
- package/dist/rich-text-editor/keymap.d.ts.map +1 -0
- package/dist/rich-text-editor/keymap.js +393 -0
- package/dist/rich-text-editor/keymap.js.map +1 -0
- package/dist/rich-text-editor/keys.d.ts +29 -0
- package/dist/rich-text-editor/keys.d.ts.map +1 -0
- package/dist/rich-text-editor/keys.js +93 -0
- package/dist/rich-text-editor/keys.js.map +1 -0
- package/dist/rich-text-editor/look.d.ts +71 -0
- package/dist/rich-text-editor/look.d.ts.map +1 -0
- package/dist/rich-text-editor/look.js +342 -0
- package/dist/rich-text-editor/look.js.map +1 -0
- package/dist/rich-text-editor/markdown.d.ts +18 -0
- package/dist/rich-text-editor/markdown.d.ts.map +1 -0
- package/dist/rich-text-editor/markdown.js +496 -0
- package/dist/rich-text-editor/markdown.js.map +1 -0
- package/dist/rich-text-editor/nodes.d.ts +135 -0
- package/dist/rich-text-editor/nodes.d.ts.map +1 -0
- package/dist/rich-text-editor/nodes.js +397 -0
- package/dist/rich-text-editor/nodes.js.map +1 -0
- package/dist/rich-text-editor/render.d.ts +68 -0
- package/dist/rich-text-editor/render.d.ts.map +1 -0
- package/dist/rich-text-editor/render.js +500 -0
- package/dist/rich-text-editor/render.js.map +1 -0
- package/dist/rich-text-editor/schema.d.ts +16 -0
- package/dist/rich-text-editor/schema.d.ts.map +1 -0
- package/dist/rich-text-editor/schema.js +386 -0
- package/dist/rich-text-editor/schema.js.map +1 -0
- package/dist/rich-text-editor/store.d.ts +11 -0
- package/dist/rich-text-editor/store.d.ts.map +1 -0
- package/dist/rich-text-editor/store.js +43 -0
- package/dist/rich-text-editor/store.js.map +1 -0
- package/dist/rich-text-editor/suggest.d.ts +127 -0
- package/dist/rich-text-editor/suggest.d.ts.map +1 -0
- package/dist/rich-text-editor/suggest.js +0 -0
- package/dist/rich-text-editor/suggest.js.map +1 -0
- package/dist/rich-text-editor/tables.d.ts +41 -0
- package/dist/rich-text-editor/tables.d.ts.map +1 -0
- package/dist/rich-text-editor/tables.js +204 -0
- package/dist/rich-text-editor/tables.js.map +1 -0
- package/dist/rich-text-editor/toolbar.d.ts +58 -0
- package/dist/rich-text-editor/toolbar.d.ts.map +1 -0
- package/dist/rich-text-editor/toolbar.js +548 -0
- package/dist/rich-text-editor/toolbar.js.map +1 -0
- package/dist/rich-text-editor/view.d.ts +368 -0
- package/dist/rich-text-editor/view.d.ts.map +1 -0
- package/dist/rich-text-editor/view.js +1968 -0
- package/dist/rich-text-editor/view.js.map +1 -0
- package/dist/rich-text-editor/virtual.d.ts +54 -0
- package/dist/rich-text-editor/virtual.d.ts.map +1 -0
- package/dist/rich-text-editor/virtual.js +262 -0
- package/dist/rich-text-editor/virtual.js.map +1 -0
- package/dist/richtext/node.d.ts +25 -2
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +46 -24
- package/dist/richtext/node.js.map +1 -1
- package/dist/terminal/backends.d.ts +4 -1
- package/dist/terminal/backends.d.ts.map +1 -1
- package/dist/terminal/backends.js.map +1 -1
- package/dist/terminal/index.d.ts +18 -7
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +28 -11
- package/dist/terminal/index.js.map +1 -1
- package/package.json +23 -4
- package/src/charts/node.ts +6 -2
- package/src/embed/client.ts +102 -8
- package/src/embed/index.ts +2 -0
- package/src/html/node.ts +7 -5
- package/src/index.ts +2 -0
- package/src/{markdown → internal/markdown}/ast.ts +24 -7
- package/src/{markdown → internal/markdown}/parse.ts +134 -24
- package/src/internal/markdown/stringify.ts +772 -0
- package/src/internal/scroll.ts +5 -3
- package/src/maps/anchors.ts +607 -0
- package/src/maps/controller.ts +999 -0
- package/src/maps/gl/buckets.ts +457 -0
- package/src/maps/gl/build-worker.ts +55 -0
- package/src/maps/gl/color.ts +62 -0
- package/src/maps/gl/cover.ts +170 -0
- package/src/maps/gl/index.ts +23 -0
- package/src/maps/gl/markers.ts +83 -0
- package/src/maps/gl/overlays.ts +379 -0
- package/src/maps/gl/pane.ts +42 -0
- package/src/maps/gl/placement.ts +816 -0
- package/src/maps/gl/renderer.ts +1576 -0
- package/src/maps/gl/shaders.ts +486 -0
- package/src/maps/gl/store.ts +566 -0
- package/src/maps/gl/text.ts +495 -0
- package/src/maps/gl/view.ts +1224 -0
- package/src/maps/index.ts +270 -81
- package/src/maps/labels.ts +214 -121
- package/src/maps/node.ts +763 -629
- package/src/maps/overlay.ts +148 -43
- package/src/maps/paint.ts +3 -0
- package/src/maps/proj.ts +31 -0
- package/src/maps/renderer.ts +155 -0
- package/src/maps/sources.ts +38 -3
- package/src/maps/theme.ts +51 -0
- package/src/maps/tiles.ts +191 -33
- package/src/maps/types.ts +188 -20
- package/src/markdown/expressions.ts +5 -1
- package/src/markdown/index.ts +14 -11
- package/src/markdown/spans.ts +1 -1
- package/src/media-player/index.ts +18 -4
- package/src/rich-text-editor/clipboard.ts +439 -0
- package/src/rich-text-editor/collab.ts +91 -0
- package/src/rich-text-editor/commands.ts +448 -0
- package/src/rich-text-editor/dom-globals.d.ts +23 -0
- package/src/rich-text-editor/drag.ts +211 -0
- package/src/rich-text-editor/html.ts +619 -0
- package/src/rich-text-editor/index.ts +1331 -0
- package/src/rich-text-editor/inline.ts +345 -0
- package/src/rich-text-editor/keymap.ts +510 -0
- package/src/rich-text-editor/keys.ts +119 -0
- package/src/rich-text-editor/look.ts +427 -0
- package/src/rich-text-editor/markdown.ts +653 -0
- package/src/rich-text-editor/nodes.ts +497 -0
- package/src/rich-text-editor/render.ts +800 -0
- package/src/rich-text-editor/schema.ts +431 -0
- package/src/rich-text-editor/store.ts +39 -0
- package/src/rich-text-editor/suggest.ts +597 -0
- package/src/rich-text-editor/tables.ts +272 -0
- package/src/rich-text-editor/toolbar.ts +724 -0
- package/src/rich-text-editor/view.ts +2287 -0
- package/src/rich-text-editor/virtual.ts +347 -0
- package/src/richtext/node.ts +59 -30
- package/src/terminal/backends.ts +4 -1
- package/src/terminal/index.ts +43 -15
- package/dist/markdown/ast.d.ts.map +0 -1
- package/dist/markdown/ast.js +0 -17
- package/dist/markdown/ast.js.map +0 -1
- package/dist/markdown/parse.d.ts.map +0 -1
- package/dist/markdown/parse.js.map +0 -1
- package/dist/markdown/tags.d.ts.map +0 -1
- package/dist/markdown/tags.js.map +0 -1
- /package/dist/{markdown → internal/markdown}/parse.d.ts +0 -0
- /package/dist/{markdown → internal/markdown}/tags.d.ts +0 -0
- /package/dist/{markdown → internal/markdown}/tags.js +0 -0
- /package/src/{markdown → internal/markdown}/tags.ts +0 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
// What the document looks like: the theme, read once per render, into the
|
|
2
|
+
// styles every block and mark is drawn with.
|
|
3
|
+
//
|
|
4
|
+
// The numbers are `<Markdown>`'s (src/markdown/index.ts, `deriveLook`) — the
|
|
5
|
+
// heading scales, the block gap, the chip behind inline code — and a fenced
|
|
6
|
+
// block's whole look comes from the same shared module both use
|
|
7
|
+
// (`src/codeblock/`). A component never imports another, so the two are kept
|
|
8
|
+
// in step by value: a note edited here and rendered there should look like
|
|
9
|
+
// one document, and a change to one of these numbers belongs in both.
|
|
10
|
+
//
|
|
11
|
+
// A schema this file has never heard of still gets a look. A node or mark is
|
|
12
|
+
// recognised by name first (the reference schema's, then TipTap's), and then
|
|
13
|
+
// by the tag its own `toDOM` writes: an unknown node that says `['h2', 0]` is
|
|
14
|
+
// a second-level heading, an unknown mark that says `['u', 0]` underlines, and
|
|
15
|
+
// a `style` attribute on either is read for the few properties text can
|
|
16
|
+
// carry. The app's `markStyles` has the last word.
|
|
17
|
+
import { tint } from 'react-x11/style';
|
|
18
|
+
import type { Mark, Node as PMNode } from 'prosemirror-model';
|
|
19
|
+
|
|
20
|
+
import { codeBlockLook, codeBlockRuns } from '../codeblock/index.js';
|
|
21
|
+
import type { CodeBlockLook } from '../codeblock/index.js';
|
|
22
|
+
import type { Language } from '../code-language/index.js';
|
|
23
|
+
import type { InlineLook, RunStyle } from './inline.js';
|
|
24
|
+
|
|
25
|
+
/** How a mark looks: a fixed style, or one worked out from what it covers. */
|
|
26
|
+
export type MarkStyle = RunStyle | ((mark: Mark, under: RunStyle) => RunStyle);
|
|
27
|
+
|
|
28
|
+
export interface LookOptions {
|
|
29
|
+
fontSize?: number;
|
|
30
|
+
fontFamily?: string;
|
|
31
|
+
monoFamily?: string;
|
|
32
|
+
markStyles?: Readonly<Record<string, MarkStyle>>;
|
|
33
|
+
resolveLanguage?: (tag: string) => Language | null;
|
|
34
|
+
highlight?: boolean;
|
|
35
|
+
/** A disabled editor: the document is set in the muted ink. (react-x11
|
|
36
|
+
* styles have no opacity to fade a subtree with.) */
|
|
37
|
+
dim?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Where a textblock sits, as far as its look is concerned. */
|
|
41
|
+
export interface BlockContext {
|
|
42
|
+
/** Inside a blockquote: set in the muted ink, as `<Markdown>` sets it. */
|
|
43
|
+
quote: boolean;
|
|
44
|
+
/** A table's header row. */
|
|
45
|
+
header: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface EditorLook {
|
|
49
|
+
size: number;
|
|
50
|
+
family: string;
|
|
51
|
+
mono: string;
|
|
52
|
+
text: string;
|
|
53
|
+
muted: string;
|
|
54
|
+
link: string;
|
|
55
|
+
accent: string;
|
|
56
|
+
accentText: string;
|
|
57
|
+
border: string;
|
|
58
|
+
background: string;
|
|
59
|
+
surface: string;
|
|
60
|
+
selection: string;
|
|
61
|
+
/** The selection while focus is elsewhere — still there, but quieter. */
|
|
62
|
+
selectionBlurred: string;
|
|
63
|
+
caret: string;
|
|
64
|
+
codeBg: string;
|
|
65
|
+
headerBg: string;
|
|
66
|
+
highlight: string;
|
|
67
|
+
radius: number;
|
|
68
|
+
blockGap: number;
|
|
69
|
+
headingScales: readonly number[];
|
|
70
|
+
code: CodeBlockLook;
|
|
71
|
+
/** Two looks with the same key draw identically — the render cache's epoch. */
|
|
72
|
+
key: string;
|
|
73
|
+
/** A textblock's inline look. Cached: the same node type in the same
|
|
74
|
+
* context is the same object, which is what lets a block that did not
|
|
75
|
+
* change skip its layout. */
|
|
76
|
+
inline(node: PMNode, context: BlockContext): InlineLook;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const HEADING_SCALES = [1.75, 1.4, 1.2, 1.05, 0.95, 0.85] as const;
|
|
80
|
+
|
|
81
|
+
type Role =
|
|
82
|
+
| 'strong'
|
|
83
|
+
| 'em'
|
|
84
|
+
| 'code'
|
|
85
|
+
| 'strike'
|
|
86
|
+
| 'link'
|
|
87
|
+
| 'underline'
|
|
88
|
+
| 'highlight'
|
|
89
|
+
| 'sub'
|
|
90
|
+
| 'sup'
|
|
91
|
+
| 'textStyle';
|
|
92
|
+
|
|
93
|
+
const MARK_ROLES: Record<string, Role> = {
|
|
94
|
+
strong: 'strong',
|
|
95
|
+
bold: 'strong',
|
|
96
|
+
b: 'strong',
|
|
97
|
+
em: 'em',
|
|
98
|
+
italic: 'em',
|
|
99
|
+
i: 'em',
|
|
100
|
+
code: 'code',
|
|
101
|
+
strike: 'strike',
|
|
102
|
+
strikethrough: 'strike',
|
|
103
|
+
s: 'strike',
|
|
104
|
+
del: 'strike',
|
|
105
|
+
link: 'link',
|
|
106
|
+
a: 'link',
|
|
107
|
+
underline: 'underline',
|
|
108
|
+
u: 'underline',
|
|
109
|
+
highlight: 'highlight',
|
|
110
|
+
mark: 'highlight',
|
|
111
|
+
subscript: 'sub',
|
|
112
|
+
sub: 'sub',
|
|
113
|
+
superscript: 'sup',
|
|
114
|
+
sup: 'sup',
|
|
115
|
+
textStyle: 'textStyle',
|
|
116
|
+
span: 'textStyle',
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/** The tag and attributes a node's or mark's `toDOM` writes, if it writes an
|
|
120
|
+
* array — the one shape readable without a DOM. */
|
|
121
|
+
export function domTagOf(
|
|
122
|
+
spec: { toDOM?: unknown } | undefined,
|
|
123
|
+
value: unknown,
|
|
124
|
+
): { tag: string; attrs: Record<string, unknown> } | null {
|
|
125
|
+
const toDOM = spec?.toDOM as
|
|
126
|
+
((v: unknown, inline?: boolean) => unknown) | undefined;
|
|
127
|
+
if (typeof toDOM !== 'function') return null;
|
|
128
|
+
try {
|
|
129
|
+
const out = toDOM(value, true);
|
|
130
|
+
if (!Array.isArray(out) || typeof out[0] !== 'string') return null;
|
|
131
|
+
const second = out[1];
|
|
132
|
+
const attrs =
|
|
133
|
+
second && typeof second === 'object' && !Array.isArray(second)
|
|
134
|
+
? (second as Record<string, unknown>)
|
|
135
|
+
: {};
|
|
136
|
+
return { tag: out[0].replace(/^.*\s/, '').toLowerCase(), attrs };
|
|
137
|
+
} catch {
|
|
138
|
+
// a `toDOM` that builds real DOM nodes has no document to build them in
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The part of a CSS declaration block text can carry — colour, background,
|
|
145
|
+
* weight, style, decoration, family, pixel size. What a decoration's
|
|
146
|
+
* `style` attribute and an unknown mark's `toDOM` attributes are read
|
|
147
|
+
* through; everything else in them is ignored.
|
|
148
|
+
*/
|
|
149
|
+
export function styleFromCSS(css: string, under: RunStyle): RunStyle {
|
|
150
|
+
const out: RunStyle = {};
|
|
151
|
+
for (const decl of css.split(';')) {
|
|
152
|
+
const colon = decl.indexOf(':');
|
|
153
|
+
if (colon <= 0) continue;
|
|
154
|
+
const name = decl.slice(0, colon).trim().toLowerCase();
|
|
155
|
+
const value = decl.slice(colon + 1).trim();
|
|
156
|
+
if (!value) continue;
|
|
157
|
+
switch (name) {
|
|
158
|
+
case 'color':
|
|
159
|
+
out.color = value;
|
|
160
|
+
break;
|
|
161
|
+
case 'background':
|
|
162
|
+
case 'background-color':
|
|
163
|
+
out.bg = value;
|
|
164
|
+
break;
|
|
165
|
+
case 'font-weight': {
|
|
166
|
+
const n = Number(value);
|
|
167
|
+
if (value === 'bold' || value === 'bolder' || n >= 600)
|
|
168
|
+
out.weight = 700;
|
|
169
|
+
else if (value === 'normal' || (Number.isFinite(n) && n < 600))
|
|
170
|
+
out.weight = 'normal';
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'font-style':
|
|
174
|
+
out.style =
|
|
175
|
+
value === 'italic' || value === 'oblique' ? 'italic' : 'normal';
|
|
176
|
+
break;
|
|
177
|
+
case 'text-decoration':
|
|
178
|
+
case 'text-decoration-line':
|
|
179
|
+
if (/line-through/.test(value))
|
|
180
|
+
out.strike = out.color ?? under.color ?? 'currentColor';
|
|
181
|
+
if (/underline/.test(value))
|
|
182
|
+
out.underline = out.color ?? under.color ?? 'currentColor';
|
|
183
|
+
break;
|
|
184
|
+
case 'font-family':
|
|
185
|
+
out.family = value;
|
|
186
|
+
break;
|
|
187
|
+
case 'font-size': {
|
|
188
|
+
const px = /^(\d+(?:\.\d+)?)px$/.exec(value);
|
|
189
|
+
if (px) out.size = Number(px[1]);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function str(value: unknown, fallback: string): string {
|
|
198
|
+
return typeof value === 'string' && value ? value : fallback;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** The first word of a code block's info string — its language. */
|
|
202
|
+
function languageOf(node: PMNode): string {
|
|
203
|
+
const info = node.attrs.params ?? node.attrs.language ?? '';
|
|
204
|
+
return String(info).trim().split(/\s/, 1)[0].toLowerCase();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** What kind of textblock this is, for its look: its name, then its tag. */
|
|
208
|
+
function blockKind(node: PMNode): {
|
|
209
|
+
kind: 'paragraph' | 'heading' | 'code';
|
|
210
|
+
level: number;
|
|
211
|
+
} {
|
|
212
|
+
const name = node.type.name;
|
|
213
|
+
if (node.type.spec.code || name === 'code_block' || name === 'codeBlock') {
|
|
214
|
+
return { kind: 'code', level: 0 };
|
|
215
|
+
}
|
|
216
|
+
if (name === 'heading') {
|
|
217
|
+
return { kind: 'heading', level: Number(node.attrs.level ?? 1) };
|
|
218
|
+
}
|
|
219
|
+
const dom = domTagOf(node.type.spec, node);
|
|
220
|
+
const h = dom && /^h([1-6])$/.exec(dom.tag);
|
|
221
|
+
if (h) return { kind: 'heading', level: Number(h[1]) };
|
|
222
|
+
if (dom?.tag === 'pre') return { kind: 'code', level: 0 };
|
|
223
|
+
return { kind: 'paragraph', level: 0 };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export function deriveLook(
|
|
227
|
+
theme: Record<string, unknown>,
|
|
228
|
+
options: LookOptions,
|
|
229
|
+
): EditorLook {
|
|
230
|
+
const muted = str(theme.textMuted, '#7f8c8d');
|
|
231
|
+
const text = options.dim ? muted : str(theme.text, '#2d3436');
|
|
232
|
+
const accent = str(theme.accent, '#2980b9');
|
|
233
|
+
const accentText = str(theme.accentText, '#ffffff');
|
|
234
|
+
const link = str(theme.link, accent);
|
|
235
|
+
const border = str(theme.border, '#b2bec3');
|
|
236
|
+
const background = str(theme.background, '#ffffff');
|
|
237
|
+
const surface = str(theme.surface, background);
|
|
238
|
+
const size = options.fontSize ?? Number(theme.fontSize ?? 14);
|
|
239
|
+
const family = options.fontFamily ?? str(theme.fontFamily, 'sans-serif');
|
|
240
|
+
const mono = options.monoFamily ?? 'monospace';
|
|
241
|
+
const selection = str(theme.selection, tint(accent, 0.35));
|
|
242
|
+
const caret = str(theme.caret, text);
|
|
243
|
+
const code = codeBlockLook(theme, { baseSize: size, monoFamily: mono });
|
|
244
|
+
const codeBg = tint(text, 0.08);
|
|
245
|
+
const highlight = tint('#f5c400', 0.45);
|
|
246
|
+
const radius = Number(theme.radius ?? 6);
|
|
247
|
+
|
|
248
|
+
const markStyles = options.markStyles;
|
|
249
|
+
const resolveLanguage = options.resolveLanguage;
|
|
250
|
+
const highlightCode = options.highlight !== false;
|
|
251
|
+
|
|
252
|
+
const markStyle = (mark: Mark, under: RunStyle): RunStyle => {
|
|
253
|
+
const role =
|
|
254
|
+
MARK_ROLES[mark.type.name] ??
|
|
255
|
+
MARK_ROLES[domTagOf(mark.type.spec, mark)?.tag ?? ''];
|
|
256
|
+
let out: RunStyle = {};
|
|
257
|
+
switch (role) {
|
|
258
|
+
case 'strong':
|
|
259
|
+
out = { weight: 700 };
|
|
260
|
+
break;
|
|
261
|
+
case 'em':
|
|
262
|
+
out = { style: 'italic' };
|
|
263
|
+
break;
|
|
264
|
+
case 'code':
|
|
265
|
+
out = {
|
|
266
|
+
family: mono,
|
|
267
|
+
size: Math.round((under.size ?? size) * 0.9),
|
|
268
|
+
color: under.color === muted ? muted : text,
|
|
269
|
+
bg: codeBg,
|
|
270
|
+
};
|
|
271
|
+
break;
|
|
272
|
+
case 'strike':
|
|
273
|
+
out = { strike: under.color ?? text };
|
|
274
|
+
break;
|
|
275
|
+
case 'link': {
|
|
276
|
+
const href = mark.attrs.href;
|
|
277
|
+
out = {
|
|
278
|
+
color: link,
|
|
279
|
+
underline: link,
|
|
280
|
+
href: typeof href === 'string' ? href : null,
|
|
281
|
+
};
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
case 'underline':
|
|
285
|
+
out = { underline: under.color ?? text };
|
|
286
|
+
break;
|
|
287
|
+
case 'highlight':
|
|
288
|
+
out = { bg: str(mark.attrs.color, highlight) };
|
|
289
|
+
break;
|
|
290
|
+
case 'sub':
|
|
291
|
+
case 'sup':
|
|
292
|
+
out = { size: Math.round((under.size ?? size) * 0.8) };
|
|
293
|
+
break;
|
|
294
|
+
case 'textStyle': {
|
|
295
|
+
const a = mark.attrs as Record<string, unknown>;
|
|
296
|
+
if (typeof a.color === 'string') out.color = a.color;
|
|
297
|
+
if (typeof a.fontFamily === 'string') out.family = a.fontFamily;
|
|
298
|
+
if (typeof a.fontSize === 'string') {
|
|
299
|
+
const px = /^(\d+(?:\.\d+)?)px$/.exec(a.fontSize);
|
|
300
|
+
if (px) out.size = Number(px[1]);
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// an unknown mark's own `style` attribute, and a known one's too
|
|
306
|
+
const dom = domTagOf(mark.type.spec, mark);
|
|
307
|
+
if (dom && typeof dom.attrs.style === 'string') {
|
|
308
|
+
out = { ...out, ...styleFromCSS(dom.attrs.style, { ...under, ...out }) };
|
|
309
|
+
}
|
|
310
|
+
const custom = markStyles?.[mark.type.name];
|
|
311
|
+
if (custom) {
|
|
312
|
+
const merged = { ...under, ...out };
|
|
313
|
+
out = {
|
|
314
|
+
...out,
|
|
315
|
+
...(typeof custom === 'function' ? custom(mark, merged) : custom),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
return out;
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const atom = (node: PMNode): { text: string; style?: RunStyle } => {
|
|
322
|
+
const name = node.type.name;
|
|
323
|
+
if (
|
|
324
|
+
name === 'hard_break' ||
|
|
325
|
+
name === 'hardBreak' ||
|
|
326
|
+
domTagOf(node.type.spec, node)?.tag === 'br'
|
|
327
|
+
) {
|
|
328
|
+
return { text: '\n' };
|
|
329
|
+
}
|
|
330
|
+
if (name === 'image') {
|
|
331
|
+
const src = String(node.attrs.src ?? '');
|
|
332
|
+
const label =
|
|
333
|
+
str(node.attrs.alt, '') ||
|
|
334
|
+
str(node.attrs.title, '') ||
|
|
335
|
+
src.split(/[/\\]/).pop() ||
|
|
336
|
+
'image';
|
|
337
|
+
return { text: label, style: { color: muted, bg: codeBg } };
|
|
338
|
+
}
|
|
339
|
+
const leaf = node.type.spec.leafText?.(node) ?? '';
|
|
340
|
+
return { text: leaf || name, style: { color: muted, bg: codeBg } };
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const cache = new Map<string, InlineLook>();
|
|
344
|
+
const inline = (node: PMNode, context: BlockContext): InlineLook => {
|
|
345
|
+
const { kind, level } = blockKind(node);
|
|
346
|
+
const lang = kind === 'code' ? languageOf(node) : '';
|
|
347
|
+
const key = `${node.type.name}|${kind}|${level}|${lang}|${context.quote ? 'q' : ''}${context.header ? 'h' : ''}`;
|
|
348
|
+
const hit = cache.get(key);
|
|
349
|
+
if (hit) return hit;
|
|
350
|
+
const ink = context.quote ? muted : text;
|
|
351
|
+
let base: RunStyle;
|
|
352
|
+
if (kind === 'heading') {
|
|
353
|
+
const scale = HEADING_SCALES[Math.max(1, Math.min(6, level)) - 1];
|
|
354
|
+
base = {
|
|
355
|
+
family,
|
|
356
|
+
size: Math.round(size * scale),
|
|
357
|
+
weight: 700,
|
|
358
|
+
color: ink,
|
|
359
|
+
};
|
|
360
|
+
} else if (kind === 'code') {
|
|
361
|
+
base = { family: code.family, size: code.size, color: code.color };
|
|
362
|
+
} else {
|
|
363
|
+
base = {
|
|
364
|
+
family,
|
|
365
|
+
size,
|
|
366
|
+
color: ink,
|
|
367
|
+
...(context.header ? { weight: 700 } : null),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
const look: InlineLook = {
|
|
371
|
+
base,
|
|
372
|
+
mark: markStyle,
|
|
373
|
+
atom,
|
|
374
|
+
...(kind === 'code'
|
|
375
|
+
? {
|
|
376
|
+
code: (source: string) =>
|
|
377
|
+
codeBlockRuns(source, code, {
|
|
378
|
+
lang,
|
|
379
|
+
highlight: highlightCode,
|
|
380
|
+
...(resolveLanguage ? { resolveLanguage } : null),
|
|
381
|
+
}),
|
|
382
|
+
}
|
|
383
|
+
: null),
|
|
384
|
+
};
|
|
385
|
+
cache.set(key, look);
|
|
386
|
+
return look;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
size,
|
|
391
|
+
family,
|
|
392
|
+
mono,
|
|
393
|
+
text,
|
|
394
|
+
muted,
|
|
395
|
+
link,
|
|
396
|
+
accent,
|
|
397
|
+
accentText,
|
|
398
|
+
border,
|
|
399
|
+
background,
|
|
400
|
+
surface,
|
|
401
|
+
selection,
|
|
402
|
+
selectionBlurred: tint(text, 0.14),
|
|
403
|
+
caret,
|
|
404
|
+
codeBg,
|
|
405
|
+
headerBg: tint(text, 0.05),
|
|
406
|
+
highlight,
|
|
407
|
+
radius,
|
|
408
|
+
blockGap: Math.round(size * 0.7),
|
|
409
|
+
headingScales: HEADING_SCALES,
|
|
410
|
+
code,
|
|
411
|
+
key: [
|
|
412
|
+
text,
|
|
413
|
+
muted,
|
|
414
|
+
link,
|
|
415
|
+
accent,
|
|
416
|
+
border,
|
|
417
|
+
background,
|
|
418
|
+
size,
|
|
419
|
+
family,
|
|
420
|
+
mono,
|
|
421
|
+
selection,
|
|
422
|
+
caret,
|
|
423
|
+
highlightCode,
|
|
424
|
+
].join('|'),
|
|
425
|
+
inline,
|
|
426
|
+
};
|
|
427
|
+
}
|