Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #!/usr/bin/env node
'use strict'
/**
* verify-preview
*
* Deterministically verifies that every eligible icon made it into the
* previewer data, and emits the per-set `?search=` preview URLs for the
* human visual check. Does NOT start a server (a long-running dev server
* can't return JSON) — the SKILL starts the previewer and the human
* opens the URLs.
*
* Usage:
* node .claude/skills/icons-release/scripts/verify-preview.js --release R264 [--port 3000] [--skip-build]
*
* Output: { success, step, data: { expected, rendered, missing, previewUrls } }
*/
const fs = require('fs')
const path = require('path')
const { spawnSync } = require('child_process')
const { succeed, failWith, run, log } = require('./lib/output')
const { parseArgs } = require('./lib/args')
const { loadWorkset } = require('./lib/workset')
const STEP = 'verify-preview'
const MODEL_PATH = path.join('public', 'icons-all.json')
function main() {
const args = parseArgs(process.argv.slice(2))
if (!args.release) {
throw Object.assign(new Error('--release is required (e.g. --release R264)'), {
code: 'MISSING_ARG'
})
}
const port = args.port || '3000'
const baseUrl = args['base-url'] || `http://localhost:${port}`
const { release, icons } = loadWorkset(args.release)
// Regenerate previewer data unless told to skip (so the check is fresh).
if (!args['skip-build']) {
log('> yarn build:public')
// Child output → our stderr; stdout stays reserved for the JSON envelope.
const result = spawnSync('yarn build:public', {
shell: true,
stdio: ['ignore', 2, 2]
})
if (result.status !== 0) {
failWith(STEP, 'previewerDataFailed', `yarn build:public exited with code ${result.status}`)
}
}
if (!fs.existsSync(MODEL_PATH)) {
failWith(STEP, 'noModelData', `${MODEL_PATH} not found. Run the previewer build first.`)
}
const model = JSON.parse(fs.readFileSync(MODEL_PATH, 'utf8'))
const missing = []
const bySet = {}
for (const icon of icons) {
const set = icon.icon_type
const entry = model[set] || { common: [], directional: [] }
const present =
(entry.common || []).includes(icon.icon_name) ||
(entry.directional || []).includes(icon.icon_name)
if (!present) {
missing.push({ icon: icon.icon_name, icon_type: set })
} else {
;(bySet[set] = bySet[set] || []).push(icon.icon_name)
}
}
const previewUrls = {}
for (const [set, names] of Object.entries(bySet)) {
previewUrls[set] = `${baseUrl}/${set}?search=${names.join(',')}`
}
succeed(STEP, {
release,
expected: icons.length,
rendered: icons.length - missing.length,
missing,
previewUrls
})
}
run(STEP, main)
|