@ours.network/fleet 0.15.6 → 0.16.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.
@@ -0,0 +1,401 @@
1
+ import { Document, isMap, isPair, isScalar, isSeq, parseDocument, } from 'yaml';
2
+ /**
3
+ * Surgical fleet-YAML editing.
4
+ *
5
+ * The web console edits a JSON *model* of the configuration, but the file on
6
+ * disk belongs to the user. A `parse -> plain JS -> stringify` round-trip keeps
7
+ * the data and destroys everything around it. Re-rendering the parsed document
8
+ * is barely better: `yaml` keeps a comment's text but not its position, so
9
+ * `permissions: # note` comes back as `permissions:` with the note moved onto
10
+ * the next line, shifting everything below it. On `examples/fleet.yaml` a plain
11
+ * round-trip rewrites 80 of 147 lines.
12
+ *
13
+ * So edits are computed as *text splices* against the original bytes. Only the
14
+ * regions that genuinely changed are replaced; everything else is byte-identical
15
+ * by construction, which makes an unchanged save a true no-op and keeps a trailing
16
+ * inline comment attached to the scalar it annotates.
17
+ *
18
+ * The contract is deliberately narrower than "nothing else ever changes":
19
+ *
20
+ * - A *scalar* edit replaces only the value's source range, so the trailing
21
+ * comment beside it survives untouched.
22
+ * - Changing the *length* of a block sequence replaces that collection WHOLESALE,
23
+ * because an index-shifting edit cannot be attributed to particular items. Inline
24
+ * comments written on the individual items of that sequence are therefore LOST.
25
+ * The loss is bounded to the one collection being edited — every other line in
26
+ * the file keeps its bytes — and the caller diffs the real before/after text, so
27
+ * it is visible in review before anything is written and the save can be declined.
28
+ * - A model change that cannot be expressed as a splice at all falls back to
29
+ * re-rendering the whole document. That path does reflow, which is the other
30
+ * reason the caller diffs real bytes: reflow must be visible, never silent.
31
+ * - Deleting a mapping entry leaves any comment written above it in place. Removing
32
+ * a value must not quietly remove the operator's prose about it.
33
+ */
34
+ const PARSE_OPTIONS = { strict: true, uniqueKeys: true, prettyErrors: true };
35
+ const MIN_INDENT = 1;
36
+ const MAX_INDENT = 8;
37
+ const DEFAULT_INDENT = 2;
38
+ /**
39
+ * Apply `model` to `source`, returning the new document text.
40
+ *
41
+ * Guarantees:
42
+ * - an unchanged model returns `source` byte for byte;
43
+ * - regions outside a change keep their bytes whenever the change is spliceable;
44
+ * - the result parses back to exactly `model`, verified before returning, so a
45
+ * planning bug can never silently write something else to disk.
46
+ */
47
+ export function renderModelOntoSource(source, model) {
48
+ const document = parseSource(source);
49
+ const formatting = detectFormatting(source);
50
+ const plan = [];
51
+ const spliceable = planEdits(document, source, formatting, [], documentValue(document), model, plan);
52
+ const rendered = !spliceable ? reRender(document, source, formatting, model)
53
+ : plan.length === 0 ? source
54
+ : applySplices(source, plan);
55
+ const check = parseSource(rendered);
56
+ if (!deepEqual(documentValue(check), model))
57
+ throw new Error('surgical YAML edit did not reproduce the requested model');
58
+ return rendered;
59
+ }
60
+ /**
61
+ * Replace every `defaults.env` / `roles.*.env` value — and every `vars:` entry
62
+ * those values interpolate — with `marker`.
63
+ *
64
+ * Splices the scalars out of the original bytes rather than re-rendering, so the
65
+ * only difference from `source` is the secrets themselves. Redaction must not be
66
+ * able to introduce (or conceal) a formatting change in a review diff.
67
+ */
68
+ export function redactSourceSecrets(source, marker) {
69
+ const document = parseSource(source);
70
+ const secretVars = new Set();
71
+ const plan = [];
72
+ const redactEnvMap = (path) => {
73
+ const node = document.getIn(path, true);
74
+ if (!isMap(node))
75
+ return;
76
+ for (const item of node.items) {
77
+ if (!isPair(item) || !isScalar(item.value))
78
+ continue;
79
+ if (typeof item.value.value === 'string')
80
+ for (const match of item.value.value.matchAll(/\$\{(\w+)\}/g))
81
+ secretVars.add(match[1]);
82
+ pushValueSplice(plan, item.value, marker);
83
+ }
84
+ };
85
+ redactEnvMap(['defaults', 'env']);
86
+ for (const name of mapKeys(document, ['roles']))
87
+ redactEnvMap(['roles', name, 'env']);
88
+ const vars = document.getIn(['vars'], true);
89
+ if (isMap(vars))
90
+ for (const item of vars.items) {
91
+ if (isPair(item) && isScalar(item.key) && isScalar(item.value)
92
+ && secretVars.has(String(item.key.value)))
93
+ pushValueSplice(plan, item.value, marker);
94
+ }
95
+ return plan.length === 0 ? source : applySplices(source, plan);
96
+ }
97
+ function pushValueSplice(plan, node, marker) {
98
+ const range = node.range;
99
+ if (range)
100
+ plan.push({ start: range[0], end: range[1], text: marker });
101
+ }
102
+ /**
103
+ * Best-effort detection of the document's block indentation, used only when a
104
+ * change is not spliceable and the document has to be re-rendered. Detection
105
+ * failure falls back to the library defaults; correctness never depends on it.
106
+ */
107
+ export function detectFormatting(source) {
108
+ const lines = source.split('\n')
109
+ .filter(line => line.trim() !== '' && !line.trimStart().startsWith('#'));
110
+ let indent;
111
+ let indentSeq;
112
+ let previousWidth = 0;
113
+ let previousOpensBlock = false;
114
+ for (const line of lines) {
115
+ const width = line.length - line.trimStart().length;
116
+ const isItem = /^-(\s|$)/.test(line.trimStart());
117
+ if (previousOpensBlock && width >= previousWidth) {
118
+ if (isItem)
119
+ indentSeq ??= width > previousWidth;
120
+ if (width > previousWidth)
121
+ indent ??= width - previousWidth;
122
+ }
123
+ previousOpensBlock = !isItem && /:\s*(#.*)?$/.test(line);
124
+ previousWidth = width;
125
+ }
126
+ return {
127
+ indent: indent !== undefined && indent >= MIN_INDENT && indent <= MAX_INDENT
128
+ ? indent : DEFAULT_INDENT,
129
+ indentSeq: indentSeq ?? true,
130
+ };
131
+ }
132
+ /* ------------------------------------------------------------------ *
133
+ * Planning: turn a model diff into text splices
134
+ * ------------------------------------------------------------------ */
135
+ /**
136
+ * Walk `next` against `current` and record the splices that would realise it.
137
+ * Returns false as soon as a change cannot be expressed against the source text,
138
+ * in which case the caller re-renders instead.
139
+ */
140
+ function planEdits(document, source, formatting, path, current, next, plan) {
141
+ if (deepEqual(current, next))
142
+ return true;
143
+ if (isPlainObject(current) && isPlainObject(next)) {
144
+ const node = document.getIn(path, true);
145
+ if (!isMap(node))
146
+ return false;
147
+ // Removing every entry one by one would leave `watchdogs:` with no value,
148
+ // which reads back as null rather than the empty mapping that was asked for.
149
+ if (path.length > 0 && Object.keys(next).length === 0 && Object.keys(current).length > 0)
150
+ return planReplace(document, source, formatting, path, next, plan);
151
+ for (const key of Object.keys(current))
152
+ if (!hasOwn(next, key) && !planDelete(node, source, key, plan))
153
+ return false;
154
+ for (const key of Object.keys(next)) {
155
+ if (hasOwn(current, key)) {
156
+ if (!planEdits(document, source, formatting, [...path, key], own(current, key), own(next, key), plan))
157
+ return false;
158
+ }
159
+ else if (!planInsert(node, source, formatting, key, own(next, key), plan))
160
+ return false;
161
+ }
162
+ return true;
163
+ }
164
+ if (Array.isArray(current) && Array.isArray(next) && current.length === next.length)
165
+ return next.every((value, index) => planEdits(document, source, formatting, [...path, index], current[index], value, plan));
166
+ return planReplace(document, source, formatting, path, next, plan);
167
+ }
168
+ /** Replace one value in place, keeping the key, its layout and its comment. */
169
+ function planReplace(document, source, formatting, path, next, plan) {
170
+ if (path.length === 0)
171
+ return false;
172
+ const node = document.getIn(path, true);
173
+ if (!isNodeWithRange(node))
174
+ return false;
175
+ // A block scalar's body cannot be swapped for an inline one by splicing.
176
+ if (isScalar(node) && (node.type === 'BLOCK_LITERAL' || node.type === 'BLOCK_FOLDED'))
177
+ return false;
178
+ const start = node.range[0];
179
+ // A block collection's range runs past the newline that terminates it, while a
180
+ // scalar's stops at the value. Splicing over that newline would pull the next
181
+ // line up onto this one, so leave it where it is.
182
+ let end = node.range[1];
183
+ while (end > start && source[end - 1] === '\n')
184
+ end -= 1;
185
+ const ownLine = source.slice(lineStart(source, start), start).trim() === '';
186
+ // `roles: [Alice]` must not come back as a block list just because it grew.
187
+ const flow = (isSeq(node) || isMap(node)) && node.flow === true;
188
+ const text = renderValue(next, formatting, flow);
189
+ // An emptied collection belongs beside its key, not alone on the next line.
190
+ if (ownLine && (text === '{}' || text === '[]')
191
+ && planCollapseOntoKey(document, source, path, start, end, text, plan))
192
+ return true;
193
+ if (text.includes('\n') && !ownLine)
194
+ return false;
195
+ plan.push({ start, end, text: ownLine ? indentContinuation(text, columnOf(source, start)) : text });
196
+ return true;
197
+ }
198
+ /** Rewrite `key:\n <block>` as `key: {}` when the block became empty. */
199
+ function planCollapseOntoKey(document, source, path, start, end, text, plan) {
200
+ const key = path[path.length - 1];
201
+ if (typeof key !== 'string')
202
+ return false;
203
+ const parent = document.getIn(path.slice(0, -1), true);
204
+ const pair = parent === undefined ? undefined : findPair(parent, key);
205
+ if (!pair || !isNodeWithRange(pair.key))
206
+ return false;
207
+ const colon = source.indexOf(':', pair.key.range[1]);
208
+ // Anything but whitespace between the key and its value is a comment; keep it.
209
+ if (colon < 0 || colon >= start || source.slice(colon + 1, start).trim() !== '')
210
+ return false;
211
+ plan.push({ start: colon + 1, end, text: ` ${text}` });
212
+ return true;
213
+ }
214
+ /** Remove a whole `key: value` entry, including the line it sits on. */
215
+ function planDelete(node, source, key, plan) {
216
+ const pair = findPair(node, key);
217
+ if (!pair || !isNodeWithRange(pair.key))
218
+ return false;
219
+ const end = isNodeWithRange(pair.value) ? pair.value.range[2] : pair.key.range[2];
220
+ plan.push({ start: lineStart(source, pair.key.range[0]), end, text: '' });
221
+ return true;
222
+ }
223
+ /** Append a new `key: value` entry to an existing block mapping. */
224
+ function planInsert(node, source, formatting, key, value, plan) {
225
+ if (!isMap(node) || node.flow)
226
+ return false;
227
+ const last = [...node.items].reverse().find(isPair);
228
+ // An empty mapping has no sibling to copy an indent or a position from.
229
+ if (!last || !isNodeWithRange(last.key))
230
+ return false;
231
+ const column = columnOf(source, last.key.range[0]);
232
+ const at = isNodeWithRange(last.value) ? last.value.range[2] : last.key.range[2];
233
+ const entry = indentContinuation(renderValue({ [key]: value }, formatting), column);
234
+ const prefix = at > 0 && source[at - 1] !== '\n' ? '\n' : '';
235
+ plan.push({ start: at, end: at, text: `${prefix}${' '.repeat(column)}${entry}\n` });
236
+ return true;
237
+ }
238
+ function applySplices(source, plan) {
239
+ const ordered = [...plan].sort((a, b) => b.start - a.start || b.end - a.end);
240
+ let out = source;
241
+ for (const splice of ordered)
242
+ out = out.slice(0, splice.start) + splice.text + out.slice(splice.end);
243
+ return out;
244
+ }
245
+ /* ------------------------------------------------------------------ *
246
+ * Fallback: re-render the whole document
247
+ * ------------------------------------------------------------------ */
248
+ function reRender(document, source, formatting, model) {
249
+ applyToDocument(document, [], documentValue(document), model);
250
+ return restoreCommentAlignment(source, document.toString({ lineWidth: 0, ...formatting }));
251
+ }
252
+ function applyToDocument(document, path, current, next) {
253
+ if (deepEqual(current, next))
254
+ return;
255
+ if (isPlainObject(current) && isPlainObject(next)) {
256
+ for (const key of Object.keys(next))
257
+ applyToDocument(document, [...path, key], own(current, key), own(next, key));
258
+ for (const key of Object.keys(current))
259
+ if (!hasOwn(next, key))
260
+ document.deleteIn([...path, key]);
261
+ return;
262
+ }
263
+ if (Array.isArray(current) && Array.isArray(next) && current.length === next.length) {
264
+ for (const [index, value] of next.entries())
265
+ applyToDocument(document, [...path, index], current[index], value);
266
+ return;
267
+ }
268
+ if (next === undefined) {
269
+ document.deleteIn(path);
270
+ return;
271
+ }
272
+ // Mutating an existing scalar keeps its comment and quoting; replacing it loses both.
273
+ const existing = document.getIn(path, true);
274
+ if (isScalar(existing) && isScalarValue(next) && existing.type !== 'BLOCK_LITERAL' && existing.type !== 'BLOCK_FOLDED') {
275
+ existing.value = next;
276
+ return;
277
+ }
278
+ if (path.length === 0)
279
+ document.contents = document.createNode(next);
280
+ else
281
+ document.setIn(path, document.createNode(next));
282
+ }
283
+ /**
284
+ * `yaml` keeps a comment's text but not the padding in front of it. Put the
285
+ * original spacing back on lines that are otherwise byte-identical to the
286
+ * source; ambiguous or altered lines are left as rendered, and the caller
287
+ * re-parses the result, so this can never change what the file means.
288
+ */
289
+ function restoreCommentAlignment(source, rendered) {
290
+ const AMBIGUOUS = '';
291
+ const originals = new Map();
292
+ for (const line of source.split('\n')) {
293
+ const at = trailingCommentIndex(line);
294
+ if (at < 0)
295
+ continue;
296
+ const collapsed = `${line.slice(0, at).replace(/\s+$/, '')} ${line.slice(at)}`;
297
+ if (collapsed === line)
298
+ continue;
299
+ originals.set(collapsed, originals.has(collapsed) ? AMBIGUOUS : line);
300
+ }
301
+ if (originals.size === 0)
302
+ return rendered;
303
+ return rendered.split('\n').map(line => originals.get(line) || line).join('\n');
304
+ }
305
+ /** Index of a line's trailing `#` comment, ignoring `#` inside quoted scalars. */
306
+ function trailingCommentIndex(line) {
307
+ let quote;
308
+ for (let index = 0; index < line.length; index += 1) {
309
+ const character = line[index];
310
+ if (quote === "'") {
311
+ if (character !== "'")
312
+ continue;
313
+ if (line[index + 1] === "'")
314
+ index += 1;
315
+ else
316
+ quote = undefined;
317
+ }
318
+ else if (quote === '"') {
319
+ if (character === '\\')
320
+ index += 1;
321
+ else if (character === '"')
322
+ quote = undefined;
323
+ }
324
+ else if (character === '"' || character === "'")
325
+ quote = character;
326
+ else if (character === '#' && index > 0 && /\s/.test(line[index - 1]))
327
+ return index;
328
+ }
329
+ return -1;
330
+ }
331
+ /* ------------------------------------------------------------------ *
332
+ * Shared helpers
333
+ * ------------------------------------------------------------------ */
334
+ function parseSource(source) {
335
+ const document = parseDocument(source, PARSE_OPTIONS);
336
+ if (document.errors.length)
337
+ throw new Error(document.errors.map(error => error.message).join('; '));
338
+ return document;
339
+ }
340
+ function documentValue(document) {
341
+ return document.contents == null ? {} : document.toJS({ maxAliasCount: 100 });
342
+ }
343
+ function mapKeys(document, path) {
344
+ const node = document.getIn(path, true);
345
+ if (!isMap(node))
346
+ return [];
347
+ return node.items.flatMap(item => (isPair(item) && isScalar(item.key) ? [String(item.key.value)] : []));
348
+ }
349
+ function findPair(node, key) {
350
+ if (!isMap(node))
351
+ return undefined;
352
+ return node.items.find((item) => isPair(item) && isScalar(item.key) && String(item.key.value) === key);
353
+ }
354
+ function renderValue(value, formatting, flow = false) {
355
+ const document = new Document(value);
356
+ if (flow && (isSeq(document.contents) || isMap(document.contents)))
357
+ document.contents.flow = true;
358
+ return document
359
+ .toString({ lineWidth: 0, indent: formatting.indent, indentSeq: formatting.indentSeq })
360
+ .replace(/\n$/, '');
361
+ }
362
+ /** Indent every line but the first, which is spliced in after existing text. */
363
+ function indentContinuation(text, column) {
364
+ if (!text.includes('\n'))
365
+ return text;
366
+ const pad = ' '.repeat(column);
367
+ return text.split('\n').map((line, index) => (index === 0 || line === '' ? line : `${pad}${line}`)).join('\n');
368
+ }
369
+ const lineStart = (source, offset) => source.lastIndexOf('\n', offset - 1) + 1;
370
+ const columnOf = (source, offset) => offset - lineStart(source, offset);
371
+ function isNodeWithRange(node) {
372
+ return (isScalar(node) || isMap(node) || isSeq(node)) && Array.isArray(node.range);
373
+ }
374
+ function isScalarValue(value) {
375
+ return value === null || ['string', 'number', 'boolean'].includes(typeof value);
376
+ }
377
+ function isPlainObject(value) {
378
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
379
+ }
380
+ function hasOwn(value, key) {
381
+ return Object.prototype.hasOwnProperty.call(value, key);
382
+ }
383
+ function own(value, key) {
384
+ return hasOwn(value, key) ? value[key] : undefined;
385
+ }
386
+ function deepEqual(a, b) {
387
+ if (a === b)
388
+ return true;
389
+ if (typeof a === 'number' && typeof b === 'number')
390
+ return Number.isNaN(a) && Number.isNaN(b);
391
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
392
+ return false;
393
+ if (Array.isArray(a) !== Array.isArray(b))
394
+ return false;
395
+ if (Array.isArray(a) && Array.isArray(b))
396
+ return a.length === b.length && a.every((item, index) => deepEqual(item, b[index]));
397
+ const [left, right] = [a, b];
398
+ const keys = Object.keys(left);
399
+ return keys.length === Object.keys(right).length
400
+ && keys.every(key => hasOwn(right, key) && deepEqual(left[key], right[key]));
401
+ }
@@ -1,4 +1,4 @@
1
- import{r as le,a as Ee,j as re}from"./index-Cde9auW0.js";var ge={exports:{}},Se;function ke(){return Se||(Se=1,(function(se,ne){(function(Q,X){se.exports=X()})(globalThis,(()=>(()=>{var Q={4567:function(B,r,o){var l=this&&this.__decorate||function(e,i,a,v){var f,g=arguments.length,c=g<3?i:v===null?v=Object.getOwnPropertyDescriptor(i,a):v;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")c=Reflect.decorate(e,i,a,v);else for(var m=e.length-1;m>=0;m--)(f=e[m])&&(c=(g<3?f(c):g>3?f(i,a,c):f(i,a))||c);return g>3&&c&&Object.defineProperty(i,a,c),c},_=this&&this.__param||function(e,i){return function(a,v){i(a,v,e)}};Object.defineProperty(r,"__esModule",{value:!0}),r.AccessibilityManager=void 0;const n=o(9042),d=o(9924),u=o(844),p=o(4725),h=o(2585),t=o(3656);let s=r.AccessibilityManager=class extends u.Disposable{constructor(e,i,a,v){super(),this._terminal=e,this._coreBrowserService=a,this._renderService=v,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let f=0;f<this._terminal.rows;f++)this._rowElements[f]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[f]);if(this._topBoundaryFocusListener=f=>this._handleBoundaryFocus(f,0),this._bottomBoundaryFocusListener=f=>this._handleBoundaryFocus(f,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new d.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((f=>this._handleResize(f.rows)))),this.register(this._terminal.onRender((f=>this._refreshRows(f.start,f.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((f=>this._handleChar(f)))),this.register(this._terminal.onLineFeed((()=>this._handleChar(`
1
+ import{r as le,a as Ee,j as re}from"./index-CsHEL0f6.js";var ge={exports:{}},Se;function ke(){return Se||(Se=1,(function(se,ne){(function(Q,X){se.exports=X()})(globalThis,(()=>(()=>{var Q={4567:function(B,r,o){var l=this&&this.__decorate||function(e,i,a,v){var f,g=arguments.length,c=g<3?i:v===null?v=Object.getOwnPropertyDescriptor(i,a):v;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")c=Reflect.decorate(e,i,a,v);else for(var m=e.length-1;m>=0;m--)(f=e[m])&&(c=(g<3?f(c):g>3?f(i,a,c):f(i,a))||c);return g>3&&c&&Object.defineProperty(i,a,c),c},_=this&&this.__param||function(e,i){return function(a,v){i(a,v,e)}};Object.defineProperty(r,"__esModule",{value:!0}),r.AccessibilityManager=void 0;const n=o(9042),d=o(9924),u=o(844),p=o(4725),h=o(2585),t=o(3656);let s=r.AccessibilityManager=class extends u.Disposable{constructor(e,i,a,v){super(),this._terminal=e,this._coreBrowserService=a,this._renderService=v,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let f=0;f<this._terminal.rows;f++)this._rowElements[f]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[f]);if(this._topBoundaryFocusListener=f=>this._handleBoundaryFocus(f,0),this._bottomBoundaryFocusListener=f=>this._handleBoundaryFocus(f,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new d.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((f=>this._handleResize(f.rows)))),this.register(this._terminal.onRender((f=>this._refreshRows(f.start,f.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((f=>this._handleChar(f)))),this.register(this._terminal.onLineFeed((()=>this._handleChar(`
2
2
  `)))),this.register(this._terminal.onA11yTab((f=>this._handleTab(f)))),this.register(this._terminal.onKey((f=>this._handleKey(f.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,t.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,u.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let i=0;i<e;i++)this._handleChar(" ")}_handleChar(e){this._liveRegionLineCount<21&&(this._charsToConsume.length>0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,e===`
3
3
  `&&(this._liveRegionLineCount++,this._liveRegionLineCount===21&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),new RegExp("\\p{Control}","u").test(e)||this._charsToConsume.push(e)}_refreshRows(e,i){this._liveRegionDebouncer.refresh(e,i,this._terminal.rows)}_renderRows(e,i){const a=this._terminal.buffer,v=a.lines.length.toString();for(let f=e;f<=i;f++){const g=a.lines.get(a.ydisp+f),c=[],m=g?.translateToString(!0,void 0,void 0,c)||"",E=(a.ydisp+f+1).toString(),k=this._rowElements[f];k&&(m.length===0?(k.innerText=" ",this._rowColumns.set(k,[0,1])):(k.textContent=m,this._rowColumns.set(k,c)),k.setAttribute("aria-posinset",E),k.setAttribute("aria-setsize",v))}this._announceCharacters()}_announceCharacters(){this._charsToAnnounce.length!==0&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,i){const a=e.target,v=this._rowElements[i===0?1:this._rowElements.length-2];if(a.getAttribute("aria-posinset")===(i===0?"1":`${this._terminal.buffer.lines.length}`)||e.relatedTarget!==v)return;let f,g;if(i===0?(f=a,g=this._rowElements.pop(),this._rowContainer.removeChild(g)):(f=this._rowElements.shift(),g=a,this._rowContainer.removeChild(f)),f.removeEventListener("focus",this._topBoundaryFocusListener),g.removeEventListener("focus",this._bottomBoundaryFocusListener),i===0){const c=this._createAccessibilityTreeNode();this._rowElements.unshift(c),this._rowContainer.insertAdjacentElement("afterbegin",c)}else{const c=this._createAccessibilityTreeNode();this._rowElements.push(c),this._rowContainer.appendChild(c)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(i===0?-1:1),this._rowElements[i===0?1:this._rowElements.length-2].focus(),e.preventDefault(),e.stopImmediatePropagation()}_handleSelectionChange(){if(this._rowElements.length===0)return;const e=document.getSelection();if(!e)return;if(e.isCollapsed)return void(this._rowContainer.contains(e.anchorNode)&&this._terminal.clearSelection());if(!e.anchorNode||!e.focusNode)return void console.error("anchorNode and/or focusNode are null");let i={node:e.anchorNode,offset:e.anchorOffset},a={node:e.focusNode,offset:e.focusOffset};if((i.node.compareDocumentPosition(a.node)&Node.DOCUMENT_POSITION_PRECEDING||i.node===a.node&&i.offset>a.offset)&&([i,a]=[a,i]),i.node.compareDocumentPosition(this._rowElements[0])&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_FOLLOWING)&&(i={node:this._rowElements[0].childNodes[0],offset:0}),!this._rowContainer.contains(i.node))return;const v=this._rowElements.slice(-1)[0];if(a.node.compareDocumentPosition(v)&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_PRECEDING)&&(a={node:v,offset:v.textContent?.length??0}),!this._rowContainer.contains(a.node))return;const f=({node:m,offset:E})=>{const k=m instanceof Text?m.parentNode:m;let D=parseInt(k?.getAttribute("aria-posinset"),10)-1;if(isNaN(D))return console.warn("row is invalid. Race condition?"),null;const b=this._rowColumns.get(k);if(!b)return console.warn("columns is null. Race condition?"),null;let x=E<b.length?b[E]:b.slice(-1)[0]+1;return x>=this._terminal.cols&&(++D,x=0),{row:D,column:x}},g=f(i),c=f(a);if(g&&c){if(g.row>c.row||g.row===c.row&&g.column>=c.column)throw new Error("invalid range");this._terminal.select(g.column,g.row,(c.row-g.row)*this._terminal.cols-g.column+c.column)}}_handleResize(e){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let i=this._rowContainer.children.length;i<this._terminal.rows;i++)this._rowElements[i]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[i]);for(;this._rowElements.length>e;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const e=this._coreBrowserService.mainDocument.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let e=0;e<this._terminal.rows;e++)this._refreshRowDimensions(this._rowElements[e])}}_refreshRowDimensions(e){e.style.height=`${this._renderService.dimensions.css.cell.height}px`}};r.AccessibilityManager=s=l([_(1,h.IInstantiationService),_(2,p.ICoreBrowserService),_(3,p.IRenderService)],s)},3614:(B,r)=>{function o(d){return d.replace(/\r?\n/g,"\r")}function l(d,u){return u?"\x1B[200~"+d+"\x1B[201~":d}function _(d,u,p,h){d=l(d=o(d),p.decPrivateModes.bracketedPasteMode&&h.rawOptions.ignoreBracketedPasteMode!==!0),p.triggerDataEvent(d,!0),u.value=""}function n(d,u,p){const h=p.getBoundingClientRect(),t=d.clientX-h.left-10,s=d.clientY-h.top-10;u.style.width="20px",u.style.height="20px",u.style.left=`${t}px`,u.style.top=`${s}px`,u.style.zIndex="1000",u.focus()}Object.defineProperty(r,"__esModule",{value:!0}),r.rightClickHandler=r.moveTextAreaUnderMouseCursor=r.paste=r.handlePasteEvent=r.copyHandler=r.bracketTextForPaste=r.prepareTextForTerminal=void 0,r.prepareTextForTerminal=o,r.bracketTextForPaste=l,r.copyHandler=function(d,u){d.clipboardData&&d.clipboardData.setData("text/plain",u.selectionText),d.preventDefault()},r.handlePasteEvent=function(d,u,p,h){d.stopPropagation(),d.clipboardData&&_(d.clipboardData.getData("text/plain"),u,p,h)},r.paste=_,r.moveTextAreaUnderMouseCursor=n,r.rightClickHandler=function(d,u,p,h,t){n(d,u,p),t&&h.rightClickSelect(d),u.value=h.selectionText,u.select()}},7239:(B,r,o)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.ColorContrastCache=void 0;const l=o(1505);r.ColorContrastCache=class{constructor(){this._color=new l.TwoKeyMap,this._css=new l.TwoKeyMap}setCss(_,n,d){this._css.set(_,n,d)}getCss(_,n){return this._css.get(_,n)}setColor(_,n,d){this._color.set(_,n,d)}getColor(_,n){return this._color.get(_,n)}clear(){this._color.clear(),this._css.clear()}}},3656:(B,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.addDisposableDomListener=void 0,r.addDisposableDomListener=function(o,l,_,n){o.addEventListener(l,_,n);let d=!1;return{dispose:()=>{d||(d=!0,o.removeEventListener(l,_,n))}}}},3551:function(B,r,o){var l=this&&this.__decorate||function(s,e,i,a){var v,f=arguments.length,g=f<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,i):a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")g=Reflect.decorate(s,e,i,a);else for(var c=s.length-1;c>=0;c--)(v=s[c])&&(g=(f<3?v(g):f>3?v(e,i,g):v(e,i))||g);return f>3&&g&&Object.defineProperty(e,i,g),g},_=this&&this.__param||function(s,e){return function(i,a){e(i,a,s)}};Object.defineProperty(r,"__esModule",{value:!0}),r.Linkifier=void 0;const n=o(3656),d=o(8460),u=o(844),p=o(2585),h=o(4725);let t=r.Linkifier=class extends u.Disposable{get currentLink(){return this._currentLink}constructor(s,e,i,a,v){super(),this._element=s,this._mouseService=e,this._renderService=i,this._bufferService=a,this._linkProviderService=v,this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new d.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new d.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,u.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,u.toDisposable)((()=>{this._lastMouseEvent=void 0,this._activeProviderReplies?.clear()}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0}))),this.register((0,n.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,n.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(s){this._lastMouseEvent=s;const e=this._positionFromMouseEvent(s,this._element,this._mouseService);if(!e)return;this._isMouseOut=!1;const i=s.composedPath();for(let a=0;a<i.length;a++){const v=i[a];if(v.classList.contains("xterm"))break;if(v.classList.contains("xterm-hover"))return}this._lastBufferCell&&e.x===this._lastBufferCell.x&&e.y===this._lastBufferCell.y||(this._handleHover(e),this._lastBufferCell=e)}_handleHover(s){if(this._activeLine!==s.y||this._wasResized)return this._clearCurrentLink(),this._askForLink(s,!1),void(this._wasResized=!1);this._currentLink&&this._linkAtPosition(this._currentLink.link,s)||(this._clearCurrentLink(),this._askForLink(s,!0))}_askForLink(s,e){this._activeProviderReplies&&e||(this._activeProviderReplies?.forEach((a=>{a?.forEach((v=>{v.link.dispose&&v.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=s.y);let i=!1;for(const[a,v]of this._linkProviderService.linkProviders.entries())e?this._activeProviderReplies?.get(a)&&(i=this._checkLinkProviderResult(a,s,i)):v.provideLinks(s.y,(f=>{if(this._isMouseOut)return;const g=f?.map((c=>({link:c})));this._activeProviderReplies?.set(a,g),i=this._checkLinkProviderResult(a,s,i),this._activeProviderReplies?.size===this._linkProviderService.linkProviders.length&&this._removeIntersectingLinks(s.y,this._activeProviderReplies)}))}_removeIntersectingLinks(s,e){const i=new Set;for(let a=0;a<e.size;a++){const v=e.get(a);if(v)for(let f=0;f<v.length;f++){const g=v[f],c=g.link.range.start.y<s?0:g.link.range.start.x,m=g.link.range.end.y>s?this._bufferService.cols:g.link.range.end.x;for(let E=c;E<=m;E++){if(i.has(E)){v.splice(f--,1);break}i.add(E)}}}}_checkLinkProviderResult(s,e,i){if(!this._activeProviderReplies)return i;const a=this._activeProviderReplies.get(s);let v=!1;for(let f=0;f<s;f++)this._activeProviderReplies.has(f)&&!this._activeProviderReplies.get(f)||(v=!0);if(!v&&a){const f=a.find((g=>this._linkAtPosition(g.link,e)));f&&(i=!0,this._handleNewLink(f))}if(this._activeProviderReplies.size===this._linkProviderService.linkProviders.length&&!i)for(let f=0;f<this._activeProviderReplies.size;f++){const g=this._activeProviderReplies.get(f)?.find((c=>this._linkAtPosition(c.link,e)));if(g){i=!0,this._handleNewLink(g);break}}return i}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(s){if(!this._currentLink)return;const e=this._positionFromMouseEvent(s,this._element,this._mouseService);e&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,e)&&this._currentLink.link.activate(s,this._currentLink.link.text)}_clearCurrentLink(s,e){this._currentLink&&this._lastMouseEvent&&(!s||!e||this._currentLink.link.range.start.y>=s&&this._currentLink.link.range.end.y<=e)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,u.disposeArray)(this._linkCacheDisposables))}_handleNewLink(s){if(!this._lastMouseEvent)return;const e=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);e&&this._linkAtPosition(s.link,e)&&(this._currentLink=s,this._currentLink.state={decorations:{underline:s.link.decorations===void 0||s.link.decorations.underline,pointerCursor:s.link.decorations===void 0||s.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,s.link,this._lastMouseEvent),s.link.decorations={},Object.defineProperties(s.link.decorations,{pointerCursor:{get:()=>this._currentLink?.state?.decorations.pointerCursor,set:i=>{this._currentLink?.state&&this._currentLink.state.decorations.pointerCursor!==i&&(this._currentLink.state.decorations.pointerCursor=i,this._currentLink.state.isHovered&&this._element.classList.toggle("xterm-cursor-pointer",i))}},underline:{get:()=>this._currentLink?.state?.decorations.underline,set:i=>{this._currentLink?.state&&this._currentLink?.state?.decorations.underline!==i&&(this._currentLink.state.decorations.underline=i,this._currentLink.state.isHovered&&this._fireUnderlineEvent(s.link,i))}}}),this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((i=>{if(!this._currentLink)return;const a=i.start===0?0:i.start+1+this._bufferService.buffer.ydisp,v=this._bufferService.buffer.ydisp+1+i.end;if(this._currentLink.link.range.start.y>=a&&this._currentLink.link.range.end.y<=v&&(this._clearCurrentLink(a,v),this._lastMouseEvent)){const f=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);f&&this._askForLink(f,!1)}}))))}_linkHover(s,e,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(e,!0),this._currentLink.state.decorations.pointerCursor&&s.classList.add("xterm-cursor-pointer")),e.hover&&e.hover(i,e.text)}_fireUnderlineEvent(s,e){const i=s.range,a=this._bufferService.buffer.ydisp,v=this._createLinkUnderlineEvent(i.start.x-1,i.start.y-a-1,i.end.x,i.end.y-a-1,void 0);(e?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(v)}_linkLeave(s,e,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(e,!1),this._currentLink.state.decorations.pointerCursor&&s.classList.remove("xterm-cursor-pointer")),e.leave&&e.leave(i,e.text)}_linkAtPosition(s,e){const i=s.range.start.y*this._bufferService.cols+s.range.start.x,a=s.range.end.y*this._bufferService.cols+s.range.end.x,v=e.y*this._bufferService.cols+e.x;return i<=v&&v<=a}_positionFromMouseEvent(s,e,i){const a=i.getCoords(s,e,this._bufferService.cols,this._bufferService.rows);if(a)return{x:a[0],y:a[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(s,e,i,a,v){return{x1:s,y1:e,x2:i,y2:a,cols:this._bufferService.cols,fg:v}}};r.Linkifier=t=l([_(1,h.IMouseService),_(2,h.IRenderService),_(3,p.IBufferService),_(4,h.ILinkProviderService)],t)},9042:(B,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.tooMuchOutput=r.promptLabel=void 0,r.promptLabel="Terminal input",r.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(B,r,o){var l=this&&this.__decorate||function(h,t,s,e){var i,a=arguments.length,v=a<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,s):e;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")v=Reflect.decorate(h,t,s,e);else for(var f=h.length-1;f>=0;f--)(i=h[f])&&(v=(a<3?i(v):a>3?i(t,s,v):i(t,s))||v);return a>3&&v&&Object.defineProperty(t,s,v),v},_=this&&this.__param||function(h,t){return function(s,e){t(s,e,h)}};Object.defineProperty(r,"__esModule",{value:!0}),r.OscLinkProvider=void 0;const n=o(511),d=o(2585);let u=r.OscLinkProvider=class{constructor(h,t,s){this._bufferService=h,this._optionsService=t,this._oscLinkService=s}provideLinks(h,t){const s=this._bufferService.buffer.lines.get(h-1);if(!s)return void t(void 0);const e=[],i=this._optionsService.rawOptions.linkHandler,a=new n.CellData,v=s.getTrimmedLength();let f=-1,g=-1,c=!1;for(let m=0;m<v;m++)if(g!==-1||s.hasContent(m)){if(s.loadCell(m,a),a.hasExtendedAttrs()&&a.extended.urlId){if(g===-1){g=m,f=a.extended.urlId;continue}c=a.extended.urlId!==f}else g!==-1&&(c=!0);if(c||g!==-1&&m===v-1){const E=this._oscLinkService.getLinkData(f)?.uri;if(E){const k={start:{x:g+1,y:h},end:{x:m+(c||m!==v-1?0:1),y:h}};let D=!1;if(!i?.allowNonHttpProtocols)try{const b=new URL(E);["http:","https:"].includes(b.protocol)||(D=!0)}catch{D=!0}D||e.push({text:E,range:k,activate:(b,x)=>i?i.activate(b,x,k):p(0,x),hover:(b,x)=>i?.hover?.(b,x,k),leave:(b,x)=>i?.leave?.(b,x,k)})}c=!1,a.hasExtendedAttrs()&&a.extended.urlId?(g=m,f=a.extended.urlId):(g=-1,f=-1)}}t(e)}};function p(h,t){if(confirm(`Do you want to navigate to ${t}?
4
4