@textui/core 0.1.0 → 0.3.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 +17 -20
- package/dist/app/app.d.ts +64 -0
- package/dist/app/app.d.ts.map +1 -1
- package/dist/app/app.js +202 -1
- package/dist/core/focus.d.ts.map +1 -1
- package/dist/core/focus.js +12 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +2 -10
- package/dist/jsx/intrinsics.d.ts +18 -0
- package/dist/jsx/intrinsics.d.ts.map +1 -1
- package/dist/render/layout.js +10 -2
- package/dist/runtime/bindings.d.ts.map +1 -1
- package/dist/runtime/bindings.js +31 -4
- package/dist/runtime/hooks.d.ts +14 -2
- package/dist/runtime/hooks.d.ts.map +1 -1
- package/dist/runtime/hooks.js +15 -4
- package/dist/themes/builtin.d.ts +2 -0
- package/dist/themes/builtin.d.ts.map +1 -1
- package/dist/themes/builtin.js +64 -1
- package/dist/themes/dividers.d.ts +14 -0
- package/dist/themes/dividers.d.ts.map +1 -0
- package/dist/themes/dividers.js +42 -0
- package/dist/themes/glyphs.d.ts.map +1 -1
- package/dist/themes/glyphs.js +4 -0
- package/dist/themes/index.d.ts +1 -0
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +1 -0
- package/dist/themes/registry.d.ts.map +1 -1
- package/dist/themes/registry.js +31 -1
- package/dist/types/app.d.ts +15 -0
- package/dist/types/app.d.ts.map +1 -1
- package/dist/types/command.d.ts +18 -1
- package/dist/types/command.d.ts.map +1 -1
- package/dist/types/input.d.ts +9 -0
- package/dist/types/input.d.ts.map +1 -1
- package/dist/types/markdown.d.ts +36 -1
- package/dist/types/markdown.d.ts.map +1 -1
- package/dist/types/style.d.ts +28 -1
- package/dist/types/style.d.ts.map +1 -1
- package/dist/types/terminal.d.ts +9 -0
- package/dist/types/terminal.d.ts.map +1 -1
- package/dist/types/theme.d.ts +26 -1
- package/dist/types/theme.d.ts.map +1 -1
- package/dist/util/markdown.d.ts.map +1 -1
- package/dist/util/markdown.js +172 -2
- package/dist/util/paths.d.ts +9 -3
- package/dist/util/paths.d.ts.map +1 -1
- package/dist/util/paths.js +11 -16
- package/package.json +5 -5
- package/src/app/app.ts +198 -1
- package/src/core/focus.ts +12 -1
- package/src/core/store.ts +2 -7
- package/src/jsx/intrinsics.ts +18 -0
- package/src/render/layout.ts +7 -2
- package/src/runtime/bindings.ts +29 -3
- package/src/runtime/hooks.ts +15 -4
- package/src/themes/builtin.ts +65 -1
- package/src/themes/dividers.ts +48 -0
- package/src/themes/glyphs.ts +4 -0
- package/src/themes/index.ts +1 -0
- package/src/themes/registry.ts +30 -2
- package/src/types/app.ts +13 -0
- package/src/types/command.ts +18 -1
- package/src/types/input.ts +9 -0
- package/src/types/markdown.ts +38 -2
- package/src/types/style.ts +33 -1
- package/src/types/terminal.ts +9 -0
- package/src/types/theme.ts +29 -1
- package/src/util/markdown.ts +202 -3
- package/src/util/paths.ts +12 -15
package/dist/types/markdown.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StyleColor } from './style.js';
|
|
1
|
+
import type { StyleColor, TableRules } from './style.js';
|
|
2
2
|
/**
|
|
3
3
|
* Markdown, as rows a terminal can scroll.
|
|
4
4
|
*
|
|
@@ -12,6 +12,8 @@ import type { StyleColor } from './style.js';
|
|
|
12
12
|
* several rows here, each tagged with the fence it belongs to so a painter can
|
|
13
13
|
* put the visible ones back into one box.
|
|
14
14
|
*/
|
|
15
|
+
/** Which edge a table column's text is pushed against. */
|
|
16
|
+
export type MarkdownAlign = 'left' | 'center' | 'right';
|
|
15
17
|
/** A run of text with one style. Inline emphasis is why rows are not strings. */
|
|
16
18
|
export interface MarkdownRun {
|
|
17
19
|
text: string;
|
|
@@ -39,6 +41,29 @@ export type MarkdownRow = {
|
|
|
39
41
|
part: 'open' | 'code' | 'close';
|
|
40
42
|
text?: string;
|
|
41
43
|
language?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* One line of a table, with its cells already fitted to their columns.
|
|
47
|
+
*
|
|
48
|
+
* The widths are decided once for the whole table and repeated on every row
|
|
49
|
+
* of it, because a column that is measured per row is not a column. Cells
|
|
50
|
+
* arrive padded and truncated to exactly `widths[i]`, so a painter only has
|
|
51
|
+
* to put the separators in - which is also what keeps the one-row-per-row
|
|
52
|
+
* invariant: a cell too long for its column is cut, never wrapped, or the
|
|
53
|
+
* table would be a different height than the document said it was.
|
|
54
|
+
*
|
|
55
|
+
* `top`, `rule` and `bottom` are edges and carry no cells; the painter draws
|
|
56
|
+
* them from the widths, in whatever the theme's border characters are. They
|
|
57
|
+
* are rows here for the same reason a fence's rules are: they take a line on
|
|
58
|
+
* the screen, so anything counting rows has to be able to count them.
|
|
59
|
+
*/
|
|
60
|
+
| {
|
|
61
|
+
kind: 'table';
|
|
62
|
+
table: number;
|
|
63
|
+
part: 'top' | 'head' | 'rule' | 'body' | 'bottom';
|
|
64
|
+
cells: MarkdownRun[][];
|
|
65
|
+
widths: number[];
|
|
66
|
+
align: MarkdownAlign[];
|
|
42
67
|
};
|
|
43
68
|
export interface MarkdownLayoutOptions {
|
|
44
69
|
/** Cells to wrap to. Zero means "not measured yet" - nothing is wrapped. */
|
|
@@ -54,5 +79,15 @@ export interface MarkdownLayoutOptions {
|
|
|
54
79
|
* rules nobody draws stops two rows short of the end of the document.
|
|
55
80
|
*/
|
|
56
81
|
ruled?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* How much of a table gets ruled. The theme's `tableRules`, passed through.
|
|
84
|
+
*
|
|
85
|
+
* It has to be decided here rather than by whatever paints the rows,
|
|
86
|
+
* because a rule between two rows *is* a row - it takes a line on the
|
|
87
|
+
* screen. A painter that added them would be drawing more lines than the
|
|
88
|
+
* layout counted, and every viewer that scrolls by row index would land in
|
|
89
|
+
* the wrong place by one per table row.
|
|
90
|
+
*/
|
|
91
|
+
tableRules?: TableRules;
|
|
57
92
|
}
|
|
58
93
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/types/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/types/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;;;;;;;GAYG;AAEH,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExD,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,WAAW,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,EAAE,CAAC,EAAE,UAAU,CAAA;CAAE,GAC9F;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AACrG;;;;;;;;;;;;;;GAcG;GACD;IACA,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClD,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB,CAAC;AAEJ,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB"}
|
package/dist/types/style.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { EdgeSpec } from './geometry.js';
|
|
|
5
5
|
* what lets one catalog render the same under a light theme, a dark theme and
|
|
6
6
|
* a 16-colour ssh session.
|
|
7
7
|
*/
|
|
8
|
-
export type ColorToken = 'canvas' | 'surface' | 'surfaceAlt' | 'overlay' | 'border' | 'borderStrong' | 'borderSubtle' | 'text' | 'muted' | 'subtle' | 'inverted' | 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'onDefault' | 'onMuted' | 'onAccent' | 'onPrimary' | 'onSecondary' | 'onSuccess' | 'onWarning' | 'onDanger' | 'onInfo' | 'hover' | 'active' | 'selected' | 'focus' | 'disabled' | 'scrim' | 'cursor' | 'shadow';
|
|
8
|
+
export type ColorToken = 'canvas' | 'surface' | 'surfaceAlt' | 'overlay' | 'border' | 'borderStrong' | 'borderSubtle' | 'text' | 'muted' | 'subtle' | 'inverted' | 'accent' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'onDefault' | 'onMuted' | 'onAccent' | 'onPrimary' | 'onSecondary' | 'onSuccess' | 'onWarning' | 'onDanger' | 'onInfo' | 'hover' | 'active' | 'selected' | 'focus' | 'disabled' | 'scrim' | 'cursor' | 'shadow' | 'divider';
|
|
9
9
|
/** Anywhere a colour is accepted, a semantic token is accepted too. */
|
|
10
10
|
export type StyleColor = ColorToken | Color;
|
|
11
11
|
export type Dimension = number | `${number}%` | 'auto';
|
|
@@ -27,6 +27,33 @@ export interface BorderChars {
|
|
|
27
27
|
teeLeft: string;
|
|
28
28
|
teeRight: string;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* A rule that separates, rather than a frame that encloses.
|
|
32
|
+
*
|
|
33
|
+
* Kept apart from `BorderStyle` on purpose: a theme that draws no frames may
|
|
34
|
+
* still want a rule, and tying the two means choosing a divider glyph decides
|
|
35
|
+
* whether every bordered component reserves a ring.
|
|
36
|
+
*/
|
|
37
|
+
export type DividerStyle = 'none' | 'single' | 'double' | 'dashed' | 'thick' | 'ascii';
|
|
38
|
+
/** A divider runs either way, so it names both. */
|
|
39
|
+
export interface DividerChars {
|
|
40
|
+
horizontal: string;
|
|
41
|
+
vertical: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The shape of the caret.
|
|
45
|
+
*
|
|
46
|
+
* Named for DECSCUSR, which is what a terminal understands, so a theme value
|
|
47
|
+
* maps straight onto the escape sequence with nothing to translate.
|
|
48
|
+
*/
|
|
49
|
+
export type CursorStyle = 'block' | 'underline' | 'bar';
|
|
50
|
+
/**
|
|
51
|
+
* How much of a table gets ruled: the header only, or between every row.
|
|
52
|
+
*
|
|
53
|
+
* Not a border style - it is a question about how many lines, not which
|
|
54
|
+
* glyphs. The glyphs are the theme's border set either way.
|
|
55
|
+
*/
|
|
56
|
+
export type TableRules = 'header' | 'all';
|
|
30
57
|
export type BorderSides = {
|
|
31
58
|
top?: boolean;
|
|
32
59
|
right?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/types/style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB,QAAQ,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAC/C,QAAQ,GAAG,cAAc,GAAG,cAAc,GAC1C,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GACxC,QAAQ,GAAG,SAAS,GAAG,WAAW,GAClC,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GACzC,WAAW,GAAG,SAAS,GACvB,UAAU,GAAG,WAAW,GAAG,aAAa,GACxC,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GACjD,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GACtD,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/types/style.ts"],"names":[],"mappings":"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"}
|
package/dist/types/terminal.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CursorStyle } from './style.js';
|
|
1
2
|
import type { Disposable } from './disposable.js';
|
|
2
3
|
import type { Size } from './geometry.js';
|
|
3
4
|
import type { TerminalCapabilities, CapabilityOverrides } from './capabilities.js';
|
|
@@ -28,6 +29,8 @@ export interface AcquiredState {
|
|
|
28
29
|
focusEvents: boolean;
|
|
29
30
|
paste: boolean;
|
|
30
31
|
cursorHidden: boolean;
|
|
32
|
+
/** Whether this session changed the caret shape, and so owes a reset. */
|
|
33
|
+
cursorShaped?: boolean;
|
|
31
34
|
enhancedKeys: boolean;
|
|
32
35
|
rawMode: boolean;
|
|
33
36
|
titleSet: boolean;
|
|
@@ -48,5 +51,11 @@ export interface TerminalAdapter extends Disposable {
|
|
|
48
51
|
/** OSC 52, when the terminal allows it. */
|
|
49
52
|
writeClipboard?(text: string): void;
|
|
50
53
|
setTitle?(title: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* DECSCUSR. Session state rather than frame state - it survives until
|
|
56
|
+
* something changes it, so it is set when it changes and put back on
|
|
57
|
+
* teardown, the way the alt screen and raw mode are.
|
|
58
|
+
*/
|
|
59
|
+
setCursorShape?(shape: CursorStyle): void;
|
|
51
60
|
}
|
|
52
61
|
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/types/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,IAAI,IAAI,IAAI,CAAC;IACb,YAAY,IAAI,oBAAoB,CAAC;IACrC,6CAA6C;IAC7C,sBAAsB,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAE7D,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IACjF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAExC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE9B,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,UAAU,CAAC;IACrD,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,UAAU,CAAC;IAE/C,2CAA2C;IAC3C,cAAc,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/types/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,yEAAyE;IACzE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,IAAI,IAAI,IAAI,CAAC;IACb,YAAY,IAAI,oBAAoB,CAAC;IACrC,6CAA6C;IAC7C,sBAAsB,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAE7D,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAAC;IACjF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAExC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE9B,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,UAAU,CAAC;IACrD,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,UAAU,CAAC;IAE/C,2CAA2C;IAC3C,cAAc,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,cAAc,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CAC3C"}
|
package/dist/types/theme.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Color } from './cells.js';
|
|
2
|
-
import type { BorderChars, BorderStyle, ColorToken, Density, Style, StyleColor } from './style.js';
|
|
2
|
+
import type { BorderChars, BorderStyle, ColorToken, CursorStyle, Density, DividerChars, DividerStyle, Style, StyleColor, TableRules } from './style.js';
|
|
3
3
|
import type { SyntaxScope } from './syntax.js';
|
|
4
4
|
import type { Disposable } from './disposable.js';
|
|
5
5
|
import type { TerminalCapabilities } from './capabilities.js';
|
|
@@ -31,6 +31,8 @@ export interface ThemeGlyphs {
|
|
|
31
31
|
chevronUp: string;
|
|
32
32
|
arrowUp: string;
|
|
33
33
|
arrowDown: string;
|
|
34
|
+
arrowLeft: string;
|
|
35
|
+
arrowRight: string;
|
|
34
36
|
ellipsis: string;
|
|
35
37
|
search: string;
|
|
36
38
|
radioOn: string;
|
|
@@ -77,6 +79,25 @@ export interface ThemeDefinition {
|
|
|
77
79
|
/** Default border style for chrome. `'none'` gives the borderless look. */
|
|
78
80
|
border?: BorderStyle;
|
|
79
81
|
borderChars?: Partial<Record<BorderStyle, BorderChars>>;
|
|
82
|
+
/**
|
|
83
|
+
* Default rule style. Independent of `border`, so a borderless theme can
|
|
84
|
+
* still separate with a line.
|
|
85
|
+
*/
|
|
86
|
+
divider?: DividerStyle;
|
|
87
|
+
dividerChars?: Partial<Record<DividerStyle, DividerChars>>;
|
|
88
|
+
/** The caret's shape. The terminal's own setting is the default. */
|
|
89
|
+
cursor?: CursorStyle;
|
|
90
|
+
/**
|
|
91
|
+
* How much of a table gets ruled.
|
|
92
|
+
*
|
|
93
|
+
* `header` is the default and the quiet one: a box, and a rule under the
|
|
94
|
+
* header. `all` puts a rule between every pair of rows as well, which is
|
|
95
|
+
* what a table of few, long rows wants - a wrapped-looking cell beside a
|
|
96
|
+
* short one is ambiguous about which row it belongs to until something
|
|
97
|
+
* separates them. On a table of twenty short rows the same lines are noise,
|
|
98
|
+
* which is why it is the theme's call rather than the default.
|
|
99
|
+
*/
|
|
100
|
+
tableRules?: TableRules;
|
|
80
101
|
density?: Density;
|
|
81
102
|
/** Per-component style overrides, keyed by component name then variant. */
|
|
82
103
|
components?: Record<string, Record<string, Style>>;
|
|
@@ -96,6 +117,9 @@ export interface ResolvedTheme {
|
|
|
96
117
|
spacing: ThemeSpacing;
|
|
97
118
|
glyphs: ThemeGlyphs;
|
|
98
119
|
border: BorderStyle;
|
|
120
|
+
divider: DividerStyle;
|
|
121
|
+
cursor: CursorStyle | undefined;
|
|
122
|
+
tableRules: TableRules;
|
|
99
123
|
density: Density;
|
|
100
124
|
components: Record<string, Record<string, Style>>;
|
|
101
125
|
/** Every syntax scope, resolved to a colour. */
|
|
@@ -103,6 +127,7 @@ export interface ResolvedTheme {
|
|
|
103
127
|
/** Resolve a token (or pass a literal colour through). */
|
|
104
128
|
color(token: string): Color;
|
|
105
129
|
borderChars(style?: BorderStyle): BorderChars;
|
|
130
|
+
dividerChars(style?: DividerStyle): DividerChars;
|
|
106
131
|
/** Component style for a name + variant list, merged in order. */
|
|
107
132
|
styleFor(component: string, variants?: string[]): Style;
|
|
108
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/types/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/types/theme.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/util/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/util/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACK,qBAAqB,EAAE,WAAW,EAAE,WAAW,EAC/D,MAAM,sBAAsB,CAAC;AAuC9B;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAiBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE,CA2C5E;AAwBD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,OAAO,EAAE,qBAAqB,GAC7B,WAAW,EAAE,CA4Ff;AAgLD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAEtD;AAED,yEAAyE;AACzE,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAI5D"}
|
package/dist/util/markdown.js
CHANGED
|
@@ -136,13 +136,17 @@ function withPrefix(runs, width, prefix, options = {}) {
|
|
|
136
136
|
}));
|
|
137
137
|
}
|
|
138
138
|
export function layoutMarkdown(source, options) {
|
|
139
|
-
const { width, bullet = '-', quoteBar = '|', ruled = true } = options;
|
|
139
|
+
const { width, bullet = '-', quoteBar = '|', ruled = true, tableRules = 'header' } = options;
|
|
140
140
|
const lines = Array.isArray(source) ? source : source.replace(/\r\n/g, '\n').split('\n');
|
|
141
141
|
const rows = [];
|
|
142
142
|
let fence = 0;
|
|
143
143
|
let inFence = false;
|
|
144
144
|
let language = '';
|
|
145
|
-
|
|
145
|
+
let table = 0;
|
|
146
|
+
// By index rather than by value: a table is only a table because of the line
|
|
147
|
+
// *after* its header, so this loop has to be able to look at it.
|
|
148
|
+
for (let at = 0; at < lines.length; at++) {
|
|
149
|
+
const line = lines[at];
|
|
146
150
|
const marker = /^\s*```(\S*)\s*$/.exec(line);
|
|
147
151
|
if (marker) {
|
|
148
152
|
// An open fence is laid out as a fence from the moment it opens. A turn
|
|
@@ -162,6 +166,24 @@ export function layoutMarkdown(source, options) {
|
|
|
162
166
|
rows.push({ kind: 'fence', fence, part: 'code', text: line, ...(language ? { language } : {}) });
|
|
163
167
|
continue;
|
|
164
168
|
}
|
|
169
|
+
// Before headings and lists, because a cell may contain either and the
|
|
170
|
+
// pipes are what decide. After fences, because inside one nothing is.
|
|
171
|
+
if (line.includes('|') && DIVIDER.test(lines[at + 1] ?? '')) {
|
|
172
|
+
const align = cellsOf(lines[at + 1]).map(alignOf);
|
|
173
|
+
const body = [];
|
|
174
|
+
let end = at + 2;
|
|
175
|
+
while (end < lines.length) {
|
|
176
|
+
const next = lines[end];
|
|
177
|
+
if (!next.includes('|') || next.trim() === '')
|
|
178
|
+
break;
|
|
179
|
+
body.push(cellsOf(next));
|
|
180
|
+
end++;
|
|
181
|
+
}
|
|
182
|
+
rows.push(...tableRows(cellsOf(line), body, align, width, table, tableRules));
|
|
183
|
+
table++;
|
|
184
|
+
at = end - 1;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
165
187
|
const heading = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
166
188
|
if (heading) {
|
|
167
189
|
const level = heading[1].length;
|
|
@@ -207,6 +229,154 @@ export function layoutMarkdown(source, options) {
|
|
|
207
229
|
rows.push({ kind: 'fence', fence, part: 'close' });
|
|
208
230
|
return rows;
|
|
209
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* The `|---|:--:|---:|` line, which is what makes the line above it a header.
|
|
234
|
+
*
|
|
235
|
+
* A row of pipes on its own is a row of pipes - `a | b` is arithmetic or a
|
|
236
|
+
* shell pipeline far more often than it is a one-column table, and treating
|
|
237
|
+
* every line with a bar in it as a table is how prose ends up in a grid.
|
|
238
|
+
*/
|
|
239
|
+
const DIVIDER = /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/;
|
|
240
|
+
/**
|
|
241
|
+
* One line into its cells.
|
|
242
|
+
*
|
|
243
|
+
* The outer pipes are optional in every dialect anybody writes, so they are
|
|
244
|
+
* stripped rather than required. `\|` is an escaped bar inside a cell and not
|
|
245
|
+
* a boundary - which is the only way to put a bar in a table at all.
|
|
246
|
+
*/
|
|
247
|
+
function cellsOf(line) {
|
|
248
|
+
const trimmed = line.trim().replace(/^\|/, '').replace(/\|$/, '');
|
|
249
|
+
return trimmed
|
|
250
|
+
.split(/(?<!\\)\|/)
|
|
251
|
+
.map((cell) => cell.replace(/\\\|/g, '|').trim());
|
|
252
|
+
}
|
|
253
|
+
function alignOf(spec) {
|
|
254
|
+
const left = spec.startsWith(':');
|
|
255
|
+
const right = spec.endsWith(':');
|
|
256
|
+
if (left && right)
|
|
257
|
+
return 'center';
|
|
258
|
+
return right ? 'right' : 'left';
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Cut and pad one cell to exactly `width`, keeping the styles.
|
|
262
|
+
*
|
|
263
|
+
* Cut, never wrapped: a table row has to stay one row tall or the document's
|
|
264
|
+
* length stops being a count of rows, and every viewer that windows this
|
|
265
|
+
* scrolls to the wrong place.
|
|
266
|
+
*/
|
|
267
|
+
function fitRuns(runs, width, align) {
|
|
268
|
+
const out = [];
|
|
269
|
+
let used = 0;
|
|
270
|
+
for (const run of runs) {
|
|
271
|
+
if (used >= width)
|
|
272
|
+
break;
|
|
273
|
+
const room = width - used;
|
|
274
|
+
if (stringWidth(run.text) <= room) {
|
|
275
|
+
out.push(run);
|
|
276
|
+
used += stringWidth(run.text);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
// The ellipsis costs a cell, so it is only worth it when there is a cell
|
|
280
|
+
// to spend: at a width of one, a bare glyph says less than the letter.
|
|
281
|
+
const keep = room > 1 ? room - 1 : room;
|
|
282
|
+
const cut = [];
|
|
283
|
+
let taken = 0;
|
|
284
|
+
for (const g of graphemes(run.text)) {
|
|
285
|
+
const w = stringWidth(g);
|
|
286
|
+
if (taken + w > keep)
|
|
287
|
+
break;
|
|
288
|
+
cut.push(g);
|
|
289
|
+
taken += w;
|
|
290
|
+
}
|
|
291
|
+
out.push({ ...run, text: room > 1 ? `${cut.join('')}\u2026` : cut.join('') });
|
|
292
|
+
used = width;
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
const slack = Math.max(0, width - used);
|
|
296
|
+
if (slack === 0)
|
|
297
|
+
return out;
|
|
298
|
+
const before = align === 'right' ? slack : align === 'center' ? Math.floor(slack / 2) : 0;
|
|
299
|
+
const after = slack - before;
|
|
300
|
+
return [
|
|
301
|
+
...(before ? [{ text: ' '.repeat(before) }] : []),
|
|
302
|
+
...out,
|
|
303
|
+
...(after ? [{ text: ' '.repeat(after) }] : []),
|
|
304
|
+
];
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* A whole table, measured once.
|
|
308
|
+
*
|
|
309
|
+
* The columns are as wide as their widest cell wants, and when that is more
|
|
310
|
+
* than the space there is they give it back in proportion - the widest loses
|
|
311
|
+
* the most, because it is the one with the most to lose. Three cells is the
|
|
312
|
+
* floor: below that a column is an ellipsis and a space, which is narrower
|
|
313
|
+
* than saying nothing.
|
|
314
|
+
*/
|
|
315
|
+
function tableRows(head, body, align, width, table, rules) {
|
|
316
|
+
const columns = Math.max(head.length, align.length, ...body.map((r) => r.length));
|
|
317
|
+
const at = (row, i) => row[i] ?? '';
|
|
318
|
+
const runsFor = (text, bold) => inlineRuns(text).map((run) => (bold ? { ...run, bold: true } : run));
|
|
319
|
+
const natural = Array.from({ length: columns }, (_, i) => Math.max(stringWidth(at(head, i)), ...body.map((row) => stringWidth(at(row, i))), 1));
|
|
320
|
+
// A rule between every pair of columns, and a box around the lot. The box
|
|
321
|
+
// is what makes it read as a table rather than as text that happens to line
|
|
322
|
+
// up - which matters most on a theme that draws no borders anywhere else,
|
|
323
|
+
// because there a table with only its columns ruled has nothing to say it
|
|
324
|
+
// ended.
|
|
325
|
+
const gaps = (columns - 1) * SEPARATOR + OUTER;
|
|
326
|
+
const room = width > 0 ? Math.max(columns * MIN_COLUMN, width - gaps) : Infinity;
|
|
327
|
+
const wanted = natural.reduce((sum, n) => sum + n, 0);
|
|
328
|
+
const widths = wanted <= room
|
|
329
|
+
? natural
|
|
330
|
+
: share(natural, room);
|
|
331
|
+
const line = (cells, part) => ({
|
|
332
|
+
kind: 'table',
|
|
333
|
+
table,
|
|
334
|
+
part,
|
|
335
|
+
widths,
|
|
336
|
+
align,
|
|
337
|
+
cells: widths.map((w, i) => fitRuns(runsFor(at(cells, i), part === 'head'), w, align[i] ?? 'left')),
|
|
338
|
+
});
|
|
339
|
+
const edge = (part) => ({ kind: 'table', table, part, cells: [], widths, align });
|
|
340
|
+
return [
|
|
341
|
+
edge('top'),
|
|
342
|
+
line(head, 'head'),
|
|
343
|
+
edge('rule'),
|
|
344
|
+
// A rule between every pair, when the theme asked for them. Between, not
|
|
345
|
+
// after: a rule under the last row and then the box's own bottom edge is
|
|
346
|
+
// two lines saying the same thing.
|
|
347
|
+
...body.flatMap((row, i) => (rules === 'all' && i > 0
|
|
348
|
+
? [edge('rule'), line(row, 'body')]
|
|
349
|
+
: [line(row, 'body')])),
|
|
350
|
+
edge('bottom'),
|
|
351
|
+
];
|
|
352
|
+
}
|
|
353
|
+
/** Cells between two columns: a space, a rule, a space. */
|
|
354
|
+
const SEPARATOR = 3;
|
|
355
|
+
/** The box: a rule and a space at each end. */
|
|
356
|
+
const OUTER = 4;
|
|
357
|
+
const MIN_COLUMN = 3;
|
|
358
|
+
/**
|
|
359
|
+
* Shrink columns into `room`, proportionally, without losing a cell to
|
|
360
|
+
* rounding.
|
|
361
|
+
*
|
|
362
|
+
* The remainder goes to the widest columns one at a time rather than to the
|
|
363
|
+
* first: handing every leftover cell to column one is what turns a five-column
|
|
364
|
+
* table into one wide column and four ellipses.
|
|
365
|
+
*/
|
|
366
|
+
function share(natural, room) {
|
|
367
|
+
const total = natural.reduce((sum, n) => sum + n, 0);
|
|
368
|
+
const scaled = natural.map((n) => Math.max(MIN_COLUMN, Math.floor((n / total) * room)));
|
|
369
|
+
let spare = room - scaled.reduce((sum, n) => sum + n, 0);
|
|
370
|
+
const order = natural
|
|
371
|
+
.map((n, i) => [n, i])
|
|
372
|
+
.sort((a, b) => b[0] - a[0])
|
|
373
|
+
.map(([, i]) => i);
|
|
374
|
+
for (let i = 0; spare > 0; i = (i + 1) % order.length) {
|
|
375
|
+
scaled[order[i]] = scaled[order[i]] + 1;
|
|
376
|
+
spare--;
|
|
377
|
+
}
|
|
378
|
+
return scaled;
|
|
379
|
+
}
|
|
210
380
|
/** Every run's text, for a measurement or a test that does not care how it looks. */
|
|
211
381
|
export function runsToText(runs) {
|
|
212
382
|
return runs.map((run) => run.text).join('');
|
package/dist/util/paths.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare function segments(path: string): string[];
|
|
|
24
24
|
* Canonical map key for a path: segments joined, no sigil.
|
|
25
25
|
*
|
|
26
26
|
* The segments are re-escaped on the way out. Everything downstream - the
|
|
27
|
-
* store's own walk, `
|
|
27
|
+
* store's own walk, `keysTouch`, `matchKey` - splits a key on `/`, so a
|
|
28
28
|
* segment that legitimately contains one (a URI used as a key, a filename with
|
|
29
29
|
* a slash) has to stay escaped or it silently becomes several segments and the
|
|
30
30
|
* value lands somewhere nobody looks.
|
|
@@ -38,9 +38,15 @@ export declare function joinPath(...parts: (string | number)[]): BindingPath;
|
|
|
38
38
|
export declare function resolvePath(path: string, dataContext?: string): BindingPath;
|
|
39
39
|
export declare function scopeOf(path: string): string;
|
|
40
40
|
export declare function parentKey(key: string): string | null;
|
|
41
|
-
/** Every ancestor key of `key`, closest first, including `''` for the root. */
|
|
42
|
-
export declare function ancestorKeys(key: string): string[];
|
|
43
41
|
export declare function isDescendantKey(key: string, ancestor: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether two concrete keys can affect the same subscribed value.
|
|
44
|
+
*
|
|
45
|
+
* A write to a descendant changes the ancestor object a subscriber reads, and a
|
|
46
|
+
* write to an ancestor may replace the whole subtree below it. This relation is
|
|
47
|
+
* symmetric and avoids building ancestor lists in hot subscription checks.
|
|
48
|
+
*/
|
|
49
|
+
export declare function keysTouch(a: string, b: string): boolean;
|
|
44
50
|
export declare function hasWildcard(path: string): boolean;
|
|
45
51
|
/** Match a concrete key against a pattern key that may contain `*`. */
|
|
46
52
|
export declare function matchKey(key: string, pattern: string, subtree?: boolean): boolean;
|
package/dist/util/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AAEH,qBAAa,SAAU,SAAQ,KAAK;IACL,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAtC,OAAO,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM;CAInD;AAMD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,MAAM,EAAE,CAE9D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,WAAW,CASnE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAW3E;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpD;AAED
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AAEH,qBAAa,SAAU,SAAQ,KAAK;IACL,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAtC,OAAO,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM;CAInD;AAMD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,KAAK,MAAM,EAAE,CAE9D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,WAAW,CASnE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAW3E;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGtE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAa/E"}
|
package/dist/util/paths.js
CHANGED
|
@@ -46,7 +46,7 @@ export function segments(path) {
|
|
|
46
46
|
* Canonical map key for a path: segments joined, no sigil.
|
|
47
47
|
*
|
|
48
48
|
* The segments are re-escaped on the way out. Everything downstream - the
|
|
49
|
-
* store's own walk, `
|
|
49
|
+
* store's own walk, `keysTouch`, `matchKey` - splits a key on `/`, so a
|
|
50
50
|
* segment that legitimately contains one (a URI used as a key, a filename with
|
|
51
51
|
* a slash) has to stay escaped or it silently becomes several segments and the
|
|
52
52
|
* value lands somewhere nobody looks.
|
|
@@ -90,26 +90,21 @@ export function parentKey(key) {
|
|
|
90
90
|
const i = key.lastIndexOf('/');
|
|
91
91
|
return i === -1 ? (key === '' ? null : '') : key.slice(0, i);
|
|
92
92
|
}
|
|
93
|
-
/** Every ancestor key of `key`, closest first, including `''` for the root. */
|
|
94
|
-
export function ancestorKeys(key) {
|
|
95
|
-
const out = [];
|
|
96
|
-
let cur = key;
|
|
97
|
-
for (;;) {
|
|
98
|
-
const p = parentKey(cur);
|
|
99
|
-
if (p === null)
|
|
100
|
-
break;
|
|
101
|
-
out.push(p);
|
|
102
|
-
cur = p;
|
|
103
|
-
if (p === '')
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
return out;
|
|
107
|
-
}
|
|
108
93
|
export function isDescendantKey(key, ancestor) {
|
|
109
94
|
if (ancestor === '')
|
|
110
95
|
return key !== '';
|
|
111
96
|
return key.startsWith(ancestor + '/');
|
|
112
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether two concrete keys can affect the same subscribed value.
|
|
100
|
+
*
|
|
101
|
+
* A write to a descendant changes the ancestor object a subscriber reads, and a
|
|
102
|
+
* write to an ancestor may replace the whole subtree below it. This relation is
|
|
103
|
+
* symmetric and avoids building ancestor lists in hot subscription checks.
|
|
104
|
+
*/
|
|
105
|
+
export function keysTouch(a, b) {
|
|
106
|
+
return a === b || isDescendantKey(a, b) || isDescendantKey(b, a);
|
|
107
|
+
}
|
|
113
108
|
export function hasWildcard(path) {
|
|
114
109
|
return path.includes('*');
|
|
115
110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@textui/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Graph-mounted terminal UI runtime - store, registries, renderer, host primitives",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"terminal",
|
|
@@ -58,13 +58,13 @@
|
|
|
58
58
|
"import": "./dist/themes/index.js"
|
|
59
59
|
}
|
|
60
60
|
},
|
|
61
|
-
"publishConfig": {
|
|
62
|
-
"access": "public"
|
|
63
|
-
},
|
|
64
61
|
"scripts": {
|
|
65
62
|
"build": "tsc -p tsconfig.json",
|
|
66
63
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
67
64
|
"test": "vitest run",
|
|
68
65
|
"test:watch": "vitest"
|
|
66
|
+
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public"
|
|
69
69
|
}
|
|
70
|
-
}
|
|
70
|
+
}
|