Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Convert Stitch-generated screens into validated React component systems with design token consistency
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/validate.js
1/**2* Copyright 2026 Google LLC3*4* Licensed under the Apache License, Version 2.0 (the "License");5* you may not use this file except in compliance with the License.6* You may obtain a copy of the License at7*8* http://www.apache.org/licenses/LICENSE-2.09*10* Unless required by applicable law or agreed to in writing, software11* distributed under the License is distributed on an "AS IS" BASIS,12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13* See the License for the specific language governing permissions and14* limitations under the License.15*/1617import swc from '@swc/core';18import fs from 'node:fs';19import path from 'node:path';2021const HEX_COLOR_REGEX = /#[0-9A-Fa-f]{6}/;2223async function validateComponent(filePath) {24const code = fs.readFileSync(filePath, 'utf-8');25const filename = path.basename(filePath);26try {27const ast = await swc.parse(code, { syntax: "typescript", tsx: true });28let hasInterface = false;29let tailwindIssues = [];3031console.log("๐ Scanning AST...");3233const walk = (node) => {34if (!node) return;35if (node.type === 'TsInterfaceDeclaration' && node.id.value.endsWith('Props')) hasInterface = true;36if (node.type === 'JSXAttribute' && node.name.name === 'className') {37if (node.value?.value && HEX_COLOR_REGEX.test(node.value.value)) tailwindIssues.push(node.value.value);38}39for (const key in node) { if (node[key] && typeof node[key] === 'object') walk(node[key]); }40};41walk(ast);4243console.log(`--- Validation for: ${filename} ---`);44if (hasInterface) {45console.log("โ Props declaration found.");46} else {47console.error("โ MISSING: Props interface (must end in 'Props').");48}4950if (tailwindIssues.length === 0) {51console.log("โ No hardcoded hex values found.");52} else {53console.error(`โ STYLE: Found ${tailwindIssues.length} hardcoded hex codes.`);54tailwindIssues.forEach(hex => console.error(` - ${hex}`));55}5657if (hasInterface && tailwindIssues.length === 0) {58console.log("\nโจ COMPONENT VALID.");59process.exit(0);60} else {61console.error("\n๐ซ VALIDATION FAILED.");62process.exit(1);63}64} catch (err) {65console.error("โ PARSE ERROR:", err.message);66process.exit(1);67}68}6970validateComponent(process.argv[2]);71