Skip to content

Commit a303f0c

Browse files
committed
Add a format check to CI
1 parent 3022a27 commit a303f0c

3 files changed

Lines changed: 116 additions & 0 deletions

File tree

.github/algorithm-format-check.mjs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { readFile, readdir } from "node:fs/promises";
2+
3+
const SPEC_DIR = new URL("../spec", import.meta.url).pathname;
4+
5+
process.exitCode = 0;
6+
const filenames = await readdir(SPEC_DIR);
7+
for (const filename of filenames) {
8+
if (!filename.endsWith(".md")) {
9+
continue;
10+
}
11+
const markdown = await readFile(`${SPEC_DIR}/${filename}`, "utf8");
12+
13+
/**
14+
* Not strictly 'lines' since we try and group indented things together as if
15+
* they were one line. Close enough though.
16+
*/
17+
const lines = markdown.split(/\n(?=[\S\n]|\s*(?:-|[0-9]+\.) )/);
18+
19+
for (let i = 0, l = lines.length; i < l; i++) {
20+
const line = lines[i];
21+
22+
// Check algorithm is consistently formatted
23+
{
24+
// Is it an algorithm definition?
25+
const matches = line.match(/^([a-z0-9A-Z]+)(\s*)\(([^)]*)\)(\s*):(\s*)$/);
26+
if (matches) {
27+
const [, algorithmName, ns1, _args, ns2, ns3] = matches;
28+
if (ns1 || ns2 || ns3) {
29+
console.log(
30+
`Bad whitespace in definition of ${algorithmName} in '${filename}':`
31+
);
32+
console.log(line);
33+
console.log();
34+
process.exitCode = 1;
35+
}
36+
if (lines[i + 1] !== "") {
37+
console.log(
38+
`No empty space after algorithm ${algorithmName} header in '${filename}'`
39+
);
40+
console.log();
41+
process.exitCode = 1;
42+
}
43+
for (let j = i + 2; j < l; j++) {
44+
const step = lines[j];
45+
if (!step.match(/^\s*(-|[0-9]+\.) /)) {
46+
if (step !== "") {
47+
console.log(
48+
`Bad algorithm ${algorithmName} step in '${filename}':`
49+
);
50+
console.log(step);
51+
console.log();
52+
process.exitCode = 1;
53+
}
54+
break;
55+
}
56+
if (!step.match(/[.:]$/)) {
57+
console.log(
58+
`Bad formatting for '${algorithmName}' step (does not end in '.' or ':') in '${filename}':`
59+
);
60+
console.log(step);
61+
console.log();
62+
process.exitCode = 1;
63+
}
64+
if (step.match(/^\s*(-|[0-9]\.)\s+[a-z]/)) {
65+
console.log(
66+
`Bad formatting of '${algorithmName}' step (should start with a capital) in '${filename}':`
67+
);
68+
console.log(step);
69+
console.log();
70+
process.exitCode = 1;
71+
}
72+
const trimmedInnerLine = step.replace(/\s+/g, " ");
73+
if (
74+
trimmedInnerLine.match(
75+
/(?:[rR]eturn|is (?:not )?)(true|false|null)\b/
76+
) &&
77+
!trimmedInnerLine.match(/null or empty/)
78+
) {
79+
console.log(
80+
`Potential bad formatting of '${algorithmName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':`
81+
);
82+
console.log(step);
83+
console.log();
84+
process.exitCode = 1;
85+
}
86+
}
87+
}
88+
}
89+
90+
// Check `- ...:` step is followed by an indent
91+
{
92+
const matches = line.match(/^(\s*)- .*:\s*$/);
93+
if (matches) {
94+
const indent = matches[1];
95+
const nextLine = lines[i + 1];
96+
if (!nextLine.startsWith(`${indent} `)) {
97+
console.log(
98+
`Lacking indent in '${filename}' following ':' character:`
99+
);
100+
console.dir(line);
101+
console.dir(nextLine);
102+
console.log();
103+
// TODO: process.exitCode = 1;
104+
}
105+
}
106+
}
107+
}
108+
}
109+
110+
if (process.exitCode === 0) {
111+
console.log(`Everything looks okay!`);
112+
} else {
113+
console.log(`Please resolve the errors detailed above.`);
114+
}

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
- uses: actions/setup-node@v3
2222
- run: npm ci
2323
- run: npm run test:format
24+
- run: npm run test:algorithm-format
2425
test-build:
2526
runs-on: ubuntu-latest
2627
steps:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"test:spelling": "cspell \"spec/**/*.md\" README.md",
1818
"format": "prettier --write \"**/*.{md,yml,yaml,json}\"",
1919
"test:format": "prettier --check \"**/*.{md,yml,yaml,json}\" || npm run suggest:format",
20+
"test:algorithm-format": "node .github/algorithm-format-check.mjs",
2021
"suggest:format": "echo \"\nTo resolve this, run: $(tput bold)npm run format$(tput sgr0)\" && exit 1",
2122
"build": "./build.sh",
2223
"test:build": "spec-md --metadata spec/metadata.json spec/GraphQL.md > /dev/null",

0 commit comments

Comments
 (0)