Skip to content

Commit 8a4f003

Browse files
feat: detect Biome lint config + docs
1 parent 11e787f commit 8a4f003

4 files changed

Lines changed: 130 additions & 7 deletions

File tree

guides/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Sometimes it's not so easy to find the entry point, so we provide a few hints to
88

99
Please help use to improve this guide. If you have any suggestions, please create an issue or a pull request.
1010

11-
## Hint "No ESLint configuration was found. ESLint is very helpful, it is worth using it even for small projects."
11+
## Hint "No linter configuration was found. A linter is very helpful, it is worth using one even for small projects."
1212

13-
To get started with ESLint, check out [ESLint](eslint.md).
13+
To get started with a linter, check out [ESLint](eslint.md) or [Biome](biome.md).
1414

1515
## Hint "Recommendation: The README seems not to have a config example. Please add one."
1616

guides/biome.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# How to use Biome for your MagicMirror² module
2+
3+
It's recommend using a linter to help you catch errors and enforce coding standards in your JavaScript code. Biome is a fast all-in-one tool that can handle both linting and formatting.
4+
5+
If you want to better understand how to set up Biome by yourself, check out the [Biome documentation](https://biomejs.dev/guides/getting-started/).
6+
7+
## Guide to using Biome for your MagicMirror² module
8+
9+
This guide will help you set up Biome for your MagicMirror² module. It will cover the installation, configuration, and how to run it.
10+
11+
### 0 - Prerequisites
12+
13+
- Make sure you have a `package.json` file in your module's root directory. If you don't have one, you can create it by running `npm init -y` in your terminal.
14+
- Make sure you have a `.gitignore` file in your module's root directory. If you don't have one, you can create it by running `touch .gitignore` in your terminal.
15+
- Add `node_modules` to your `.gitignore` file to prevent committing the `node_modules` directory to your repository.
16+
17+
### 1 - Install Biome
18+
19+
Install Biome as a development dependency:
20+
21+
```bash
22+
npm install --save-dev @biomejs/biome
23+
```
24+
25+
### 2 - Create Biome configuration file
26+
27+
Create a file named `biome.jsonc` in the root directory of your module:
28+
29+
```json
30+
{
31+
"$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
32+
"linter": {
33+
"enabled": true
34+
},
35+
"formatter": {
36+
"enabled": true
37+
},
38+
"javascript": {
39+
"formatter": {
40+
"quoteStyle": "double"
41+
}
42+
}
43+
},
44+
```
45+
46+
### 3 - Add scripts to package.json
47+
48+
Add the following scripts to your `package.json` file:
49+
50+
```json
51+
{
52+
"scripts": {
53+
"lint": "biome lint .",
54+
"lint:fix": "biome lint --write .",
55+
"format": "biome format --write .",
56+
"check": "biome check ."
57+
}
58+
},
59+
```
60+
61+
### 4 - Run Biome
62+
63+
Run linting:
64+
65+
```bash
66+
node --run lint
67+
```
68+
69+
Run linting with automatic fixes:
70+
71+
```bash
72+
node --run lint:fix
73+
```
74+
75+
Run formatting:
76+
77+
```bash
78+
node --run format
79+
```
80+
81+
Run all checks:
82+
83+
```bash
84+
node --run check
85+
```

scripts/check-modules/__tests__/module-analyzer.test.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,42 @@ test("analyzer applies classic-module exceptions for mmpm", async () => {
140140
assert.equal(result.issues.some(issue => issue.includes("README seems not to have an update section")), false);
141141
assert.equal(result.issues.some(issue => issue.includes("There is no CODE_OF_CONDUCT file")), true);
142142
assert.equal(result.issues.some(issue => issue.includes("There is no dependabot configuration file")), false);
143-
assert.equal(result.issues.some(issue => issue.includes("No ESLint configuration was found")), false);
143+
assert.equal(result.issues.some(issue => issue.includes("No linter configuration was found")), false);
144+
});
145+
146+
test("analyzer accepts biome config as linting setup", async () => {
147+
const moduleRoot = await fsPromises.mkdtemp(join(tmpdir(), "module-analyzer-biome-test-"));
148+
149+
await fsPromises.writeFile(join(moduleRoot, "README.md"), "# MMM-Biome-Test\n");
150+
await fsPromises.writeFile(join(moduleRoot, "CHANGELOG.md"), "changelog\n");
151+
await fsPromises.writeFile(join(moduleRoot, "CODE_OF_CONDUCT.md"), "code of conduct\n");
152+
await fsPromises.writeFile(join(moduleRoot, "LICENSE.md"), "MIT\n");
153+
await fsPromises.writeFile(join(moduleRoot, "biome.jsonc"), "{\n \"linter\": { \"enabled\": true }\n}\n");
154+
await fsPromises.writeFile(
155+
join(moduleRoot, "package.json"),
156+
JSON.stringify({
157+
name: "mmm-biome-test",
158+
version: "1.0.0"
159+
})
160+
);
161+
162+
const files = [
163+
join(moduleRoot, "README.md"),
164+
join(moduleRoot, "CHANGELOG.md"),
165+
join(moduleRoot, "CODE_OF_CONDUCT.md"),
166+
join(moduleRoot, "LICENSE.md"),
167+
join(moduleRoot, "biome.jsonc"),
168+
join(moduleRoot, "package.json")
169+
];
170+
171+
const result = await analyzeModule(
172+
moduleRoot,
173+
"MMM-Biome-Test",
174+
"https://github.com/example/MMM-Biome-Test",
175+
files
176+
);
177+
178+
assert.equal(result.issues.some(issue => issue.includes("No linter configuration was found")), false);
179+
assert.equal(result.issues.some(issue => issue.includes("ESLint is not in the dependencies or devDependencies")), false);
180+
assert.equal(result.issues.some(issue => issue.includes("lint script in package.json does not contain `eslint`")), false);
144181
});

scripts/check-modules/module-analyzer.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,18 +523,19 @@ export async function analyzeModule(
523523
);
524524
}
525525

526-
// ESLint checks
526+
// Linting setup checks (ESLint or Biome)
527527
if (!moduleExceptions.skipEslintChecks) {
528528
const hasOldEslintrc = filenames.has("ESLINTRC") || filenames.has("ESLINTRC.JSON") || filenames.has("ESLINTRC.JS") || filenames.has("ESLINTRC.YML") || filenames.has("ESLINTRC.YAML");
529529
const hasNewEslint = filenames.has("ESLINT.CONFIG.JS") || filenames.has("ESLINT.CONFIG.MJS");
530+
const hasBiome = filenames.has("BIOME.JSON") || filenames.has("BIOME.JSONC");
530531

531532
if (hasOldEslintrc) {
532533
issues.push("Recommendation: Replace eslintrc by new flat config.");
533-
} else if (!hasNewEslint) {
534+
} else if (!hasNewEslint && !hasBiome) {
534535
issues.push(
535-
"Recommendation: No ESLint configuration was found. ESLint is very helpful, it is worth using it even for small projects ([basic instructions](https://github.com/MagicMirrorOrg/MagicMirror-3rd-Party-Modules/blob/main/guides/eslint.md))."
536+
"Recommendation: No linter configuration was found. A linter is very helpful, it is worth using one even for small projects. You can use ESLint or Biome ([ESLint guide](https://github.com/MagicMirrorOrg/MagicMirror-3rd-Party-Modules/blob/main/guides/eslint.md), [Biome guide](https://github.com/MagicMirrorOrg/MagicMirror-3rd-Party-Modules/blob/main/guides/biome.md))."
536537
);
537-
} else {
538+
} else if (hasNewEslint) {
538539
// Check if ESLint is in package.json dependencies
539540
const packageJsonFiles = relevantFiles.filter((f) => f.endsWith("package.json"));
540541
for (const pkgFile of packageJsonFiles) {

0 commit comments

Comments
 (0)