@alchemy.run/sigil 0.0.0-alpha.4 → 0.0.0-alpha.6

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 (138) hide show
  1. package/README.md +21 -9
  2. package/THIRD_PARTY_NOTICES.md +39 -1
  3. package/dist/Text-BobFKi74.d.ts +452 -0
  4. package/dist/ansi.d.ts +122 -131
  5. package/dist/ansi.js +86 -6
  6. package/dist/capabilities.d.ts +5 -0
  7. package/dist/capabilities.js +3 -0
  8. package/dist/cell-_ZVhbfl0.js +44 -0
  9. package/dist/color-CkbalRqK.js +2 -0
  10. package/dist/color-policy-BMzMwV7Q.d.ts +22 -0
  11. package/dist/color-policy-SVj1pYTA.js +560 -0
  12. package/dist/color-profile-DHhQHY55.js +36 -0
  13. package/dist/color-profile-u0Nhe9Nv.d.ts +97 -0
  14. package/dist/color.d.ts +21 -0
  15. package/dist/color.js +3 -0
  16. package/dist/cursor-position-D2LAkRG0.d.ts +7 -0
  17. package/dist/detect-Bh4yGP6w.d.ts +186 -0
  18. package/dist/detect-BuTXtY6e.js +373 -0
  19. package/dist/env-YVw64yZS.js +9 -0
  20. package/dist/escapes-CB_6CWOE.d.ts +72 -0
  21. package/dist/geometry-BxXOzJgo.d.ts +11 -0
  22. package/dist/index-DZ88EXJv.d.ts +21 -0
  23. package/dist/index.d.ts +143 -498
  24. package/dist/index.js +1026 -2244
  25. package/dist/osc-CCH7xDoS.js +71 -0
  26. package/dist/osc-Cn0fw77g.d.ts +23 -0
  27. package/dist/paint-C19minOS.d.ts +81 -0
  28. package/dist/query-vaIeGOkH.d.ts +152 -0
  29. package/dist/router.d.ts +392 -0
  30. package/dist/router.js +709 -0
  31. package/dist/sample-Cqw1bjUL.js +445 -0
  32. package/dist/screen-BOSLQ8fF.d.ts +49 -0
  33. package/dist/screen-CiPytswf.js +342 -0
  34. package/dist/screen.d.ts +5 -0
  35. package/dist/screen.js +5 -0
  36. package/dist/semantic-text-style-DIMzC7xt.js +91 -0
  37. package/dist/serialize-BTkAZgw1.js +79 -0
  38. package/dist/session-aZr9O8h3.js +665 -0
  39. package/dist/sgr-BhwaWAJB.js +246 -0
  40. package/dist/store-CgrG9K4y.d.ts +72 -0
  41. package/dist/string-width-CijQwpIk.js +69 -0
  42. package/dist/strip-BvU4toXG.js +6 -0
  43. package/dist/terminal.d.ts +118 -0
  44. package/dist/terminal.js +2 -0
  45. package/dist/tokenize-AjqbvtiT.js +1242 -0
  46. package/dist/tokenize-Dx1y_l5H.d.ts +57 -0
  47. package/dist/truncate-D31fhU6i.js +562 -0
  48. package/dist/use-focus-BzqAJi0n.js +1337 -0
  49. package/package.json +41 -9
  50. package/src/ansi/chalk.ts +5 -3
  51. package/src/ansi/escapes.ts +14 -0
  52. package/src/ansi/graphemes.ts +8 -0
  53. package/src/ansi/hyperlink.ts +44 -0
  54. package/src/ansi/index.ts +3 -1
  55. package/src/ansi/osc.ts +77 -0
  56. package/src/ansi/tokenize.ts +3 -4
  57. package/src/capabilities/color-policy.ts +34 -0
  58. package/src/capabilities/detect.ts +594 -0
  59. package/src/capabilities/index.ts +37 -0
  60. package/src/capabilities/query.ts +657 -0
  61. package/src/capabilities/store.ts +379 -0
  62. package/src/color/index.ts +3 -0
  63. package/src/color/paint.ts +169 -0
  64. package/src/color/palette.ts +48 -0
  65. package/src/color/sample.ts +323 -0
  66. package/src/color.ts +1 -0
  67. package/src/components/AnsiText.tsx +42 -0
  68. package/src/components/App.tsx +98 -10
  69. package/src/components/BackgroundContext.ts +2 -3
  70. package/src/components/Box.tsx +0 -8
  71. package/src/components/CursorContext.ts +1 -1
  72. package/src/components/Hyperlink.tsx +56 -0
  73. package/src/components/TerminalOscContext.ts +25 -0
  74. package/src/components/Text.tsx +22 -45
  75. package/src/components/Transform.tsx +1 -1
  76. package/src/dom.ts +11 -2
  77. package/src/global.d.ts +3 -0
  78. package/src/hooks/use-capabilities.ts +73 -0
  79. package/src/hooks/use-cursor.ts +2 -2
  80. package/src/hooks/use-terminal-osc.ts +59 -0
  81. package/src/index.ts +45 -1
  82. package/src/ink.tsx +213 -153
  83. package/src/{render-node-to-output.ts → paint-tree.ts} +75 -48
  84. package/src/reconciler.ts +24 -3
  85. package/src/render-background.ts +36 -15
  86. package/src/render-border.ts +94 -61
  87. package/src/render-frame.ts +83 -0
  88. package/src/render-to-string.ts +21 -6
  89. package/src/render.ts +15 -6
  90. package/src/router/components.tsx +343 -0
  91. package/src/router/context.ts +41 -0
  92. package/src/router/history.ts +194 -0
  93. package/src/router/hooks.tsx +391 -0
  94. package/src/router/index.ts +34 -0
  95. package/src/router/matcher.ts +571 -0
  96. package/src/screen/ansi.ts +184 -0
  97. package/src/screen/canvas.ts +160 -0
  98. package/src/screen/cell.ts +138 -0
  99. package/src/screen/color-profile.ts +47 -0
  100. package/src/screen/geometry.ts +9 -0
  101. package/src/screen/index.ts +6 -0
  102. package/src/screen/screen.ts +305 -0
  103. package/src/screen/serialize.ts +129 -0
  104. package/src/screen.ts +1 -0
  105. package/src/semantic-text-style.ts +118 -0
  106. package/src/squash-text-nodes.ts +2 -5
  107. package/src/structured-text.ts +325 -0
  108. package/src/styles.ts +19 -14
  109. package/src/terminal/index.ts +2 -0
  110. package/src/terminal/inline-presenter.ts +120 -0
  111. package/src/terminal/input.ts +86 -0
  112. package/src/terminal/render-scheduler.ts +37 -0
  113. package/src/terminal/screen-presenter.ts +188 -0
  114. package/src/terminal/session.ts +407 -0
  115. package/src/terminal.ts +1 -0
  116. package/src/testing/browser.ts +588 -0
  117. package/src/testing/emulators.ts +205 -0
  118. package/src/testing/explorer-app/index.html +12 -0
  119. package/src/testing/explorer-app/main.ts +381 -0
  120. package/src/testing/explorer-app/style.css +194 -0
  121. package/src/testing/explorer-app/tsconfig.json +15 -0
  122. package/src/testing/explorer-app/vite-env.d.ts +1 -0
  123. package/src/testing/index.ts +26 -0
  124. package/src/testing/keys.ts +56 -0
  125. package/src/testing/live.ts +85 -0
  126. package/src/testing/matchers.ts +70 -0
  127. package/src/testing/public.ts +94 -0
  128. package/src/testing/terminal.ts +349 -0
  129. package/src/testing/vitest.ts +157 -0
  130. package/src/transform-adapter.ts +14 -0
  131. package/src/wrap-text.ts +4 -0
  132. package/dist/sgr-CMfEpjSk.d.ts +0 -91
  133. package/dist/truncate-Cr6xVFMa.js +0 -2330
  134. package/src/ansi/supports-color.ts +0 -207
  135. package/src/colorize.ts +0 -60
  136. package/src/log-update.ts +0 -370
  137. package/src/output.ts +0 -308
  138. package/src/renderer.ts +0 -73
@@ -0,0 +1,342 @@
1
+ import { d as tokenize, l as styledCharsFromTokens } from "./tokenize-AjqbvtiT.js";
2
+ import { t as stringWidth } from "./string-width-CijQwpIk.js";
3
+ import { i as emptyCell, r as createCell, t as cellAttributes } from "./cell-_ZVhbfl0.js";
4
+ import { t as blend } from "./sample-Cqw1bjUL.js";
5
+ import "./color-profile-DHhQHY55.js";
6
+ import "./serialize-BTkAZgw1.js";
7
+ //#region src/screen/ansi.ts
8
+ const ESC = "\x1B";
9
+ const BEL = "\x07";
10
+ const C1_ST = "œ";
11
+ const LINK_PREFIX = `${ESC}]8;`;
12
+ /** Converts the renderer's canonical ANSI state into backend-neutral cells. */
13
+ function cellsFromAnsi(text) {
14
+ return styledCharsFromTokens(tokenize(text)).map((character) => cellFromStyledChar(character));
15
+ }
16
+ function cellFromStyledChar(character, width = stringWidth(character.value)) {
17
+ const parsed = parseStyles(character.styles);
18
+ const style = {
19
+ ...parsed.foreground ? { foreground: parsed.foreground } : {},
20
+ ...parsed.background ? { background: parsed.background } : {},
21
+ ...parsed.underlineColor ? { underlineColor: parsed.underlineColor } : {},
22
+ underline: parsed.underline,
23
+ attributes: parsed.attributes
24
+ };
25
+ return createCell(character.value, Math.max(1, width), style, parsed.hyperlink);
26
+ }
27
+ function parseStyles(codes) {
28
+ let foreground;
29
+ let background;
30
+ let underlineColor;
31
+ let underline = "none";
32
+ let attributes = cellAttributes.none;
33
+ let hyperlink;
34
+ for (const { code } of codes) {
35
+ if (code.startsWith(LINK_PREFIX)) {
36
+ hyperlink = parseHyperlink(code);
37
+ continue;
38
+ }
39
+ if (!code.startsWith(`${ESC}[`) || !code.endsWith("m")) continue;
40
+ const parameters = code.slice(2, -1);
41
+ const primary = Number.parseInt(parameters, 10);
42
+ if (primary >= 30 && primary <= 37) foreground = {
43
+ model: "indexed",
44
+ index: primary - 30,
45
+ encoding: "ansi16"
46
+ };
47
+ else if (primary >= 90 && primary <= 97) foreground = {
48
+ model: "indexed",
49
+ index: primary - 90 + 8,
50
+ encoding: "ansi16"
51
+ };
52
+ else if (primary >= 40 && primary <= 47) background = {
53
+ model: "indexed",
54
+ index: primary - 40,
55
+ encoding: "ansi16"
56
+ };
57
+ else if (primary >= 100 && primary <= 107) background = {
58
+ model: "indexed",
59
+ index: primary - 100 + 8,
60
+ encoding: "ansi16"
61
+ };
62
+ else if (primary === 38) foreground = parseExtendedColor(parameters);
63
+ else if (primary === 48) background = parseExtendedColor(parameters);
64
+ else if (primary === 58) underlineColor = parseExtendedColor(parameters);
65
+ else if (primary === 1) attributes += cellAttributes.bold;
66
+ else if (primary === 2) attributes += cellAttributes.faint;
67
+ else if (primary === 3) attributes += cellAttributes.italic;
68
+ else if (primary === 5) attributes += cellAttributes.blink;
69
+ else if (primary === 6) attributes += cellAttributes.rapidBlink;
70
+ else if (primary === 7) attributes += cellAttributes.inverse;
71
+ else if (primary === 8) attributes += cellAttributes.hidden;
72
+ else if (primary === 9) attributes += cellAttributes.strikethrough;
73
+ else if (primary === 4) underline = parseUnderline(parameters);
74
+ }
75
+ return {
76
+ ...foreground ? { foreground } : {},
77
+ ...background ? { background } : {},
78
+ ...underlineColor ? { underlineColor } : {},
79
+ underline,
80
+ attributes,
81
+ ...hyperlink ? { hyperlink } : {}
82
+ };
83
+ }
84
+ function parseExtendedColor(parameters) {
85
+ const parts = parameters.split(parameters.includes(":") ? ":" : ";");
86
+ const model = parts[1];
87
+ if (model === "5") {
88
+ const index = Number(parts[2]);
89
+ return Number.isInteger(index) && index >= 0 && index <= 255 ? {
90
+ model: "indexed",
91
+ index,
92
+ encoding: "ansi256"
93
+ } : void 0;
94
+ }
95
+ if (model !== "2") return;
96
+ const channels = parts.slice(-3).map(Number);
97
+ if (channels.length !== 3 || channels.some((channel) => !isByte(channel))) return;
98
+ return {
99
+ model: "rgb",
100
+ red: channels[0],
101
+ green: channels[1],
102
+ blue: channels[2],
103
+ alpha: 255
104
+ };
105
+ }
106
+ function parseUnderline(parameters) {
107
+ return {
108
+ 0: "none",
109
+ 1: "single",
110
+ 2: "double",
111
+ 3: "curly",
112
+ 4: "dotted",
113
+ 5: "dashed"
114
+ }[parameters.includes(":") ? Number(parameters.split(":").at(-1)) : 1] ?? "single";
115
+ }
116
+ function parseHyperlink(code) {
117
+ let body = code.slice(LINK_PREFIX.length);
118
+ if (body.endsWith(`${ESC}\\`)) body = body.slice(0, -2);
119
+ else if (body.endsWith(BEL) || body.endsWith(C1_ST)) body = body.slice(0, -1);
120
+ const separator = body.indexOf(";");
121
+ if (separator < 0) return;
122
+ const parameters = body.slice(0, separator);
123
+ const url = body.slice(separator + 1);
124
+ return parameters ? {
125
+ url,
126
+ parameters
127
+ } : { url };
128
+ }
129
+ function isByte(value) {
130
+ return Number.isInteger(value) && value >= 0 && value <= 255;
131
+ }
132
+ //#endregion
133
+ //#region src/screen/screen.ts
134
+ /**
135
+ A mutable two-dimensional terminal cell buffer. Cells themselves are immutable,
136
+ so current and next screens can compare them by value or safely share constants.
137
+ */
138
+ var Screen = class {
139
+ #width;
140
+ #height;
141
+ #rows;
142
+ #painted;
143
+ #dirty;
144
+ constructor(width, height) {
145
+ validateDimensions(width, height);
146
+ this.#width = width;
147
+ this.#height = height;
148
+ this.#rows = Array.from({ length: height }, () => Array(width).fill(emptyCell));
149
+ this.#painted = Array.from({ length: height }, () => Array(width).fill(false));
150
+ this.#dirty = Array.from({ length: height }, () => width > 0 ? {
151
+ start: 0,
152
+ end: width
153
+ } : void 0);
154
+ }
155
+ get width() {
156
+ return this.#width;
157
+ }
158
+ /**
159
+ The populated length of one row: the nominal width, or more when overflow
160
+ writes (`textWrap: "none"` content) extended it past the screen's width.
161
+ */
162
+ rowLength(y) {
163
+ return Math.max(this.#width, this.#rows[y]?.length ?? 0);
164
+ }
165
+ get height() {
166
+ return this.#height;
167
+ }
168
+ bounds() {
169
+ return {
170
+ x: 0,
171
+ y: 0,
172
+ width: this.width,
173
+ height: this.height
174
+ };
175
+ }
176
+ cellAt(x, y) {
177
+ return this.#rows[y]?.[x];
178
+ }
179
+ /** Whether a drawable explicitly touched this position. */
180
+ isPainted(x, y) {
181
+ return this.#painted[y]?.[x] ?? false;
182
+ }
183
+ setCell(x, y, cell, options) {
184
+ const row = this.#rows[y];
185
+ const overflow = options?.overflow === true;
186
+ if (!row || x < 0 || !overflow && x >= this.width) return;
187
+ if (!Number.isInteger(cell.width) || cell.width < 1) throw new Error("Only leading cells with a positive width may be written");
188
+ const finalColumn = x + cell.width;
189
+ if (overflow && finalColumn > row.length) this.#growRow(row, y, finalColumn);
190
+ const capacity = overflow ? row.length : this.width;
191
+ const clipped = finalColumn > capacity;
192
+ const overwriteEnd = Math.min(finalColumn, capacity);
193
+ for (let column = x; column < overwriteEnd; column++) this.#clearGraphemeAt(row, y, column);
194
+ if (clipped) {
195
+ for (let column = x; column < capacity; column++) row[column] = emptyCell;
196
+ this.#markDirty(y, x, capacity);
197
+ return;
198
+ }
199
+ row[x] = cell;
200
+ this.#painted[y][x] = true;
201
+ for (let column = x + 1; column < finalColumn; column++) {
202
+ row[column] = {
203
+ grapheme: "",
204
+ width: 0,
205
+ style: cell.style,
206
+ ...cell.hyperlink ? { hyperlink: cell.hyperlink } : {}
207
+ };
208
+ this.#painted[y][column] = true;
209
+ }
210
+ this.#markDirty(y, x, finalColumn);
211
+ }
212
+ /**
213
+ Composes independent cell channels over the existing cell. An undefined
214
+ patch is transparent; an explicit space in `content` paints a blank.
215
+ */
216
+ composeCell(x, y, patch, options) {
217
+ if (!patch) return;
218
+ const row = this.#rows[y];
219
+ if (!row || x < 0 || options?.overflow !== true && x >= this.width) return;
220
+ let leadingColumn = x;
221
+ while (leadingColumn > 0 && row[leadingColumn]?.width === 0) leadingColumn--;
222
+ const destination = row[leadingColumn] ?? emptyCell;
223
+ const writeColumn = patch.content ? x : leadingColumn;
224
+ const style = {
225
+ ...this.#composeColor(destination.style, patch, "foreground"),
226
+ ...this.#composeColor(destination.style, patch, "background"),
227
+ ...this.#composeColor(destination.style, patch, "underlineColor"),
228
+ underline: patch.underline ?? destination.style.underline,
229
+ attributes: patch.attributes ?? destination.style.attributes
230
+ };
231
+ const content = patch.content ?? destination;
232
+ const hyperlink = patch.hyperlink === void 0 ? destination.hyperlink : patch.hyperlink ?? void 0;
233
+ this.setCell(writeColumn, y, createCell(content.grapheme, content.width, style, hyperlink), options);
234
+ }
235
+ /** Composes a patch throughout a rectangle, clipped to this screen. */
236
+ fill(bounds, patch) {
237
+ if (!patch) return;
238
+ const startX = Math.max(0, bounds.x);
239
+ const startY = Math.max(0, bounds.y);
240
+ const endX = Math.min(this.width, bounds.x + bounds.width);
241
+ const endY = Math.min(this.height, bounds.y + bounds.height);
242
+ const step = Math.max(1, patch.content?.width ?? 1);
243
+ for (let y = startY; y < endY; y++) for (let x = startX; x < endX; x += step) this.composeCell(x, y, patch);
244
+ }
245
+ /** Resizes while preserving complete graphemes in the shared top-left area. */
246
+ resize(width, height) {
247
+ validateDimensions(width, height);
248
+ const rows = Array.from({ length: height }, () => Array(width).fill(emptyCell));
249
+ const painted = Array.from({ length: height }, () => Array(width).fill(false));
250
+ const sharedHeight = Math.min(height, this.height);
251
+ for (let y = 0; y < sharedHeight; y++) {
252
+ const source = this.#rows[y];
253
+ const destination = rows[y];
254
+ for (let x = 0; x < Math.min(width, this.width); x++) {
255
+ const cell = source[x];
256
+ if (cell.width === 0 || x + cell.width > width) continue;
257
+ destination[x] = cell;
258
+ painted[y][x] = this.#painted[y][x];
259
+ for (let column = x + 1; column < x + cell.width; column++) {
260
+ destination[column] = source[column];
261
+ painted[y][column] = this.#painted[y][column];
262
+ }
263
+ }
264
+ }
265
+ this.#width = width;
266
+ this.#height = height;
267
+ this.#rows = rows;
268
+ this.#painted = painted;
269
+ this.#dirty = Array.from({ length: height }, () => width > 0 ? {
270
+ start: 0,
271
+ end: width
272
+ } : void 0);
273
+ }
274
+ clear() {
275
+ for (const [y, row] of this.#rows.entries()) {
276
+ row.fill(emptyCell);
277
+ this.#painted[y].fill(true);
278
+ this.#markDirty(y, 0, this.rowLength(y));
279
+ }
280
+ }
281
+ toRows() {
282
+ return this.#rows;
283
+ }
284
+ dirtySpans() {
285
+ return this.#dirty.flatMap((span, y) => span ? [{
286
+ y,
287
+ ...span
288
+ }] : []);
289
+ }
290
+ takeDirtySpans() {
291
+ const spans = this.dirtySpans();
292
+ this.#dirty.fill(void 0);
293
+ return spans;
294
+ }
295
+ /** Extends a row (and its paint mask) so overflow writes land past `width`. */
296
+ #growRow(row, y, length) {
297
+ const painted = this.#painted[y];
298
+ while (row.length < length) {
299
+ row.push(emptyCell);
300
+ painted.push(false);
301
+ }
302
+ }
303
+ #clearGraphemeAt(row, y, x) {
304
+ const existing = row[x];
305
+ if (!existing || existing === emptyCell) return;
306
+ let leadingColumn = x;
307
+ while (leadingColumn > 0 && row[leadingColumn]?.width === 0) leadingColumn--;
308
+ const leadingCell = row[leadingColumn];
309
+ const width = Math.max(1, leadingCell?.width ?? 1);
310
+ for (let column = leadingColumn; column < Math.min(leadingColumn + width, row.length); column++) {
311
+ row[column] = emptyCell;
312
+ this.#painted[y][column] = true;
313
+ }
314
+ this.#markDirty(y, leadingColumn, leadingColumn + width);
315
+ }
316
+ #composeColor(destination, patch, channel) {
317
+ const value = patch[channel];
318
+ if (value === void 0) return destination[channel] ? { [channel]: destination[channel] } : {};
319
+ if (value === null) return {};
320
+ const destinationColor = destination[channel];
321
+ if (value.model === "rgb" && value.alpha < 255 && destinationColor) return { [channel]: blend(value, destinationColor) };
322
+ return { [channel]: value };
323
+ }
324
+ #markDirty(y, start, end) {
325
+ if (y < 0 || y >= this.height || start >= end) return;
326
+ const clippedStart = Math.max(0, start);
327
+ const clippedEnd = Math.min(this.rowLength(y), end);
328
+ const current = this.#dirty[y];
329
+ this.#dirty[y] = current ? {
330
+ start: Math.min(current.start, clippedStart),
331
+ end: Math.max(current.end, clippedEnd)
332
+ } : {
333
+ start: clippedStart,
334
+ end: clippedEnd
335
+ };
336
+ }
337
+ };
338
+ function validateDimensions(width, height) {
339
+ if (!Number.isInteger(width) || width < 0 || !Number.isInteger(height) || height < 0) throw new Error("Screen dimensions must be non-negative integers");
340
+ }
341
+ //#endregion
342
+ export { cellFromStyledChar as n, cellsFromAnsi as r, Screen as t };
@@ -0,0 +1,5 @@
1
+ import { _ as emptyCellStyle, a as CellContent, c as Color, d as RgbColor, f as UnderlineStyle, g as emptyCell, h as createCell, i as Cell, l as Hyperlink, m as cellsEqual, n as colorProfileFromLevel, o as CellPatch, p as cellAttributes, r as quantizeColor, s as CellStyle, t as ColorProfile, u as IndexedColor } from "./color-profile-u0Nhe9Nv.js";
2
+ import { n as Rect, t as Point } from "./geometry-BxXOzJgo.js";
3
+ import { a as cellFromStyledChar, i as styledCharFromCell, n as serializeLine, o as cellsFromAnsi, r as serializeScreen, t as SerializeOptions } from "./index-DZ88EXJv.js";
4
+ import { n as Screen, t as Line } from "./screen-BOSLQ8fF.js";
5
+ export { Cell, CellContent, CellPatch, CellStyle, Color, ColorProfile, Hyperlink, IndexedColor, type Line, Point, Rect, RgbColor, Screen, SerializeOptions, UnderlineStyle, cellAttributes, cellFromStyledChar, cellsEqual, cellsFromAnsi, colorProfileFromLevel, createCell, emptyCell, emptyCellStyle, quantizeColor, serializeLine, serializeScreen, styledCharFromCell };
package/dist/screen.js ADDED
@@ -0,0 +1,5 @@
1
+ import { a as emptyCellStyle, i as emptyCell, n as cellsEqual, r as createCell, t as cellAttributes } from "./cell-_ZVhbfl0.js";
2
+ import { n as cellFromStyledChar, r as cellsFromAnsi, t as Screen } from "./screen-CiPytswf.js";
3
+ import { n as quantizeColor, t as colorProfileFromLevel } from "./color-profile-DHhQHY55.js";
4
+ import { n as serializeScreen, r as styledCharFromCell, t as serializeLine } from "./serialize-BTkAZgw1.js";
5
+ export { Screen, cellAttributes, cellFromStyledChar, cellsEqual, cellsFromAnsi, colorProfileFromLevel, createCell, emptyCell, emptyCellStyle, quantizeColor, serializeLine, serializeScreen, styledCharFromCell };
@@ -0,0 +1,91 @@
1
+ import { l as hexToRgb } from "./sgr-BhwaWAJB.js";
2
+ import { t as cellAttributes } from "./cell-_ZVhbfl0.js";
3
+ //#region src/semantic-text-style.ts
4
+ const emptySemanticTextStyle = { attributes: cellAttributes.none };
5
+ const namedColors = {
6
+ black: 0,
7
+ red: 1,
8
+ green: 2,
9
+ yellow: 3,
10
+ blue: 4,
11
+ magenta: 5,
12
+ cyan: 6,
13
+ white: 7,
14
+ blackBright: 8,
15
+ gray: 8,
16
+ grey: 8,
17
+ redBright: 9,
18
+ greenBright: 10,
19
+ yellowBright: 11,
20
+ blueBright: 12,
21
+ magentaBright: 13,
22
+ cyanBright: 14,
23
+ whiteBright: 15
24
+ };
25
+ const rgbPattern = /^rgb\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/;
26
+ const ansi256Pattern = /^ansi256\(\s?(\d+)\s?\)$/;
27
+ function parseSemanticColor(value) {
28
+ if (!value) return;
29
+ if (typeof value !== "string") return value;
30
+ const named = namedColors[value];
31
+ if (named !== void 0) return {
32
+ model: "indexed",
33
+ index: named,
34
+ encoding: "ansi16"
35
+ };
36
+ if (value.startsWith("#")) {
37
+ const [red, green, blue] = hexToRgb(value);
38
+ return {
39
+ model: "rgb",
40
+ red,
41
+ green,
42
+ blue,
43
+ alpha: 255
44
+ };
45
+ }
46
+ const rgb = rgbPattern.exec(value);
47
+ if (rgb) return {
48
+ model: "rgb",
49
+ red: Number(rgb[1]),
50
+ green: Number(rgb[2]),
51
+ blue: Number(rgb[3]),
52
+ alpha: 255
53
+ };
54
+ const ansi256 = ansi256Pattern.exec(value);
55
+ if (ansi256) return {
56
+ model: "indexed",
57
+ index: Number(ansi256[1]),
58
+ encoding: "ansi256"
59
+ };
60
+ }
61
+ function mergeSemanticTextStyles(parent, child) {
62
+ if (!child) return parent;
63
+ const attributes = parent.attributes | child.attributes;
64
+ const foreground = child.resetForeground ? void 0 : child.foreground ?? parent.foreground;
65
+ const background = child.resetBackground ? void 0 : child.background ?? parent.background;
66
+ return {
67
+ ...foreground ? { foreground } : {},
68
+ ...background ? { background } : {},
69
+ ...child.resetForeground ? { resetForeground: true } : {},
70
+ ...child.resetBackground ? { resetBackground: true } : {},
71
+ ...child.underline ?? parent.underline ? { underline: child.underline ?? parent.underline } : {},
72
+ attributes
73
+ };
74
+ }
75
+ function semanticTextStyleToCellStyle(style) {
76
+ const foreground = solidColor(style.foreground);
77
+ const background = solidColor(style.background);
78
+ return {
79
+ ...foreground ? { foreground } : {},
80
+ ...background ? { background } : {},
81
+ underline: style.underline ?? "none",
82
+ attributes: style.attributes
83
+ };
84
+ }
85
+ function solidColor(paint) {
86
+ if (!paint) return void 0;
87
+ if (typeof paint === "string") return parseSemanticColor(paint);
88
+ return "model" in paint ? paint : void 0;
89
+ }
90
+ //#endregion
91
+ export { semanticTextStyleToCellStyle as i, mergeSemanticTextStyles as n, parseSemanticColor as r, emptySemanticTextStyle as t };
@@ -0,0 +1,79 @@
1
+ import { i as getEndCode, u as styledCharsToString } from "./tokenize-AjqbvtiT.js";
2
+ import { t as cellAttributes } from "./cell-_ZVhbfl0.js";
3
+ import { n as quantizeColor } from "./color-profile-DHhQHY55.js";
4
+ //#region src/screen/serialize.ts
5
+ const ESC = "\x1B";
6
+ const BEL = "\x07";
7
+ /** Serializes one structured cell run with minimal style transitions. */
8
+ function serializeLine(line, options) {
9
+ const characters = line.map((cell) => styledCharFromCell(cell, options.colorProfile, options.styles ?? true));
10
+ const output = styledCharsToString(characters);
11
+ return options.trimEnd === false ? output : output.trimEnd();
12
+ }
13
+ function serializeScreen(screen, options) {
14
+ return screen.toRows().map((line) => serializeLine(line, options)).join("\n");
15
+ }
16
+ /** Converts a semantic cell to the canonical ANSI compatibility style state. */
17
+ function styledCharFromCell(cell, profile, styles = true) {
18
+ return {
19
+ type: "char",
20
+ value: cell.grapheme,
21
+ fullWidth: cell.width > 1,
22
+ styles: styles ? ansiCodesFromCell(cell, profile) : []
23
+ };
24
+ }
25
+ function ansiCodesFromCell(cell, profile) {
26
+ const result = [];
27
+ const { style } = cell;
28
+ if (cell.hyperlink) result.push(codePair(hyperlinkStart(cell.hyperlink)));
29
+ addAttribute(result, style.attributes, cellAttributes.inverse, 7);
30
+ addAttribute(result, style.attributes, cellAttributes.hidden, 8);
31
+ addAttribute(result, style.attributes, cellAttributes.strikethrough, 9);
32
+ if (style.underline !== "none") {
33
+ const variant = {
34
+ single: "4",
35
+ double: "4:2",
36
+ curly: "4:3",
37
+ dotted: "4:4",
38
+ dashed: "4:5"
39
+ }[style.underline];
40
+ result.push(codePair(`${ESC}[${variant}m`));
41
+ }
42
+ addAttribute(result, style.attributes, cellAttributes.italic, 3);
43
+ addAttribute(result, style.attributes, cellAttributes.bold, 1);
44
+ addAttribute(result, style.attributes, cellAttributes.rapidBlink, 6);
45
+ addAttribute(result, style.attributes, cellAttributes.blink, 5);
46
+ const background = quantizeColor(style.background, profile);
47
+ if (background) result.push(codePair(colorCode(background, "background")));
48
+ const foreground = quantizeColor(style.foreground, profile);
49
+ if (foreground) result.push(codePair(colorCode(foreground, "foreground")));
50
+ addAttribute(result, style.attributes, cellAttributes.faint, 2);
51
+ const underlineColor = quantizeColor(style.underlineColor, profile);
52
+ if (underlineColor) result.push(codePair(colorCode(underlineColor, "underline")));
53
+ return result;
54
+ }
55
+ function addAttribute(result, attributes, attribute, sgr) {
56
+ if (Math.floor(attributes / attribute) % 2 === 1) result.push(codePair(`${ESC}[${sgr}m`));
57
+ }
58
+ function colorCode(color, channel) {
59
+ const prefix = {
60
+ foreground: 38,
61
+ background: 48,
62
+ underline: 58
63
+ }[channel];
64
+ if (color.model === "rgb") return `${ESC}[${prefix};2;${color.red};${color.green};${color.blue}m`;
65
+ if (channel === "underline" || color.index >= 16 || color.encoding === "ansi256") return `${ESC}[${prefix};5;${color.index}m`;
66
+ const basic = color.index < 8 ? color.index : color.index - 8 + 60;
67
+ return `${ESC}[${(channel === "background" ? 40 : 30) + basic}m`;
68
+ }
69
+ function hyperlinkStart(hyperlink) {
70
+ return `${ESC}]8;${hyperlink.parameters ?? ""};${hyperlink.url}${BEL}`;
71
+ }
72
+ function codePair(code) {
73
+ return {
74
+ code,
75
+ endCode: getEndCode(code)
76
+ };
77
+ }
78
+ //#endregion
79
+ export { serializeScreen as n, styledCharFromCell as r, serializeLine as t };