schmelczer-dev/scripts/check-no-em-dashes.mjs
2026-07-12 21:33:49 +01:00

76 lines
1.5 KiB
JavaScript

import { readFile, stat } from 'node:fs/promises';
import path from 'node:path';
import { walk } from './lib/walk.mjs';
const forbidden = String.fromCodePoint(0x2014);
const root = process.cwd();
const textExtensions = new Set([
'.astro',
'.css',
'.html',
'.js',
'.json',
'.md',
'.mjs',
'.ts',
'.txt',
'.webmanifest',
'.xml',
]);
const roots = [
'src',
'public',
'scripts',
'README.md',
'package.json',
'astro.config.mjs',
].map((entry) => path.resolve(root, entry));
async function exists(filePath) {
try {
await stat(filePath);
return true;
} catch {
return false;
}
}
function lineAndColumn(text, index) {
const before = text.slice(0, index);
const lines = before.split('\n');
return {
line: lines.length,
column: lines.at(-1).length + 1,
};
}
const files = [];
for (const entry of roots) {
if (!(await exists(entry))) continue;
files.push(...(await walk(entry)));
}
const textFiles = files.filter((file) => textExtensions.has(path.extname(file)));
const failures = [];
for (const file of textFiles) {
const text = await readFile(file, 'utf8');
let index = text.indexOf(forbidden);
while (index !== -1) {
const { line, column } = lineAndColumn(text, index);
failures.push(`${path.relative(root, file)}:${line}:${column}`);
index = text.indexOf(forbidden, index + forbidden.length);
}
}
if (failures.length > 0) {
console.error(`Em dashes are not allowed:\n${failures.join('\n')}`);
process.exit(1);
}
console.log('No em dashes found.');