Skip to content

Commit 0ab923d

Browse files
authored
Merge branch 'main' into patch-2
2 parents 6e3d2d3 + 96271da commit 0ab923d

26 files changed

+3216
-2314
lines changed

.github/algorithm-format-check.mjs

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
import { readFile, readdir } from "node:fs/promises";
2+
3+
const SPEC_DIR = new URL("../spec", import.meta.url).pathname;
4+
5+
/** @see {@link https://spec-md.com/#sec-Value-Literals} */
6+
const valueLiteralsRegexp = /\{((?:[^{}]|(?:\{[^{}]*\}))+)\}/g;
7+
8+
process.exitCode = 0;
9+
const filenames = await readdir(SPEC_DIR);
10+
for (const filename of filenames) {
11+
if (!filename.endsWith(".md")) {
12+
continue;
13+
}
14+
const markdown = await readFile(`${SPEC_DIR}/${filename}`, "utf8");
15+
16+
/**
17+
* Not strictly 'lines' since we try and group indented things together as if
18+
* they were one line. Close enough though.
19+
*/
20+
const lines = markdown.split(/\n(?=[\S\n]|\s*(?:-|[0-9]+\.) )/);
21+
22+
for (let i = 0, l = lines.length; i < l; i++) {
23+
const line = lines[i];
24+
25+
// Check algorithm is consistently formatted
26+
{
27+
// Is it an algorithm definition?
28+
const matches = line.match(/^([a-z0-9A-Z]+)(\s*)\(([^)]*)\)(\s*):(\s*)$/);
29+
const grammarMatches =
30+
filename === "Section 2 -- Language.md" &&
31+
line.match(/^([A-Za-z0-9]+) ::?\s+((\S).*)$/);
32+
if (matches) {
33+
const [, algorithmName, ns1, _args, ns2, ns3] = matches;
34+
if (ns1 || ns2 || ns3) {
35+
console.log(
36+
`Bad whitespace in definition of ${algorithmName} in '${filename}':`
37+
);
38+
console.dir(line);
39+
console.log();
40+
process.exitCode = 1;
41+
}
42+
if (lines[i + 1] !== "") {
43+
console.log(
44+
`No empty space after algorithm ${algorithmName} header in '${filename}'`
45+
);
46+
console.log();
47+
process.exitCode = 1;
48+
}
49+
for (let j = i + 2; j < l; j++) {
50+
const step = lines[j];
51+
if (!step.match(/^\s*(-|[0-9]+\.) /)) {
52+
if (step !== "") {
53+
console.log(
54+
`Bad algorithm ${algorithmName} step in '${filename}':`
55+
);
56+
console.dir(step);
57+
console.log();
58+
process.exitCode = 1;
59+
}
60+
break;
61+
}
62+
if (!step.match(/[.:]$/)) {
63+
console.log(
64+
`Bad formatting for '${algorithmName}' step (does not end in '.' or ':') in '${filename}':`
65+
);
66+
console.dir(step);
67+
console.log();
68+
process.exitCode = 1;
69+
}
70+
if (step.match(/^\s*(-|[0-9]+\.)\s+[a-z]/)) {
71+
console.log(
72+
`Bad formatting of '${algorithmName}' step (should start with a capital) in '${filename}':`
73+
);
74+
console.dir(step);
75+
console.log();
76+
process.exitCode = 1;
77+
}
78+
const assertMatch = step.match(/^\s*(-|[0-9]+\.)\s*Assert([^:])/);
79+
if (assertMatch) {
80+
console.log(
81+
`Bad formatting of '${algorithmName}' step (Assert should be immediately followed by ':'; found '${assertMatch[2]}') in '${filename}':`
82+
);
83+
console.dir(step);
84+
console.log();
85+
process.exitCode = 1;
86+
}
87+
88+
const stepWithoutValueLiterals = step.replace(
89+
valueLiteralsRegexp,
90+
""
91+
);
92+
if (stepWithoutValueLiterals.match(/\b[A-Z][A-Za-z0-9]+\(/)) {
93+
console.log(
94+
`Bad formatting of '${algorithmName}' step (algorithm call should be wrapped in braces: \`{MyAlgorithm(a, b, c)}\`) in '${filename}':`
95+
);
96+
console.dir(step);
97+
console.log();
98+
process.exitCode = 1;
99+
}
100+
101+
const valueLiterals = step.matchAll(valueLiteralsRegexp, "");
102+
for (const lit of valueLiterals) {
103+
const inner = lit[1];
104+
if (inner.includes("{")) {
105+
console.log(
106+
`Bad formatting of '${algorithmName}' step (algorithm call should not contain braces: \`${lit}\`) in '${filename}':`
107+
);
108+
console.dir(step);
109+
console.log();
110+
process.exitCode = 1;
111+
}
112+
}
113+
114+
const trimmedInnerLine = step.replace(/\s+/g, " ");
115+
if (
116+
trimmedInnerLine.match(
117+
/(?:[rR]eturn|is (?:not )?)(true|false|null)\b/
118+
) &&
119+
!trimmedInnerLine.match(/null or empty/)
120+
) {
121+
console.log(
122+
`Potential bad formatting of '${algorithmName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':`
123+
);
124+
console.dir(step);
125+
console.log();
126+
process.exitCode = 1;
127+
}
128+
}
129+
} else if (grammarMatches) {
130+
// This is super loosey-goosey
131+
const [, grammarName, rest] = grammarMatches;
132+
if (rest.trim() === "one of") {
133+
// Still grammar, not algorithm
134+
continue;
135+
}
136+
if (rest.trim() === "" && lines[i + 1] !== "") {
137+
console.log(
138+
`No empty space after grammar ${grammarName} header in '${filename}'`
139+
);
140+
console.log();
141+
process.exitCode = 1;
142+
}
143+
while (lines[i + 1].trim() !== "") {
144+
// Continuation of definition
145+
i++;
146+
}
147+
if (!lines[i + 2].startsWith("- ")) {
148+
// Not an algorithm; probably more grammar
149+
continue;
150+
}
151+
for (let j = i + 2; j < l; j++) {
152+
const step = lines[j];
153+
if (!step.match(/^\s*(-|[0-9]+\.) /)) {
154+
if (step !== "") {
155+
console.log(`Bad grammar ${grammarName} step in '${filename}':`);
156+
console.dir(step);
157+
console.log();
158+
process.exitCode = 1;
159+
}
160+
break;
161+
}
162+
if (!step.match(/[.:]$/)) {
163+
console.log(
164+
`Bad formatting for '${grammarName}' step (does not end in '.' or ':') in '${filename}':`
165+
);
166+
console.dir(step);
167+
console.log();
168+
process.exitCode = 1;
169+
}
170+
if (step.match(/^\s*(-|[0-9]\.)\s+[a-z]/)) {
171+
console.log(
172+
`Bad formatting of '${grammarName}' step (should start with a capital) in '${filename}':`
173+
);
174+
console.dir(step);
175+
console.log();
176+
process.exitCode = 1;
177+
}
178+
const trimmedInnerLine = step.replace(/\s+/g, " ");
179+
if (
180+
trimmedInnerLine.match(
181+
/(?:[rR]eturn|is (?:not )?)(true|false|null)\b/
182+
) &&
183+
!trimmedInnerLine.match(/null or empty/)
184+
) {
185+
console.log(
186+
`Potential bad formatting of '${grammarName}' step (true/false/null should be wrapped in curly braces, e.g. '{true}') in '${filename}':`
187+
);
188+
console.dir(step);
189+
console.log();
190+
process.exitCode = 1;
191+
}
192+
const assertMatch = step.match(/^\s*(-|[0-9]+\.)\s*Assert([^:])/);
193+
if (assertMatch) {
194+
console.log(
195+
`Bad formatting of '${grammarName}' step (Assert should be immediately followed by ':'; found '${assertMatch[2]}') in '${filename}':`
196+
);
197+
console.dir(step);
198+
console.log();
199+
process.exitCode = 1;
200+
}
201+
}
202+
}
203+
}
204+
205+
// Check `- ...:` step is followed by an indent
206+
{
207+
const matches = line.match(/^(\s*)- .*:\s*$/);
208+
if (matches) {
209+
const indent = matches[1];
210+
const nextLine = lines[i + 1];
211+
if (!nextLine.startsWith(`${indent} `)) {
212+
console.log(
213+
`Lacking indent in '${filename}' following ':' character:`
214+
);
215+
console.dir(line);
216+
console.dir(nextLine);
217+
console.log();
218+
// TODO: process.exitCode = 1;
219+
}
220+
}
221+
}
222+
}
223+
}
224+
225+
if (process.exitCode === 0) {
226+
console.log(`Everything looks okay!`);
227+
} else {
228+
console.log(`Please resolve the errors detailed above.`);
229+
}

.github/workflows/ci.yml

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,46 @@
11
name: CI
2+
23
on:
34
push:
45
branches:
56
- main
67
pull_request:
7-
branches:
8-
- main
8+
99
jobs:
10-
test:
10+
test-spelling:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v2
14-
- uses: actions/setup-node@v1
15-
with:
16-
node-version: "16.x"
13+
- uses: actions/checkout@v3
14+
- uses: actions/setup-node@v3
15+
- run: npm ci
16+
- run: npm run test:spelling
17+
test-format:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v3
21+
- uses: actions/setup-node@v3
1722
- run: npm ci
18-
- run: npm test
23+
- run: npm run test:format
24+
- run: npm run test:algorithm-format
25+
test-build:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v3
29+
- uses: actions/setup-node@v3
30+
- run: npm ci
31+
- run: npm run test:build
1932
publish:
2033
if: github.ref == 'refs/heads/main'
21-
needs: test
34+
needs:
35+
- test-spelling
36+
- test-format
37+
- test-build
2238
runs-on: ubuntu-latest
2339
steps:
24-
- uses: actions/checkout@v2
40+
- uses: actions/checkout@v3
2541
with:
2642
fetch-depth: 0
27-
- uses: actions/setup-node@v1
28-
with:
29-
node-version: "16.x"
43+
- uses: actions/setup-node@v3
3044
- run: npm ci
3145
- run: npm run build
3246
- uses: peaceiris/actions-gh-pages@v3

.github/workflows/prettier.yaml

Lines changed: 0 additions & 13 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ contributions.
66

77
Contributions that do not change the interpretation of the spec but instead
88
improve legibility, fix editorial errors, clear up ambiguity and improve
9-
examples are encouraged and are often merged by a spec editor with little
10-
process.
9+
examples are encouraged. These "editorial changes" will normally be given the
10+
["✏ Editorial" label](https://github.com/graphql/graphql-spec/issues?q=sort%3Aupdated-desc+is%3Aopen+label%3A%22%E2%9C%8F%EF%B8%8F+Editorial%22)
11+
and are often merged by a spec editor with little process.
1112

1213
However, contributions that _do_ meaningfully change the interpretation of the
1314
spec must follow an RFC (Request For Comments) process led by a _champion_

LICENSE.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Appendix: Copyright and Licensing
2+
3+
The GraphQL Specification Project is made available by the
4+
[Joint Development Foundation](https://www.jointdevelopment.org/) Projects, LLC,
5+
GraphQL Series. The current
6+
[Working Group](https://github.com/graphql/graphql-wg) charter, which includes
7+
the IP policy governing all working group deliverables (including
8+
specifications, source code, and datasets) may be found at
9+
[https://technical-charter.graphql.org](https://technical-charter.graphql.org).
10+
11+
**Copyright Notice**
12+
13+
Copyright © 2015-2018, Facebook, Inc.
14+
15+
Copyright © 2019-present, GraphQL contributors
16+
17+
THESE MATERIALS ARE PROVIDED “AS IS”. The parties expressly disclaim any
18+
warranties (express, implied, or otherwise), including implied warranties of
19+
merchantability, non-infringement, fitness for a particular purpose, or title,
20+
related to the materials. The entire risk as to implementing or otherwise using
21+
the materials is assumed by the implementer and user. IN NO EVENT WILL THE
22+
PARTIES BE LIABLE TO ANY OTHER PARTY FOR LOST PROFITS OR ANY FORM OF INDIRECT,
23+
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER FROM ANY CAUSES
24+
OF ACTION OF ANY KIND WITH RESPECT TO THIS DELIVERABLE OR ITS GOVERNING
25+
AGREEMENT, WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR
26+
OTHERWISE, AND WHETHER OR NOT THE OTHER MEMBER HAS BEEN ADVISED OF THE
27+
POSSIBILITY OF SUCH DAMAGE.
28+
29+
**Licensing**
30+
31+
The licenses for the GraphQL Specification Project are:
32+
33+
| Deliverable | License |
34+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
35+
| Specifications | [Open Web Foundation Agreement 1.0 (Patent and Copyright Grants)](https://www.openwebfoundation.org/the-agreements/the-owf-1-0-agreements-granted-claims/owfa-1-0) |
36+
| Source code | [MIT License](https://opensource.org/licenses/MIT) |
37+
| Data sets | [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) |

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
[![GraphQLConf 2025 Banner: September 08-10, Amsterdam. Hosted by the GraphQL Foundation](./assets/graphql.org_conf_2025_.png)](https://graphql.org/conf/2025/?utm_source=github&utm_medium=graphql_js&utm_campaign=readme)
2+
13
# GraphQL
24

35
<img alt="GraphQL Logo" align="right" src="https://graphql.org/img/logo.svg" width="15%" />

0 commit comments

Comments
 (0)