Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
42 lines
2.0 KiB
JavaScript
42 lines
2.0 KiB
JavaScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import ts from '../../web/node_modules/typescript/lib/typescript.js';
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
const file = 'web/app/src/app/App.tsx';
|
|
const labels = process.argv.slice(2);
|
|
if (!labels.length || labels.length > 8 || labels.some(label => label.length > 100)) {
|
|
throw new Error('Provide one to eight exact workflow aria-labels');
|
|
}
|
|
const tree = ts.createSourceFile(file, fs.readFileSync(path.join(root, file), 'utf8'),
|
|
ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
const results = [];
|
|
function inspect(node) {
|
|
if (ts.isJsxElement(node)) {
|
|
const attribute = node.openingElement.attributes.properties.find(item => ts.isJsxAttribute(item)
|
|
&& item.name.text === 'aria-label' && item.initializer && ts.isStringLiteral(item.initializer)
|
|
&& labels.includes(item.initializer.text));
|
|
if (attribute) {
|
|
const record = { workflow: attribute.initializer.text, file,
|
|
line: tree.getLineAndCharacterOfPosition(node.getStart(tree)).line + 1, controls: [], buttons: [] };
|
|
function visit(child) {
|
|
if (ts.isJsxAttribute(child) && ['aria-label', 'data-testid'].includes(child.name.text)
|
|
&& child.initializer && ts.isStringLiteral(child.initializer)) {
|
|
record.controls.push({ attribute: child.name.text, value: child.initializer.text });
|
|
}
|
|
if (ts.isJsxElement(child) && ts.isIdentifier(child.openingElement.tagName)
|
|
&& child.openingElement.tagName.text === 'button') {
|
|
record.buttons.push(child.children.filter(ts.isJsxText).map(text => text.text.trim()).filter(Boolean).join(' '));
|
|
}
|
|
ts.forEachChild(child, visit);
|
|
}
|
|
visit(node);
|
|
results.push(record);
|
|
}
|
|
}
|
|
ts.forEachChild(node, inspect);
|
|
}
|
|
inspect(tree);
|
|
console.log(JSON.stringify({ results, missing: labels.filter(label => !results.some(result => result.workflow === label)) }));
|