Skip to content

Commit fe8a009

Browse files
committed
Use ESLint and Stylelint to check for potential errors and enforce a consistent coding style
* ESLint checks JS, JSON, and some CSS * Stylelint checks CSS * Stylistic plugins for both enforce coding style * Adds GitHub workflow to run checks on push and PR * Adds pre-commit hook to run checks that devs can install * Update CONTRIBUTING.md
1 parent 672ff9a commit fe8a009

19 files changed

Lines changed: 3093 additions & 496 deletions

.github/workflows/lint.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
lint:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v6
17+
18+
- name: Set up Node.js
19+
uses: actions/setup-node@v6
20+
with:
21+
node-version: '24'
22+
cache: 'npm'
23+
24+
- name: Install dependencies
25+
run: npm install
26+
27+
- parallel:
28+
- name: ESLint
29+
run: npm run lint:js
30+
31+
- name: Stylelint
32+
run: npm run lint:css

CONTRIBUTING.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ If you encounter a bug, graphical glitch, or something isn't working as expected
3232

3333
**Create a Pull Request:** Do you have a feature you would like added, or a task that you would like added that could benefit other Tenno? Fork the repository, and create a pull request!
3434

35+
### Coding Style
36+
37+
This project uses [ESLint](https://eslint.org/) and [Stylelint](https://stylelint.io/) to enforce a consistent coding style.
38+
A GitHub workflow will check your code automatically when you push changes or create a pull request.
39+
You can also run the checks locally with `npm run lint`, and [a git pre-commit hook is provided](./pre-commit) that you can install.
40+
Extensions may also be available for your editor.
41+
42+
### AI Policy
43+
3544
You must disclose any use of AI that went in to preparing your pull request by **both**:
3645

3746
1. Marking the appropriate box in the pull request template, *and*

eslint.config.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import js from "@eslint/js";
2+
import globals from "globals";
3+
import json from "@eslint/json";
4+
import css from "@eslint/css";
5+
import { defineConfig } from "eslint/config";
6+
import stylistic from "@stylistic/eslint-plugin";
7+
8+
export default defineConfig([
9+
{ ignores: [".coverage/**/*"] },
10+
{
11+
linterOptions: {
12+
reportUnusedInlineConfigs: "warn",
13+
},
14+
},
15+
{
16+
files: ["sources/**/*.{js,mjs,cjs}", "*.config.*js"],
17+
plugins: { js },
18+
languageOptions: {
19+
globals: globals.browser,
20+
},
21+
extends: [
22+
"js/recommended",
23+
stylistic.configs.customize({
24+
indent: 4,
25+
semi: true,
26+
quotes: "double",
27+
jsx: false,
28+
arrowParens: true,
29+
quoteProps: "consistent",
30+
}),
31+
],
32+
rules: {
33+
// "important" stuff
34+
"curly": ["error", "all"],
35+
"eqeqeq": ["error", "always"],
36+
"no-var": "error",
37+
"prefer-const": "error",
38+
"radix": "error",
39+
// niche stuff
40+
"array-callback-return": "error",
41+
"no-duplicate-imports": "error",
42+
"no-self-compare": "error",
43+
"no-template-curly-in-string": "warn",
44+
"no-unreachable-loop": "error",
45+
"no-use-before-define": ["error", "nofunc"],
46+
"block-scoped-var": "error",
47+
"consistent-return": "error",
48+
"default-param-last": "error",
49+
"dot-notation": "warn",
50+
"func-style": ["error", "declaration"],
51+
"no-empty-function": "error",
52+
"no-extend-native": "error",
53+
"no-labels": "error",
54+
"no-implicit-coercion": "error",
55+
"no-lone-blocks": "error",
56+
"no-lonely-if": "error",
57+
"no-new-wrappers": "error",
58+
"no-object-constructor": "error",
59+
"no-proto": "error",
60+
"no-return-assign": ["error", "always"],
61+
"no-sequences": ["error", { "allowInParentheses": false }],
62+
"no-shadow": "error",
63+
"no-throw-literal": "error",
64+
"no-unused-expressions": "error",
65+
"no-useless-concat": "error",
66+
"no-useless-rename": "error",
67+
"no-void": "error",
68+
"prefer-arrow-callback": "error",
69+
"prefer-numeric-literals": "error",
70+
"unicode-bom": "error",
71+
// eval
72+
"no-eval": "error",
73+
"no-implied-eval": "error",
74+
"no-new-func": "error",
75+
"no-script-url": "error",
76+
// complexity
77+
"complexity": ["warn", 20],
78+
"id-length": ["warn", { "min": 1, "max": 30 }],
79+
"max-depth": ["warn", 4],
80+
"max-lines-per-function": ["warn", {
81+
"max": 60,
82+
"skipBlankLines": true,
83+
"skipComments": true,
84+
}],
85+
"max-nested-callbacks": ["warn", 4],
86+
"max-params": ["warn", 4],
87+
// stylistic
88+
"@stylistic/quotes": ["error", "double", { "avoidEscape": true }],
89+
"@stylistic/brace-style": ["error", "1tbs", { "allowSingleLine": true }],
90+
"@stylistic/no-multiple-empty-lines": ["error", { "max": 2 }],
91+
"@stylistic/max-statements-per-line": ["error", { "max": 2 }],
92+
"@stylistic/object-curly-spacing": ["error", "always", { "emptyObjects": "never" }],
93+
},
94+
},
95+
{
96+
files: ["sources/tests/*.js", "*.config.*js"],
97+
languageOptions: {
98+
globals: globals.node,
99+
},
100+
},
101+
{
102+
files: ["sources/**/*.json"],
103+
plugins: { json },
104+
language: "json/json",
105+
extends: ["json/recommended"],
106+
},
107+
{
108+
files: ["sources/**/*.css"],
109+
plugins: { css },
110+
language: "css/css",
111+
extends: ["css/recommended"],
112+
languageOptions: {
113+
tolerant: true,
114+
},
115+
rules: {
116+
/* allowUnknownVariables suppresses errors from variables defined in other files.
117+
Stylelint does proper checking for this kind of error with its `referenceFiles` feature. */
118+
"css/no-invalid-properties": ["error", { "allowUnknownVariables": true }],
119+
"css/use-baseline": ["warn", {
120+
"available": "widely",
121+
"allowProperties": [
122+
"backdrop-filter", // baseline 2024
123+
],
124+
"allowPropertyValues": {
125+
"background-attachment": ["fixed"], // only unavailable in iOS
126+
},
127+
"allowAtRules": [
128+
"starting-style", // baseline 2024
129+
],
130+
}],
131+
"css/no-important": "warn",
132+
},
133+
},
134+
]);

0 commit comments

Comments
 (0)