mirror of
https://github.com/ckelsoe/obsidian-plaud-importer.git
synced 2026-07-22 07:49:02 +00:00
scripts/check-icons.mjs validates every hardcoded Lucide icon id in main.ts (the RIBBON_ICON_CHOICES list, DEFAULT_RIBBON_ICON, and literal setIcon ids) against the offline lucide-static package, chained into npm run lint. An unknown id (like the shipped #34 bug 'tape' vs 'cassette-tape') now fails CI instead of rendering a blank icon. Strips comments before extraction and preflights missing main.ts / lucide-static with clear messages. Caveat noted in-script: catches ids that exist in no Lucide, not per-version drift vs Obsidian's bundled set.
This commit is contained in:
parent
f230f3730d
commit
da9550d4e7
4 changed files with 104 additions and 1 deletions
|
|
@ -4,6 +4,10 @@ All notable changes to Plaud Importer will be documented in this file.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- Development tooling: a CI check now validates every hardcoded ribbon-icon id against the Lucide icon set, so an invalid id (which would render a blank icon) fails the build instead of shipping. No behavior change.
|
||||
|
||||
## [0.24.0] - 2026-07-06
|
||||
|
||||
### Added
|
||||
|
|
|
|||
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -20,6 +20,7 @@
|
|||
"eslint-plugin-obsidianmd": "^0.4.1",
|
||||
"globals": "^17.1.0",
|
||||
"jest": "^30.2.0",
|
||||
"lucide-static": "^1.23.0",
|
||||
"moment": "^2.29.4",
|
||||
"obsidian": "^1.13.0",
|
||||
"ts-jest": "^29.4.6",
|
||||
|
|
@ -7454,6 +7455,13 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lucide-static": {
|
||||
"version": "1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/lucide-static/-/lucide-static-1.23.0.tgz",
|
||||
"integrity": "sha512-V4tqLEHfvsptGaAZMD8sFJKeGsz2nTAU0+ctxTX3afao/5bs+mhrvvGDmvQmyI7YhQwpIFodZmnkPTMYyGzH4Q==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"package:brat": "npm run build && node package-brat.mjs",
|
||||
"lint": "eslint main.ts plaud-client.ts plaud-client-re.ts plaud-login.ts import-core.ts import-modal.ts import-runner.ts attachment-importer.ts note-writer.ts folder-catalog.ts debug-logger.ts vault-index.ts __tests__/plaud-client-re.test.ts __tests__/import-modal.test.ts __tests__/import-runner.test.ts __tests__/note-writer.test.ts __tests__/folder-catalog.test.ts __tests__/attachment-importer.test.ts __tests__/debug-logger.test.ts __tests__/vault-index.test.ts --max-warnings 0 && node scripts/check-submission.mjs",
|
||||
"lint": "eslint main.ts plaud-client.ts plaud-client-re.ts plaud-login.ts import-core.ts import-modal.ts import-runner.ts attachment-importer.ts note-writer.ts folder-catalog.ts debug-logger.ts vault-index.ts __tests__/plaud-client-re.test.ts __tests__/import-modal.test.ts __tests__/import-runner.test.ts __tests__/note-writer.test.ts __tests__/folder-catalog.test.ts __tests__/attachment-importer.test.ts __tests__/debug-logger.test.ts __tests__/vault-index.test.ts --max-warnings 0 && node scripts/check-submission.mjs && node scripts/check-icons.mjs",
|
||||
"test": "jest --passWithNoTests",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
"eslint-plugin-obsidianmd": "^0.4.1",
|
||||
"globals": "^17.1.0",
|
||||
"jest": "^30.2.0",
|
||||
"lucide-static": "^1.23.0",
|
||||
"moment": "^2.29.4",
|
||||
"obsidian": "^1.13.0",
|
||||
"ts-jest": "^29.4.6",
|
||||
|
|
|
|||
90
scripts/check-icons.mjs
Normal file
90
scripts/check-icons.mjs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Guard for the hardcoded Lucide icon ids in main.ts.
|
||||
//
|
||||
// Obsidian renders icons from the Lucide set; `setIcon` with an id that is not a
|
||||
// real Lucide icon renders nothing (a blank ribbon icon). The ribbon-icon picker
|
||||
// offers a hand-curated list of ids, and a wrong one shipped once (issue #34:
|
||||
// `tape` instead of `cassette-tape`) and stayed latent for months because a unit
|
||||
// test cannot reach Obsidian's runtime icon registry. This script validates every
|
||||
// hardcoded id against the offline `lucide-static` package so a bad id fails CI.
|
||||
//
|
||||
// Caveat: lucide-static is Lucide's own release, which may differ from the exact
|
||||
// version Obsidian bundles, so this catches ids that exist in NO Lucide (the
|
||||
// issue #34 class), not per-version drift. The developer-dashboard preview and
|
||||
// hands-on testing remain the authoritative checks. Exits non-zero on any finding
|
||||
// so it chains into `npm run lint` and CI.
|
||||
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
|
||||
const ICONS_DIR = "node_modules/lucide-static/icons";
|
||||
|
||||
// Preflight: a clear message beats a raw stack trace or a misleading "unknown
|
||||
// icon id" report when the real cause is a missing install or a moved file.
|
||||
if (!existsSync(ICONS_DIR)) {
|
||||
console.error(`check-icons: ${ICONS_DIR} not found. Run \`npm install\` (lucide-static is a devDependency).`);
|
||||
process.exit(1);
|
||||
}
|
||||
let source;
|
||||
try {
|
||||
source = readFileSync("main.ts", "utf8");
|
||||
} catch (error) {
|
||||
console.error(`check-icons: could not read main.ts (${error.message}).`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Strip comments before extracting ids, so a `];` or a commented-out setIcon call
|
||||
// inside a comment cannot truncate the array block or add a phantom id. Block
|
||||
// comments and whole-line `//` comments cover the styles used in main.ts; a `//`
|
||||
// inside a string (e.g. a URL) is left alone because only full-line comments are
|
||||
// removed.
|
||||
const code = source
|
||||
.replace(/\/\*[\s\S]*?\*\//g, "")
|
||||
.replace(/^\s*\/\/.*$/gm, "");
|
||||
|
||||
const ids = new Map(); // id -> reason (for the error message)
|
||||
function add(id, reason) {
|
||||
if (!ids.has(id)) ids.set(id, reason);
|
||||
}
|
||||
|
||||
// 1. The curated ribbon-icon list: extract ids only from inside the
|
||||
// RIBBON_ICON_CHOICES array, so command ids and other `id:` keys are not treated
|
||||
// as icons. The closing `];` is required at the start of a line (the array's real
|
||||
// close), a second guard against an in-body `];`.
|
||||
const listMatch = code.match(/RIBBON_ICON_CHOICES[^=]*=\s*\[([\s\S]*?)\n\s*\];/);
|
||||
if (!listMatch) {
|
||||
console.error("check-icons: could not locate the RIBBON_ICON_CHOICES array in main.ts (did its shape change?).");
|
||||
process.exit(1);
|
||||
}
|
||||
for (const m of listMatch[1].matchAll(/id:\s*"([a-z0-9-]+)"/g)) {
|
||||
add(m[1], "RIBBON_ICON_CHOICES");
|
||||
}
|
||||
|
||||
// 2. The default ribbon icon.
|
||||
const defaultMatch = code.match(/DEFAULT_RIBBON_ICON\s*=\s*"([a-z0-9-]+)"/);
|
||||
if (defaultMatch) add(defaultMatch[1], "DEFAULT_RIBBON_ICON");
|
||||
|
||||
// 3. Literal ids passed to setIcon(...) (both `el.setIcon("x")` and
|
||||
// `setIcon(el, "x")`). Calls that pass a variable, template literal, or helper
|
||||
// result (e.g. resolveRibbonIconId(...)) are skipped: they resolve to a value
|
||||
// already covered above or coerced to the default at runtime. The convention this
|
||||
// guard assumes is "curated list + plain quoted literals".
|
||||
for (const m of code.matchAll(/setIcon\(\s*(?:[^,"'()]+,\s*)?"([a-z0-9-]+)"\s*\)/g)) {
|
||||
add(m[1], 'setIcon("...")');
|
||||
}
|
||||
|
||||
const missing = [];
|
||||
for (const [id, reason] of ids) {
|
||||
if (!existsSync(`${ICONS_DIR}/${id}.svg`)) {
|
||||
missing.push(` - "${id}" (${reason}) is not a Lucide icon id.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.length > 0) {
|
||||
console.error("Icon check failed: unknown Lucide icon id(s) in main.ts:");
|
||||
for (const line of missing) console.error(line);
|
||||
console.error("");
|
||||
console.error("Find the correct id at https://lucide.dev/icons and fix it, or remove the entry.");
|
||||
console.error("An unknown id makes setIcon render nothing (a blank ribbon icon).");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Icon check passed: ${ids.size} hardcoded Lucide icon id(s) all valid.`);
|
||||
Loading…
Reference in a new issue