#!/usr/bin/env node import { readdirSync, readFileSync, statSync } from 'node:fs' import { join, relative } from 'node:path' const appRoot = join(process.cwd(), 'src', 'app') const textLikePatterns = [ /
sum + (source.match(pattern) ?? []).length, 0) } function routeFromPage(filePath) { return relative(appRoot, filePath) .replace(/\/page\.tsx$/, '') .replace(/\[locale\]/, ':locale') } const pages = collectPages(appRoot) .map(filePath => { const source = readFileSync(filePath, 'utf8') const lineCount = source.split('\n').length const textSignals = countMatches(source, textLikePatterns) const controls = countMatches(source, controlPatterns) const layoutSignals = countMatches(source, layoutPatterns) const textWallSignals = countMatches(source, textWallPatterns) const manualSignals = countMatches(source, manualTerms) const fixedTaxonomySignals = countMatches(source, fixedTaxonomyPatterns) const nestedCardSignals = (source.match(/rounded-(?:md|lg|xl)[^`'"]*border/g) ?? []).length const score = Math.round( (textSignals * 1.2) + (textWallSignals * 8) + (manualSignals * 4) + (fixedTaxonomySignals * 10) + (nestedCardSignals * 0.7) - (controls * 1.5) - (layoutSignals * 0.4), ) return { route: routeFromPage(filePath), file: relative(process.cwd(), filePath), lines: lineCount, score, textSignals, controls, layoutSignals, textWallSignals, manualSignals, fixedTaxonomySignals, nestedCardSignals, } }) .sort((a, b) => b.score - a.score) console.log('AWOOOI_UI_DENSITY_AUDIT') console.table( pages.slice(0, 20).map(page => ({ route: page.route, score: page.score, lines: page.lines, text: page.textSignals, controls: page.controls, manual: page.manualSignals, fixedTaxonomy: page.fixedTaxonomySignals, })), ) console.log(JSON.stringify({ page_count: pages.length, top_routes: pages.slice(0, 20), }, null, 2))