Files
thermcool/audit_headings.js
T

110 lines
3.3 KiB
JavaScript

const fs = require('fs');
const path = require('path');
function walkDir(dir, callback) {
if (!fs.existsSync(dir)) return;
fs.readdirSync(dir).forEach(f => {
const dirPath = path.join(dir, f);
const isDirectory = fs.statSync(dirPath).isDirectory();
if (isDirectory) {
walkDir(dirPath, callback);
} else if (dirPath.endsWith('.tsx')) {
callback(dirPath);
}
});
}
const appFiles = [];
const componentsFiles = [];
walkDir('app', f => appFiles.push(f));
walkDir('components', f => componentsFiles.push(f));
const allFiles = [...appFiles, ...componentsFiles];
const results = {};
allFiles.forEach(file => {
const content = fs.readFileSync(file, 'utf8');
const lines = content.split('\n');
const headings = [];
lines.forEach((line, index) => {
const regex = /<h([1-6])[\s>]/g;
let match;
while ((match = regex.exec(line)) !== null) {
headings.push({ level: parseInt(match[1]), line: index + 1, content: line.trim() });
}
});
if (headings.length > 0 || file.endsWith('page.tsx')) {
results[file] = headings;
}
});
// Analysis
console.log("=== HEADINGS AUDIT ===");
// 1. Pages with >1 H1
console.log("\n1. Strony z więcej niż jednym <h1>:");
let foundMultipleH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.includes('page.tsx')) {
const h1s = headings.filter(h => h.level === 1);
if (h1s.length > 1) {
console.log(`- ${file} (Liczba <h1>: ${h1s.length})`);
foundMultipleH1 = true;
}
}
}
if (!foundMultipleH1) console.log("Brak.");
// 2. Pages with 0 H1
console.log("\n2. Strony (page.tsx) bez <h1>:");
let foundZeroH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.includes('page.tsx') && !file.includes('api/')) { // ignoring api if any
const h1s = headings.filter(h => h.level === 1);
if (h1s.length === 0) {
console.log(`- ${file}`);
foundZeroH1 = true;
}
}
}
if (!foundZeroH1) console.log("Brak.");
// 3. Components rendering H1
console.log("\n3. Komponenty współdzielone (w components/) z <h1>:");
let foundComponentH1 = false;
for (const [file, headings] of Object.entries(results)) {
if (file.startsWith('components/')) {
const h1s = headings.filter(h => h.level === 1);
if (h1s.length > 0) {
console.log(`- ${file} (${h1s.length} wystąpień <h1>)`);
foundComponentH1 = true;
}
}
}
if (!foundComponentH1) console.log("Brak.");
// 4. Heading Skips
console.log("\n4. Skoki poziomów nagłówków w plikach:");
let foundSkips = false;
for (const [file, headings] of Object.entries(results)) {
if (headings.length === 0) continue;
let currentLevel = null;
for (const h of headings) {
if (currentLevel !== null) {
// A skip happens if the new level is strictly greater than currentLevel + 1
if (h.level > currentLevel + 1) {
console.log(`- ${file}: Skok z <h${currentLevel}> na <h${h.level}> w linii ${h.line}`);
foundSkips = true;
}
}
currentLevel = h.level;
}
}
if (!foundSkips) console.log("Brak oczywistych skoków.");