Skip to content

Commit b1fb896

Browse files
docs: add linting and code snippet validation (#1983)
* Add linting and code snippet validation for docs * Remove unused link checkers * Add link checking to CONTRIBUTING.md and remove package-lock.json * update pnpm lockfile to sync with package.json * feedback from Benjie * build docs locally to test broken links * fix failing build * fix another snippets ignore --------- Co-authored-by: Saihajpreet Singh <[email protected]>
1 parent 7361ab3 commit b1fb896

File tree

8 files changed

+282
-27
lines changed

8 files changed

+282
-27
lines changed

.eslintrc.cjs

+26-17
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
/* eslint-env node */
22

33
const CODE_EXT = "js,jsx,cjs,mjs,ts,tsx,cts,mts"
4-
54
const MARKDOWN_EXT = "md,mdx"
65

76
module.exports = {
87
root: true,
8+
plugins: ["@graphql-eslint", "mdx", "@typescript-eslint", "tailwindcss"],
99
overrides: [
1010
{
1111
files: [`**/*.{${CODE_EXT}}`],
12-
// TODO: extract graphql documents from code files
13-
// to lint graphql documents marked with /* GraphQL */ comments inside js/ts codeblocks in markdown
14-
// processor: '@graphql-eslint/graphql',
15-
// plugins: ['@graphql-eslint'],
1612
extends: [
1713
"eslint:recommended",
1814
"plugin:@typescript-eslint/recommended",
@@ -34,7 +30,6 @@ module.exports = {
3430
},
3531
],
3632
"prefer-const": ["error", { destructuring: "all" }],
37-
// TODO: fix below
3833
"prefer-rest-params": "off",
3934
"@typescript-eslint/no-explicit-any": "off",
4035
"@typescript-eslint/no-unused-vars": "off",
@@ -51,27 +46,45 @@ module.exports = {
5146
{
5247
files: [`**/*.{${MARKDOWN_EXT}}`],
5348
parser: "eslint-mdx",
49+
extends: ["plugin:mdx/recommended"],
5450
processor: "mdx/remark",
55-
plugins: ["mdx"],
5651
parserOptions: {
5752
ecmaVersion: 13,
5853
sourceType: "module",
5954
},
6055
settings: {
6156
"mdx/code-blocks": true,
57+
"mdx/language-mapper": {
58+
js: "espree",
59+
graphql: "@graphql-eslint/parser",
60+
ts: "@typescript-eslint/parser",
61+
typescript: "@typescript-eslint/parser",
62+
},
6263
},
6364
rules: {
6465
"mdx/remark": "error",
6566
},
6667
},
6768
{
68-
files: [`**/*.{${MARKDOWN_EXT}}/*.{${CODE_EXT}}`],
69+
files: ["**/*.graphql"],
70+
parser: "@graphql-eslint/parser",
6971
rules: {
70-
"no-unused-labels": "off",
71-
"no-undef": "off",
72-
"no-redeclare": "off",
73-
"no-import-assign": "off",
74-
"no-prototype-builtins": "off",
72+
"@graphql-eslint/no-syntax-errors": "error",
73+
"@graphql-eslint/unique-operation-name": "error",
74+
"@graphql-eslint/unique-fragment-name": "error",
75+
"@graphql-eslint/no-anonymous-operations": "warn",
76+
"@graphql-eslint/lone-anonymous-operation": "error",
77+
"@graphql-eslint/no-duplicate-fields": "error",
78+
"@graphql-eslint/no-unused-fragments": "warn",
79+
"@graphql-eslint/no-duplicate-fragment-names": "error",
80+
"@graphql-eslint/no-undefined-variables": "error",
81+
"@graphql-eslint/unique-variable-names": "error",
82+
},
83+
},
84+
{
85+
files: [`**/*.{${CODE_EXT}}`, `**/*.{${MARKDOWN_EXT}}`],
86+
parserOptions: {
87+
plugins: ["graphql"],
7588
},
7689
},
7790
{
@@ -84,9 +97,5 @@ module.exports = {
8497
"mdx/remark": "off",
8598
},
8699
},
87-
{
88-
files: ["**/*.graphql"],
89-
parser: "@graphql-eslint/eslint-plugin",
90-
},
91100
],
92101
}

.github/workflows/docs-validation.yml

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Docs validation workflow runs on each PR on main w/ broken link checker
2+
# and code snippet validation
3+
4+
name: Docs validation
5+
6+
on:
7+
pull_request:
8+
branches:
9+
- main
10+
push:
11+
branches:
12+
- main
13+
14+
jobs:
15+
link-check:
16+
name: Broken link checker
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Node.js
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: "20"
27+
cache: "pnpm"
28+
29+
- name: Install dependencies
30+
run: pnpm install --frozen-lockfile
31+
32+
- name: Build static site
33+
run: pnpm build
34+
35+
- name: Set up Rust
36+
uses: actions-rs/toolchain@v1
37+
with:
38+
toolchain: stable
39+
40+
- name: Install lychee
41+
run: cargo install lychee
42+
43+
- name: Check links
44+
run: lychee --verbose --no-progress './out/**/*.html'
45+
46+
code-validate:
47+
name: Code snippet and GraphQL validation
48+
runs-on: ubuntu-latest
49+
steps:
50+
- uses: actions/checkout@v4
51+
52+
- uses: actions/setup-node@v4
53+
with:
54+
node-version: "20"
55+
cache: "pnpm"
56+
57+
- name: Install dependencies
58+
run: pnpm install --frozen-lockfile
59+
60+
- name: Run validation w/ annotations
61+
run: pnpm lint:docs:ci
62+
63+
- name: Validate code snippets
64+
run: pnpm validate:snippets

CONTRIBUTING.md

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ There are many ways to get involved. Follow this guide and feel free to [reach o
1010

1111
- [Development guide](#development-guide)
1212
- [Running the site locally](#running-the-site-locally)
13+
- [Checking for broken links](#checking-for-broken-links)
1314
- [Branching](#branching)
1415
- [Project structure](#project-structure)
1516
- [Publishing the updated site](#publishing-the-updated-site)
@@ -53,6 +54,21 @@ Finally, open http://localhost:3000 to view it in the browser.
5354

5455
The GraphQL website is built with [Nextra](https://nextra.site). This means that a hot-reloading development environment will be accessible by default.
5556

57+
### Checking for broken links
58+
59+
We use [Lychee](https://github.com/lycheeverse/lychee), a Rust-based CLI tool, to check for broken links in our documentation.
60+
61+
To install Lychee locally:
62+
63+
1. Install Rust: https://www.rust-lang.org/tools/install
64+
2. After installing Rust, run:
65+
66+
```bash
67+
cargo install lychee
68+
```
69+
70+
With Rust and Lychee installed, run the link checker: `pnpm run check:links`.
71+
5672
### Branching
5773

5874
Active development for graphql.org happens on the `source` branch. Be sure to create any new branches or direct any pull requests back to `source`.

package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
"packageManager": "[email protected]",
77
"scripts": {
88
"build": "next build && next-image-export-optimizer",
9+
"check:links": "lychee --verbose --no-progress './src/pages/**/*.mdx' --base https://graphql.org",
910
"dev": "next",
1011
"format": "pnpm format:check --write",
1112
"format:check": "prettier --cache --check .",
1213
"lint": "eslint --ignore-path .gitignore .",
14+
"lint:docs": "eslint --ignore-path .gitignore src/pages/learn --format stylish",
15+
"lint:docs:ci": "eslint --ignore-path .gitignore src/pages/learn --format eslint-formatter-github",
1316
"postbuild": "next-sitemap",
1417
"prebuild": "tsx src/get-github-info.ts",
1518
"start": "next start",
16-
"test": "echo \"no tests\" && exit 1"
19+
"test": "echo \"no tests\" && exit 1",
20+
"validate:snippets": "node scripts/validate-snippets.js"
1721
},
1822
"dependencies": {
1923
"@graphql-tools/schema": "10.0.15",
@@ -23,7 +27,7 @@
2327
"@tailwindcss/typography": "^0.5.10",
2428
"autoprefixer": "^10.4.17",
2529
"clsx": "^2.1.0",
26-
"codemirror": "5.65.1",
30+
"codemirror": "^5.65.19",
2731
"codemirror-graphql": "1.3.2",
2832
"date-fns": "^2.30.0",
2933
"fast-glob": "^3.3.2",

pnpm-lock.yaml

+8-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)