Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixed-347-ui-reserved-switch-names.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The builder UI now reports a blank named after a reserved switch (`json`, `cross`, `status`, `no-interactive`, `help`) in the preview instead of emitting a command the CLI rejects. (#347)
5 changes: 3 additions & 2 deletions dist/ui-bootstrap.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/ui-bootstrap.test.js.map

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion dist/ui-builder.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/ui-builder.test.js.map

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions dist/ui-command-quoting.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions dist/ui-interactions.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions dist/ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@
// counterpart to drift from.
import { parseVars, expand as sharedExpand, VAR_PATTERN } from './parser.js';
import { cartesian as sharedCartesian, zip as sharedZip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';

(function () {
const DEBOUNCE_MS = 120;
Expand Down Expand Up @@ -857,6 +858,7 @@

const results = [];
try {
assertNoReservedVars(parseVars(text));
for (const combo of combos) {
const vals = Object.assign(Object.create(null), scalarValues);
arrayVars.forEach((v, i) => { vals[v.name] = combo[i]; });
Expand Down
1 change: 1 addition & 0 deletions dist/ui.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/ui.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions dist/ui.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/ui.test.js.map

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/ui-bootstrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { expand, parseVars, VAR_PATTERN } from './parser.js';
import { cartesian, zip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';
import { compileInlineScript } from './ui-harness.js';

/**
Expand Down Expand Up @@ -267,9 +268,9 @@ function loadPage(env?: EnvPayload): Page {

const run = compileInlineScript<void>('ui-bootstrap', [
'document', 'window', 'navigator',
'parseVars', 'sharedExpand', 'VAR_PATTERN', 'sharedCartesian', 'sharedZip',
'parseVars', 'sharedExpand', 'VAR_PATTERN', 'sharedCartesian', 'sharedZip', 'assertNoReservedVars',
], iifeBody);
run(document, window, navigator, parseVars, expand, VAR_PATTERN, cartesian, zip);
run(document, window, navigator, parseVars, expand, VAR_PATTERN, cartesian, zip, assertNoReservedVars);

return {
tmpl, varBody, addBtn, presetGrid, previewBody, previewCount, cliText, copyBtn, modeDesc, modeButtons,
Expand Down
13 changes: 13 additions & 0 deletions src/ui-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { expand, parseVars, VAR_PATTERN } from './parser.js';
import { cartesian, zip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';
import { compileInlineScript } from './ui-harness.js';

/**
Expand Down Expand Up @@ -92,10 +93,12 @@ function makeHarness(mode: 'zip' | 'cross' = 'zip'): Harness {
const factory = compileInlineScript<() => void>('ui-update', [
'tmpl', 'varBody', 'previewBody', 'previewCount', 'cliText', 'mode',
'sharedCartesian', 'sharedZip', 'sharedExpand', 'VAR_PATTERN',
'parseVars', 'assertNoReservedVars',
], `${src}\nreturn update;`);
const update = factory(
tmpl, varBody, previewBody, previewCount, cliText, mode,
cartesian, zip, expand, VAR_PATTERN,
parseVars, assertNoReservedVars,
);

return {
Expand Down Expand Up @@ -222,6 +225,16 @@ test('update highlights variables that remain unfilled after expansion', () => {
assert.deepEqual(expandedTexts(h), ['Fix <span class="unfilled">{{issue}}</span> in main.go']);
});

test('update reports a blank named after a reserved switch instead of building a command the CLI rejects', () => {
const h = makeHarness();
h.tmpl.value = 'Output {{json}}';
h.rows.push({ name: 'json', values: 'yaml' });
h.update();
assert.match(h.previewBody.innerHTML, /reserved for the --json switch/);
assert.equal(h.previewCount.textContent, 'error');
assert.equal(h.cli(), 'promptargs');
});

test('update renders the parser error for a dotted variable and resets the command', () => {
const h = makeHarness();
h.tmpl.value = 'Owner is {{repo.owner}} of {{name}}';
Expand Down
9 changes: 7 additions & 2 deletions src/ui-command-quoting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { spawnSync } from 'node:child_process';
import { VAR_PATTERN, expand } from './parser.js';
import { VAR_PATTERN, expand, parseVars } from './parser.js';
import { cartesian, zip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';
import { compileInlineScript } from './ui-harness.js';

/**
Expand Down Expand Up @@ -50,8 +51,12 @@ function commandFor(template: string, rows: Row[]): string {
const factory = compileInlineScript<() => void>('ui-update', [
'tmpl', 'varBody', 'previewBody', 'previewCount', 'cliText', 'mode',
'sharedCartesian', 'sharedZip', 'sharedExpand', 'VAR_PATTERN',
'parseVars', 'assertNoReservedVars',
], `${src}\nreturn update;`);
const update = factory({ value: template }, varBody, node(), node(), cliText, 'zip', cartesian, zip, expand, VAR_PATTERN);
const update = factory(
{ value: template }, varBody, node(), node(), cliText, 'zip', cartesian, zip, expand, VAR_PATTERN,
parseVars, assertNoReservedVars,
);
update();
return cliText.innerHTML
.replace(/^<span class="dollar">\$<\/span>/, '')
Expand Down
5 changes: 3 additions & 2 deletions src/ui-interactions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { expand, parseVars, VAR_PATTERN } from './parser.js';
import { cartesian, zip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';
import { compileInlineScript } from './ui-harness.js';

/**
Expand Down Expand Up @@ -253,7 +254,7 @@ function makeHarness(debounceMs = 1): Harness {
const factory = compileInlineScript<Api>('ui-interactions', [
'document', 'tmpl', 'varBody', 'presetGrid', 'modeDesc',
'previewBody', 'previewCount', 'cliText', 'PRESETS', 'DEBOUNCE_MS',
'parseVars', 'sharedCartesian', 'sharedZip', 'sharedExpand', 'VAR_PATTERN',
'parseVars', 'sharedCartesian', 'sharedZip', 'sharedExpand', 'VAR_PATTERN', 'assertNoReservedVars',
], `let mode = 'zip';
let debounceTimer = null;
${src}
Expand All @@ -265,7 +266,7 @@ function makeHarness(debounceMs = 1): Harness {
const api = factory(
document, tmpl, varBody, presetGrid, modeDesc,
previewBody, previewCount, cliText, presets, debounceMs,
parseVars, cartesian, zip, expand, VAR_PATTERN,
parseVars, cartesian, zip, expand, VAR_PATTERN, assertNoReservedVars,
);

return {
Expand Down
2 changes: 2 additions & 0 deletions src/ui.html
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@
// counterpart to drift from.
import { parseVars, expand as sharedExpand, VAR_PATTERN } from './parser.js';
import { cartesian as sharedCartesian, zip as sharedZip } from './iterate.js';
import { assertNoReservedVars } from './flags.js';

(function () {
const DEBOUNCE_MS = 120;
Expand Down Expand Up @@ -857,6 +858,7 @@

const results = [];
try {
assertNoReservedVars(parseVars(text));
for (const combo of combos) {
const vals = Object.assign(Object.create(null), scalarValues);
arrayVars.forEach((v, i) => { vals[v.name] = combo[i]; });
Expand Down
4 changes: 4 additions & 0 deletions src/ui.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ test('startUI serves the parser/iterate/mustache modules the browser imports', a
assert.match(iterate.body, /export function cartesian/);
assert.match(iterate.body, /export function zip/);

const flags = await request(port, `127.0.0.1:${port}`, '/flags.js');
assert.equal(flags.statusCode, 200);
assert.match(flags.body, /export function assertNoReservedVars/);

const mustache = await request(port, `127.0.0.1:${port}`, '/mustache.mjs');
assert.equal(mustache.statusCode, 200);
assert.match(mustache.body, /export default mustache/);
Expand Down
1 change: 1 addition & 0 deletions src/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function buildUIHtml(rawHtml: string, envVars: EnvData): string {
const STATIC_JS_ROUTES: Record<string, string> = {
'/parser.js': 'parser.js',
'/iterate.js': 'iterate.js',
'/flags.js': 'flags.js',
'/mustache.mjs': 'mustache.mjs',
};

Expand Down
Loading