@hivecommons/promptargs 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -6
- package/dist/autodetect.d.ts +2 -0
- package/dist/autodetect.js +53 -3
- package/dist/autodetect.js.map +1 -1
- package/dist/autodetect.test.d.ts +1 -0
- package/dist/autodetect.test.js +207 -0
- package/dist/autodetect.test.js.map +1 -0
- package/dist/cli.js +13 -8
- package/dist/cli.js.map +1 -1
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +310 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +59 -0
- package/dist/index.test.js.map +1 -0
- package/dist/iterate.d.ts +8 -0
- package/dist/iterate.js +28 -0
- package/dist/iterate.js.map +1 -0
- package/dist/iterate.test.d.ts +1 -0
- package/dist/iterate.test.js +20 -0
- package/dist/iterate.test.js.map +1 -0
- package/dist/loader.test.d.ts +1 -0
- package/dist/loader.test.js +65 -0
- package/dist/loader.test.js.map +1 -0
- package/dist/mustache.mjs +764 -0
- package/dist/parser.d.ts +1 -0
- package/dist/parser.js +16 -4
- package/dist/parser.js.map +1 -1
- package/dist/parser.test.js +37 -0
- package/dist/parser.test.js.map +1 -1
- package/dist/resolver.js +58 -44
- package/dist/resolver.js.map +1 -1
- package/dist/resolver.test.d.ts +1 -0
- package/dist/resolver.test.js +184 -0
- package/dist/resolver.test.js.map +1 -0
- package/dist/sanitize.d.ts +10 -0
- package/dist/sanitize.js +21 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/sanitize.test.d.ts +1 -0
- package/dist/sanitize.test.js +38 -0
- package/dist/sanitize.test.js.map +1 -0
- package/dist/status.js +4 -1
- package/dist/status.js.map +1 -1
- package/dist/status.test.d.ts +1 -0
- package/dist/status.test.js +33 -0
- package/dist/status.test.js.map +1 -0
- package/dist/ui-bootstrap.test.d.ts +1 -0
- package/dist/ui-bootstrap.test.js +479 -0
- package/dist/ui-bootstrap.test.js.map +1 -0
- package/dist/ui-builder.test.d.ts +1 -0
- package/dist/ui-builder.test.js +272 -0
- package/dist/ui-builder.test.js.map +1 -0
- package/dist/ui-command-quoting.test.d.ts +1 -0
- package/dist/ui-command-quoting.test.js +95 -0
- package/dist/ui-command-quoting.test.js.map +1 -0
- package/dist/ui-harness.d.ts +20 -0
- package/dist/ui-harness.js +40 -0
- package/dist/ui-harness.js.map +1 -0
- package/dist/ui-harness.test.d.ts +1 -0
- package/dist/ui-harness.test.js +30 -0
- package/dist/ui-harness.test.js.map +1 -0
- package/dist/ui-inline.test.d.ts +1 -0
- package/dist/ui-inline.test.js +90 -0
- package/dist/ui-inline.test.js.map +1 -0
- package/dist/ui-interactions.test.d.ts +1 -0
- package/dist/ui-interactions.test.js +489 -0
- package/dist/ui-interactions.test.js.map +1 -0
- package/dist/ui.d.ts +13 -1
- package/dist/ui.html +30 -57
- package/dist/ui.js +61 -18
- package/dist/ui.js.map +1 -1
- package/dist/ui.test.d.ts +1 -0
- package/dist/ui.test.js +283 -0
- package/dist/ui.test.js.map +1 -0
- package/package.json +4 -3
package/dist/parser.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export interface TemplateVar {
|
|
|
7
7
|
defaultValue?: string;
|
|
8
8
|
raw: string;
|
|
9
9
|
}
|
|
10
|
+
export declare const VAR_PATTERN: RegExp;
|
|
10
11
|
export declare function parseVars(template: string): TemplateVar[];
|
|
11
12
|
export declare function expand(template: string, values: Record<string, string>): string;
|
package/dist/parser.js
CHANGED
|
@@ -3,7 +3,17 @@
|
|
|
3
3
|
* Uses Mustache for expansion, with a promptargs extension for defaults.
|
|
4
4
|
*/
|
|
5
5
|
import Mustache from 'mustache';
|
|
6
|
-
|
|
6
|
+
// Exported so any code that needs to recognize the same {{var}} / {{var=default}}
|
|
7
|
+
// grammar (e.g. CLI syntax highlighting) reuses this single definition instead
|
|
8
|
+
// of re-declaring the pattern and risking drift.
|
|
9
|
+
//
|
|
10
|
+
// Whitespace padding inside the delimiters ({{ name }}, {{ name=default }}) is
|
|
11
|
+
// accepted because Mustache accepts it: a padded tag that this pattern did not
|
|
12
|
+
// recognize would still be handed to Mustache as a variable, which renders it
|
|
13
|
+
// as an empty string — the blank silently vanished instead of being asked for,
|
|
14
|
+
// filled from --flags, highlighted by `show`, or preserved as {{name}}.
|
|
15
|
+
// Trailing padding after a default is not part of the default.
|
|
16
|
+
export const VAR_PATTERN = /\{\{\s*(\w+)(?:=([^}]*?))?\s*\}\}/g;
|
|
7
17
|
export function parseVars(template) {
|
|
8
18
|
const seen = new Set();
|
|
9
19
|
const vars = [];
|
|
@@ -34,8 +44,10 @@ export function expand(template, values) {
|
|
|
34
44
|
}
|
|
35
45
|
// Convert {{var=default}} to {{var}} so Mustache can handle it
|
|
36
46
|
const normalized = template.replace(VAR_PATTERN, (_match, name) => `{{${name}}}`);
|
|
37
|
-
// Disable HTML escaping — we want raw text output
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
// Disable HTML escaping for this render only — we want raw text output.
|
|
48
|
+
// Passed via the per-call config (4th arg) rather than assigning to the
|
|
49
|
+
// module-level Mustache.escape, which would permanently disable escaping
|
|
50
|
+
// for every other consumer of the shared `mustache` module in this process.
|
|
51
|
+
return Mustache.render(normalized, view, undefined, { escape: (text) => text });
|
|
40
52
|
}
|
|
41
53
|
//# sourceMappingURL=parser.js.map
|
package/dist/parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAQhC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,UAAU,CAAC;AAQhC,kFAAkF;AAClF,+EAA+E;AAC/E,iDAAiD;AACjD,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,wEAAwE;AACxE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAC;AAEhE,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAkB,EAAE,CAAC;IAE/B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CAAC;YACR,IAAI;YACJ,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;YACtB,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;SACd,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,QAAgB,EAAE,MAA8B;IACrE,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,IAAI,GAA2B,EAAE,GAAG,MAAM,EAAE,CAAC;IAEnD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACtD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;QAChC,CAAC;QACD,+CAA+C;QAC/C,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC;QACjC,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAE1F,wEAAwE;IACxE,wEAAwE;IACxE,yEAAyE;IACzE,4EAA4E;IAC5E,OAAO,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1F,CAAC"}
|
package/dist/parser.test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
+
import Mustache from 'mustache';
|
|
3
4
|
import { parseVars, expand } from './parser.js';
|
|
4
5
|
describe('parseVars', () => {
|
|
5
6
|
it('finds simple variables', () => {
|
|
@@ -22,6 +23,23 @@ describe('parseVars', () => {
|
|
|
22
23
|
const vars = parseVars('No variables here');
|
|
23
24
|
assert.strictEqual(vars.length, 0);
|
|
24
25
|
});
|
|
26
|
+
it('accepts whitespace padding inside the delimiters, as Mustache does', () => {
|
|
27
|
+
const vars = parseVars('Review {{ file }} for {{ focus=bugs }} in {{\tbranch }}');
|
|
28
|
+
assert.deepStrictEqual(vars.map(v => [v.name, v.defaultValue]), [
|
|
29
|
+
['file', undefined],
|
|
30
|
+
['focus', 'bugs'],
|
|
31
|
+
['branch', undefined],
|
|
32
|
+
]);
|
|
33
|
+
assert.strictEqual(vars[0].raw, '{{ file }}');
|
|
34
|
+
});
|
|
35
|
+
it('treats padded and unpadded spellings as the same variable', () => {
|
|
36
|
+
const vars = parseVars('{{name}} and {{ name }}');
|
|
37
|
+
assert.strictEqual(vars.length, 1);
|
|
38
|
+
});
|
|
39
|
+
it('keeps interior whitespace in defaults', () => {
|
|
40
|
+
const vars = parseVars('{{ audience=junior developer }}');
|
|
41
|
+
assert.strictEqual(vars[0].defaultValue, 'junior developer');
|
|
42
|
+
});
|
|
25
43
|
});
|
|
26
44
|
describe('expand', () => {
|
|
27
45
|
it('substitutes values', () => {
|
|
@@ -52,5 +70,24 @@ describe('expand', () => {
|
|
|
52
70
|
const result = expand('{{code}}', { code: '<div class="test">' });
|
|
53
71
|
assert.strictEqual(result, '<div class="test">');
|
|
54
72
|
});
|
|
73
|
+
it('fills padded tags from values and defaults', () => {
|
|
74
|
+
const result = expand('Review {{ file }} for {{ focus=bugs }}', { file: 'a.ts' });
|
|
75
|
+
assert.strictEqual(result, 'Review a.ts for bugs');
|
|
76
|
+
});
|
|
77
|
+
it('preserves unfilled padded tags instead of erasing them', () => {
|
|
78
|
+
// Before padding was recognised, Mustache rendered {{ name }} as "".
|
|
79
|
+
const result = expand('Hello {{ name }}, see {{file}}', { file: 'x' });
|
|
80
|
+
assert.strictEqual(result, 'Hello {{name}}, see x');
|
|
81
|
+
});
|
|
82
|
+
it('does not mutate the shared Mustache.escape global', () => {
|
|
83
|
+
// `expand` must disable escaping for its own render only, via the
|
|
84
|
+
// per-call config, not by assigning Mustache.escape — that would leak
|
|
85
|
+
// into any other code in the process that also imports `mustache` and
|
|
86
|
+
// relies on its default HTML-escaping behavior.
|
|
87
|
+
const before = Mustache.escape;
|
|
88
|
+
expand('{{code}}', { code: '<b>' });
|
|
89
|
+
assert.strictEqual(Mustache.escape, before);
|
|
90
|
+
assert.strictEqual(Mustache.escape('<b>'), '<b>');
|
|
91
|
+
});
|
|
55
92
|
});
|
|
56
93
|
//# sourceMappingURL=parser.test.js.map
|
package/dist/parser.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../src/parser.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../src/parser.test.ts"],"names":[],"mappings":"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"}
|
package/dist/resolver.js
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Handles array expansion (comma-separated, globs, @file, stdin).
|
|
4
4
|
*/
|
|
5
5
|
import { createInterface } from 'node:readline';
|
|
6
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
7
|
-
import {
|
|
6
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
8
|
import { autodetect } from './autodetect.js';
|
|
9
|
+
import { cartesian, zip } from './iterate.js';
|
|
9
10
|
function expandArrayValue(raw) {
|
|
10
11
|
// @file — read lines from file
|
|
11
12
|
if (raw.startsWith('@') && existsSync(raw.slice(1))) {
|
|
@@ -17,19 +18,13 @@ function expandArrayValue(raw) {
|
|
|
17
18
|
// - (stdin) handled at CLI level before this
|
|
18
19
|
if (raw === '-')
|
|
19
20
|
return [raw];
|
|
20
|
-
// Glob pattern
|
|
21
|
+
// Glob pattern — expanded in-process (never via a shell) to avoid
|
|
22
|
+
// command injection through crafted values.
|
|
21
23
|
if (raw.includes('*') || raw.includes('?')) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.filter(Boolean);
|
|
27
|
-
if (files.length > 0)
|
|
28
|
-
return files;
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
// Not a valid glob, treat as literal
|
|
32
|
-
}
|
|
24
|
+
const files = expandGlob(raw);
|
|
25
|
+
if (files.length > 0)
|
|
26
|
+
return files;
|
|
27
|
+
// Not a valid glob, treat as literal
|
|
33
28
|
}
|
|
34
29
|
// Comma-separated
|
|
35
30
|
if (raw.includes(',')) {
|
|
@@ -37,18 +32,50 @@ function expandArrayValue(raw) {
|
|
|
37
32
|
}
|
|
38
33
|
return [raw];
|
|
39
34
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
function segmentToRegExp(segment) {
|
|
36
|
+
const escaped = segment
|
|
37
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
38
|
+
.replace(/\*/g, '[^/]*')
|
|
39
|
+
.replace(/\?/g, '.');
|
|
40
|
+
return new RegExp(`^${escaped}$`);
|
|
41
|
+
}
|
|
42
|
+
function expandGlob(pattern) {
|
|
43
|
+
const absolute = pattern.startsWith('/');
|
|
44
|
+
const segments = pattern.split('/').filter(Boolean);
|
|
45
|
+
let bases = [absolute ? '/' : ''];
|
|
46
|
+
for (const segment of segments) {
|
|
47
|
+
const next = [];
|
|
48
|
+
if (!segment.includes('*') && !segment.includes('?')) {
|
|
49
|
+
for (const base of bases) {
|
|
50
|
+
const p = base === '' ? segment : join(base, segment);
|
|
51
|
+
if (existsSync(p))
|
|
52
|
+
next.push(p);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const re = segmentToRegExp(segment);
|
|
57
|
+
const matchHidden = segment.startsWith('.');
|
|
58
|
+
for (const base of bases) {
|
|
59
|
+
let entries;
|
|
60
|
+
try {
|
|
61
|
+
entries = readdirSync(base === '' ? '.' : base);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
if (!matchHidden && entry.startsWith('.'))
|
|
68
|
+
continue;
|
|
69
|
+
if (re.test(entry))
|
|
70
|
+
next.push(base === '' ? entry : join(base, entry));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
49
73
|
}
|
|
74
|
+
bases = next;
|
|
75
|
+
if (bases.length === 0)
|
|
76
|
+
break;
|
|
50
77
|
}
|
|
51
|
-
return
|
|
78
|
+
return bases.sort();
|
|
52
79
|
}
|
|
53
80
|
export async function resolve(vars, flags, interactive, cross = false) {
|
|
54
81
|
const values = {};
|
|
@@ -97,27 +124,14 @@ export async function resolve(vars, flags, interactive, cross = false) {
|
|
|
97
124
|
}
|
|
98
125
|
const arrayNames = Object.keys(arrayVars);
|
|
99
126
|
const iterations = [];
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
iter[arrayNames[j]] = combo[j];
|
|
107
|
-
}
|
|
108
|
-
iterations.push(iter);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
const maxLen = Math.max(...arrayNames.map(n => arrayVars[n].length));
|
|
113
|
-
for (let i = 0; i < maxLen; i++) {
|
|
114
|
-
const iter = { ...values };
|
|
115
|
-
for (const name of arrayNames) {
|
|
116
|
-
const arr = arrayVars[name];
|
|
117
|
-
iter[name] = arr[i % arr.length];
|
|
118
|
-
}
|
|
119
|
-
iterations.push(iter);
|
|
127
|
+
const arrays = arrayNames.map(n => arrayVars[n]);
|
|
128
|
+
const combos = cross ? cartesian(arrays) : zip(arrays);
|
|
129
|
+
for (const combo of combos) {
|
|
130
|
+
const iter = { ...values };
|
|
131
|
+
for (let j = 0; j < arrayNames.length; j++) {
|
|
132
|
+
iter[arrayNames[j]] = combo[j];
|
|
120
133
|
}
|
|
134
|
+
iterations.push(iter);
|
|
121
135
|
}
|
|
122
136
|
return { values, iterations };
|
|
123
137
|
}
|
package/dist/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, it, before, after } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { PassThrough } from 'node:stream';
|
|
6
|
+
import { resolve } from './resolver.js';
|
|
7
|
+
// Variable names are deliberately obscure so the autodetect env-var
|
|
8
|
+
// fallback never picks them up from the test environment.
|
|
9
|
+
function v(name, defaultValue) {
|
|
10
|
+
return { name, defaultValue, raw: `{{${name}}}` };
|
|
11
|
+
}
|
|
12
|
+
let tmp;
|
|
13
|
+
before(() => {
|
|
14
|
+
tmp = mkdtempSync(join(process.cwd(), '.pa-resolver-'));
|
|
15
|
+
});
|
|
16
|
+
after(() => {
|
|
17
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
describe('resolve scalar values', () => {
|
|
20
|
+
it('takes values from flags', async () => {
|
|
21
|
+
const r = await resolve([v('pa_x')], { pa_x: 'hello' }, false);
|
|
22
|
+
assert.strictEqual(r.values.pa_x, 'hello');
|
|
23
|
+
assert.deepStrictEqual(r.iterations, [{ pa_x: 'hello' }]);
|
|
24
|
+
});
|
|
25
|
+
it('flags win over defaults', async () => {
|
|
26
|
+
const r = await resolve([v('pa_x', 'dflt')], { pa_x: 'flag' }, false);
|
|
27
|
+
assert.strictEqual(r.values.pa_x, 'flag');
|
|
28
|
+
});
|
|
29
|
+
it('falls back to defaults', async () => {
|
|
30
|
+
const r = await resolve([v('pa_x', 'dflt')], {}, false);
|
|
31
|
+
assert.strictEqual(r.values.pa_x, 'dflt');
|
|
32
|
+
});
|
|
33
|
+
it('leaves unfilled vars unset when non-interactive', async () => {
|
|
34
|
+
const r = await resolve([v('pa_missing')], {}, false);
|
|
35
|
+
assert.ok(!('pa_missing' in r.values));
|
|
36
|
+
assert.deepStrictEqual(r.iterations, [{}]);
|
|
37
|
+
});
|
|
38
|
+
it('autodetect wins over defaults', async () => {
|
|
39
|
+
process.env.pa_env_var = 'from-env';
|
|
40
|
+
try {
|
|
41
|
+
const r = await resolve([v('pa_env_var', 'dflt')], {}, false);
|
|
42
|
+
assert.strictEqual(r.values.pa_env_var, 'from-env');
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
delete process.env.pa_env_var;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('resolve array expansion', () => {
|
|
50
|
+
it('splits comma-separated flag values into iterations', async () => {
|
|
51
|
+
const r = await resolve([v('pa_f')], { pa_f: 'a.go, b.go,c.go' }, false);
|
|
52
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), ['a.go', 'b.go', 'c.go']);
|
|
53
|
+
});
|
|
54
|
+
it('reads @file values one per line', async () => {
|
|
55
|
+
const listFile = join(tmp, 'list.txt');
|
|
56
|
+
writeFileSync(listFile, 'one\n two \n\nthree\n');
|
|
57
|
+
const r = await resolve([v('pa_f')], { pa_f: `@${listFile}` }, false);
|
|
58
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), ['one', 'two', 'three']);
|
|
59
|
+
});
|
|
60
|
+
it('treats @nonexistent as a literal value', async () => {
|
|
61
|
+
const r = await resolve([v('pa_f')], { pa_f: '@/no/such/file' }, false);
|
|
62
|
+
assert.strictEqual(r.values.pa_f, '@/no/such/file');
|
|
63
|
+
});
|
|
64
|
+
it('zips arrays of equal length by default', async () => {
|
|
65
|
+
const r = await resolve([v('pa_a'), v('pa_b')], { pa_a: '1,2', pa_b: 'x,y' }, false);
|
|
66
|
+
assert.deepStrictEqual(r.iterations.map(i => [i.pa_a, i.pa_b]), [['1', 'x'], ['2', 'y']]);
|
|
67
|
+
});
|
|
68
|
+
it('recycles shorter arrays when zipping', async () => {
|
|
69
|
+
const r = await resolve([v('pa_a'), v('pa_b')], { pa_a: '1,2,3', pa_b: 'x,y' }, false);
|
|
70
|
+
assert.deepStrictEqual(r.iterations.map(i => [i.pa_a, i.pa_b]), [['1', 'x'], ['2', 'y'], ['3', 'x']]);
|
|
71
|
+
});
|
|
72
|
+
it('builds the cartesian product with cross=true', async () => {
|
|
73
|
+
const r = await resolve([v('pa_a'), v('pa_b')], { pa_a: '1,2', pa_b: 'x,y' }, false, true);
|
|
74
|
+
assert.strictEqual(r.iterations.length, 4);
|
|
75
|
+
assert.deepStrictEqual(r.iterations.map(i => `${i.pa_a}${i.pa_b}`).sort(), ['1x', '1y', '2x', '2y']);
|
|
76
|
+
});
|
|
77
|
+
it('carries scalar values into every iteration', async () => {
|
|
78
|
+
const r = await resolve([v('pa_a'), v('pa_s', 'fixed')], { pa_a: '1,2' }, false);
|
|
79
|
+
assert.deepStrictEqual(r.iterations.map(i => [i.pa_a, i.pa_s]), [['1', 'fixed'], ['2', 'fixed']]);
|
|
80
|
+
});
|
|
81
|
+
it('keeps "-" (stdin placeholder) as a single literal', async () => {
|
|
82
|
+
const r = await resolve([v('pa_f')], { pa_f: '-' }, false);
|
|
83
|
+
assert.strictEqual(r.values.pa_f, '-');
|
|
84
|
+
assert.strictEqual(r.iterations.length, 1);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('resolve glob expansion', () => {
|
|
88
|
+
it('expands a matching glob into sorted file iterations', async () => {
|
|
89
|
+
const dir = join(tmp, 'glob');
|
|
90
|
+
mkdirSync(dir);
|
|
91
|
+
writeFileSync(join(dir, 'b.txt'), '');
|
|
92
|
+
writeFileSync(join(dir, 'a.txt'), '');
|
|
93
|
+
writeFileSync(join(dir, 'c.md'), '');
|
|
94
|
+
const r = await resolve([v('pa_f')], { pa_f: join(dir, '*.txt') }, false);
|
|
95
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), [join(dir, 'a.txt'), join(dir, 'b.txt')]);
|
|
96
|
+
});
|
|
97
|
+
it('skips hidden files unless the segment starts with a dot', async () => {
|
|
98
|
+
const dir = join(tmp, 'hidden');
|
|
99
|
+
mkdirSync(dir);
|
|
100
|
+
writeFileSync(join(dir, '.secret.txt'), '');
|
|
101
|
+
writeFileSync(join(dir, 'plain.txt'), '');
|
|
102
|
+
const r = await resolve([v('pa_f')], { pa_f: join(dir, '*.txt') }, false);
|
|
103
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), [join(dir, 'plain.txt')]);
|
|
104
|
+
});
|
|
105
|
+
it('treats a non-matching glob as a literal', async () => {
|
|
106
|
+
const pattern = join(tmp, 'nope', '*.zzz');
|
|
107
|
+
const r = await resolve([v('pa_f')], { pa_f: pattern }, false);
|
|
108
|
+
assert.strictEqual(r.values.pa_f, pattern);
|
|
109
|
+
});
|
|
110
|
+
it('expands a relative glob against the current directory', async () => {
|
|
111
|
+
// All other glob tests use absolute patterns; this walks the base === ''
|
|
112
|
+
// branches (readdir of '.', bare-entry results) in expandGlob.
|
|
113
|
+
const dir = join(tmp, 'relative');
|
|
114
|
+
mkdirSync(dir);
|
|
115
|
+
writeFileSync(join(dir, 'one.txt'), '');
|
|
116
|
+
writeFileSync(join(dir, 'two.txt'), '');
|
|
117
|
+
const prevCwd = process.cwd();
|
|
118
|
+
process.chdir(dir);
|
|
119
|
+
try {
|
|
120
|
+
const r = await resolve([v('pa_f')], { pa_f: '*.txt' }, false);
|
|
121
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), ['one.txt', 'two.txt']);
|
|
122
|
+
// A literal leading segment resolved relative to the cwd.
|
|
123
|
+
mkdirSync(join(dir, 'sub'));
|
|
124
|
+
writeFileSync(join(dir, 'sub', 'three.txt'), '');
|
|
125
|
+
const r2 = await resolve([v('pa_f')], { pa_f: 'sub/*.txt' }, false);
|
|
126
|
+
assert.deepStrictEqual(r2.iterations.map(i => i.pa_f), [join('sub', 'three.txt')]);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
process.chdir(prevCwd);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
it('expands a ? wildcard segment without a *', async () => {
|
|
133
|
+
const dir = join(tmp, 'qmark');
|
|
134
|
+
mkdirSync(dir);
|
|
135
|
+
writeFileSync(join(dir, 'a1.txt'), '');
|
|
136
|
+
writeFileSync(join(dir, 'a2.txt'), '');
|
|
137
|
+
writeFileSync(join(dir, 'a12.txt'), '');
|
|
138
|
+
const r = await resolve([v('pa_f')], { pa_f: join(dir, 'a?.txt') }, false);
|
|
139
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_f), [join(dir, 'a1.txt'), join(dir, 'a2.txt')]);
|
|
140
|
+
});
|
|
141
|
+
it('survives an unreadable glob base (file used as directory)', async () => {
|
|
142
|
+
// "plain-file/*.md": the base exists but readdirSync throws ENOTDIR;
|
|
143
|
+
// the expander must skip it instead of crashing, leaving a literal.
|
|
144
|
+
const file = join(tmp, 'plain-file');
|
|
145
|
+
writeFileSync(file, 'not a dir');
|
|
146
|
+
const pattern = join(file, '*.md');
|
|
147
|
+
const r = await resolve([v('pa_f')], { pa_f: pattern }, false);
|
|
148
|
+
assert.strictEqual(r.values.pa_f, pattern);
|
|
149
|
+
assert.strictEqual(r.iterations.length, 1);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
describe('resolve interactive prompting', () => {
|
|
153
|
+
// resolve()'s ask() reads from process.stdin via readline; swap in a
|
|
154
|
+
// PassThrough so answers can be scripted without a child process.
|
|
155
|
+
async function withStdin(input, fn) {
|
|
156
|
+
const fake = new PassThrough();
|
|
157
|
+
const desc = Object.getOwnPropertyDescriptor(process, 'stdin');
|
|
158
|
+
Object.defineProperty(process, 'stdin', { value: fake, configurable: true });
|
|
159
|
+
try {
|
|
160
|
+
fake.write(input);
|
|
161
|
+
return await fn();
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
Object.defineProperty(process, 'stdin', desc);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
it('asks for missing values and trims the answer', async () => {
|
|
168
|
+
const r = await withStdin(' spaced answer \n', () => resolve([v('pa_ask')], {}, true));
|
|
169
|
+
assert.strictEqual(r.values.pa_ask, 'spaced answer');
|
|
170
|
+
assert.deepStrictEqual(r.iterations, [{ pa_ask: 'spaced answer' }]);
|
|
171
|
+
});
|
|
172
|
+
it('expands a comma-separated interactive answer into iterations', async () => {
|
|
173
|
+
const r = await withStdin('one,two,three\n', () => resolve([v('pa_ask')], {}, true));
|
|
174
|
+
assert.deepStrictEqual(r.iterations.map(i => i.pa_ask), ['one', 'two', 'three']);
|
|
175
|
+
});
|
|
176
|
+
it('prefers flags and defaults over prompting', async () => {
|
|
177
|
+
// A sentinel answer is queued: if resolve prompted for either var it
|
|
178
|
+
// would consume it and the assertions below would fail.
|
|
179
|
+
const r = await withStdin('SENTINEL_NOT_CONSUMED\n', () => resolve([v('pa_flag'), v('pa_dflt', 'd')], { pa_flag: 'f' }, true));
|
|
180
|
+
assert.strictEqual(r.values.pa_flag, 'f');
|
|
181
|
+
assert.strictEqual(r.values.pa_dflt, 'd');
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
//# sourceMappingURL=resolver.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.test.js","sourceRoot":"","sources":["../src/resolver.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip terminal escape sequences and control characters from text that is
|
|
3
|
+
* displayed in the user's terminal but originates from untrusted sources
|
|
4
|
+
* (repo-checked-in .prompts/ templates, git diff output, env values).
|
|
5
|
+
*
|
|
6
|
+
* Without this, a cloned repository's template could embed OSC/CSI sequences
|
|
7
|
+
* that retitle the window, write to the clipboard (OSC 52), or overwrite
|
|
8
|
+
* previously printed lines when the user runs `promptargs list` or `show`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sanitizeForTerminal(text: string): string;
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip terminal escape sequences and control characters from text that is
|
|
3
|
+
* displayed in the user's terminal but originates from untrusted sources
|
|
4
|
+
* (repo-checked-in .prompts/ templates, git diff output, env values).
|
|
5
|
+
*
|
|
6
|
+
* Without this, a cloned repository's template could embed OSC/CSI sequences
|
|
7
|
+
* that retitle the window, write to the clipboard (OSC 52), or overwrite
|
|
8
|
+
* previously printed lines when the user runs `promptargs list` or `show`.
|
|
9
|
+
*/
|
|
10
|
+
// ESC-initiated sequences: CSI, OSC (BEL- or ST-terminated), DCS/SOS/PM/APC,
|
|
11
|
+
// and single-character escapes.
|
|
12
|
+
const ANSI_SEQ =
|
|
13
|
+
// eslint-disable-next-line no-control-regex
|
|
14
|
+
/\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07\x1b]*(?:\x07|\x1b\\)?|[PX^_][^\x1b]*(?:\x1b\\)?|[0-~])/g;
|
|
15
|
+
// Remaining C0 controls (except \t and \n), DEL, and the C1 CSI byte.
|
|
16
|
+
// eslint-disable-next-line no-control-regex
|
|
17
|
+
const CONTROL_CHARS = /[\x00-\x08\x0b-\x1f\x7f\u0080-\u009f]/g;
|
|
18
|
+
export function sanitizeForTerminal(text) {
|
|
19
|
+
return text.replace(ANSI_SEQ, '').replace(CONTROL_CHARS, '');
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,6EAA6E;AAC7E,gCAAgC;AAChC,MAAM,QAAQ;AACZ,4CAA4C;AAC5C,6FAA6F,CAAC;AAEhG,sEAAsE;AACtE,4CAA4C;AAC5C,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAE/D,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { sanitizeForTerminal } from './sanitize.js';
|
|
4
|
+
test('passes plain text through unchanged', () => {
|
|
5
|
+
assert.strictEqual(sanitizeForTerminal('hello world'), 'hello world');
|
|
6
|
+
});
|
|
7
|
+
test('preserves newlines and tabs', () => {
|
|
8
|
+
assert.strictEqual(sanitizeForTerminal('a\n\tb'), 'a\n\tb');
|
|
9
|
+
});
|
|
10
|
+
test('strips CSI color/cursor sequences', () => {
|
|
11
|
+
assert.strictEqual(sanitizeForTerminal('\x1b[31mred\x1b[0m'), 'red');
|
|
12
|
+
assert.strictEqual(sanitizeForTerminal('up\x1b[2Aover\x1b[10D'), 'upover');
|
|
13
|
+
});
|
|
14
|
+
test('strips OSC sequences (BEL and ST terminated)', () => {
|
|
15
|
+
// Window retitle
|
|
16
|
+
assert.strictEqual(sanitizeForTerminal('\x1b]0;pwned\x07safe'), 'safe');
|
|
17
|
+
// OSC 52 clipboard write, ST-terminated
|
|
18
|
+
assert.strictEqual(sanitizeForTerminal('\x1b]52;c;ZXZpbA==\x1b\\safe'), 'safe');
|
|
19
|
+
});
|
|
20
|
+
test('strips unterminated OSC sequence', () => {
|
|
21
|
+
assert.strictEqual(sanitizeForTerminal('a\x1b]0;title'), 'a');
|
|
22
|
+
});
|
|
23
|
+
test('strips DCS/SOS/PM/APC sequences', () => {
|
|
24
|
+
assert.strictEqual(sanitizeForTerminal('\x1bPq payload\x1b\\ok'), 'ok');
|
|
25
|
+
assert.strictEqual(sanitizeForTerminal('\x1b_apc\x1b\\ok'), 'ok');
|
|
26
|
+
});
|
|
27
|
+
test('strips single-character escapes', () => {
|
|
28
|
+
assert.strictEqual(sanitizeForTerminal('a\x1bcb'), 'ab');
|
|
29
|
+
});
|
|
30
|
+
test('strips carriage returns, C0 controls, DEL, and C1 bytes', () => {
|
|
31
|
+
assert.strictEqual(sanitizeForTerminal('fake\rreal'), 'fakereal');
|
|
32
|
+
assert.strictEqual(sanitizeForTerminal('a\x00b\x08c\x7fd'), 'abcd');
|
|
33
|
+
assert.strictEqual(sanitizeForTerminal('a\u009b31mb'), 'a31mb');
|
|
34
|
+
});
|
|
35
|
+
test('handles empty string', () => {
|
|
36
|
+
assert.strictEqual(sanitizeForTerminal(''), '');
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=sanitize.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.test.js","sourceRoot":"","sources":["../src/sanitize.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;IAC/C,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC,CAAC;AACxE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACvC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAC7C,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC,CAAC;IACrE,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;IACxD,iBAAiB;IACjB,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC,CAAC;IACxE,wCAAwC;IACxC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,8BAA8B,CAAC,EAAE,MAAM,CAAC,CAAC;AAClF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAC5C,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC3C,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,wBAAwB,CAAC,EAAE,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC3C,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACnE,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;IAClE,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAChC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC"}
|
package/dist/status.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Status line rendering for Claude Code's status area.
|
|
3
3
|
* Shows current template state: filled vars, unfilled vars, progress.
|
|
4
4
|
*/
|
|
5
|
+
import { sanitizeForTerminal } from './sanitize.js';
|
|
5
6
|
export function renderStatus(templateName, vars, values, iteration) {
|
|
6
7
|
const parts = [];
|
|
7
8
|
for (const v of vars) {
|
|
@@ -17,6 +18,8 @@ export function renderStatus(templateName, vars, values, iteration) {
|
|
|
17
18
|
const allFilled = vars.every(v => v.name in values);
|
|
18
19
|
const icon = allFilled ? '✅' : '📋';
|
|
19
20
|
const progress = iteration ? ` [${iteration.current}/${iteration.total}]` : '';
|
|
20
|
-
|
|
21
|
+
// Values may come from repo-controlled sources (templates, git diff);
|
|
22
|
+
// never let them inject escape sequences into the status line.
|
|
23
|
+
return sanitizeForTerminal(`${icon} ${templateName}${progress}: ${parts.join(' ')}`);
|
|
21
24
|
}
|
|
22
25
|
//# sourceMappingURL=status.js.map
|
package/dist/status.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,UAAU,YAAY,CAC1B,YAAoB,EACpB,IAAmB,EACnB,MAA8B,EAC9B,SAA8C;IAE9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,GAAG,MAAM,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAE/E,sEAAsE;IACtE,+DAA+D;IAC/D,OAAO,mBAAmB,CAAC,GAAG,IAAI,IAAI,YAAY,GAAG,QAAQ,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|