@x12i/kit-cli 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/doctor.ts","../src/main.ts","../src/cli.ts"],"names":["path","readFile","themeNames","densityNames"],"mappings":"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","file":"cli.js","sourcesContent":["import { readFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { densityNames, themeNames, type DensityName, type ThemeName } from \"@x12i/tokens\";\r\n\r\nexport const CONFIG_FILE = \"kit.config.json\";\r\nexport const CONFIG_VERSION = 1;\r\n\r\nexport interface KitConfig {\r\n version: typeof CONFIG_VERSION;\r\n /** The theme the project starts with. */\r\n theme: ThemeName;\r\n density: DensityName;\r\n doctor: {\r\n /** Paths, relative to the config file, that `kit doctor` skips. */\r\n ignore: string[];\r\n };\r\n}\r\n\r\nexport function isThemeName(value: string): value is ThemeName {\r\n return (themeNames as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isDensityName(value: string): value is DensityName {\r\n return (densityNames as readonly string[]).includes(value);\r\n}\r\n\r\nexport function createConfig(options: { theme?: ThemeName; density?: DensityName } = {}): KitConfig {\r\n return {\r\n version: CONFIG_VERSION,\r\n theme: options.theme ?? \"light\",\r\n density: options.density ?? \"default\",\r\n doctor: { ignore: [] },\r\n };\r\n}\r\n\r\n/** Reads `kit.config.json` from `cwd`. Returns `null` when there is none. */\r\nexport async function loadConfig(cwd: string): Promise<KitConfig | null> {\r\n let text: string;\r\n try {\r\n text = await readFile(path.join(cwd, CONFIG_FILE), \"utf8\");\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\r\n throw error;\r\n }\r\n\r\n let raw: unknown;\r\n try {\r\n raw = JSON.parse(text);\r\n } catch {\r\n throw new Error(`${CONFIG_FILE} is not valid JSON.`);\r\n }\r\n\r\n const input = (typeof raw === \"object\" && raw !== null ? raw : {}) as Partial<KitConfig>;\r\n const defaults = createConfig();\r\n const ignore = input.doctor?.ignore;\r\n\r\n return {\r\n version: CONFIG_VERSION,\r\n theme: typeof input.theme === \"string\" && isThemeName(input.theme) ? input.theme : defaults.theme,\r\n density:\r\n typeof input.density === \"string\" && isDensityName(input.density) ? input.density : defaults.density,\r\n doctor: {\r\n ignore: Array.isArray(ignore) ? ignore.filter((item): item is string => typeof item === \"string\") : [],\r\n },\r\n };\r\n}\r\n","import { readdir, readFile, stat } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\n\r\nexport interface Finding {\r\n /** Path relative to the scan root, with forward slashes. */\r\n file: string;\r\n line: number;\r\n column: number;\r\n /** The text that matched, such as `#ff0000`. */\r\n match: string;\r\n}\r\n\r\nexport interface ScanOptions {\r\n /** Paths, relative to `cwd`, to skip. A prefix skips everything under it. */\r\n ignore?: string[];\r\n}\r\n\r\nconst SCANNED_EXTENSIONS = new Set([\r\n \".css\",\r\n \".scss\",\r\n \".sass\",\r\n \".less\",\r\n \".ts\",\r\n \".tsx\",\r\n \".js\",\r\n \".jsx\",\r\n \".mjs\",\r\n \".cjs\",\r\n \".html\",\r\n \".vue\",\r\n \".svelte\",\r\n \".mdx\",\r\n]);\r\n\r\nconst SKIPPED_DIRECTORIES = new Set([\r\n \"node_modules\",\r\n \"dist\",\r\n \"build\",\r\n \"out\",\r\n \"coverage\",\r\n \".git\",\r\n \".next\",\r\n \".turbo\",\r\n \".svelte-kit\",\r\n]);\r\n\r\nconst MAX_FILE_BYTES = 1_000_000;\r\n\r\n/**\r\n * 3, 4, 6 or 8 hex digits after a `#`. The lookbehind skips URL fragments such\r\n * as `page#abc`, HTML entities such as `&#123456;` and `href=\"#abc\"` anchors.\r\n */\r\nconst HEX_COLOR = /(?<![\\w&#/-])(?<!\\bhref=[\"'])#(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})(?![\\w-])/g;\r\n\r\n/** A line that contains this text is skipped, for a color that is meant to stay. */\r\nexport const IGNORE_MARKER = \"kit-ignore\";\r\n\r\nconst toPosix = (value: string) => value.split(path.sep).join(\"/\");\r\n\r\nfunction isIgnored(relativePath: string, ignore: string[]): boolean {\r\n return ignore.some((entry) => {\r\n const prefix = entry.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\");\r\n return prefix !== \"\" && (relativePath === prefix || relativePath.startsWith(`${prefix}/`));\r\n });\r\n}\r\n\r\n/** Finds hard-coded hex colors in one piece of text. */\r\nexport function findHexColors(text: string): Array<Omit<Finding, \"file\">> {\r\n const findings: Array<Omit<Finding, \"file\">> = [];\r\n const lines = text.split(/\\r?\\n/);\r\n\r\n lines.forEach((line, index) => {\r\n if (line.includes(IGNORE_MARKER)) return;\r\n for (const found of line.matchAll(HEX_COLOR)) {\r\n findings.push({ line: index + 1, column: (found.index ?? 0) + 1, match: found[0] });\r\n }\r\n });\r\n\r\n return findings;\r\n}\r\n\r\nasync function* walk(directory: string): AsyncGenerator<string> {\r\n const entries = await readdir(directory, { withFileTypes: true });\r\n entries.sort((a, b) => a.name.localeCompare(b.name));\r\n\r\n for (const entry of entries) {\r\n // Symlinks are skipped so a link back up the tree cannot loop forever.\r\n if (entry.isSymbolicLink()) continue;\r\n const full = path.join(directory, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n if (!SKIPPED_DIRECTORIES.has(entry.name)) yield* walk(full);\r\n } else if (entry.isFile()) {\r\n yield full;\r\n }\r\n }\r\n}\r\n\r\nfunction isScannable(file: string): boolean {\r\n const name = path.basename(file);\r\n if (name.includes(\".min.\") || name.endsWith(\".d.ts\")) return false;\r\n return SCANNED_EXTENSIONS.has(path.extname(name));\r\n}\r\n\r\n/**\r\n * Scans files and folders for hard-coded hex colors. Paths that do not exist\r\n * throw, so a typo in a path is not reported as a clean result.\r\n */\r\nexport async function scanForHardcodedColors(\r\n cwd: string,\r\n targets: string[] = [\".\"],\r\n { ignore = [] }: ScanOptions = {},\r\n): Promise<Finding[]> {\r\n const findings: Finding[] = [];\r\n const seen = new Set<string>();\r\n\r\n for (const target of targets) {\r\n const root = path.resolve(cwd, target);\r\n const info = await stat(root);\r\n const files = info.isDirectory() ? walk(root) : (async function* () { yield root; })();\r\n\r\n for await (const file of files) {\r\n if (seen.has(file)) continue;\r\n seen.add(file);\r\n\r\n const relative = toPosix(path.relative(cwd, file));\r\n if (isIgnored(relative, ignore) || !isScannable(file)) continue;\r\n\r\n const { size } = await stat(file);\r\n if (size > MAX_FILE_BYTES) continue;\r\n\r\n const text = await readFile(file, \"utf8\");\r\n for (const finding of findHexColors(text)) {\r\n findings.push({ file: relative, ...finding });\r\n }\r\n }\r\n }\r\n\r\n return findings;\r\n}\r\n","import { readFileSync } from \"node:fs\";\r\nimport { access, writeFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { parseArgs } from \"node:util\";\r\nimport { densityNames, themeNames } from \"@x12i/tokens\";\r\nimport { CONFIG_FILE, createConfig, isDensityName, isThemeName, loadConfig } from \"./config\";\r\nimport { scanForHardcodedColors } from \"./doctor\";\r\n\r\nexport interface Io {\r\n cwd: string;\r\n out: (text: string) => void;\r\n err: (text: string) => void;\r\n}\r\n\r\n/** Exit codes: 0 success, 1 the command ran and found a problem, 2 bad usage. */\r\ntype ExitCode = 0 | 1 | 2;\r\n\r\nconst HELP = `kit: command line for the Unified UI Kit\r\n\r\nUsage\r\n kit <command> [options]\r\n\r\nCommands\r\n init [--theme <name>] [--density <name>] [--force]\r\n Write ${CONFIG_FILE} in the current folder.\r\n add <component...>\r\n Add a component to your project. Planned.\r\n theme [name]\r\n List the themes and densities. Generating a theme is planned.\r\n doctor [paths...] [--json]\r\n Find hard-coded hex colors that should be --kit- tokens.\r\n Exits with 1 when it finds any.\r\n\r\nOptions\r\n -h, --help Show this help.\r\n -v, --version Show the version.\r\n`;\r\n\r\nfunction readVersion(): string {\r\n const file = new URL(\"../package.json\", import.meta.url);\r\n return (JSON.parse(readFileSync(file, \"utf8\")) as { version: string }).version;\r\n}\r\n\r\nasync function exists(file: string): Promise<boolean> {\r\n try {\r\n await access(file);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nasync function init(values: { theme?: string; density?: string; force?: boolean }, io: Io): Promise<ExitCode> {\r\n if (values.theme !== undefined && !isThemeName(values.theme)) {\r\n io.err(`Unknown theme \"${values.theme}\". Choose one of: ${themeNames.join(\", \")}.\\n`);\r\n return 2;\r\n }\r\n if (values.density !== undefined && !isDensityName(values.density)) {\r\n io.err(`Unknown density \"${values.density}\". Choose one of: ${densityNames.join(\", \")}.\\n`);\r\n return 2;\r\n }\r\n\r\n const target = path.join(io.cwd, CONFIG_FILE);\r\n if (!values.force && (await exists(target))) {\r\n io.err(`${CONFIG_FILE} already exists. Use --force to replace it.\\n`);\r\n return 1;\r\n }\r\n\r\n const config = createConfig({ theme: values.theme, density: values.density });\r\n await writeFile(target, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\r\n io.out(`Created ${CONFIG_FILE}\\n`);\r\n return 0;\r\n}\r\n\r\nfunction add(components: string[], io: Io): ExitCode {\r\n const wanted = components.length > 0 ? ` (${components.join(\", \")})` : \"\";\r\n io.err(\r\n `kit add${wanted} is not available yet. The component registry is planned. ` +\r\n `Until then, import components from @x12i/ui.\\n`,\r\n );\r\n return 1;\r\n}\r\n\r\nfunction theme(name: string | undefined, io: Io): ExitCode {\r\n if (name === undefined) {\r\n io.out(`Themes: ${themeNames.join(\", \")}\\n`);\r\n io.out(`Densities: ${densityNames.join(\", \")}\\n`);\r\n return 0;\r\n }\r\n\r\n if (isThemeName(name)) {\r\n io.out(`\"${name}\" is built in. Import @x12i/themes/${name}.css, or set data-theme=\"${name}\" on <html>.\\n`);\r\n return 0;\r\n }\r\n\r\n io.err(\r\n `Generating a custom theme is planned and is not available yet. ` +\r\n `Built-in themes: ${themeNames.join(\", \")}.\\n`,\r\n );\r\n return 1;\r\n}\r\n\r\nasync function doctor(paths: string[], json: boolean, io: Io): Promise<ExitCode> {\r\n const config = await loadConfig(io.cwd);\r\n const targets = paths.length > 0 ? paths : [\".\"];\r\n\r\n let findings;\r\n try {\r\n findings = await scanForHardcodedColors(io.cwd, targets, { ignore: config?.doctor.ignore });\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n io.err(`Path not found: ${(error as NodeJS.ErrnoException).path ?? targets.join(\", \")}\\n`);\r\n return 2;\r\n }\r\n throw error;\r\n }\r\n\r\n if (json) {\r\n io.out(`${JSON.stringify(findings, null, 2)}\\n`);\r\n return findings.length > 0 ? 1 : 0;\r\n }\r\n\r\n if (findings.length === 0) {\r\n io.out(\"No hard-coded colors found.\\n\");\r\n return 0;\r\n }\r\n\r\n for (const finding of findings) {\r\n io.out(`${finding.file}:${finding.line}:${finding.column} ${finding.match} Use a --kit- color token.\\n`);\r\n }\r\n const files = new Set(findings.map((finding) => finding.file)).size;\r\n io.out(\r\n `\\n${findings.length} hard-coded ${findings.length === 1 ? \"color\" : \"colors\"} ` +\r\n `found in ${files} ${files === 1 ? \"file\" : \"files\"}.\\n`,\r\n );\r\n return 1;\r\n}\r\n\r\n/** Runs the command line and returns the exit code. */\r\nexport async function run(argv: string[], io: Io): Promise<ExitCode> {\r\n let parsed;\r\n try {\r\n parsed = parseArgs({\r\n args: argv,\r\n allowPositionals: true,\r\n options: {\r\n help: { type: \"boolean\", short: \"h\" },\r\n version: { type: \"boolean\", short: \"v\" },\r\n force: { type: \"boolean\" },\r\n json: { type: \"boolean\" },\r\n theme: { type: \"string\" },\r\n density: { type: \"string\" },\r\n },\r\n });\r\n } catch (error) {\r\n io.err(`${(error as Error).message}\\n\\n${HELP}`);\r\n return 2;\r\n }\r\n\r\n const { values, positionals } = parsed;\r\n const [command, ...rest] = positionals;\r\n\r\n if (values.version) {\r\n io.out(`${readVersion()}\\n`);\r\n return 0;\r\n }\r\n if (values.help || command === undefined || command === \"help\") {\r\n io.out(HELP);\r\n return 0;\r\n }\r\n\r\n switch (command) {\r\n case \"init\":\r\n return init(values, io);\r\n case \"add\":\r\n return add(rest, io);\r\n case \"theme\":\r\n return theme(rest[0], io);\r\n case \"doctor\":\r\n return doctor(rest, values.json ?? false, io);\r\n default:\r\n io.err(`Unknown command \"${command}\".\\n\\n${HELP}`);\r\n return 2;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { run } from \"./main\";\r\n\r\nprocess.exitCode = await run(process.argv.slice(2), {\r\n cwd: process.cwd(),\r\n out: (text) => process.stdout.write(text),\r\n err: (text) => process.stderr.write(text),\r\n});\r\n"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/rules.ts","../src/doctor.ts","../src/main.ts","../src/cli.ts"],"names":["path","readFile","add","themeNames","densityNames","theme"],"mappings":"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","file":"cli.js","sourcesContent":["import { readFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { densityNames, themeNames, type DensityName, type ThemeName } from \"@x12i/tokens\";\r\nimport type { RuleSetting } from \"./rules\";\r\n\r\nexport const CONFIG_FILE = \"kit.config.json\";\r\nexport const CONFIG_VERSION = 1;\r\n\r\nexport interface KitConfig {\r\n version: typeof CONFIG_VERSION;\r\n /** The theme the project starts with. */\r\n theme: ThemeName;\r\n density: DensityName;\r\n doctor: {\r\n /** Paths, relative to the config file, that `kit doctor` skips. */\r\n ignore: string[];\r\n /**\r\n * Per rule: `off`, `warn` or `error`. Only what the file sets is here. `kit init`\r\n * does not write it, so a new config stays as small as it was.\r\n */\r\n rules?: Record<string, RuleSetting>;\r\n };\r\n}\r\n\r\nconst RULE_SETTINGS: readonly string[] = [\"off\", \"warn\", \"error\"];\r\n\r\nexport function isThemeName(value: string): value is ThemeName {\r\n return (themeNames as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isDensityName(value: string): value is DensityName {\r\n return (densityNames as readonly string[]).includes(value);\r\n}\r\n\r\nexport function createConfig(options: { theme?: ThemeName; density?: DensityName } = {}): KitConfig {\r\n return {\r\n version: CONFIG_VERSION,\r\n theme: options.theme ?? \"light\",\r\n density: options.density ?? \"default\",\r\n doctor: { ignore: [] },\r\n };\r\n}\r\n\r\n/** Reads `kit.config.json` from `cwd`. Returns `null` when there is none. */\r\nexport async function loadConfig(cwd: string): Promise<KitConfig | null> {\r\n let text: string;\r\n try {\r\n text = await readFile(path.join(cwd, CONFIG_FILE), \"utf8\");\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\r\n throw error;\r\n }\r\n\r\n let raw: unknown;\r\n try {\r\n raw = JSON.parse(text);\r\n } catch {\r\n throw new Error(`${CONFIG_FILE} is not valid JSON.`);\r\n }\r\n\r\n const input = (typeof raw === \"object\" && raw !== null ? raw : {}) as Partial<KitConfig>;\r\n const defaults = createConfig();\r\n const ignore = input.doctor?.ignore;\r\n const rawRules: unknown = input.doctor?.rules;\r\n const rules: Record<string, RuleSetting> = {};\r\n if (typeof rawRules === \"object\" && rawRules !== null) {\r\n for (const [id, setting] of Object.entries(rawRules)) {\r\n // A bad setting is a mistake worth stopping for, not a rule to skip quietly.\r\n if (typeof setting !== \"string\" || !RULE_SETTINGS.includes(setting)) {\r\n throw new Error(`${CONFIG_FILE}: doctor.rules.${id} must be \"off\", \"warn\" or \"error\".`);\r\n }\r\n rules[id] = setting as RuleSetting;\r\n }\r\n }\r\n\r\n return {\r\n version: CONFIG_VERSION,\r\n theme: typeof input.theme === \"string\" && isThemeName(input.theme) ? input.theme : defaults.theme,\r\n density:\r\n typeof input.density === \"string\" && isDensityName(input.density) ? input.density : defaults.density,\r\n doctor: {\r\n ignore: Array.isArray(ignore) ? ignore.filter((item): item is string => typeof item === \"string\") : [],\r\n rules,\r\n },\r\n };\r\n}\r\n","import path from \"node:path\";\n\n/**\n * The rules behind `kit doctor`.\n *\n * Each rule checks one habit that breaks a kit convention: values that should be\n * `--kit-*` tokens, layout that will not mirror in right to left languages,\n * motion that is slow, janky or ignores the reader's settings, and focus that\n * has been switched off.\n *\n * The motion rules and the idea of a deterministic design linter come from two\n * open source sets of design rules, read and rewritten here against the kit's own\n * tokens: Impeccable's detector (Apache-2.0, https://github.com/pbakaus/impeccable)\n * and Emil Kowalski's animation standards (MIT, https://github.com/emilkowalski/skills).\n * See docs/design-sources-audit.md.\n */\n\nexport type Severity = \"error\" | \"warn\";\nexport type RuleSetting = Severity | \"off\";\n\nexport interface RuleInfo {\n id: string;\n /** What a rule reports as, unless `kit.config.json` says otherwise. */\n severity: Severity;\n description: string;\n}\n\nexport interface RuleHit {\n rule: string;\n line: number;\n column: number;\n /** The text that triggered the rule, trimmed for display. */\n match: string;\n message: string;\n}\n\n/** Where a file animates, used to decide whether the project handles reduced motion. */\nexport interface MotionUse {\n /** The first animation or transition in the file, if there is one. */\n first: { line: number; column: number } | null;\n handlesReducedMotion: boolean;\n}\n\nexport const RULES: readonly RuleInfo[] = [\n { id: \"hardcoded-color\", severity: \"error\", description: \"A #hex color. Use a --kit-color-* token.\" },\n {\n id: \"hardcoded-color-function\",\n severity: \"warn\",\n description: \"An rgb(), hsl(), oklch() or similar color with literal numbers. Use a --kit-color-* token.\",\n },\n { id: \"hardcoded-font-size\", severity: \"warn\", description: \"A literal font size. Use a --kit-text-*-size token.\" },\n { id: \"hardcoded-font-family\", severity: \"warn\", description: \"A literal font stack. Use --kit-font-family-sans or -mono.\" },\n { id: \"hardcoded-spacing\", severity: \"warn\", description: \"A literal padding, margin or gap. Use a --kit-space-* token.\" },\n { id: \"hardcoded-radius\", severity: \"warn\", description: \"A literal border radius. Use a --kit-radius-* token.\" },\n { id: \"hardcoded-duration\", severity: \"warn\", description: \"A literal animation time. Use a --kit-duration-* token.\" },\n { id: \"hardcoded-easing\", severity: \"warn\", description: \"A literal cubic-bezier curve. Use a --kit-easing-* token.\" },\n { id: \"bounce-easing\", severity: \"warn\", description: \"An easing curve that overshoots. Application UI should be crisp, not bouncy.\" },\n { id: \"transition-all\", severity: \"warn\", description: \"`transition: all`. List the properties you animate.\" },\n {\n id: \"layout-animation\",\n severity: \"warn\",\n description: \"A transition on width, height, margin, padding or position. Animate transform and opacity instead.\",\n },\n {\n id: \"missing-reduced-motion\",\n severity: \"warn\",\n description: \"The project animates but nothing handles prefers-reduced-motion.\",\n },\n {\n id: \"physical-property\",\n severity: \"warn\",\n description: \"A left or right property. Use the logical one (inline-start, inline-end) so right to left works.\",\n },\n { id: \"outline-none\", severity: \"warn\", description: \"The focus outline is removed with no replacement style.\" },\n { id: \"important\", severity: \"warn\", description: \"`!important`. Kit styles have zero specificity, so plain selectors win.\" },\n];\n\nexport const RULE_IDS: ReadonlySet<string> = new Set(RULES.map((rule) => rule.id));\n\n// ---------------------------------------------------------------------------\n// Reading style out of source text\n// ---------------------------------------------------------------------------\n\nconst CSS_FILES = new Set([\".css\", \".scss\", \".less\"]);\nconst SCRIPT_FILES = new Set([\".js\", \".jsx\", \".ts\", \".tsx\", \".mjs\", \".cjs\"]);\nconst MARKUP_FILES = new Set([\".html\", \".vue\", \".svelte\"]);\n\ninterface Declaration {\n /** kebab-case, lowercase. */\n prop: string;\n /** The value, with `!important` taken off. */\n value: string;\n important: boolean;\n /** Offset of the property name in the file text. */\n index: number;\n /** `css` for stylesheet syntax, `js` for a style object such as `{ marginLeft: \"8px\" }`. */\n source: \"css\" | \"js\";\n}\n\nconst toKebab = (name: string) => name.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n/** Replaces comments with spaces, so every offset and line break stays where it was. */\nfunction blankComments(text: string, lineComments: boolean): string {\n const blank = (match: string) => match.replace(/[^\\n]/g, \" \");\n let result = text.replace(/\\/\\*[\\s\\S]*?\\*\\//g, blank);\n if (lineComments) result = result.replace(/(?<![:\"'`\\w])\\/\\/[^\\n]*/g, blank);\n return result;\n}\n\ninterface Region {\n start: number;\n end: number;\n}\n\n/** The slices of a file that are CSS text, as opposed to code or prose. */\nfunction styleRegions(text: string, extension: string): Region[] {\n if (CSS_FILES.has(extension)) return [{ start: 0, end: text.length }];\n\n const patterns: RegExp[] = [];\n if (SCRIPT_FILES.has(extension)) patterns.push(/`((?:[^`\\\\]|\\\\[\\s\\S])*)`/gd);\n if (MARKUP_FILES.has(extension)) {\n patterns.push(/<style\\b[^>]*>([\\s\\S]*?)<\\/style>/gid, /\\sstyle\\s*=\\s*\"([^\"]*)\"/gd, /\\sstyle\\s*=\\s*'([^']*)'/gd);\n }\n\n const regions: Region[] = [];\n for (const pattern of patterns) {\n for (const match of text.matchAll(pattern)) {\n const span = match.indices?.[1];\n if (span) regions.push({ start: span[0], end: span[1] });\n }\n }\n return regions;\n}\n\n/**\n * `property: value;` pairs in CSS text. Custom property definitions (`--x: 4px`)\n * are never matched: that is where raw values are supposed to live.\n */\nfunction cssDeclarations(text: string, region: Region): Declaration[] {\n const found: Declaration[] = [];\n const slice = text.slice(region.start, region.end);\n const pattern = /(?<![\\w$@#.:-])(-?[a-zA-Z][\\w-]*)[ \\t]*:[ \\t\\r\\n]*([^;{}]*?)[ \\t\\r\\n]*(?=;|}|$)/g;\n\n for (const match of slice.matchAll(pattern)) {\n const [, prop, raw] = match;\n if (prop === undefined || raw === undefined || raw === \"\") continue;\n const important = /!\\s*important\\s*$/i.test(raw);\n const value = important ? raw.replace(/!\\s*important\\s*$/i, \"\").trim() : raw;\n found.push({ prop: prop.toLowerCase(), value, important, index: region.start + (match.index ?? 0), source: \"css\" });\n }\n return found;\n}\n\n/** `marginLeft: \"8px\"` entries of a style object in a script. */\nfunction jsDeclarations(text: string): Declaration[] {\n const found: Declaration[] = [];\n const pattern = /(?<![\\w$.])([a-z][A-Za-z]*)\\s*:\\s*([\"'`])((?:(?!\\2)[^\\\\\\n]|\\\\.)*)\\2/g;\n\n for (const match of text.matchAll(pattern)) {\n const [, prop, , value] = match;\n if (prop === undefined || value === undefined) continue;\n found.push({ prop: toKebab(prop), value, important: false, index: match.index ?? 0, source: \"js\" });\n }\n return found;\n}\n\n// ---------------------------------------------------------------------------\n// Values\n// ---------------------------------------------------------------------------\n\nconst hasVar = (value: string) => /\\bvar\\(/.test(value);\n\n/** Index of the `)` that closes the `(` at `open`, or the end of the text. */\nfunction closingParen(text: string, open: number): number {\n let depth = 0;\n for (let i = open; i < text.length; i += 1) {\n if (text[i] === \"(\") depth += 1;\n else if (text[i] === \")\") {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n return text.length - 1;\n}\n\n/**\n * The part of a value that is written out by hand. A `var(...)` is a token, and\n * so is a `calc()`, `clamp()`, `min()` or `max()` that is built from one, so\n * `calc(var(--kit-space-2) + 2px)` is fine while `var(--kit-space-2) 12px` still\n * has a hard-coded `12px` in it.\n */\nfunction literalPart(value: string): string {\n let result = \"\";\n let cursor = 0;\n for (const match of value.matchAll(/\\b(var|calc|clamp|min|max)\\(/g)) {\n const start = match.index ?? 0;\n if (start < cursor) continue;\n const end = closingParen(value, start + match[0].length - 1);\n const group = value.slice(start, end + 1);\n if (match[1] === \"var\" || hasVar(group)) {\n result += `${value.slice(cursor, start)} `;\n cursor = end + 1;\n }\n }\n return result + value.slice(cursor);\n}\n\n/** Literal lengths in a value, as pixels (1rem and 1em count as 16). */\nfunction lengths(value: string): number[] {\n return [...value.matchAll(/(?<![\\w.#-])(-?\\d*\\.?\\d+)(px|rem|em)\\b/g)].map(\n (match) => Number.parseFloat(match[1] ?? \"0\") * (match[2] === \"px\" ? 1 : 16),\n );\n}\n\n/** Literal times in a value, in milliseconds. */\nfunction times(value: string): number[] {\n return [...value.matchAll(/(?<![\\w.#-])(\\d*\\.?\\d+)(ms|s)\\b/g)].map(\n (match) => Number.parseFloat(match[1] ?? \"0\") * (match[2] === \"s\" ? 1000 : 1),\n );\n}\n\nconst SPACING =\n /^(?:(?:padding|margin)(?:-(?:top|right|bottom|left|block|inline)(?:-(?:start|end))?)?|(?:row-|column-)?gap)$/;\nconst RADIUS = /^border-(?:(?:top|bottom)-(?:left|right)-|(?:start|end)-(?:start|end)-)?radius$/;\nconst MOTION =\n /^(?:transition(?:-duration|-delay|-timing-function|-property)?|animation(?:-duration|-delay|-timing-function|-name)?)$/;\nconst TRANSITION = /^transition(?:-property)?$/;\n\nconst LAYOUT_PROPERTY =\n /^(?:width|height|min-width|min-height|max-width|max-height|top|right|bottom|left|inset(?:-[a-z-]+)?|margin(?:-[a-z-]+)?|padding(?:-[a-z-]+)?|border-width|font-size|flex-basis|gap)$/;\n\n/** Splits on commas that are not inside parentheses. */\nconst splitTopLevel = (value: string) => value.split(/,(?![^(]*\\))/).map((part) => part.trim());\n\n/** The logical property for each physical one the rule reports. */\nconst PHYSICAL = new Map<string, string>([\n [\"margin-left\", \"margin-inline-start\"],\n [\"margin-right\", \"margin-inline-end\"],\n [\"padding-left\", \"padding-inline-start\"],\n [\"padding-right\", \"padding-inline-end\"],\n [\"border-left\", \"border-inline-start\"],\n [\"border-right\", \"border-inline-end\"],\n [\"border-left-width\", \"border-inline-start-width\"],\n [\"border-right-width\", \"border-inline-end-width\"],\n [\"border-left-color\", \"border-inline-start-color\"],\n [\"border-right-color\", \"border-inline-end-color\"],\n [\"border-left-style\", \"border-inline-start-style\"],\n [\"border-right-style\", \"border-inline-end-style\"],\n [\"border-top-left-radius\", \"border-start-start-radius\"],\n [\"border-top-right-radius\", \"border-start-end-radius\"],\n [\"border-bottom-left-radius\", \"border-end-start-radius\"],\n [\"border-bottom-right-radius\", \"border-end-end-radius\"],\n]);\n\n/** Only reported in stylesheets: in a script, `left` and `right` are too often not CSS. */\n/**\n * `left` or `right` as a whole word in a selector: after a dot, a dash, a quote\n * or a bracket, and before anything that is not a letter or digit. `.copyright`\n * and `.leftover` do not match.\n */\nconst PHYSICAL_SIDE_SELECTOR = /(?:^|[^a-z0-9])(?:left|right)(?![a-z0-9])/i;\n\nconst PHYSICAL_STYLESHEET_ONLY = new Map<string, string>([\n [\"left\", \"inset-inline-start\"],\n [\"right\", \"inset-inline-end\"],\n]);\n\n/** Something in the same rule that still shows where focus is. */\nconst FOCUS_REPLACEMENT = /\\b(?:box-shadow|border[\\w-]*|background[\\w-]*|text-decoration[\\w-]*)\\s*:/i;\n\n// ---------------------------------------------------------------------------\n// Blocks (only the few rules that need to know what surrounds a declaration)\n// ---------------------------------------------------------------------------\n\ninterface Enclosing {\n /** The text before the `{`, such as `@media print` or `.button:focus`. */\n header: string;\n open: number;\n}\n\n/** Every `{ ... }` block around an offset, innermost first. */\nfunction enclosing(text: string, index: number): Enclosing[] {\n const blocks: Enclosing[] = [];\n let depth = 0;\n for (let i = index - 1; i >= 0; i -= 1) {\n const char = text[i];\n if (char === \"}\") depth += 1;\n else if (char === \"{\") {\n if (depth > 0) {\n depth -= 1;\n continue;\n }\n let start = i;\n while (start > 0 && !\";{}\".includes(text[start - 1] ?? \"\")) start -= 1;\n blocks.push({ header: text.slice(start, i).trim(), open: i });\n }\n }\n return blocks;\n}\n\n/** The text between the braces of the block that opens at `open`. */\nfunction bodyOf(text: string, open: number): string {\n let depth = 0;\n for (let i = open + 1; i < text.length; i += 1) {\n const char = text[i];\n if (char === \"{\") depth += 1;\n else if (char === \"}\") {\n if (depth === 0) return text.slice(open + 1, i);\n depth -= 1;\n }\n }\n return text.slice(open + 1);\n}\n\n// ---------------------------------------------------------------------------\n// The checks\n// ---------------------------------------------------------------------------\n\nfunction snippet(declaration: Declaration): string {\n const text = `${declaration.prop}: ${declaration.value}${declaration.important ? \" !important\" : \"\"}`;\n return text.length > 60 ? `${text.slice(0, 57)}...` : text;\n}\n\ntype Report = (rule: string, declaration: Declaration, message: string) => void;\n\nfunction checkDeclaration(declaration: Declaration, text: string, report: Report): void {\n const { prop, value } = declaration;\n // What is left once tokens are taken out. Only this part can be hard-coded.\n const literal = literalPart(value);\n\n if (prop === \"font-size\" && lengths(literal).some((px) => px !== 0)) {\n report(\"hardcoded-font-size\", declaration, \"Use a --kit-text-*-size token.\");\n }\n\n // A font stack often follows its token with a fallback, so any token is enough.\n if (prop === \"font-family\" && !hasVar(value) && !/^(?:inherit|initial|unset|revert(?:-layer)?)$/i.test(value)) {\n const isFontFace =\n declaration.source === \"css\" && enclosing(text, declaration.index).some((block) => /^@font-face\\b/i.test(block.header));\n if (!isFontFace) report(\"hardcoded-font-family\", declaration, \"Use --kit-font-family-sans or --kit-font-family-mono.\");\n }\n\n if (SPACING.test(prop) && lengths(literal).some((px) => Math.abs(px) > 1)) {\n report(\"hardcoded-spacing\", declaration, \"Use a --kit-space-* token.\");\n }\n\n if (RADIUS.test(prop) && lengths(literal).some((px) => px > 0)) {\n report(\"hardcoded-radius\", declaration, \"Use a --kit-radius-* token.\");\n }\n\n if (MOTION.test(prop)) {\n if (times(literal).some((ms) => ms > 0)) {\n report(\"hardcoded-duration\", declaration, \"Use a --kit-duration-* token.\");\n }\n\n const curves = [...literal.matchAll(/cubic-bezier\\(([^)]*)\\)/gi)];\n if (curves.length > 0) {\n report(\"hardcoded-easing\", declaration, \"Use a --kit-easing-* token.\");\n }\n const overshoots = curves.some((curve) => {\n const numbers = (curve[1] ?? \"\").split(\",\").map((part) => Number.parseFloat(part));\n return [numbers[1], numbers[3]].some((y) => y !== undefined && !Number.isNaN(y) && (y < 0 || y > 1));\n });\n if (overshoots) {\n report(\"bounce-easing\", declaration, \"This curve overshoots, so the motion bounces. Use a --kit-easing-* token.\");\n }\n }\n\n if (TRANSITION.test(prop)) {\n const properties =\n prop === \"transition-property\"\n ? value.split(/[\\s,]+/).filter(Boolean)\n : splitTopLevel(value).map((part) => part.split(/\\s+/)[0] ?? \"\");\n\n if (properties.some((name) => name.toLowerCase() === \"all\")) {\n report(\"transition-all\", declaration, \"List the properties you animate. `all` also animates layout and anything added later.\");\n }\n const layout = properties.find((name) => LAYOUT_PROPERTY.test(name.toLowerCase()));\n if (layout !== undefined) {\n report(\"layout-animation\", declaration, `Animating ${layout} runs layout and paint on every frame. Animate transform and opacity.`);\n }\n }\n\n // A selector that names a side (`.panel.left`, `.handle-right`, `[data-side=\"left\"]`,\n // `.text-left`) puts things on that physical side on purpose. Libraries such as\n // React Flow name their parts this way, so asking for a logical property there\n // would be noise.\n const namesSide =\n declaration.source === \"css\" && PHYSICAL_SIDE_SELECTOR.test(enclosing(text, declaration.index)[0]?.header ?? \"\");\n\n // `left: 50%` is how a thing is centered or anchored next to another, usually\n // with a physical `translate(-50%)`. Its logical twin would break in right to\n // left, so a percentage is left alone.\n const bareInset = declaration.source === \"css\" && !value.includes(\"%\") ? PHYSICAL_STYLESHEET_ONLY.get(prop) : undefined;\n const logical = PHYSICAL.get(prop) ?? bareInset;\n if (namesSide) {\n // Placed on a named side: nothing to report.\n } else if (logical !== undefined) {\n report(\"physical-property\", declaration, `Use ${logical}, so the layout mirrors in right to left languages.`);\n } else if (/^(?:text-align|float|clear)$/.test(prop) && /^(?:left|right)$/i.test(value)) {\n const side = value.toLowerCase() === \"left\" ? \"start\" : \"end\";\n const replacement = prop === \"text-align\" ? side : `inline-${side}`;\n report(\"physical-property\", declaration, `Use ${prop}: ${replacement}, so the layout mirrors in right to left languages.`);\n }\n\n if (declaration.source !== \"css\") return;\n\n const removesOutline =\n (prop === \"outline\" && /^(?:none|0|0px)$/i.test(value)) ||\n (prop === \"outline-style\" && /^none$/i.test(value)) ||\n (prop === \"outline-width\" && /^0(?:px)?$/i.test(value));\n if (removesOutline) {\n const [block] = enclosing(text, declaration.index);\n const replaced =\n block !== undefined &&\n (FOCUS_REPLACEMENT.test(bodyOf(text, block.open)) || /:not\\(\\s*:focus-visible\\s*\\)/i.test(block.header));\n if (!replaced) {\n report(\n \"outline-none\",\n declaration,\n \"Removing the outline hides keyboard focus. Add a visible focus style, such as --kit-color-border-focus.\",\n );\n }\n }\n\n if (declaration.important) {\n const allowed = enclosing(text, declaration.index).some((block) => /prefers-reduced-motion|@media\\s+print/i.test(block.header));\n if (!allowed) report(\"important\", declaration, \"Kit styles have zero specificity, so a plain selector wins. Remove !important.\");\n }\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\nfunction lineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i += 1) if (text[i] === \"\\n\") starts.push(i + 1);\n return starts;\n}\n\nfunction positionOf(starts: number[], index: number): { line: number; column: number } {\n let low = 0;\n let high = starts.length - 1;\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n if ((starts[middle] ?? 0) <= index) low = middle;\n else high = middle - 1;\n }\n return { line: low + 1, column: index - (starts[low] ?? 0) + 1 };\n}\n\nconst FUNCTION_COLOR = /(?<![\\w-])(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch)\\(\\s*[-+]?[\\d.][^)]*\\)/gi;\nconst REDUCED_MOTION = /prefers-reduced-motion|useReducedMotion|reducedMotion/i;\nconst NO_MOTION = /^(?:none|initial|unset)\\b/i;\n\n/**\n * Runs every declaration rule on one file. The caller decides which rules are\n * on and at what severity. Hex colors are not found here: they keep their own,\n * older scanner in `doctor.ts`.\n *\n * A line that contains `ignoreMarker` is skipped by every rule.\n */\nexport function checkText(text: string, file: string, ignoreMarker: string): { hits: RuleHit[]; motion: MotionUse } {\n const extension = path.extname(file).toLowerCase();\n const stripped = blankComments(text, extension !== \".css\");\n const starts = lineStarts(text);\n const rawLines = text.split(/\\r?\\n/);\n const hits: RuleHit[] = [];\n const seen = new Set<string>();\n\n const push = (rule: string, index: number, match: string, message: string) => {\n const { line, column } = positionOf(starts, index);\n if ((rawLines[line - 1] ?? \"\").includes(ignoreMarker)) return;\n const key = `${rule}:${line}:${column}`;\n if (seen.has(key)) return;\n seen.add(key);\n hits.push({ rule, line, column, match, message });\n };\n\n for (const match of stripped.matchAll(FUNCTION_COLOR)) {\n push(\"hardcoded-color-function\", match.index ?? 0, match[0], \"Use a --kit-color-* token.\");\n }\n\n const declarations = [\n ...styleRegions(stripped, extension).flatMap((region) => cssDeclarations(stripped, region)),\n ...(SCRIPT_FILES.has(extension) ? jsDeclarations(stripped) : []),\n ];\n\n let firstMotion: number | null = null;\n const sawMotion = (index: number) => {\n firstMotion = firstMotion === null ? index : Math.min(firstMotion, index);\n };\n\n for (const declaration of declarations) {\n checkDeclaration(declaration, stripped, (rule, source, message) => push(rule, source.index, snippet(source), message));\n\n const { prop, value } = declaration;\n const animates =\n ((/^animation(?:-name)?$/.test(prop) || TRANSITION.test(prop)) && !NO_MOTION.test(value)) ||\n (/^(?:animation|transition)-duration$/.test(prop) && times(value).some((ms) => ms > 0));\n if (animates) sawMotion(declaration.index);\n }\n\n if (CSS_FILES.has(extension)) {\n for (const match of stripped.matchAll(/@keyframes\\b/gi)) sawMotion(match.index ?? 0);\n }\n\n hits.sort((a, b) => a.line - b.line || a.column - b.column);\n return {\n hits,\n motion: {\n first: firstMotion === null ? null : positionOf(starts, firstMotion),\n handlesReducedMotion: REDUCED_MOTION.test(stripped),\n },\n };\n}\n","import { readdir, readFile, stat } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { checkText, RULES, type RuleSetting, type Severity } from \"./rules\";\r\n\r\nexport interface Finding {\r\n /** Path relative to the scan root, with forward slashes. */\r\n file: string;\r\n line: number;\r\n column: number;\r\n /** The text that matched, such as `#ff0000`. */\r\n match: string;\r\n}\r\n\r\nexport interface ScanOptions {\r\n /** Paths, relative to `cwd`, to skip. A prefix skips everything under it. */\r\n ignore?: string[];\r\n}\r\n\r\nconst SCANNED_EXTENSIONS = new Set([\r\n \".css\",\r\n \".scss\",\r\n \".sass\",\r\n \".less\",\r\n \".ts\",\r\n \".tsx\",\r\n \".js\",\r\n \".jsx\",\r\n \".mjs\",\r\n \".cjs\",\r\n \".html\",\r\n \".vue\",\r\n \".svelte\",\r\n \".mdx\",\r\n]);\r\n\r\nconst SKIPPED_DIRECTORIES = new Set([\r\n \"node_modules\",\r\n \"dist\",\r\n \"build\",\r\n \"out\",\r\n \"coverage\",\r\n \".git\",\r\n \".next\",\r\n \".turbo\",\r\n \".svelte-kit\",\r\n]);\r\n\r\nconst MAX_FILE_BYTES = 1_000_000;\r\n\r\n/**\r\n * 3, 4, 6 or 8 hex digits after a `#`. The lookbehind skips URL fragments such\r\n * as `page#abc`, HTML entities such as `&#123456;` and `href=\"#abc\"` anchors.\r\n */\r\nconst HEX_COLOR = /(?<![\\w&#/-])(?<!\\bhref=[\"'])#(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})(?![\\w-])/g;\r\n\r\n/** A line that contains this text is skipped, for a color that is meant to stay. */\r\nexport const IGNORE_MARKER = \"kit-ignore\";\r\n\r\nconst toPosix = (value: string) => value.split(path.sep).join(\"/\");\r\n\r\nfunction isIgnored(relativePath: string, ignore: string[]): boolean {\r\n return ignore.some((entry) => {\r\n const prefix = entry.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\");\r\n return prefix !== \"\" && (relativePath === prefix || relativePath.startsWith(`${prefix}/`));\r\n });\r\n}\r\n\r\n/** Finds hard-coded hex colors in one piece of text. */\r\nexport function findHexColors(text: string): Array<Omit<Finding, \"file\">> {\r\n const findings: Array<Omit<Finding, \"file\">> = [];\r\n const lines = text.split(/\\r?\\n/);\r\n\r\n lines.forEach((line, index) => {\r\n if (line.includes(IGNORE_MARKER)) return;\r\n for (const found of line.matchAll(HEX_COLOR)) {\r\n findings.push({ line: index + 1, column: (found.index ?? 0) + 1, match: found[0] });\r\n }\r\n });\r\n\r\n return findings;\r\n}\r\n\r\nasync function* walk(directory: string): AsyncGenerator<string> {\r\n const entries = await readdir(directory, { withFileTypes: true });\r\n entries.sort((a, b) => a.name.localeCompare(b.name));\r\n\r\n for (const entry of entries) {\r\n // Symlinks are skipped so a link back up the tree cannot loop forever.\r\n if (entry.isSymbolicLink()) continue;\r\n const full = path.join(directory, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n if (!SKIPPED_DIRECTORIES.has(entry.name)) yield* walk(full);\r\n } else if (entry.isFile()) {\r\n yield full;\r\n }\r\n }\r\n}\r\n\r\nfunction isScannable(file: string): boolean {\r\n const name = path.basename(file);\r\n if (name.includes(\".min.\") || name.endsWith(\".d.ts\")) return false;\r\n return SCANNED_EXTENSIONS.has(path.extname(name));\r\n}\r\n\r\n/**\r\n * The source files under the targets, once each, as `{ file, relative, text }`.\r\n * Paths that do not exist throw, so a typo in a path is not reported as a clean\r\n * result.\r\n */\r\nasync function* sourceFiles(\r\n cwd: string,\r\n targets: string[],\r\n ignore: string[],\r\n): AsyncGenerator<{ relative: string; text: string }> {\r\n const seen = new Set<string>();\r\n\r\n for (const target of targets) {\r\n const root = path.resolve(cwd, target);\r\n const info = await stat(root);\r\n const files = info.isDirectory() ? walk(root) : (async function* () { yield root; })();\r\n\r\n for await (const file of files) {\r\n if (seen.has(file)) continue;\r\n seen.add(file);\r\n\r\n const relative = toPosix(path.relative(cwd, file));\r\n if (isIgnored(relative, ignore) || !isScannable(file)) continue;\r\n\r\n const { size } = await stat(file);\r\n if (size > MAX_FILE_BYTES) continue;\r\n\r\n yield { relative, text: await readFile(file, \"utf8\") };\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Scans files and folders for hard-coded hex colors. Paths that do not exist\r\n * throw, so a typo in a path is not reported as a clean result.\r\n *\r\n * This is the original, colors-only scan. `scanProject` runs every rule.\r\n */\r\nexport async function scanForHardcodedColors(\r\n cwd: string,\r\n targets: string[] = [\".\"],\r\n { ignore = [] }: ScanOptions = {},\r\n): Promise<Finding[]> {\r\n const findings: Finding[] = [];\r\n for await (const { relative, text } of sourceFiles(cwd, targets, ignore)) {\r\n for (const finding of findHexColors(text)) findings.push({ file: relative, ...finding });\r\n }\r\n return findings;\r\n}\r\n\r\nexport interface RuleFinding extends Finding {\r\n /** The rule's id, such as `hardcoded-spacing`. */\r\n rule: string;\r\n severity: Severity;\r\n /** What to do about it. */\r\n message: string;\r\n}\r\n\r\nexport interface ProjectScanOptions extends ScanOptions {\r\n /** Per rule: `off`, `warn` or `error`. A rule not listed keeps its default. */\r\n rules?: Record<string, RuleSetting>;\r\n}\r\n\r\n/** The severity a rule reports at, or `null` when it is switched off. */\r\nfunction severityOf(rule: string, overrides: Record<string, RuleSetting>): Severity | null {\r\n const setting = overrides[rule] ?? RULES.find((item) => item.id === rule)?.severity ?? \"warn\";\r\n return setting === \"off\" ? null : setting;\r\n}\r\n\r\n/**\r\n * Checks files and folders against every `kit doctor` rule. Hard-coded hex\r\n * colors are an error unless the config says otherwise; the other rules warn.\r\n */\r\nexport async function scanProject(\r\n cwd: string,\r\n targets: string[] = [\".\"],\r\n { ignore = [], rules = {} }: ProjectScanOptions = {},\r\n): Promise<RuleFinding[]> {\r\n const findings: RuleFinding[] = [];\r\n const animated: Array<{ file: string; line: number; column: number }> = [];\r\n let handlesReducedMotion = false;\r\n\r\n const add = (finding: Omit<RuleFinding, \"severity\">) => {\r\n const severity = severityOf(finding.rule, rules);\r\n if (severity !== null) findings.push({ ...finding, severity });\r\n };\r\n\r\n for await (const { relative, text } of sourceFiles(cwd, targets, ignore)) {\r\n const found: Array<Omit<RuleFinding, \"severity\">> = [];\r\n\r\n for (const hex of findHexColors(text)) {\r\n found.push({ file: relative, ...hex, rule: \"hardcoded-color\", message: \"Use a --kit-color-* token.\" });\r\n }\r\n\r\n const { hits, motion } = checkText(text, relative, IGNORE_MARKER);\r\n for (const hit of hits) found.push({ file: relative, ...hit });\r\n\r\n found.sort((a, b) => a.line - b.line || a.column - b.column);\r\n for (const finding of found) add(finding);\r\n\r\n if (motion.first) animated.push({ file: relative, ...motion.first });\r\n if (motion.handlesReducedMotion) handlesReducedMotion = true;\r\n }\r\n\r\n const [first] = animated;\r\n if (first && !handlesReducedMotion) {\r\n const files = animated.length === 1 ? \"1 file animates\" : `${animated.length} files animate`;\r\n add({\r\n ...first,\r\n match: \"prefers-reduced-motion\",\r\n rule: \"missing-reduced-motion\",\r\n message: `${files}, and nothing scanned handles prefers-reduced-motion. Add a @media (prefers-reduced-motion: reduce) rule that drops movement.`,\r\n });\r\n }\r\n\r\n return findings;\r\n}\r\n","import { readFileSync } from \"node:fs\";\r\nimport { access, writeFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { parseArgs } from \"node:util\";\r\nimport { densityNames, themeNames } from \"@x12i/tokens\";\r\nimport { createDesignMd } from \"@x12i/tokens/design-md\";\r\nimport { CONFIG_FILE, createConfig, isDensityName, isThemeName, loadConfig, type KitConfig } from \"./config\";\r\nimport { scanProject, type RuleFinding } from \"./doctor\";\r\nimport { RULE_IDS, RULES } from \"./rules\";\r\n\r\nexport interface Io {\r\n cwd: string;\r\n out: (text: string) => void;\r\n err: (text: string) => void;\r\n}\r\n\r\n/** Exit codes: 0 success, 1 the command ran and found a problem, 2 bad usage. */\r\ntype ExitCode = 0 | 1 | 2;\r\n\r\nconst HELP = `kit: command line for the Unified UI Kit\r\n\r\nUsage\r\n kit <command> [options]\r\n\r\nCommands\r\n init [--theme <name>] [--density <name>] [--force]\r\n Write ${CONFIG_FILE} in the current folder.\r\n add <component...>\r\n Add a component to your project. Planned.\r\n theme [name]\r\n List the themes and densities. Generating a theme is planned.\r\n doctor [paths...] [--json] [--strict] [--list-rules]\r\n Check code against the kit's conventions: colors, sizes and motion that\r\n should be --kit- tokens, left and right properties that will not mirror,\r\n removed focus outlines, and more. Hex colors are errors and the rest are\r\n warnings. Exits with 1 on an error, or on any finding with --strict.\r\n Set a rule to off, warn or error in ${CONFIG_FILE} under doctor.rules.\r\n design [--theme <name>] [--out <file>] [--force]\r\n Write the kit's DESIGN.md, a description of the design system that coding\r\n agents read. Defaults to DESIGN.md. Use --out - to print it.\r\n\r\nOptions\r\n -h, --help Show this help.\r\n -v, --version Show the version.\r\n`;\r\n\r\nfunction readVersion(): string {\r\n const file = new URL(\"../package.json\", import.meta.url);\r\n return (JSON.parse(readFileSync(file, \"utf8\")) as { version: string }).version;\r\n}\r\n\r\nasync function exists(file: string): Promise<boolean> {\r\n try {\r\n await access(file);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nasync function init(values: { theme?: string; density?: string; force?: boolean }, io: Io): Promise<ExitCode> {\r\n if (values.theme !== undefined && !isThemeName(values.theme)) {\r\n io.err(`Unknown theme \"${values.theme}\". Choose one of: ${themeNames.join(\", \")}.\\n`);\r\n return 2;\r\n }\r\n if (values.density !== undefined && !isDensityName(values.density)) {\r\n io.err(`Unknown density \"${values.density}\". Choose one of: ${densityNames.join(\", \")}.\\n`);\r\n return 2;\r\n }\r\n\r\n const target = path.join(io.cwd, CONFIG_FILE);\r\n if (!values.force && (await exists(target))) {\r\n io.err(`${CONFIG_FILE} already exists. Use --force to replace it.\\n`);\r\n return 1;\r\n }\r\n\r\n const config = createConfig({ theme: values.theme, density: values.density });\r\n await writeFile(target, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\r\n io.out(`Created ${CONFIG_FILE}\\n`);\r\n return 0;\r\n}\r\n\r\nfunction add(components: string[], io: Io): ExitCode {\r\n const wanted = components.length > 0 ? ` (${components.join(\", \")})` : \"\";\r\n io.err(\r\n `kit add${wanted} is not available yet. The component registry is planned. ` +\r\n `Until then, import components from @x12i/ui.\\n`,\r\n );\r\n return 1;\r\n}\r\n\r\nfunction theme(name: string | undefined, io: Io): ExitCode {\r\n if (name === undefined) {\r\n io.out(`Themes: ${themeNames.join(\", \")}\\n`);\r\n io.out(`Densities: ${densityNames.join(\", \")}\\n`);\r\n return 0;\r\n }\r\n\r\n if (isThemeName(name)) {\r\n io.out(`\"${name}\" is built in. Import @x12i/themes/${name}.css, or set data-theme=\"${name}\" on <html>.\\n`);\r\n return 0;\r\n }\r\n\r\n io.err(\r\n `Generating a custom theme is planned and is not available yet. ` +\r\n `Built-in themes: ${themeNames.join(\", \")}.\\n`,\r\n );\r\n return 1;\r\n}\r\n\r\n/** Reads the config, or reports why it cannot. `undefined` means the command should stop. */\r\nasync function readConfig(io: Io): Promise<KitConfig | null | undefined> {\r\n try {\r\n return await loadConfig(io.cwd);\r\n } catch (error) {\r\n io.err(`${(error as Error).message}\\n`);\r\n return undefined;\r\n }\r\n}\r\n\r\nconst plural = (count: number, one: string, many: string) => `${count} ${count === 1 ? one : many}`;\r\n\r\nfunction listRules(io: Io): ExitCode {\r\n const width = Math.max(...RULES.map((rule) => rule.id.length));\r\n for (const rule of RULES) {\r\n io.out(`${rule.id.padEnd(width)} ${rule.severity.padEnd(5)} ${rule.description}\\n`);\r\n }\r\n return 0;\r\n}\r\n\r\nasync function doctor(\r\n paths: string[],\r\n options: { json: boolean; strict: boolean; listRules: boolean },\r\n io: Io,\r\n): Promise<ExitCode> {\r\n if (options.listRules) return listRules(io);\r\n\r\n const config = await readConfig(io);\r\n if (config === undefined) return 2;\r\n\r\n const unknown = Object.keys(config?.doctor.rules ?? {}).filter((id) => !RULE_IDS.has(id));\r\n if (unknown.length > 0) {\r\n io.err(\r\n `${CONFIG_FILE}: unknown doctor rule ${unknown.map((id) => `\"${id}\"`).join(\", \")}. ` +\r\n `Run \"kit doctor --list-rules\" for the rule names.\\n`,\r\n );\r\n return 2;\r\n }\r\n\r\n const targets = paths.length > 0 ? paths : [\".\"];\r\n\r\n let findings: RuleFinding[];\r\n try {\r\n findings = await scanProject(io.cwd, targets, {\r\n ignore: config?.doctor.ignore,\r\n rules: config?.doctor.rules,\r\n });\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n io.err(`Path not found: ${(error as NodeJS.ErrnoException).path ?? targets.join(\", \")}\\n`);\r\n return 2;\r\n }\r\n throw error;\r\n }\r\n\r\n const errors = findings.filter((finding) => finding.severity === \"error\").length;\r\n const failed = errors > 0 || (options.strict && findings.length > 0);\r\n\r\n if (options.json) {\r\n io.out(`${JSON.stringify(findings, null, 2)}\\n`);\r\n return failed ? 1 : 0;\r\n }\r\n\r\n if (findings.length === 0) {\r\n io.out(\"No problems found.\\n\");\r\n return 0;\r\n }\r\n\r\n for (const finding of findings) {\r\n io.out(\r\n `${finding.file}:${finding.line}:${finding.column} ${finding.match} ${finding.message} ` +\r\n `(${finding.severity} ${finding.rule})\\n`,\r\n );\r\n }\r\n const files = new Set(findings.map((finding) => finding.file)).size;\r\n io.out(\r\n `\\n${plural(errors, \"error\", \"errors\")} and ${plural(findings.length - errors, \"warning\", \"warnings\")} ` +\r\n `in ${plural(files, \"file\", \"files\")}.\\n`,\r\n );\r\n return failed ? 1 : 0;\r\n}\r\n\r\nasync function design(values: { theme?: string; out?: string; force?: boolean }, io: Io): Promise<ExitCode> {\r\n if (values.theme !== undefined && !isThemeName(values.theme)) {\r\n io.err(`Unknown theme \"${values.theme}\". Choose one of: ${themeNames.join(\", \")}.\\n`);\r\n return 2;\r\n }\r\n\r\n const config = await readConfig(io);\r\n if (config === undefined) return 2;\r\n\r\n const theme = values.theme !== undefined && isThemeName(values.theme) ? values.theme : (config?.theme ?? \"light\");\r\n const markdown = createDesignMd({ theme });\r\n\r\n const out = values.out ?? \"DESIGN.md\";\r\n if (out === \"-\") {\r\n io.out(markdown);\r\n return 0;\r\n }\r\n\r\n const target = path.resolve(io.cwd, out);\r\n if (!values.force && (await exists(target))) {\r\n io.err(`${out} already exists. Use --force to replace it, or --out to write somewhere else.\\n`);\r\n return 1;\r\n }\r\n\r\n try {\r\n await writeFile(target, markdown, \"utf8\");\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n io.err(`Cannot write ${out}: the folder does not exist.\\n`);\r\n return 2;\r\n }\r\n throw error;\r\n }\r\n io.out(`Created ${out} (${theme} theme)\\n`);\r\n return 0;\r\n}\r\n\r\n/** Runs the command line and returns the exit code. */\r\nexport async function run(argv: string[], io: Io): Promise<ExitCode> {\r\n let parsed;\r\n try {\r\n parsed = parseArgs({\r\n args: argv,\r\n allowPositionals: true,\r\n options: {\r\n help: { type: \"boolean\", short: \"h\" },\r\n version: { type: \"boolean\", short: \"v\" },\r\n force: { type: \"boolean\" },\r\n json: { type: \"boolean\" },\r\n strict: { type: \"boolean\" },\r\n \"list-rules\": { type: \"boolean\" },\r\n out: { type: \"string\" },\r\n theme: { type: \"string\" },\r\n density: { type: \"string\" },\r\n },\r\n });\r\n } catch (error) {\r\n io.err(`${(error as Error).message}\\n\\n${HELP}`);\r\n return 2;\r\n }\r\n\r\n const { values, positionals } = parsed;\r\n const [command, ...rest] = positionals;\r\n\r\n if (values.version) {\r\n io.out(`${readVersion()}\\n`);\r\n return 0;\r\n }\r\n if (values.help || command === undefined || command === \"help\") {\r\n io.out(HELP);\r\n return 0;\r\n }\r\n\r\n switch (command) {\r\n case \"init\":\r\n return init(values, io);\r\n case \"add\":\r\n return add(rest, io);\r\n case \"theme\":\r\n return theme(rest[0], io);\r\n case \"doctor\":\r\n return doctor(\r\n rest,\r\n { json: values.json ?? false, strict: values.strict ?? false, listRules: values[\"list-rules\"] ?? false },\r\n io,\r\n );\r\n case \"design\":\r\n return design(values, io);\r\n default:\r\n io.err(`Unknown command \"${command}\".\\n\\n${HELP}`);\r\n return 2;\r\n }\r\n}\r\n","#!/usr/bin/env node\r\nimport { run } from \"./main\";\r\n\r\nprocess.exitCode = await run(process.argv.slice(2), {\r\n cwd: process.cwd(),\r\n out: (text) => process.stdout.write(text),\r\n err: (text) => process.stderr.write(text),\r\n});\r\n"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,29 @@
1
1
  import { ThemeName, DensityName } from '@x12i/tokens';
2
2
 
3
+ /**
4
+ * The rules behind `kit doctor`.
5
+ *
6
+ * Each rule checks one habit that breaks a kit convention: values that should be
7
+ * `--kit-*` tokens, layout that will not mirror in right to left languages,
8
+ * motion that is slow, janky or ignores the reader's settings, and focus that
9
+ * has been switched off.
10
+ *
11
+ * The motion rules and the idea of a deterministic design linter come from two
12
+ * open source sets of design rules, read and rewritten here against the kit's own
13
+ * tokens: Impeccable's detector (Apache-2.0, https://github.com/pbakaus/impeccable)
14
+ * and Emil Kowalski's animation standards (MIT, https://github.com/emilkowalski/skills).
15
+ * See docs/design-sources-audit.md.
16
+ */
17
+ type Severity = "error" | "warn";
18
+ type RuleSetting = Severity | "off";
19
+ interface RuleInfo {
20
+ id: string;
21
+ /** What a rule reports as, unless `kit.config.json` says otherwise. */
22
+ severity: Severity;
23
+ description: string;
24
+ }
25
+ declare const RULES: readonly RuleInfo[];
26
+
3
27
  declare const CONFIG_FILE = "kit.config.json";
4
28
  declare const CONFIG_VERSION = 1;
5
29
  interface KitConfig {
@@ -10,6 +34,11 @@ interface KitConfig {
10
34
  doctor: {
11
35
  /** Paths, relative to the config file, that `kit doctor` skips. */
12
36
  ignore: string[];
37
+ /**
38
+ * Per rule: `off`, `warn` or `error`. Only what the file sets is here. `kit init`
39
+ * does not write it, so a new config stays as small as it was.
40
+ */
41
+ rules?: Record<string, RuleSetting>;
13
42
  };
14
43
  }
15
44
  declare function createConfig(options?: {
@@ -38,8 +67,26 @@ declare function findHexColors(text: string): Array<Omit<Finding, "file">>;
38
67
  /**
39
68
  * Scans files and folders for hard-coded hex colors. Paths that do not exist
40
69
  * throw, so a typo in a path is not reported as a clean result.
70
+ *
71
+ * This is the original, colors-only scan. `scanProject` runs every rule.
41
72
  */
42
73
  declare function scanForHardcodedColors(cwd: string, targets?: string[], { ignore }?: ScanOptions): Promise<Finding[]>;
74
+ interface RuleFinding extends Finding {
75
+ /** The rule's id, such as `hardcoded-spacing`. */
76
+ rule: string;
77
+ severity: Severity;
78
+ /** What to do about it. */
79
+ message: string;
80
+ }
81
+ interface ProjectScanOptions extends ScanOptions {
82
+ /** Per rule: `off`, `warn` or `error`. A rule not listed keeps its default. */
83
+ rules?: Record<string, RuleSetting>;
84
+ }
85
+ /**
86
+ * Checks files and folders against every `kit doctor` rule. Hard-coded hex
87
+ * colors are an error unless the config says otherwise; the other rules warn.
88
+ */
89
+ declare function scanProject(cwd: string, targets?: string[], { ignore, rules }?: ProjectScanOptions): Promise<RuleFinding[]>;
43
90
 
44
91
  interface Io {
45
92
  cwd: string;
@@ -51,5 +98,5 @@ type ExitCode = 0 | 1 | 2;
51
98
  /** Runs the command line and returns the exit code. */
52
99
  declare function run(argv: string[], io: Io): Promise<ExitCode>;
53
100
 
54
- export { CONFIG_FILE, CONFIG_VERSION, IGNORE_MARKER, createConfig, findHexColors, loadConfig, run, scanForHardcodedColors };
55
- export type { Finding, Io, KitConfig, ScanOptions };
101
+ export { CONFIG_FILE, CONFIG_VERSION, IGNORE_MARKER, RULES, createConfig, findHexColors, loadConfig, run, scanForHardcodedColors, scanProject };
102
+ export type { Finding, Io, KitConfig, ProjectScanOptions, RuleFinding, RuleInfo, RuleSetting, ScanOptions, Severity };