From 6b53bedc747d197c7eaf982d93d25679c166348a Mon Sep 17 00:00:00 2001 From: Wen Date: Wed, 14 Oct 2026 16:43:14 -0300 Subject: [PATCH] fix(frontend-slides): ignore CDPATH when resolving input and output paths Signed-off-by: Wen --- manifests/context-packs/skill-triggers@1.json | 2 +- skills/frontend-slides/scripts/export-pdf.sh | 4 +- .../skills/frontend-slides-export-pdf.test.js | 59 +++++++++++-------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/manifests/context-packs/skill-triggers@1.json b/manifests/context-packs/skill-triggers@1.json index 9a2d7380b..91e5ab168 100644 --- a/manifests/context-packs/skill-triggers@1.json +++ b/manifests/context-packs/skill-triggers@1.json @@ -10,7 +10,7 @@ "id": "hand-seeded", "source": "manual-curation-pending-regeneration" }, - "registryDigest": "b133a28198126c63f6c9a0b10688c0144cac10dd9a1b2305f4fd1e88187888e5", + "registryDigest": "7f028ff38bb4f76843d6dc46d98608c187d52a44b4da56163f4fab0ccfc703f0", "schemaVersion": 1, "triggers": { "skill:agent-runtime-gateway-smoke-test": [ diff --git a/skills/frontend-slides/scripts/export-pdf.sh b/skills/frontend-slides/scripts/export-pdf.sh index 717a0900e..8ae2cadc1 100755 --- a/skills/frontend-slides/scripts/export-pdf.sh +++ b/skills/frontend-slides/scripts/export-pdf.sh @@ -73,7 +73,7 @@ if [[ ! -f "$INPUT_HTML" ]]; then fi # Resolve to absolute path -INPUT_HTML=$(cd "$(dirname "$INPUT_HTML")" && pwd)/$(basename "$INPUT_HTML") +INPUT_HTML=$(CDPATH= cd -- "$(dirname "$INPUT_HTML")" && pwd)/$(basename "$INPUT_HTML") # Output PDF path: use second argument or derive from input name if [[ $# -ge 2 ]]; then @@ -85,7 +85,7 @@ fi # Resolve output to absolute path (the export later runs from a temp dir that is deleted) OUTPUT_DIR=$(dirname "$OUTPUT_PDF") mkdir -p "$OUTPUT_DIR" -OUTPUT_PDF="$(cd "$OUTPUT_DIR" && pwd)/$(basename "$OUTPUT_PDF")" +OUTPUT_PDF="$(CDPATH= cd -- "$OUTPUT_DIR" && pwd)/$(basename "$OUTPUT_PDF")" echo "" echo -e "${BOLD}========================================${NC}" diff --git a/tests/skills/frontend-slides-export-pdf.test.js b/tests/skills/frontend-slides-export-pdf.test.js index e38490315..5ce0bb7b4 100644 --- a/tests/skills/frontend-slides-export-pdf.test.js +++ b/tests/skills/frontend-slides-export-pdf.test.js @@ -28,6 +28,31 @@ function test(name, fn) { } } +function withStubbedExport(htmlRelPath, fn) { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'slides-export-')); + try { + const bin = path.join(root, 'bin'); + const work = path.join(root, 'work'); + fs.mkdirSync(bin); + fs.mkdirSync(path.dirname(path.join(work, htmlRelPath)), { recursive: true }); + // npm/npx succeed without doing anything; open/xdg-open must not launch a viewer. + for (const name of ['npm', 'npx', 'open', 'xdg-open']) { + fs.writeFileSync(path.join(bin, name), '#!/bin/sh\nexit 0\n', { mode: 0o755 }); + } + // node stub checks the served HTML exists, then writes the PDF to the output path argument. + fs.writeFileSync(path.join(bin, 'node'), '#!/bin/sh\n[ -f "$2/$3" ] || exit 3\nprintf "%%PDF-stub" > "$4"\n', { mode: 0o755 }); + fs.writeFileSync(path.join(work, htmlRelPath), '\n'); + const run = (args, extraEnv = {}) => spawnSync('bash', [SCRIPT, ...args], { + cwd: work, + encoding: 'utf8', + env: { ...process.env, ...extraEnv, PATH: `${bin}${path.delimiter}${process.env.PATH}` }, + }); + fn({ work, run }); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +} + function runTests() { console.log('\n=== Testing frontend-slides export-pdf.sh ===\n'); @@ -42,31 +67,19 @@ function runTests() { let failed = 0; if (test('writes a relative output path next to the caller, not into the deleted temp dir', () => { - const root = fs.mkdtempSync(path.join(os.tmpdir(), 'slides-export-')); - try { - const bin = path.join(root, 'bin'); - const work = path.join(root, 'work'); - fs.mkdirSync(bin); - fs.mkdirSync(work); - // npm/npx succeed without doing anything; open/xdg-open must not launch a viewer. - for (const name of ['npm', 'npx', 'open', 'xdg-open']) { - fs.writeFileSync(path.join(bin, name), '#!/bin/sh\nexit 0\n', { mode: 0o755 }); - } - // node stub writes the PDF to the output path argument, resolved against its cwd. - fs.writeFileSync(path.join(bin, 'node'), '#!/bin/sh\nprintf "%%PDF-stub" > "$4"\n', { mode: 0o755 }); - fs.writeFileSync(path.join(work, 'presentation.html'), '\n'); - - const result = spawnSync('bash', [SCRIPT, './presentation.html', './slides.pdf'], { - cwd: work, - encoding: 'utf8', - env: { ...process.env, PATH: `${bin}${path.delimiter}${process.env.PATH}` }, - }); - + withStubbedExport('presentation.html', ({ work, run }) => { + const result = run(['./presentation.html', './slides.pdf']); assert.strictEqual(result.status, 0, result.stdout + result.stderr); assert.ok(fs.existsSync(path.join(work, 'slides.pdf')), 'slides.pdf was not written to the working directory'); - } finally { - fs.rmSync(root, { recursive: true, force: true }); - } + }); + })) passed++; else failed++; + + if (test('resolves nested relative input and output paths when CDPATH is exported', () => { + withStubbedExport(path.join('decks', 'presentation.html'), ({ work, run }) => { + const result = run(['decks/presentation.html', 'exports/slides.pdf'], { CDPATH: '.' }); + assert.strictEqual(result.status, 0, result.stdout + result.stderr); + assert.ok(fs.existsSync(path.join(work, 'exports', 'slides.pdf')), 'exports/slides.pdf was not written'); + }); })) passed++; else failed++; console.log(`\nPassed: ${passed}`);