Skip to content

Commit 7810d18

Browse files
michaelficarraljharb
authored andcommitted
Meta: add spellchecking (#3335)
1 parent f2b2d52 commit 7810d18

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

.github/workflows/spellcheck.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: 'ecma-262'
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
spellcheck:
7+
name: 'check for newly-introduced spelling errors'
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- run: sudo apt-get install aspell
12+
- uses: actions/checkout@v3
13+
with:
14+
# Number of commits to fetch. 0 indicates all history for all branches and tags.
15+
# Default: 1
16+
fetch-depth: 0
17+
- uses: ljharb/actions/node/install@d9f477827ed71a259056764107f74afc29febcae
18+
name: 'nvm install lts/* && npm ci'
19+
with:
20+
node-version: lts/*
21+
use-npm-ci: true
22+
- run: node scripts/spellcheck.mjs origin/"${GITHUB_BASE_REF}"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ node_modules/
22
out/
33
vendor/esmeta
44
test*.js
5+
aspell.txt
56

67
# lockfiles we don't use are ignored
78
npm-shrinkwrap.json

scripts/spellcheck.mjs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { promisify } from 'node:util';
2+
import { exec } from 'node:child_process';
3+
const execP = promisify(exec);
4+
import { writeFile } from 'node:fs/promises';
5+
6+
const MIN_WORD_SIZE = 3;
7+
8+
const BASE_REF = process.argv[2];
9+
const ASPELL_OPTS = [
10+
'--add-html-check=alt,title,caption,variants',
11+
'--ignore-case',
12+
'--master=en_GB-ize',
13+
'--mode=html',
14+
'--run-together',
15+
'--run-together-limit=99',
16+
'--run-together-min=2',
17+
'list',
18+
].join(' ');
19+
20+
function makeDict(words) {
21+
return `personal_ws-1.1 en ${words.length}\n${words.join('\n')}`;
22+
}
23+
24+
function lines(text) {
25+
if (text.length === 0) return [];
26+
return text.split('\n');
27+
}
28+
29+
console.log(`base ref: ${BASE_REF}`);
30+
31+
let { stdout } = await execP(`git show "${BASE_REF}":spec.html | aspell ${ASPELL_OPTS} | sort -fu`);
32+
33+
let existingWords = lines(stdout.trim());
34+
35+
let existingComponents = Array.from(new Set(
36+
existingWords
37+
.flatMap(word => [...word.matchAll(/(?:^[a-z]|[A-Z])[a-z]{2,}/g)])
38+
.map(([w]) => w.toLowerCase())
39+
));
40+
41+
({ stdout } = await execP(`echo ${existingComponents.map(w => JSON.stringify(w)).join(' ')} | aspell ${ASPELL_OPTS} | sort -fu`));
42+
43+
let existingComponentsReduced = lines(stdout.trim());
44+
45+
await writeFile('aspell.txt', makeDict(existingComponentsReduced));
46+
47+
({ stdout } = await execP(`echo ${existingWords.map(w => JSON.stringify(w)).join(' ')} | aspell --personal=./aspell.txt ${ASPELL_OPTS}`));
48+
49+
let novel = [...existingComponentsReduced, ...lines(stdout.trim())].filter(w => w.length >= MIN_WORD_SIZE);
50+
novel.sort();
51+
console.log(`\npreviously used novel words: ${novel.join(', ')}`);
52+
await writeFile('aspell.txt', makeDict(novel));
53+
54+
({ stdout } = await execP(`aspell --personal=./aspell.txt ${ASPELL_OPTS} list <spec.html | sort -u`));
55+
let misspellings = lines(stdout.trim()).filter(w => w.length >= MIN_WORD_SIZE);
56+
57+
if (misspellings.length > 0) {
58+
console.log(`\nmisspellings: ${misspellings.join(', ')}`);
59+
let pattern = misspellings.map(w => `-e ${JSON.stringify(w)}`).join(' --or ');
60+
({ stdout } = await execP(`git grep --line-number --column --fixed-strings --only-matching ${pattern} -- spec.html`));
61+
62+
console.log('');
63+
64+
let info = lines(stdout.trim());
65+
for (let warning of info) {
66+
let [match, file, line, col, typo] = warning.match(/^([^:]+):(\d+):(\d+):(.*)$/);
67+
let title = 'Potential Typo';
68+
let message = `${JSON.stringify(typo)} is not a previously used word or composed of previously used words. Perhaps it is a typo?`;
69+
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message
70+
console.log(`::warning file=${file},line=${line},endLine=${line},col=${col},endColumn=${col + typo.length},title=${title}::${message}`);
71+
}
72+
}

0 commit comments

Comments
 (0)