@techninja/clearstack 0.4.12 → 0.4.14

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/lib/check.js CHANGED
@@ -98,7 +98,8 @@ export async function check(projectDir, scope, opts) {
98
98
  return;
99
99
  }
100
100
  console.log('🔍 Clearstack compliance checking now... 💙\n');
101
- const results = await Promise.all(checks.map((c) => c.run(opts)));
101
+ const runnable = checks.filter((c) => !c.keyBinding);
102
+ const results = await Promise.all(runnable.map((c) => c.run(opts)));
102
103
  const passed = results.filter((r) => typeof r === 'boolean' ? r : r.pass).length;
103
104
  console.log(`\n${'='.repeat(40)}`);
104
105
  console.log(`${passed}/${results.length} checks passed.`);
package/lib/spec-scan.js CHANGED
@@ -37,20 +37,25 @@ export function countFiles(root, extensions, ignoreDirs) {
37
37
  return findFiles(root, extensions, ignoreDirs, root).length;
38
38
  }
39
39
 
40
+ /** @param {string} f @param {string | string[]} pat */
41
+ function matchesPat(f, pat) {
42
+ return Array.isArray(pat) ? pat.some((p) => f.includes(p) || f.endsWith(p)) : f.endsWith(pat);
43
+ }
44
+
40
45
  /**
41
46
  * @param {string} root
42
47
  * @param {string[]} extensions
43
48
  * @param {number} max
44
49
  * @param {string[]} ignoreDirs
45
50
  * @param {string} label
46
- * @param {{ exclude?: string, include?: string, localeMax?: number, quiet?: boolean }} [filter]
51
+ * @param {{ exclude?: string | string[], include?: string | string[], localeMax?: number, quiet?: boolean }} [filter]
47
52
  * @returns {CheckResult & { violations?: LineViolation[] }}
48
53
  */
49
54
  export function checkFileLines(root, extensions, max, ignoreDirs, label, filter) {
50
55
  const start = performance.now();
51
56
  let files = findFiles(root, extensions, ignoreDirs, root);
52
- if (filter?.exclude) files = files.filter((f) => !f.endsWith(filter.exclude));
53
- if (filter?.include) files = files.filter((f) => f.endsWith(filter.include));
57
+ if (filter?.exclude) files = files.filter((f) => !matchesPat(f, filter.exclude));
58
+ if (filter?.include) files = files.filter((f) => matchesPat(f, filter.include));
54
59
  const localeMax = filter?.localeMax || max * 5;
55
60
  const violations = [];
56
61
  for (const file of files) {
@@ -74,13 +79,15 @@ export function checkFileLines(root, extensions, max, ignoreDirs, label, filter)
74
79
  * @param {string} root
75
80
  * @param {string[]} ignoreDirs
76
81
  * @param {string} label
77
- * @param {{ quiet?: boolean }} [opts]
82
+ * @param {{ quiet?: boolean, ignore?: string[] }} [opts]
78
83
  * @returns {CheckResult & { violations?: ImportViolation[] }}
79
84
  */
80
85
  export function checkImports(root, ignoreDirs, label, opts) {
81
86
  const start = performance.now();
87
+ const extraIgnore = opts?.ignore ?? [];
82
88
  const files = findFiles(root, ['.js'], ignoreDirs, root)
83
- .filter((f) => f.startsWith('src/') && !f.includes('vendor/') && !f.includes('api/') && !f.endsWith('.test.js') && !f.endsWith('server.js'));
89
+ .filter((f) => f.startsWith('src/') && !f.includes('vendor/') && !f.includes('api/') && !f.endsWith('.test.js') && !f.endsWith('server.js'))
90
+ .filter((f) => !extraIgnore.some((p) => f.includes(p)));
84
91
  const violations = [];
85
92
  const importRe = /(?:^|\n)\s*import\s.*?from\s+['"](\.\.[^'"]*)['"]/g;
86
93
  for (const file of files) {
@@ -61,6 +61,15 @@ export const setOnCopyNote = (fn) => { _onCopyNote = fn; };
61
61
  let _onFix = () => {};
62
62
  export const setOnFix = (fn) => { _onFix = fn; };
63
63
 
64
+ /** @type {Array<{ key: string, label: string, fn: () => void }>} */
65
+ let _keyCommands = [];
66
+ export const setKeyCommands = (cmds) => {
67
+ _keyCommands = cmds;
68
+ for (const { key, fn } of cmds) screen.key([key], fn);
69
+ const extra = cmds.map(({ key, label }) => ` ${key} ${label}`).join(' ');
70
+ outer.setLabel(` {blue-fg}♥{/blue-fg} Clearstack Spec Watch q quit ↑↓ scroll c copy f fix${extra} `);
71
+ };
72
+
64
73
  screen.key(['C-c', 'q'], () => _quit());
65
74
  screen.key(['pageup', 'up'], () => { logBox.scroll(-1); screen.render(); });
66
75
  screen.key(['pagedown', 'down'], () => { logBox.scroll(1); screen.render(); });
package/lib/watch.js CHANGED
@@ -12,6 +12,7 @@ import { render, renderNote } from './watch-ui.js';
12
12
  import { spawnServer, detectServerCmd } from './server-proc.js';
13
13
  import { setupLifecycle } from './watch-lifecycle.js';
14
14
  import { runKeys, schedule, setupFix } from './watch-runner.js';
15
+ import { screen, outer } from './watch-widgets.js';
15
16
 
16
17
  /**
17
18
  *
@@ -45,6 +46,16 @@ export async function startWatch(projectDir) {
45
46
 
46
47
  const run = (keys) => runKeys(specRows, keys, ctx);
47
48
 
49
+ // Wire keyBinding checks — project checks can declare keyBinding: 'd' etc.
50
+ const keyBound = specRows.filter((r) => r.keyBinding);
51
+ if (keyBound.length) {
52
+ const extra = keyBound.map(({ keyBinding, name }) => ` ${keyBinding} ${name.replace(/\s*\(.*\)/, '')}`).join(' ');
53
+ outer.setLabel(` {blue-fg}\u2665{/blue-fg} Clearstack Spec Watch q quit \u2191\u2193 scroll c copy f fix${extra} `);
54
+ for (const row of keyBound) {
55
+ screen.key([row.keyBinding], () => run(new Set([row.key])));
56
+ }
57
+ }
58
+
48
59
  if (serverCmd) {
49
60
  const proc = spawnServer(serverCmd, projectDir, cfg.rawEnv, () => {
50
61
  serverRow.status = proc.status;
@@ -56,7 +67,7 @@ export async function startWatch(projectDir) {
56
67
  }
57
68
 
58
69
  render(rows, lastCheck.value, watchDirs, currentViolations.value);
59
- run(new Set(specRows.map((r) => r.key)));
70
+ run(new Set(specRows.filter((r) => !r.keyBinding).map((r) => r.key)));
60
71
 
61
72
  setupFix(specRows, cmds, ctx, pending, timers, run);
62
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techninja/clearstack",
3
- "version": "0.4.12",
3
+ "version": "0.4.14",
4
4
  "type": "module",
5
5
  "description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
6
6
  "bin": {