@orz/ui-ansi 0.0.0-stage → 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.
Files changed (100) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +232 -2
  3. package/dist/content.d.ts +20 -0
  4. package/dist/content.d.ts.map +1 -0
  5. package/dist/content.js +90 -0
  6. package/dist/content.js.map +1 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/parse/index.d.ts +6 -0
  12. package/dist/parse/index.d.ts.map +1 -0
  13. package/dist/parse/index.js +5 -0
  14. package/dist/parse/index.js.map +1 -0
  15. package/dist/parse/level-tracker.d.ts +14 -0
  16. package/dist/parse/level-tracker.d.ts.map +1 -0
  17. package/dist/parse/level-tracker.js +87 -0
  18. package/dist/parse/level-tracker.js.map +1 -0
  19. package/dist/parse/levels.d.ts +19 -0
  20. package/dist/parse/levels.d.ts.map +1 -0
  21. package/dist/parse/levels.js +167 -0
  22. package/dist/parse/levels.js.map +1 -0
  23. package/dist/parse/line.d.ts +49 -0
  24. package/dist/parse/line.d.ts.map +1 -0
  25. package/dist/parse/line.js +289 -0
  26. package/dist/parse/line.js.map +1 -0
  27. package/dist/parse/palette.d.ts +12 -0
  28. package/dist/parse/palette.d.ts.map +1 -0
  29. package/dist/parse/palette.js +40 -0
  30. package/dist/parse/palette.js.map +1 -0
  31. package/dist/parse/parser.d.ts +18 -0
  32. package/dist/parse/parser.d.ts.map +1 -0
  33. package/dist/parse/parser.js +178 -0
  34. package/dist/parse/parser.js.map +1 -0
  35. package/dist/parse/sgr.d.ts +7 -0
  36. package/dist/parse/sgr.d.ts.map +1 -0
  37. package/dist/parse/sgr.js +179 -0
  38. package/dist/parse/sgr.js.map +1 -0
  39. package/dist/parse/styles.d.ts +15 -0
  40. package/dist/parse/styles.d.ts.map +1 -0
  41. package/dist/parse/styles.js +75 -0
  42. package/dist/parse/styles.js.map +1 -0
  43. package/dist/parse/tokenizer.d.ts +36 -0
  44. package/dist/parse/tokenizer.d.ts.map +1 -0
  45. package/dist/parse/tokenizer.js +287 -0
  46. package/dist/parse/tokenizer.js.map +1 -0
  47. package/dist/parse/types.d.ts +50 -0
  48. package/dist/parse/types.d.ts.map +1 -0
  49. package/dist/parse/types.js +2 -0
  50. package/dist/parse/types.js.map +1 -0
  51. package/dist/view/ansi-view.d.ts +27 -0
  52. package/dist/view/ansi-view.d.ts.map +1 -0
  53. package/dist/view/ansi-view.js +675 -0
  54. package/dist/view/ansi-view.js.map +1 -0
  55. package/dist/view/geometry.d.ts +30 -0
  56. package/dist/view/geometry.d.ts.map +1 -0
  57. package/dist/view/geometry.js +125 -0
  58. package/dist/view/geometry.js.map +1 -0
  59. package/dist/view/metrics.d.ts +17 -0
  60. package/dist/view/metrics.d.ts.map +1 -0
  61. package/dist/view/metrics.js +69 -0
  62. package/dist/view/metrics.js.map +1 -0
  63. package/dist/view/row.d.ts +41 -0
  64. package/dist/view/row.d.ts.map +1 -0
  65. package/dist/view/row.js +113 -0
  66. package/dist/view/row.js.map +1 -0
  67. package/dist/view/run-style.d.ts +11 -0
  68. package/dist/view/run-style.d.ts.map +1 -0
  69. package/dist/view/run-style.js +87 -0
  70. package/dist/view/run-style.js.map +1 -0
  71. package/dist/view/search.d.ts +28 -0
  72. package/dist/view/search.d.ts.map +1 -0
  73. package/dist/view/search.js +76 -0
  74. package/dist/view/search.js.map +1 -0
  75. package/dist/view/shown-lines.d.ts +15 -0
  76. package/dist/view/shown-lines.d.ts.map +1 -0
  77. package/dist/view/shown-lines.js +50 -0
  78. package/dist/view/shown-lines.js.map +1 -0
  79. package/dist/view/time-slices.d.ts +9 -0
  80. package/dist/view/time-slices.d.ts.map +1 -0
  81. package/dist/view/time-slices.js +35 -0
  82. package/dist/view/time-slices.js.map +1 -0
  83. package/dist/view/toolbar.d.ts +47 -0
  84. package/dist/view/toolbar.d.ts.map +1 -0
  85. package/dist/view/toolbar.js +58 -0
  86. package/dist/view/toolbar.js.map +1 -0
  87. package/dist/view/use-ansi-lines.d.ts +28 -0
  88. package/dist/view/use-ansi-lines.d.ts.map +1 -0
  89. package/dist/view/use-ansi-lines.js +103 -0
  90. package/dist/view/use-ansi-lines.js.map +1 -0
  91. package/dist/view/use-search.d.ts +37 -0
  92. package/dist/view/use-search.d.ts.map +1 -0
  93. package/dist/view/use-search.js +205 -0
  94. package/dist/view/use-search.js.map +1 -0
  95. package/dist/view/virtual-rows.d.ts +36 -0
  96. package/dist/view/virtual-rows.d.ts.map +1 -0
  97. package/dist/view/virtual-rows.js +156 -0
  98. package/dist/view/virtual-rows.js.map +1 -0
  99. package/package.json +58 -3
  100. package/styles.css +110 -0
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright 2026 the orzui team
4
+ Copyright 2026 the todou team
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md CHANGED
@@ -1,3 +1,233 @@
1
- # Temporary Holding Version
1
+ # @orz/ui-ansi
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Text with ANSI escape sequences, such as CI logs, `ls --color` or `git diff --color`, drawn in the
4
+ active `@orz/ui` terminal colours, and plain logs, with each line coloured and filterable by its log
5
+ level. The package contributes two renderers to `@orz/ui-content`'s registry, so an
6
+ ```` ```ansi ```` or ```` ```log ```` fence in `@orz/ui-markdown` and an `.ansi` or `.log` file in a
7
+ viewer are drawn without importing this package from either. Its parser and level detector have no
8
+ React and no DOM, and are usable on their own.
9
+
10
+ A log is the same view with levels turned on, not a second component: a `.log` file full of escapes
11
+ needs no routing decision, and plain text takes the parser's fast path at no extra cost.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add @orz/ui-ansi @orz/ui-content @orz/ui react lucide-react
17
+ ```
18
+
19
+ There are no runtime dependencies. `@orz/ui-content` is a peer dependency so that the app and every
20
+ content package share one registry.
21
+
22
+ ## CSS
23
+
24
+ ```css
25
+ @import "tailwindcss";
26
+ @import "@orz/ui/styles.css";
27
+ @import "@orz/ui-ansi/styles.css";
28
+ ```
29
+
30
+ Import it after `@orz/ui/styles.css`. It holds the selection colour (`--terminal-selection`), the level and
31
+ search-match colours, and
32
+ like `@orz/ui`'s stylesheet it registers `@source "./dist"` on its own.
33
+
34
+ ## `ansiContent`
35
+
36
+ ```tsx
37
+ import { ansiContent, logContent } from "@orz/ui-ansi";
38
+ import { codeContent } from "@orz/ui-code";
39
+ import { ContentRenderers } from "@orz/ui-content";
40
+
41
+ const RENDERERS = [ansiContent, logContent, codeContent];
42
+
43
+ <ContentRenderers renderers={RENDERERS}>{app}</ContentRenderers>;
44
+ ```
45
+
46
+ It accepts inline sources whose `lang` is `ansi` (any case), which is what a markdown fence becomes,
47
+ and files named `*.ansi` or typed `text/x-ansi`. `.log` files and `log` fences are `logContent`'s
48
+ (see [Logs](#logs)). Register it before any renderer that takes every inline source, such as a code renderer, since
49
+ the first renderer that accepts wins.
50
+
51
+ - A fence draws the terminal pane, 32rem tall at most in a document.
52
+ - A file draws the file chrome, 32rem at most in a document and the attachment pane's height in a
53
+ viewer. Its final newline is dropped, so it does not end on an empty numbered line. While it loads
54
+ the registry's fallback link shows; a file that fails to load shows the message and a Retry button.
55
+ - A file declared or loaded over `ANSI_PREVIEW_MAX_BYTES` (64 MiB) is not drawn: it shows the
56
+ download link and "Too large to preview — download to view."
57
+
58
+ ## `AnsiView`
59
+
60
+ For a surface that draws ANSI text outside the registry:
61
+
62
+ ```tsx
63
+ import { AnsiView } from "@orz/ui-ansi";
64
+
65
+ <AnsiView chrome="pane" text={output} />
66
+ <AnsiView chrome="file" text={log} filename="build.log" downloadUrl={url} maxHeight="40rem" levels />
67
+ ```
68
+
69
+ | Prop | |
70
+ |---|---|
71
+ | `text` | The text, escapes included. |
72
+ | `chrome` | `"pane"`: the terminal pane, with Copy and Wrap on hover and on focus. `"file"`: a header with the filename, the line count, Wrap, Copy and Download, a toolbar with the level chips and the search box, and a line-number gutter. |
73
+ | `filename` | Shown in the file header, and the region's accessible name. |
74
+ | `downloadUrl` | The header's Download link. |
75
+ | `boldIsBright` | Bold text in palette colours 0–7 is drawn in 8–15. Default `false`. |
76
+ | `wrap` | The initial wrap state; the Wrap button toggles it. Default `false`. |
77
+ | `maxHeight` | How tall the view may grow before it scrolls. Default: it grows to fit. |
78
+ | `levels` | `true` colours each line by its detected level and, in file chrome, adds the level filter; a function replaces the detector (see [Logs](#logs)). Default `false`. |
79
+ | `className` | On the root. |
80
+
81
+ Copy writes the whole text with its escapes stripped, not only the rows on screen; while a filter
82
+ hides lines, it writes only the shown ones. A selection copied from the view is rebuilt from the
83
+ parsed lines, so a wrapped line copies as one line and a hidden line is never pasted.
84
+
85
+ ## Logs
86
+
87
+ `logContent` accepts inline sources whose `lang` is `log` (any case), and files named `*.log` or
88
+ typed `text/x-log`. A file whose name and type disagree, such as `build.log` typed `text/x-ansi`,
89
+ goes to whichever of `logContent` and `ansiContent` is registered first. Both go before
90
+ `codeContent`: it claims the same sources, draws them with a syntax grammar, and stops at 1 MiB.
91
+ Files get everything `ansiContent`'s files get, including the 64 MiB cap. A fence draws the pane,
92
+ coloured by level but with no toolbar: fences are short, mount every row, and keep the browser's
93
+ find.
94
+
95
+ With `levels`, each line's level is read from its text, escapes stripped. A function in its place
96
+ replaces the detector for logs of a shape the rules below miss. Keep its identity across renders,
97
+ since a new function classifies the whole text again; a detector that throws is read as "no level"
98
+ for that line, and the first error is logged once.
99
+
100
+ ```tsx
101
+ import type { LevelDetector } from "@orz/ui-ansi";
102
+
103
+ // At module level, so it keeps its identity.
104
+ const detect: LevelDetector = (text) => (text.startsWith("!!") ? { level: "error" } : null);
105
+
106
+ <AnsiView chrome="file" text={log} levels={detect} />;
107
+ ```
108
+
109
+ `detectLevel` tries these rules over the first 256 characters, and the first that matches wins:
110
+
111
+ 1. A JSON line with a `level`, `lvl`, `severity` or `loglevel` key, as a word or as a pino/bunyan
112
+ number (≥60 fatal, ≥50 error, ≥40 warn, ≥30 info, ≥20 debug, below that trace).
113
+ 2. logfmt: `level=`, `lvl=` or `severity=`.
114
+ 3. A syslog priority, `<n>` at the start.
115
+ 4. glog/klog: `E1023 09:14:11…`.
116
+ 5. Android logcat, in the `brief` and `threadtime` forms.
117
+ 6. `Traceback (most recent call last):`, as error.
118
+ 7. A level word, whichever form comes first: UPPERCASE anywhere, any case inside `[…]`, `<…>` or
119
+ `(…)`, any case before `:`, or any case as the line's first or second word.
120
+
121
+ | Words (any case) | Level |
122
+ |---|---|
123
+ | `fatal`, `critical`, `crit`, `emerg`, `emergency`, `alert`, `panic` | fatal |
124
+ | `error`, `err`, `severe` | error |
125
+ | `warning`, `warn` | warn |
126
+ | `info`, `information`, `notice` | info |
127
+ | `debug`, `dbg`, `fine` | debug |
128
+ | `trace`, `verbose`, `finer`, `finest` | trace |
129
+
130
+ A lowercase word in the middle of a message does not count, so "disk I/O error" and "no errors
131
+ expected" stay unlevelled, and the word must stand whole: `ERROR_CODE` and `errorCount` do not match.
132
+ The rules are a heuristic; the fixtures in `test/parse/levels.test.ts` are their specification.
133
+
134
+ A line with no level of its own takes the level of the line above when it looks like the rest of
135
+ that entry: it is indented, starts with `Caused by:`, `Suppressed:` or `... N more`, or is an
136
+ exception head such as `java.lang.IllegalStateException: …` or `ValueError: …`. A stack trace
137
+ therefore stays with its error under the filter, while an unindented `Done in 3.2s.` after a warning
138
+ does not. Any other line, a blank one included, is "Other" and ends the chain. This applies to a
139
+ custom detector too.
140
+
141
+ How a level shows, in the theme's terminal palette:
142
+
143
+ - Fatal, error and warn rows get a stripe on the left and a faint tint, so they stand out while
144
+ scrolling; an inherited line's stripe is fainter.
145
+ - The level word takes the level's colour: bright red (inverted for fatal), red, yellow, green for
146
+ info, blue for debug and grey for trace.
147
+ - Debug and trace text is dimmed.
148
+ - A line with ANSI colours of its own keeps them: no word colour and no dimming, but still the
149
+ stripe, the tint and the filter.
150
+
151
+ In file chrome, a chip per level that occurs shows its line count. A click hides or shows that
152
+ level; shift+click shows only that level, and again shows all. Hidden lines leave the view: line
153
+ numbers keep their values, a dashed rule marks each gap, and the header reads "N of M lines".
154
+
155
+ ## Search
156
+
157
+ The file chrome has a search box that finds text in every line, including the rows a virtualised
158
+ view has not mounted. Ctrl+F (⌘F) while focus is inside the view goes to it instead of the browser's
159
+ find; outside the view the browser's find is untouched. Enter and Shift+Enter, or the arrows, step
160
+ through the matches and wrap at the ends; Escape returns to the log and keeps the highlights.
161
+
162
+ - **Aa** matches case, **.\*** reads the query as a regular expression, and **≡** shows only the
163
+ lines with a match.
164
+ - Search sees only the shown lines: a level the filter hides cannot be reached from the box.
165
+ - A match never spans two lines, and it is found in the text with escapes stripped.
166
+ - The scan runs in time slices, so typing stays responsive in a large log; the counter reads
167
+ "3 / 41…" until it finishes. It stops storing at 100,000 matches and reads "100,000+".
168
+ - The slices bound the total time, not one `exec`: a pathological regular expression on one long line
169
+ still blocks while it runs.
170
+
171
+ ## `@orz/ui-ansi/parse`
172
+
173
+ ```ts
174
+ import { createAnsiParser, parseAnsi, stripAnsi } from "@orz/ui-ansi/parse";
175
+
176
+ const { lines, styles, maxCells } = parseAnsi(text);
177
+ stripAnsi("\x1b[31merror\x1b[0m"); // "error"
178
+
179
+ const parser = createAnsiParser();
180
+ parser.push(chunk); // any split point: an escape cut in half is carried over
181
+ parser.end();
182
+ ```
183
+
184
+ ```ts
185
+ import { createLevelTracker, detectLevel } from "@orz/ui-ansi/parse";
186
+
187
+ detectLevel("2026-10-23 09:14:03 WARN pool exhausted"); // { level: "warn", from: 20, to: 24 }
188
+
189
+ const tracker = createLevelTracker(); // or createLevelTracker(detect)
190
+ tracker.push(lines, 0, lines.length); // then push(lines, tracker.count, lines.length) as lines arrive
191
+ tracker.levels; // one code per line, continuation lines included
192
+ tracker.counts; // { fatal, error, warn, info, debug, trace, other }
193
+ ```
194
+
195
+ Each line holds its text, its display width in cells, and its runs as `[offset, styleId]` pairs over
196
+ one `Uint32Array`; styles are interned, so a million lines share a few dozen style objects.
197
+
198
+ What is drawn:
199
+
200
+ - SGR: bold, dim, italic, the underline styles (`4:1`–`4:5`, `21`), blink (kept, not animated),
201
+ inverse, hidden, strike and overline; foreground, background and underline colour (`58`) as the 16
202
+ palette colours, the 256-colour palette or 24-bit RGB, in both the `;` and `:` forms.
203
+ - `\r`, `\b`, `\t` (stops every 8 cells), `CSI C`/`D`/`G` and `CSI 0K`/`1K`/`2K` within the line, so
204
+ a progress bar ends in its final state.
205
+ - OSC 8 links whose URI is `http:`, `https:` or `mailto:` and at most 2,048 characters.
206
+ - Wide characters take two cells and combining marks none, from `@orz/ui/lib/cell-width`.
207
+
208
+ What is dropped: every other CSI (cursor up and down, scroll regions, screen erase), every other OSC,
209
+ DCS, APC, PM and SOS up to its terminator, other C0 controls, and C1 controls. An unterminated OSC is
210
+ dropped once it passes 4 KiB, and the text after it is parsed normally.
211
+
212
+ ## Theming
213
+
214
+ Palette colours 0–15 are `var(--ansi-*)`, and the default foreground and background are
215
+ `var(--terminal-foreground)` and `var(--terminal-background)`, which `@orz/themes` writes for every
216
+ theme, including the terminal slot. A theme change needs no re-render. The 256-colour palette and
217
+ 24-bit colours are absolute, as in every terminal.
218
+
219
+ ## Large text
220
+
221
+ Up to 1 MiB is parsed in one go; above that, the text is parsed in slices that yield to the browser,
222
+ and the header reads "Parsing… N lines" while it runs; level counts grow with it. Up to 5,000
223
+ visual rows of the shown lines, every row is in the DOM. Above that only the rows on screen are
224
+ mounted, so the browser's find sees only those; in file chrome, the view's own search covers the
225
+ rest. A virtualised view needs a bounded height: without `maxHeight` it takes 32rem.
226
+
227
+ ## Entry points
228
+
229
+ | Import | Contents |
230
+ |---|---|
231
+ | `@orz/ui-ansi` | `ansiContent`, `logContent`, `ANSI_PREVIEW_MAX_BYTES`, `AnsiView`, `AnsiViewProps`, `LogLevel`, `LevelMatch`, `LevelDetector` |
232
+ | `@orz/ui-ansi/parse` | `parseAnsi`, `stripAnsi`, `createAnsiParser`, `detectLevel`, `createLevelTracker`, `LEVELS`, `LEVEL_INHERITED`, `levelCode`, `levelOfCode`, `xterm256`, `PALETTE_NAMES`, and the types |
233
+ | `@orz/ui-ansi/styles.css` | the selection, level and match colours |
@@ -0,0 +1,20 @@
1
+ import { type ContentRenderer } from "@orz/ui-content";
2
+ /**
3
+ * The largest file `ansiContent` or `logContent` previews. The view is virtualised, so the cap is
4
+ * set by the memory a parsed log takes rather than by layout, and sits far above
5
+ * `TEXT_PREVIEW_MAX_BYTES`.
6
+ */
7
+ export declare const ANSI_PREVIEW_MAX_BYTES: number;
8
+ /**
9
+ * The registry entry for terminal output: a source tagged `ansi` (a fenced block) and a `.ansi` or
10
+ * `text/x-ansi` file, in either placement. Register it before any renderer that takes every inline
11
+ * source, such as `codeContent`. A file over `ANSI_PREVIEW_MAX_BYTES` gets the download link.
12
+ */
13
+ export declare const ansiContent: ContentRenderer;
14
+ /**
15
+ * The registry entry for logs: a source tagged `log` and a `.log` or `text/x-log` file, drawn with
16
+ * level chips, the level filter and search. Register it before `codeContent`, which claims the same
17
+ * sources and stops at a far smaller size. Files share `ansiContent`'s cap.
18
+ */
19
+ export declare const logContent: ContentRenderer;
20
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,iBAAiB,CAAC;AAGzB;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AAyIvD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,eAKzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,eAKxB,CAAC"}
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "@orz/ui/components/button";
3
+ import { cn } from "@orz/ui/lib/utils";
4
+ import { ContentFallback, useSourceText, } from "@orz/ui-content";
5
+ import { AnsiView } from "./view/ansi-view.js";
6
+ /**
7
+ * The largest file `ansiContent` or `logContent` previews. The view is virtualised, so the cap is
8
+ * set by the memory a parsed log takes rather than by layout, and sits far above
9
+ * `TEXT_PREVIEW_MAX_BYTES`.
10
+ */
11
+ export const ANSI_PREVIEW_MAX_BYTES = 64 * 1024 * 1024;
12
+ const DOCUMENT_MAX_HEIGHT = "32rem";
13
+ function isAnsi(source) {
14
+ if (source.kind === "inline")
15
+ return source.lang?.toLowerCase() === "ansi";
16
+ if (/\.ansi$/i.test(source.name))
17
+ return true;
18
+ const mime = source.mime?.split(";")[0]?.trim().toLowerCase();
19
+ return mime === "text/x-ansi";
20
+ }
21
+ function isLog(source) {
22
+ if (source.kind === "inline")
23
+ return source.lang?.toLowerCase() === "log";
24
+ if (/\.log$/i.test(source.name))
25
+ return true;
26
+ const mime = source.mime?.split(";")[0]?.trim().toLowerCase();
27
+ return mime === "text/x-log";
28
+ }
29
+ function TooLargeFile({ source, placement, className, }) {
30
+ return (_jsxs("div", { className: className, children: [_jsx(ContentFallback, { source: source, placement: placement }), " ", _jsx("span", { children: "Too large to preview \u2014 download to view." })] }));
31
+ }
32
+ function LoadedFile({ source, placement, className, levels }) {
33
+ const text = useSourceText(source);
34
+ if (text.status === "loading") {
35
+ return (_jsx(ContentFallback, { source: source, placement: placement, className: className }));
36
+ }
37
+ if (text.status === "error") {
38
+ return (_jsxs("div", { className: className, children: [_jsx(ContentFallback, { source: source, placement: placement }), " ", _jsx("span", { children: text.error.message }), " ", _jsx(Button, { size: "xs", variant: "outline", onClick: text.retry, children: "Retry" })] }));
39
+ }
40
+ // Counted in UTF-16 units, not bytes: the cap is generous, and encoding a
41
+ // 64 MiB string only to measure it would cost more than the check saves.
42
+ if (text.text.length > ANSI_PREVIEW_MAX_BYTES) {
43
+ return (_jsx(TooLargeFile, { source: source, placement: placement, className: className }));
44
+ }
45
+ return (_jsx(AnsiView, { chrome: "file", levels: levels, filename: source.name, downloadUrl: source.url,
46
+ // The final newline would otherwise end the file on an empty numbered line.
47
+ text: text.text.replace(/\r?\n$/, ""), maxHeight: placement === "document" ? DOCUMENT_MAX_HEIGHT : undefined, className: cn(placement === "viewer" && "h-(--attachment-pane-height)", className) }));
48
+ }
49
+ function AnsiFile(props) {
50
+ const { source, placement, className } = props;
51
+ if (source.size !== undefined && source.size > ANSI_PREVIEW_MAX_BYTES) {
52
+ return (_jsx(TooLargeFile, { source: source, placement: placement, className: className }));
53
+ }
54
+ return _jsx(LoadedFile, { ...props });
55
+ }
56
+ function Source({ source, placement, className, levels, }) {
57
+ if (source.kind === "file") {
58
+ return (_jsx(AnsiFile, { source: source, placement: placement, className: className, levels: levels }));
59
+ }
60
+ return (_jsx(AnsiView, { chrome: "pane", levels: levels, text: source.text, className: className, maxHeight: placement === "document" ? DOCUMENT_MAX_HEIGHT : undefined }));
61
+ }
62
+ function Ansi(props) {
63
+ return _jsx(Source, { ...props, levels: false });
64
+ }
65
+ function Log(props) {
66
+ return _jsx(Source, { ...props, levels: true });
67
+ }
68
+ /**
69
+ * The registry entry for terminal output: a source tagged `ansi` (a fenced block) and a `.ansi` or
70
+ * `text/x-ansi` file, in either placement. Register it before any renderer that takes every inline
71
+ * source, such as `codeContent`. A file over `ANSI_PREVIEW_MAX_BYTES` gets the download link.
72
+ */
73
+ export const ansiContent = {
74
+ name: "ansi",
75
+ accepts: isAnsi,
76
+ display: "block",
77
+ Component: Ansi,
78
+ };
79
+ /**
80
+ * The registry entry for logs: a source tagged `log` and a `.log` or `text/x-log` file, drawn with
81
+ * level chips, the level filter and search. Register it before `codeContent`, which claims the same
82
+ * sources and stops at a far smaller size. Files share `ansiContent`'s cap.
83
+ */
84
+ export const logContent = {
85
+ name: "log",
86
+ accepts: isLog,
87
+ display: "block",
88
+ Component: Log,
89
+ };
90
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { ANSI_PREVIEW_MAX_BYTES, ansiContent, logContent, } from "./content.tsx";
2
+ export type { LevelDetector, LevelMatch, LogLevel } from "./parse/levels.ts";
3
+ export type { AnsiViewProps } from "./view/ansi-view.tsx";
4
+ export { AnsiView } from "./view/ansi-view.tsx";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7E,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ANSI_PREVIEW_MAX_BYTES, ansiContent, logContent, } from "./content.js";
2
+ export { AnsiView } from "./view/ansi-view.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,UAAU,GACX,MAAM,cAAe,CAAC;AAGvB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAsB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createLevelTracker, type LevelCounts, type LevelTracker, } from "./level-tracker.ts";
2
+ export { detectLevel, LEVEL_INHERITED, LEVELS, type LevelDetector, type LevelMatch, type LogLevel, levelCode, levelOfCode, } from "./levels.ts";
3
+ export { PALETTE_NAMES, xterm256 } from "./palette.ts";
4
+ export { createAnsiParser, parseAnsi, stripAnsi } from "./parser.ts";
5
+ export type { AnsiColor, AnsiLine, AnsiParse, AnsiParser, AnsiStyle, UnderlineStyle, } from "./types.ts";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parse/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,eAAe,EACf,MAAM,EACN,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { createLevelTracker, } from "./level-tracker.js";
2
+ export { detectLevel, LEVEL_INHERITED, LEVELS, levelCode, levelOfCode, } from "./levels.js";
3
+ export { PALETTE_NAMES, xterm256 } from "./palette.js";
4
+ export { createAnsiParser, parseAnsi, stripAnsi } from "./parser.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parse/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,eAAe,EACf,MAAM,EAIN,SAAS,EACT,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type LevelDetector, type LogLevel } from "./levels.ts";
2
+ import type { AnsiLine } from "./types.ts";
3
+ export type LevelCounts = Readonly<Record<LogLevel | "other", number>>;
4
+ export interface LevelTracker {
5
+ /** Classifies `lines[from…to)`; `from` must be where the last call stopped. */
6
+ push(lines: readonly Pick<AnsiLine, "text">[], from: number, to: number): void;
7
+ /** One code per line: 0 none, 1–6 `LEVELS`, `| LEVEL_INHERITED` inherited. */
8
+ readonly levels: Uint8Array;
9
+ readonly count: number;
10
+ /** An inherited line counts under its level. */
11
+ readonly counts: LevelCounts;
12
+ }
13
+ export declare function createLevelTracker(detect?: LevelDetector): LevelTracker;
14
+ //# sourceMappingURL=level-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level-tracker.d.ts","sourceRoot":"","sources":["../../src/parse/level-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAElB,KAAK,QAAQ,EAEd,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,IAAI,CACF,KAAK,EAAE,SAAS,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACxC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAAC;IACR,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAmGD,wBAAgB,kBAAkB,CAChC,MAAM,GAAE,aAA2B,GAClC,YAAY,CAEd"}
@@ -0,0 +1,87 @@
1
+ import { detectLevel, LEVEL_INHERITED, levelCode, } from "./levels.js";
2
+ const CONTINUATION = /^(?:[ \t]+\S|Caused by:|Suppressed:|\.\.\. \d+ more|[\w$]+(?:\.[\w$]+)*(?:Exception|Error|Throwable)(?::|\s|$))/;
3
+ const COUNT_KEYS = [
4
+ "other",
5
+ "fatal",
6
+ "error",
7
+ "warn",
8
+ "info",
9
+ "debug",
10
+ "trace",
11
+ ];
12
+ class Tracker {
13
+ buffer = new Uint8Array(1024);
14
+ view = this.buffer.subarray(0, 0);
15
+ tally = new Uint32Array(COUNT_KEYS.length);
16
+ snapshot = countsOf(this.tally);
17
+ reported = false;
18
+ detect;
19
+ constructor(detect) {
20
+ this.detect = detect;
21
+ }
22
+ get levels() {
23
+ return this.view;
24
+ }
25
+ get count() {
26
+ return this.view.length;
27
+ }
28
+ get counts() {
29
+ return this.snapshot;
30
+ }
31
+ push(lines, from, to) {
32
+ const count = this.view.length;
33
+ if (from !== count) {
34
+ throw new RangeError(`LevelTracker: push from ${from}, but ${count} lines are classified`);
35
+ }
36
+ if (to <= from)
37
+ return;
38
+ if (to > this.buffer.length) {
39
+ let size = this.buffer.length * 2;
40
+ while (size < to)
41
+ size *= 2;
42
+ const grown = new Uint8Array(size);
43
+ grown.set(this.view);
44
+ this.buffer = grown;
45
+ }
46
+ const buffer = this.buffer;
47
+ let prev = count > 0 ? buffer[count - 1] : 0;
48
+ for (let i = from; i < to; i++) {
49
+ const text = lines[i].text;
50
+ const match = this.classify(text);
51
+ // levelCode gives 0 for a level a custom detector made up.
52
+ let code = match ? levelCode(match.level) : 0;
53
+ if (code === 0 && prev !== 0 && CONTINUATION.test(text)) {
54
+ code = prev | LEVEL_INHERITED;
55
+ }
56
+ buffer[i] = code;
57
+ this.tally[code & ~LEVEL_INHERITED]++;
58
+ prev = code;
59
+ }
60
+ this.view = buffer.subarray(0, to);
61
+ // A new object per push, so that a store publishing it sees a change.
62
+ this.snapshot = countsOf(this.tally);
63
+ }
64
+ classify(text) {
65
+ try {
66
+ return this.detect(text);
67
+ }
68
+ catch (error) {
69
+ if (!this.reported) {
70
+ this.reported = true;
71
+ console.error("LevelTracker: the level detector threw", error);
72
+ }
73
+ return null;
74
+ }
75
+ }
76
+ }
77
+ function countsOf(tally) {
78
+ const counts = {};
79
+ COUNT_KEYS.forEach((key, code) => {
80
+ counts[key] = tally[code];
81
+ });
82
+ return counts;
83
+ }
84
+ export function createLevelTracker(detect = detectLevel) {
85
+ return new Tracker(detect);
86
+ }
87
+ //# sourceMappingURL=level-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level-tracker.js","sourceRoot":"","sources":["../../src/parse/level-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type LogLevel = "fatal" | "error" | "warn" | "info" | "debug" | "trace";
2
+ /** `from`/`to`: UTF-16 offsets of the level word in the line's text, when there is one to colour. */
3
+ export interface LevelMatch {
4
+ level: LogLevel;
5
+ from?: number;
6
+ to?: number;
7
+ }
8
+ export type LevelDetector = (text: string) => LevelMatch | null;
9
+ /** In code order: a level's code is its index + 1, and 0 is no level. */
10
+ export declare const LEVELS: readonly LogLevel[];
11
+ /** Set on a level code that a continuation line took from the line above. */
12
+ export declare const LEVEL_INHERITED = 128;
13
+ export declare function levelCode(level: LogLevel): number;
14
+ export declare function levelOfCode(code: number): LogLevel | null;
15
+ /** How much of a line the detector reads. */
16
+ export declare const LEVEL_WINDOW = 256;
17
+ /** The default detector. Pure; reads at most the first 256 UTF-16 units. */
18
+ export declare function detectLevel(text: string): LevelMatch | null;
19
+ //# sourceMappingURL=levels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levels.d.ts","sourceRoot":"","sources":["../../src/parse/levels.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/E,qGAAqG;AACrG,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;AAEhE,yEAAyE;AACzE,eAAO,MAAM,MAAM,EAAE,SAAS,QAAQ,EAOrC,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,eAAe,MAAO,CAAC;AAEpC,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAEjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAEzD;AAED,6CAA6C;AAC7C,eAAO,MAAM,YAAY,MAAM,CAAC;AAyHhC,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAgD3D"}