hlmnhkl-ui 0.20.0 → 0.20.2
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/README.md +2 -0
- package/package.json +1 -1
- package/scripts/add.js +36 -0
package/README.md
CHANGED
|
@@ -50,6 +50,8 @@ Using Next.js or React Router? The [installation guide](https://ui.hlmnhkl.my/in
|
|
|
50
50
|
|
|
51
51
|
Every copied file starts with one line naming hlmnhkl/ui and the MIT licence, so the licence notice travels with the code. `diff` and `update` ignore that line.
|
|
52
52
|
|
|
53
|
+
`add`, `diff` and `update` never change your `tokens.css`. If the latest one has tokens yours lacks, they list them after the result, with the lines to copy.
|
|
54
|
+
|
|
53
55
|
**With an AI assistant:** point it at [llms.txt](https://ui.hlmnhkl.my/llms.txt) (every component and the rules) or [llms-full.txt](https://ui.hlmnhkl.my/llms-full.txt) (props, keyboard notes and an example for each free component). There is also a [registry.json](https://ui.hlmnhkl.my/registry.json).
|
|
54
56
|
|
|
55
57
|
## What you get
|
package/package.json
CHANGED
package/scripts/add.js
CHANGED
|
@@ -464,9 +464,45 @@ async function runUpdate(opts) {
|
|
|
464
464
|
console.log(`Updated ${plural(todo.length, 'file')}.`)
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
+
const tokenNames = (text) => new Set([...text.replace(/\/\*[\s\S]*?\*\//g, '').matchAll(/(--[\w-]+)\s*:/g)].map((m) => m[1]))
|
|
468
|
+
|
|
469
|
+
// tokens.css is never replaced, so a new component can read a token the project's copy does not have yet.
|
|
470
|
+
function warnMissingTokens(opts) {
|
|
471
|
+
const mine = join(targetFolder(opts).to, 'tokens.css')
|
|
472
|
+
if (!isFile(mine)) return
|
|
473
|
+
const latest = join(SRC, 'tokens.css')
|
|
474
|
+
const text = readFileSync(latest, 'utf8')
|
|
475
|
+
const have = tokenNames(readFileSync(mine, 'utf8'))
|
|
476
|
+
const missing = [...tokenNames(text)].filter((name) => !have.has(name))
|
|
477
|
+
if (!missing.length) return
|
|
478
|
+
console.log(`\nYour tokens.css is missing ${plural(missing.length, 'token')} that the latest components use: ${missing.join(', ')}`)
|
|
479
|
+
console.log(`Your file was not changed. Copy these lines from the latest tokens.css into ${shown(CWD, mine)}, each into the same block:`)
|
|
480
|
+
// A token can be set in more than one block (dark theme, reduced motion), so every line is listed under its block.
|
|
481
|
+
const blocks = new Map()
|
|
482
|
+
const stack = []
|
|
483
|
+
let selector = ''
|
|
484
|
+
for (const line of text.split('\n').map((l) => l.trim())) {
|
|
485
|
+
if (line.endsWith('{')) {
|
|
486
|
+
stack.push(`${selector}${line.slice(0, -1)}`.trim())
|
|
487
|
+
selector = ''
|
|
488
|
+
} else if (line.startsWith('}')) stack.pop()
|
|
489
|
+
else if (line.endsWith(',') && !line.includes(': ')) selector += `${line} `
|
|
490
|
+
else if (missing.some((name) => line.startsWith(`${name}:`))) {
|
|
491
|
+
const where = stack.join(' / ')
|
|
492
|
+
blocks.set(where, [...(blocks.get(where) ?? []), line])
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const [where, found] of blocks) {
|
|
496
|
+
console.log(` In ${where}:`)
|
|
497
|
+
for (const line of found) console.log(` ${line}`)
|
|
498
|
+
}
|
|
499
|
+
console.log(`The latest file is at ${latest}`)
|
|
500
|
+
}
|
|
501
|
+
|
|
467
502
|
const opts = parseArgs(process.argv.slice(2))
|
|
468
503
|
if (opts.command === 'init') runInit(opts)
|
|
469
504
|
else if (opts.command === 'list') runList(opts)
|
|
470
505
|
else if (opts.command === 'diff') runDiff(opts)
|
|
471
506
|
else if (opts.command === 'update') await runUpdate(opts)
|
|
472
507
|
else runAdd(opts)
|
|
508
|
+
if (['add', 'diff', 'update'].includes(opts.command)) warnMissingTokens(opts)
|