mirror of
https://github.com/anthropics/claude-code.git
synced 2026-01-30 04:02:03 +00:00
Remove TypeScript check script, keep only GritQL plugin
The simpler GritQL approach is sufficient for catching direct <Box> inside <Text> nesting mistakes.
This commit is contained in:
@@ -1,136 +0,0 @@
|
||||
#!/usr/bin/env npx tsx
|
||||
/**
|
||||
* Build-time check: Ensure <Box> is never nested inside <Text>
|
||||
*
|
||||
* This catches the Ink error: "<Box> can't be nested inside <Text> component"
|
||||
*
|
||||
* Usage:
|
||||
* npx tsx scripts/check-box-in-text.ts [directory]
|
||||
* # or add to package.json scripts:
|
||||
* # "lint:ink": "tsx scripts/check-box-in-text.ts src"
|
||||
*/
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import { parse } from "@babel/parser";
|
||||
import traverse from "@babel/traverse";
|
||||
import type { NodePath } from "@babel/traverse";
|
||||
import type { JSXElement, JSXOpeningElement } from "@babel/types";
|
||||
|
||||
interface Violation {
|
||||
file: string;
|
||||
line: number;
|
||||
column: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
function getElementName(openingElement: JSXOpeningElement): string | null {
|
||||
if (openingElement.name.type === "JSXIdentifier") {
|
||||
return openingElement.name.name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isInsideTextElement(path: NodePath<JSXElement>): boolean {
|
||||
let parent = path.parentPath;
|
||||
while (parent) {
|
||||
if (
|
||||
parent.isJSXElement() &&
|
||||
parent.node.openingElement.name.type === "JSXIdentifier" &&
|
||||
parent.node.openingElement.name.name === "Text"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.parentPath;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkFile(filePath: string): Violation[] {
|
||||
const violations: Violation[] = [];
|
||||
const code = fs.readFileSync(filePath, "utf-8");
|
||||
|
||||
let ast;
|
||||
try {
|
||||
ast = parse(code, {
|
||||
sourceType: "module",
|
||||
plugins: ["jsx", "typescript"],
|
||||
});
|
||||
} catch {
|
||||
// Skip files that can't be parsed
|
||||
return violations;
|
||||
}
|
||||
|
||||
traverse(ast, {
|
||||
JSXElement(path) {
|
||||
const elementName = getElementName(path.node.openingElement);
|
||||
|
||||
if (elementName === "Box" && isInsideTextElement(path)) {
|
||||
const loc = path.node.loc;
|
||||
violations.push({
|
||||
file: filePath,
|
||||
line: loc?.start.line ?? 0,
|
||||
column: loc?.start.column ?? 0,
|
||||
message: "<Box> can't be nested inside <Text> component",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return violations;
|
||||
}
|
||||
|
||||
function findTsxFiles(dir: string): string[] {
|
||||
const files: string[] = [];
|
||||
|
||||
function walk(currentDir: string) {
|
||||
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentDir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
// Skip node_modules and hidden directories
|
||||
if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
|
||||
walk(fullPath);
|
||||
}
|
||||
} else if (entry.isFile() && /\.(tsx|jsx)$/.test(entry.name)) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir);
|
||||
return files;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const targetDir = process.argv[2] || "src";
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
console.error(`Directory not found: ${targetDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Checking for <Box> inside <Text> violations in ${targetDir}...`);
|
||||
|
||||
const files = findTsxFiles(targetDir);
|
||||
const allViolations: Violation[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const violations = checkFile(file);
|
||||
allViolations.push(...violations);
|
||||
}
|
||||
|
||||
if (allViolations.length > 0) {
|
||||
console.error(`\nFound ${allViolations.length} violation(s):\n`);
|
||||
for (const v of allViolations) {
|
||||
console.error(` ${v.file}:${v.line}:${v.column}`);
|
||||
console.error(` ${v.message}\n`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Checked ${files.length} files - no violations found.`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user