95 lines
2 KiB
JavaScript
95 lines
2 KiB
JavaScript
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
|
|
const forbidden = String.fromCodePoint(0x2014);
|
|
const root = process.cwd();
|
|
|
|
const textExtensions = new Set([
|
|
'.astro',
|
|
'.css',
|
|
'.html',
|
|
'.js',
|
|
'.json',
|
|
'.md',
|
|
'.mjs',
|
|
'.ts',
|
|
'.txt',
|
|
'.vtt',
|
|
'.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;
|
|
}
|
|
}
|
|
|
|
async function walk(entryPath) {
|
|
const entryStat = await stat(entryPath);
|
|
if (entryStat.isFile()) return [entryPath];
|
|
|
|
const entries = await readdir(entryPath, { withFileTypes: true });
|
|
const files = [];
|
|
|
|
for (const entry of entries) {
|
|
const fullPath = path.join(entryPath, entry.name);
|
|
if (entry.isDirectory()) {
|
|
files.push(...(await walk(fullPath)));
|
|
} else if (entry.isFile()) {
|
|
files.push(fullPath);
|
|
}
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
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.');
|