lognal 0.1.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/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/core/filter.d.ts +29 -0
- package/dist/core/filter.js +82 -0
- package/dist/core/layout/entry-lines.d.ts +16 -0
- package/dist/core/layout/entry-lines.js +120 -0
- package/dist/core/layout/layout.d.ts +152 -0
- package/dist/core/layout/layout.js +784 -0
- package/dist/core/layout/row-index.d.ts +33 -0
- package/dist/core/layout/row-index.js +99 -0
- package/dist/core/layout/types.d.ts +128 -0
- package/dist/core/layout/types.js +8 -0
- package/dist/core/store.d.ts +96 -0
- package/dist/core/store.js +204 -0
- package/dist/core/text/ansi.d.ts +20 -0
- package/dist/core/text/ansi.js +187 -0
- package/dist/core/text/graphemes.d.ts +17 -0
- package/dist/core/text/graphemes.js +70 -0
- package/dist/core/text/line-splitter.d.ts +18 -0
- package/dist/core/text/line-splitter.js +56 -0
- package/dist/core/text/measure.d.ts +10 -0
- package/dist/core/text/measure.js +38 -0
- package/dist/core/text/shape.d.ts +24 -0
- package/dist/core/text/shape.js +220 -0
- package/dist/core/text/unicode-width-data.d.ts +54 -0
- package/dist/core/text/unicode-width-data.js +227 -0
- package/dist/core/text/width.d.ts +20 -0
- package/dist/core/text/width.js +157 -0
- package/dist/core/text/wrap.d.ts +14 -0
- package/dist/core/text/wrap.js +94 -0
- package/dist/core/time.d.ts +10 -0
- package/dist/core/time.js +24 -0
- package/dist/core/types.d.ts +131 -0
- package/dist/core/types.js +9 -0
- package/dist/core/value/preview.d.ts +16 -0
- package/dist/core/value/preview.js +207 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +24 -0
- package/dist/lognal.css +589 -0
- package/dist/react/LogViewer.d.ts +32 -0
- package/dist/react/LogViewer.js +183 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +2 -0
- package/dist/renderer/canvas/canvas-renderer.d.ts +45 -0
- package/dist/renderer/canvas/canvas-renderer.js +464 -0
- package/dist/renderer/canvas/palette.d.ts +6 -0
- package/dist/renderer/canvas/palette.js +25 -0
- package/dist/renderer/theme.d.ts +3 -0
- package/dist/renderer/theme.js +52 -0
- package/dist/renderer/types.d.ts +82 -0
- package/dist/renderer/types.js +1 -0
- package/dist/sources/console/format.d.ts +32 -0
- package/dist/sources/console/format.js +189 -0
- package/dist/sources/console/hook.d.ts +27 -0
- package/dist/sources/console/hook.js +94 -0
- package/dist/sources/console/recorder.d.ts +41 -0
- package/dist/sources/console/recorder.js +239 -0
- package/dist/sources/console/snapshot.d.ts +22 -0
- package/dist/sources/console/snapshot.js +547 -0
- package/dist/sources/console/table.d.ts +9 -0
- package/dist/sources/console/table.js +87 -0
- package/dist/sources/text/encoding.d.ts +11 -0
- package/dist/sources/text/encoding.js +59 -0
- package/dist/sources/text/follow-file.d.ts +49 -0
- package/dist/sources/text/follow-file.js +109 -0
- package/dist/sources/text/read-file.d.ts +63 -0
- package/dist/sources/text/read-file.js +82 -0
- package/dist/viewer/icons.d.ts +14 -0
- package/dist/viewer/icons.js +30 -0
- package/dist/viewer/input-line.d.ts +46 -0
- package/dist/viewer/input-line.js +144 -0
- package/dist/viewer/labels.d.ts +35 -0
- package/dist/viewer/labels.js +61 -0
- package/dist/viewer/scrollbar.d.ts +27 -0
- package/dist/viewer/scrollbar.js +143 -0
- package/dist/viewer/theme.d.ts +15 -0
- package/dist/viewer/theme.js +105 -0
- package/dist/viewer/viewer.d.ts +217 -0
- package/dist/viewer/viewer.js +1201 -0
- package/package.json +92 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data types shared by every part of lognal.
|
|
3
|
+
*
|
|
4
|
+
* Everything under `src/core` is plain data and logic with no dependency on the DOM or on a
|
|
5
|
+
* JavaScript-only API, so that it can be ported to other runtimes, such as Dart. Platform
|
|
6
|
+
* features the core needs, such as grapheme segmentation, are passed in rather than imported.
|
|
7
|
+
*/
|
|
8
|
+
/** Severity of an entry, from least to most severe. */
|
|
9
|
+
export type LogLevel = 'debug' | 'log' | 'info' | 'warn' | 'error';
|
|
10
|
+
/** Every level, ordered from least to most severe. */
|
|
11
|
+
export declare const LOG_LEVELS: readonly LogLevel[];
|
|
12
|
+
/**
|
|
13
|
+
* What an entry represents. The viewer marks each kind differently.
|
|
14
|
+
*
|
|
15
|
+
* - `message`: a regular log message.
|
|
16
|
+
* - `input`: a command the user typed into the input line.
|
|
17
|
+
* - `output`: the reply to a command.
|
|
18
|
+
* - `group`: the header of a group started with `console.group`.
|
|
19
|
+
* - `system`: a notice from the viewer itself, such as "Console was cleared".
|
|
20
|
+
*/
|
|
21
|
+
export type LogKind = 'message' | 'input' | 'output' | 'group' | 'system';
|
|
22
|
+
/** Semantic colors, resolved by the renderer from the theme. */
|
|
23
|
+
export type StyleToken = 'default' | 'muted' | 'string' | 'number' | 'boolean' | 'null' | 'key' | 'symbol' | 'function' | 'regexp' | 'date' | 'tag' | 'attribute' | 'error' | 'warn' | 'info' | 'accent';
|
|
24
|
+
/**
|
|
25
|
+
* A color given directly rather than through a token.
|
|
26
|
+
*
|
|
27
|
+
* A number from 0 to 255 is an index into the ANSI palette; 0 to 15 follow the theme. A string
|
|
28
|
+
* is a CSS color such as `#ff0000` or `rgb(255 0 0)`.
|
|
29
|
+
*/
|
|
30
|
+
export type TextColor = number | string;
|
|
31
|
+
/** Explicit styling, from `%c` in a console message or from ANSI escape codes. */
|
|
32
|
+
export interface TextStyle {
|
|
33
|
+
color?: TextColor;
|
|
34
|
+
background?: TextColor;
|
|
35
|
+
bold?: boolean;
|
|
36
|
+
dim?: boolean;
|
|
37
|
+
italic?: boolean;
|
|
38
|
+
underline?: boolean;
|
|
39
|
+
strikethrough?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** A run of text with one style. */
|
|
42
|
+
export interface TextPart {
|
|
43
|
+
type: 'text';
|
|
44
|
+
text: string;
|
|
45
|
+
token?: StyleToken;
|
|
46
|
+
style?: TextStyle;
|
|
47
|
+
/**
|
|
48
|
+
* Set to `false` to keep every line of this part on one row, for text whose layout matters,
|
|
49
|
+
* such as a table. A line wider than the viewer then scrolls sideways instead of wrapping.
|
|
50
|
+
*/
|
|
51
|
+
wrap?: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** A captured value, displayed with type-aware formatting. */
|
|
54
|
+
export interface ValuePart {
|
|
55
|
+
type: 'value';
|
|
56
|
+
value: ValueNode;
|
|
57
|
+
}
|
|
58
|
+
/** One piece of an entry's content. Parts are displayed one after another. */
|
|
59
|
+
export type LogPart = TextPart | ValuePart;
|
|
60
|
+
/** The kinds of value a snapshot can hold. */
|
|
61
|
+
export type ValueKind = 'undefined' | 'null' | 'boolean' | 'number' | 'bigint' | 'string' | 'symbol' | 'function' | 'class' | 'date' | 'regexp' | 'error' | 'array' | 'object' | 'map' | 'set' | 'weak' | 'promise' | 'element' | 'text' | 'circular' | 'accessor';
|
|
62
|
+
/**
|
|
63
|
+
* A snapshot of a value, taken when it was logged.
|
|
64
|
+
*
|
|
65
|
+
* The tree is plain data, so it can be passed through `postMessage` or saved as JSON. It never
|
|
66
|
+
* holds a reference to the original value.
|
|
67
|
+
*/
|
|
68
|
+
export interface ValueNode {
|
|
69
|
+
kind: ValueKind;
|
|
70
|
+
/**
|
|
71
|
+
* The text of a leaf value: the string itself, a number as text, a function name, a date in
|
|
72
|
+
* ISO format, a regular expression literal, an error message, or an element's tag name.
|
|
73
|
+
*/
|
|
74
|
+
value?: string;
|
|
75
|
+
/** The constructor name of an object, such as `Map` or `User`. */
|
|
76
|
+
className?: string;
|
|
77
|
+
/** The length of an array or string, or the size of a map or set. */
|
|
78
|
+
size?: number;
|
|
79
|
+
/**
|
|
80
|
+
* The captured children of an object, array, map, set, error or element. `undefined` means
|
|
81
|
+
* the value has children that were not captured because the depth limit was reached.
|
|
82
|
+
*/
|
|
83
|
+
children?: ValueEntry[];
|
|
84
|
+
/** How many children exist but were left out because of a limit. */
|
|
85
|
+
omitted?: number;
|
|
86
|
+
/** How many characters were cut from a long string. */
|
|
87
|
+
truncated?: number;
|
|
88
|
+
/** The stack trace of an error, without its first line. */
|
|
89
|
+
stack?: string;
|
|
90
|
+
/** The attributes of an element, as name and value pairs. */
|
|
91
|
+
attributes?: [string, string][];
|
|
92
|
+
/** For an accessor property, which parts are defined. */
|
|
93
|
+
accessor?: 'get' | 'set' | 'get-set';
|
|
94
|
+
}
|
|
95
|
+
/** A child of a value: a property, an array item, a map entry or a child node. */
|
|
96
|
+
export interface ValueEntry {
|
|
97
|
+
/** The property name or index. Absent for set items and child nodes. */
|
|
98
|
+
key?: string;
|
|
99
|
+
/** How the key is displayed. */
|
|
100
|
+
keyKind?: 'property' | 'index' | 'symbol' | 'internal';
|
|
101
|
+
/** The key of a map entry. */
|
|
102
|
+
keyValue?: ValueNode;
|
|
103
|
+
value: ValueNode;
|
|
104
|
+
}
|
|
105
|
+
/** The fields a caller provides when adding an entry. */
|
|
106
|
+
export interface LogEntryInit {
|
|
107
|
+
parts: LogPart[];
|
|
108
|
+
level?: LogLevel;
|
|
109
|
+
kind?: LogKind;
|
|
110
|
+
/** Epoch milliseconds. Defaults to the time the entry is added. */
|
|
111
|
+
time?: number;
|
|
112
|
+
/** Ids of the open groups this entry belongs to, outermost first. */
|
|
113
|
+
groups?: readonly number[];
|
|
114
|
+
/** For a group header, whether the group starts collapsed. */
|
|
115
|
+
collapsed?: boolean;
|
|
116
|
+
}
|
|
117
|
+
/** An entry held by a store. */
|
|
118
|
+
export interface LogEntry {
|
|
119
|
+
readonly id: number;
|
|
120
|
+
readonly time: number;
|
|
121
|
+
readonly level: LogLevel;
|
|
122
|
+
readonly kind: LogKind;
|
|
123
|
+
readonly parts: readonly LogPart[];
|
|
124
|
+
readonly groups: readonly number[];
|
|
125
|
+
/** For a group header, whether its members are hidden. */
|
|
126
|
+
collapsed: boolean;
|
|
127
|
+
/** How many identical consecutive messages this entry stands for. */
|
|
128
|
+
repeat: number;
|
|
129
|
+
/** Increases whenever `collapsed` or `repeat` changes, so cached layouts can be refreshed. */
|
|
130
|
+
version: number;
|
|
131
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data types shared by every part of lognal.
|
|
3
|
+
*
|
|
4
|
+
* Everything under `src/core` is plain data and logic with no dependency on the DOM or on a
|
|
5
|
+
* JavaScript-only API, so that it can be ported to other runtimes, such as Dart. Platform
|
|
6
|
+
* features the core needs, such as grapheme segmentation, are passed in rather than imported.
|
|
7
|
+
*/
|
|
8
|
+
/** Every level, ordered from least to most severe. */
|
|
9
|
+
export const LOG_LEVELS = ['debug', 'log', 'info', 'warn', 'error'];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LineTextSpan } from '../layout/types.js';
|
|
2
|
+
import type { ValueEntry, ValueNode } from '../types.js';
|
|
3
|
+
/** The most cells a one-line preview of an object, array, map or set takes before it is cut. */
|
|
4
|
+
export declare const PREVIEW_CELLS = 100;
|
|
5
|
+
/** Returns whether a value can be expanded to show its children. */
|
|
6
|
+
export declare const isExpandable: (node: ValueNode) => boolean;
|
|
7
|
+
/** Formats a property key the way it would be written in an object literal. */
|
|
8
|
+
export declare const formatKey: (entry: ValueEntry) => LineTextSpan;
|
|
9
|
+
/** `TypeError: message`, or just the name when there is no message. */
|
|
10
|
+
export declare const errorTitle: (node: ValueNode) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a one-line preview of a value, such as `{id: 1, name: 'lognal'}` or
|
|
13
|
+
* `(3) [1, 2, 3]`. Objects inside the preview are shown by name only, and the preview is cut
|
|
14
|
+
* with `…` once it passes `PREVIEW_CELLS`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const previewValue: (node: ValueNode, nested?: boolean) => LineTextSpan[];
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/** The most cells a one-line preview of an object, array, map or set takes before it is cut. */
|
|
2
|
+
export const PREVIEW_CELLS = 100;
|
|
3
|
+
const IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
|
|
4
|
+
/** Returns whether a value can be expanded to show its children. */
|
|
5
|
+
export const isExpandable = (node) => {
|
|
6
|
+
if (node.kind === 'error') {
|
|
7
|
+
return Boolean(node.stack) || (node.children?.length ?? 0) > 0;
|
|
8
|
+
}
|
|
9
|
+
if (node.kind !== 'object' &&
|
|
10
|
+
node.kind !== 'array' &&
|
|
11
|
+
node.kind !== 'map' &&
|
|
12
|
+
node.kind !== 'set' &&
|
|
13
|
+
node.kind !== 'element') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return node.children !== undefined && (node.children.length > 0 || (node.omitted ?? 0) > 0);
|
|
17
|
+
};
|
|
18
|
+
const quote = (text) => {
|
|
19
|
+
const escaped = text
|
|
20
|
+
.replace(/\\/g, '\\\\')
|
|
21
|
+
.replace(/'/g, "\\'")
|
|
22
|
+
.replace(/\n/g, '\\n')
|
|
23
|
+
.replace(/\r/g, '\\r')
|
|
24
|
+
.replace(/\t/g, '\\t');
|
|
25
|
+
return `'${escaped}'`;
|
|
26
|
+
};
|
|
27
|
+
/** The longest string shown in full inside another value's preview. */
|
|
28
|
+
const NESTED_STRING_LENGTH = 50;
|
|
29
|
+
const stringText = (node, nested = false) => {
|
|
30
|
+
const value = node.value ?? '';
|
|
31
|
+
if (nested && value.length > NESTED_STRING_LENGTH) {
|
|
32
|
+
return `${quote(value.slice(0, NESTED_STRING_LENGTH))}…`;
|
|
33
|
+
}
|
|
34
|
+
return `${quote(value)}${node.truncated ? '…' : ''}`;
|
|
35
|
+
};
|
|
36
|
+
/** Formats a property key the way it would be written in an object literal. */
|
|
37
|
+
export const formatKey = (entry) => {
|
|
38
|
+
const key = entry.key ?? '';
|
|
39
|
+
if (entry.keyKind === 'symbol') {
|
|
40
|
+
return { text: key, token: 'symbol' };
|
|
41
|
+
}
|
|
42
|
+
if (entry.keyKind === 'internal') {
|
|
43
|
+
return { text: key, token: 'muted' };
|
|
44
|
+
}
|
|
45
|
+
if (entry.keyKind === 'index' || IDENTIFIER.test(key)) {
|
|
46
|
+
return { text: key, token: 'key' };
|
|
47
|
+
}
|
|
48
|
+
return { text: quote(key), token: 'key' };
|
|
49
|
+
};
|
|
50
|
+
/** The name shown before an object's contents, such as `User` or `Map(2)`. */
|
|
51
|
+
const labelOf = (node) => {
|
|
52
|
+
const size = node.size ?? node.children?.length ?? 0;
|
|
53
|
+
switch (node.kind) {
|
|
54
|
+
case 'array':
|
|
55
|
+
return node.className && node.className !== 'Array'
|
|
56
|
+
? `${node.className}(${size})`
|
|
57
|
+
: `(${size})`;
|
|
58
|
+
case 'map':
|
|
59
|
+
case 'set':
|
|
60
|
+
return `${node.className ?? (node.kind === 'map' ? 'Map' : 'Set')}(${size})`;
|
|
61
|
+
case 'object':
|
|
62
|
+
return node.className && node.className !== 'Object' ? node.className : '';
|
|
63
|
+
default:
|
|
64
|
+
return node.className ?? '';
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
/** A short name for a nested object, used inside another preview. */
|
|
68
|
+
const shortLabel = (node) => {
|
|
69
|
+
const size = node.size ?? node.children?.length ?? 0;
|
|
70
|
+
switch (node.kind) {
|
|
71
|
+
case 'array':
|
|
72
|
+
return `${node.className && node.className !== 'Array' ? node.className : 'Array'}(${size})`;
|
|
73
|
+
case 'map':
|
|
74
|
+
case 'set':
|
|
75
|
+
return labelOf(node);
|
|
76
|
+
case 'object':
|
|
77
|
+
return node.className && node.className !== 'Object' ? node.className : '{…}';
|
|
78
|
+
default:
|
|
79
|
+
return node.className ?? '';
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const elementText = (node, withAttributes) => {
|
|
83
|
+
const tag = node.value ?? 'element';
|
|
84
|
+
if (!withAttributes || !node.attributes?.length) {
|
|
85
|
+
return `<${tag}>`;
|
|
86
|
+
}
|
|
87
|
+
const attributes = node.attributes
|
|
88
|
+
.map(([name, value]) => (value === '' ? name : `${name}="${value}"`))
|
|
89
|
+
.join(' ');
|
|
90
|
+
return `<${tag} ${attributes}>`;
|
|
91
|
+
};
|
|
92
|
+
/** Spans for a leaf value, or a short label for a container nested inside a preview. */
|
|
93
|
+
const leafSpans = (node, nested) => {
|
|
94
|
+
switch (node.kind) {
|
|
95
|
+
case 'undefined':
|
|
96
|
+
return [{ text: 'undefined', token: 'null' }];
|
|
97
|
+
case 'null':
|
|
98
|
+
return [{ text: 'null', token: 'null' }];
|
|
99
|
+
case 'boolean':
|
|
100
|
+
return [{ text: node.value ?? 'false', token: 'boolean' }];
|
|
101
|
+
case 'number':
|
|
102
|
+
return [{ text: node.value ?? 'NaN', token: 'number' }];
|
|
103
|
+
case 'bigint':
|
|
104
|
+
return [{ text: `${node.value ?? '0'}n`, token: 'number' }];
|
|
105
|
+
case 'string':
|
|
106
|
+
return [{ text: stringText(node, nested), token: 'string' }];
|
|
107
|
+
case 'symbol':
|
|
108
|
+
return [{ text: node.value ?? 'Symbol()', token: 'symbol' }];
|
|
109
|
+
case 'function':
|
|
110
|
+
return [
|
|
111
|
+
{ text: 'ƒ ', token: 'function' },
|
|
112
|
+
{ text: `${node.value ?? ''}()`, token: 'default' }
|
|
113
|
+
];
|
|
114
|
+
case 'class':
|
|
115
|
+
return [
|
|
116
|
+
{ text: 'class ', token: 'function' },
|
|
117
|
+
{ text: node.value ?? '', token: 'default' }
|
|
118
|
+
];
|
|
119
|
+
case 'date':
|
|
120
|
+
return [{ text: node.value ?? 'Invalid Date', token: 'date' }];
|
|
121
|
+
case 'regexp':
|
|
122
|
+
return [{ text: node.value ?? '/(?:)/', token: 'regexp' }];
|
|
123
|
+
case 'error':
|
|
124
|
+
return [{ text: errorTitle(node), token: 'error' }];
|
|
125
|
+
case 'weak':
|
|
126
|
+
return [{ text: node.className ?? 'WeakMap', token: 'default' }];
|
|
127
|
+
case 'promise':
|
|
128
|
+
return [{ text: node.className ?? 'Promise', token: 'default' }];
|
|
129
|
+
case 'element':
|
|
130
|
+
return [{ text: elementText(node, !nested), token: 'tag' }];
|
|
131
|
+
case 'text':
|
|
132
|
+
return [{ text: stringText(node), token: 'string' }];
|
|
133
|
+
case 'circular':
|
|
134
|
+
return [{ text: '[Circular]', token: 'muted' }];
|
|
135
|
+
case 'accessor':
|
|
136
|
+
return [
|
|
137
|
+
{
|
|
138
|
+
text: node.accessor === 'set'
|
|
139
|
+
? '[Setter]'
|
|
140
|
+
: node.accessor === 'get-set'
|
|
141
|
+
? '[Getter/Setter]'
|
|
142
|
+
: '[Getter]',
|
|
143
|
+
token: 'muted'
|
|
144
|
+
}
|
|
145
|
+
];
|
|
146
|
+
default:
|
|
147
|
+
return [{ text: shortLabel(node), token: 'default' }];
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
/** `TypeError: message`, or just the name when there is no message. */
|
|
151
|
+
export const errorTitle = (node) => {
|
|
152
|
+
const name = node.className ?? 'Error';
|
|
153
|
+
return node.value ? `${name}: ${node.value}` : name;
|
|
154
|
+
};
|
|
155
|
+
const isContainer = (node) => {
|
|
156
|
+
return (node.kind === 'object' || node.kind === 'array' || node.kind === 'map' || node.kind === 'set');
|
|
157
|
+
};
|
|
158
|
+
const measure = (spans) => {
|
|
159
|
+
let cells = 0;
|
|
160
|
+
for (const span of spans) {
|
|
161
|
+
cells += span.text.length;
|
|
162
|
+
}
|
|
163
|
+
return cells;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Returns a one-line preview of a value, such as `{id: 1, name: 'lognal'}` or
|
|
167
|
+
* `(3) [1, 2, 3]`. Objects inside the preview are shown by name only, and the preview is cut
|
|
168
|
+
* with `…` once it passes `PREVIEW_CELLS`.
|
|
169
|
+
*/
|
|
170
|
+
export const previewValue = (node, nested = false) => {
|
|
171
|
+
if (!isContainer(node) || nested) {
|
|
172
|
+
return leafSpans(node, nested);
|
|
173
|
+
}
|
|
174
|
+
const label = labelOf(node);
|
|
175
|
+
const spans = [];
|
|
176
|
+
if (label) {
|
|
177
|
+
spans.push({ text: `${label} `, token: node.kind === 'object' ? 'default' : 'muted' });
|
|
178
|
+
}
|
|
179
|
+
if (node.children === undefined) {
|
|
180
|
+
spans.push({ text: node.kind === 'array' ? '[…]' : '{…}', token: 'default' });
|
|
181
|
+
return spans;
|
|
182
|
+
}
|
|
183
|
+
const isArray = node.kind === 'array';
|
|
184
|
+
spans.push({ text: isArray ? '[' : '{', token: 'default' });
|
|
185
|
+
let shown = 0;
|
|
186
|
+
for (const child of node.children) {
|
|
187
|
+
if (measure(spans) > PREVIEW_CELLS) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
if (shown > 0) {
|
|
191
|
+
spans.push({ text: ', ', token: 'default' });
|
|
192
|
+
}
|
|
193
|
+
if (node.kind === 'map' && child.keyValue) {
|
|
194
|
+
spans.push(...leafSpans(child.keyValue, true), { text: ' => ', token: 'default' });
|
|
195
|
+
}
|
|
196
|
+
else if (!isArray && node.kind !== 'set' && child.key !== undefined) {
|
|
197
|
+
spans.push(formatKey(child), { text: ': ', token: 'default' });
|
|
198
|
+
}
|
|
199
|
+
spans.push(...leafSpans(child.value, true));
|
|
200
|
+
shown++;
|
|
201
|
+
}
|
|
202
|
+
if (shown < node.children.length || (node.omitted ?? 0) > 0) {
|
|
203
|
+
spans.push({ text: shown > 0 ? ', …' : '…', token: 'muted' });
|
|
204
|
+
}
|
|
205
|
+
spans.push({ text: isArray ? ']' : '}', token: 'default' });
|
|
206
|
+
return spans;
|
|
207
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type { LogEntry, LogEntryInit, LogKind, LogLevel, LogPart, StyleToken, TextColor, TextPart, TextStyle, ValueEntry, ValueKind, ValueNode, ValuePart } from './core/types.js';
|
|
2
|
+
export { LOG_LEVELS } from './core/types.js';
|
|
3
|
+
export { DEFAULT_STORE_OPTIONS, LogStore, type LogStoreOptions, type StoreChange, type StoreListener, type WriteOptions } from './core/store.js';
|
|
4
|
+
export { compileFilter, entrySearchText, type CompiledFilter, type LogFilter } from './core/filter.js';
|
|
5
|
+
export { DEFAULT_LAYOUT_OPTIONS, LogLayout, type LayoutOptions } from './core/layout/layout.js';
|
|
6
|
+
export type { LineAction, LineIconSpan, LineSpan, LineTextSpan, LogicalLine, RowRun, TextPosition, VisualRow, WrapMode } from './core/layout/types.js';
|
|
7
|
+
export { formatTimestamp, type TimestampFormat } from './core/time.js';
|
|
8
|
+
export { AnsiParser, stripAnsi } from './core/text/ansi.js';
|
|
9
|
+
export { LineSplitter, splitLines } from './core/text/line-splitter.js';
|
|
10
|
+
export { measureCells, truncateCells } from './core/text/measure.js';
|
|
11
|
+
export { setGraphemeSplitter, splitGraphemes, type GraphemeSplitter } from './core/text/graphemes.js';
|
|
12
|
+
export { clusterWidth, codePointWidth, type AmbiguousWidth } from './core/text/width.js';
|
|
13
|
+
export { UNICODE_VERSION } from './core/text/unicode-width-data.js';
|
|
14
|
+
export { previewValue } from './core/value/preview.js';
|
|
15
|
+
export { CONSOLE_METHODS, ConsoleRecorder, type ConsoleMethod, type RecorderOptions } from './sources/console/recorder.js';
|
|
16
|
+
export { createConsole, hookConsole, type HookConsoleOptions, type LognalConsole } from './sources/console/hook.js';
|
|
17
|
+
export { applyFormat, formatArguments, parseConsoleCss, type ValueCapture } from './sources/console/format.js';
|
|
18
|
+
export { DEFAULT_CAPTURE_OPTIONS, snapshotValue, type CaptureOptions } from './sources/console/snapshot.js';
|
|
19
|
+
export { detectEncoding, legacyEncodingFor } from './sources/text/encoding.js';
|
|
20
|
+
export { readTextFile, TextLineWriter, type ReadTextOptions, type ReadTextResult } from './sources/text/read-file.js';
|
|
21
|
+
export { followTextFile, type FileHandleLike, type FollowHandle, type FollowTextOptions } from './sources/text/follow-file.js';
|
|
22
|
+
export type { CellMetrics, FontSettings, RenderFrame, RenderTheme, Renderer, RowDecoration } from './renderer/types.js';
|
|
23
|
+
export { CanvasRenderer } from './renderer/canvas/canvas-renderer.js';
|
|
24
|
+
export { DEFAULT_RENDER_THEME } from './renderer/theme.js';
|
|
25
|
+
export { LogViewer, type CoreOptions, type InputOptions, type LogViewerEvents, type LogViewerOptions, type ToolbarOptions } from './viewer/viewer.js';
|
|
26
|
+
export { EN_LABELS, KO_LABELS, labelsFor, type ViewerLabels } from './viewer/labels.js';
|
|
27
|
+
export { DEFAULT_FONT, readFont, readTheme, type ThemeMode } from './viewer/theme.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export { LOG_LEVELS } from './core/types.js';
|
|
2
|
+
export { DEFAULT_STORE_OPTIONS, LogStore } from './core/store.js';
|
|
3
|
+
export { compileFilter, entrySearchText } from './core/filter.js';
|
|
4
|
+
export { DEFAULT_LAYOUT_OPTIONS, LogLayout } from './core/layout/layout.js';
|
|
5
|
+
export { formatTimestamp } from './core/time.js';
|
|
6
|
+
export { AnsiParser, stripAnsi } from './core/text/ansi.js';
|
|
7
|
+
export { LineSplitter, splitLines } from './core/text/line-splitter.js';
|
|
8
|
+
export { measureCells, truncateCells } from './core/text/measure.js';
|
|
9
|
+
export { setGraphemeSplitter, splitGraphemes } from './core/text/graphemes.js';
|
|
10
|
+
export { clusterWidth, codePointWidth } from './core/text/width.js';
|
|
11
|
+
export { UNICODE_VERSION } from './core/text/unicode-width-data.js';
|
|
12
|
+
export { previewValue } from './core/value/preview.js';
|
|
13
|
+
export { CONSOLE_METHODS, ConsoleRecorder } from './sources/console/recorder.js';
|
|
14
|
+
export { createConsole, hookConsole } from './sources/console/hook.js';
|
|
15
|
+
export { applyFormat, formatArguments, parseConsoleCss } from './sources/console/format.js';
|
|
16
|
+
export { DEFAULT_CAPTURE_OPTIONS, snapshotValue } from './sources/console/snapshot.js';
|
|
17
|
+
export { detectEncoding, legacyEncodingFor } from './sources/text/encoding.js';
|
|
18
|
+
export { readTextFile, TextLineWriter } from './sources/text/read-file.js';
|
|
19
|
+
export { followTextFile } from './sources/text/follow-file.js';
|
|
20
|
+
export { CanvasRenderer } from './renderer/canvas/canvas-renderer.js';
|
|
21
|
+
export { DEFAULT_RENDER_THEME } from './renderer/theme.js';
|
|
22
|
+
export { LogViewer } from './viewer/viewer.js';
|
|
23
|
+
export { EN_LABELS, KO_LABELS, labelsFor } from './viewer/labels.js';
|
|
24
|
+
export { DEFAULT_FONT, readFont, readTheme } from './viewer/theme.js';
|