diff --git a/.changes/visualization/chore-tidy-adhoc-plugins-visualization-2026-11-03-fa6c9917.md b/.changes/visualization/chore-tidy-adhoc-plugins-visualization-2026-11-03-fa6c9917.md new file mode 100644 index 00000000000..b245f184469 --- /dev/null +++ b/.changes/visualization/chore-tidy-adhoc-plugins-visualization-2026-11-03-fa6c9917.md @@ -0,0 +1,7 @@ +--- +bump: patch +--- + +### Changed + +- Tidied check-deck.mjs: the K2 refusal reuses the local-result helper, and the header usage lists the hosted argument the parser already accepts. diff --git a/plugins/visualization/skills/present/scripts/check-deck.mjs b/plugins/visualization/skills/present/scripts/check-deck.mjs index c2f688a2dd5..caaff2f6b2d 100755 --- a/plugins/visualization/skills/present/scripts/check-deck.mjs +++ b/plugins/visualization/skills/present/scripts/check-deck.mjs @@ -8,7 +8,7 @@ // publish would send. Prints one JSON object. // // check-deck.mjs --class K0|K1|K2 -// [--argument terminal|file|artifact] [--option ] +// [--argument terminal|file|artifact|hosted] [--option ] // Exit 0 decided (read `medium`), 1 a deck refused, 2 usage or an unreadable root. import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync } from "node:fs"; @@ -186,7 +186,7 @@ function workTree(dir) { * @param {{root: string, visibility: string, cls: string, layers?: {argument?: string|null, option?: string|null, home?: string, project?: string|null, dataDir?: string|null}}} input */ export function checkDeck({ root, visibility, cls, layers = {} }) { - const local = (exit, reason) => ({ exit, result: { medium: "file", class: cls, reason } }); + const local = (exit, reason, refused) => ({ exit, result: { medium: "file", class: cls, reason, ...(refused && { refused }) } }); const resolved = resolve(root); if (lstatSync(resolved).isSymbolicLink() || realpathSync(resolved) !== resolved) { return local(2, `the deck root ${resolved} is or passes through a symlink; pass its real path`); @@ -212,9 +212,7 @@ export function checkDeck({ root, visibility, cls, layers = {} }) { if (badTitle) return local(1, badTitle); if (cls === "K2") { const refused = k2Refusals(files); - if (refused.length) { - return { exit: 1, result: { medium: "file", class: cls, reason: "a K2 deck carries more than text in the slide format", refused } }; - } + if (refused.length) return local(1, "a K2 deck carries more than text in the slide format", refused); } const { argument = null, option = null, home, project = findRoot(), dataDir = process.env.CLAUDE_PLUGIN_DATA || null } = layers; const resolution = resolveMedium({ lane: "visualization:present", argument, userConfig: option, projectRoot: project }, { ...(home ? { userHome: home } : {}), dataDir }); diff --git a/plugins/visualization/tests/present.test.mjs b/plugins/visualization/tests/present.test.mjs index bf79b3d7146..bf3a1a51956 100644 --- a/plugins/visualization/tests/present.test.mjs +++ b/plugins/visualization/tests/present.test.mjs @@ -138,6 +138,13 @@ describe("check-deck", () => { assert.deepEqual(result.refused, [{ file: "project/slides/s1.html", carries }]); }); } + test("a K2 refusal prints medium, class, reason and refused in that order; other refusals carry no refused key", () => { + const k2 = checkDeck({ root: deck({ s1: slide("s1", hostile[0][1]) }), visibility: "PUBLIC", cls: "K2" }); + assert.deepEqual(Object.keys(k2.result), ["medium", "class", "reason", "refused"]); + assert.equal(k2.result.class, "K2"); + const untitled = checkDeck({ root: deck(plain, { v: 4, order: ["cover"] }), visibility: "PUBLIC", cls: "K2" }); + assert.deepEqual(Object.keys(untitled.result), ["medium", "class", "reason"]); + }); test("a K2 deck of escaped text and uploaded images passes; text that reads like markup does not trip it", () => { const body = [ "

Fix <script> onload = 1 url(x) href=x & > done

",