Skip to content

Commit 5e720ed

Browse files
committed
feat: add Fresh lint plugin
1 parent b7f1abb commit 5e720ed

9 files changed

Lines changed: 127 additions & 1 deletion

File tree

deno.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"workspace": [
44
"./examples",
55
"./init",
6+
"./lint",
67
"./plugin-tailwindcss",
78
"./plugin-tailwindcss-v3",
89
"./update",
@@ -13,8 +14,8 @@
1314
"license": "MIT",
1415
"exports": {
1516
".": "./src/mod.ts",
16-
"./runtime": "./src/runtime/shared.ts",
1717
"./dev": "./src/dev/mod.ts",
18+
"./runtime": "./src/runtime/shared.ts",
1819
"./compat": "./src/compat.ts",
1920
"./do-not-use": "./src/internals.ts"
2021
},

init/src/init.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as path from "@std/path";
44

55
// Keep these as is, as we replace these version in our release script
66
const FRESH_VERSION = "2.0.0-alpha.54";
7+
const FRESH_LINT_VERSION = "0.0.0";
78
const FRESH_TAILWIND_VERSION = "0.0.1-alpha.9";
89
const PREACT_VERSION = "10.27.0";
910
const PREACT_SIGNALS_VERSION = "2.2.1";
@@ -507,13 +508,15 @@ if (Deno.args.includes("build")) {
507508
update: "deno run -A -r jsr:@fresh/update .",
508509
},
509510
lint: {
511+
plugins: ["@fresh/lint"],
510512
rules: {
511513
tags: ["fresh", "recommended"],
512514
},
513515
},
514516
exclude: ["**/_fresh/*"],
515517
imports: {
516518
"fresh": `jsr:@fresh/core@^${FRESH_VERSION}`,
519+
"@fresh/lint": `jsr:@fresh/lint@^${FRESH_LINT_VERSION}`,
517520
"preact": `npm:preact@^${PREACT_VERSION}`,
518521
"@preact/signals": `npm:@preact/signals@^${PREACT_SIGNALS_VERSION}`,
519522
} as Record<string, string>,

lint/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Fresh Lint rules
2+
3+
This is a plugin with custom rules specifically for Fresh.
4+
5+
## Usage
6+
7+
1. Install the Fresh lint plugin
8+
```sh
9+
deno add jsr:@fresh/lint
10+
```
11+
2. Configure the plugin in `deno.json`
12+
```json deno.json
13+
{
14+
"lint": {
15+
"plugins": ["@fresh/lint"],
16+
"rules": {
17+
"include": ["fresh/[lint-rule]"]
18+
}
19+
}
20+
}
21+
```
22+
3. You can now start linting Fresh code! 🎉
23+
24+
## Rules
25+
26+
TODO: COMING SOON!

lint/deno.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "@fresh/lint",
3+
"version": "0.0.0",
4+
"license": "MIT",
5+
"exports": "./src/mod.ts",
6+
"publish": {
7+
"include": [
8+
"src/**/*.ts",
9+
"deno.json",
10+
"README.md"
11+
]
12+
}
13+
}

lint/src/mod.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { rules } from "./rules.ts";
2+
3+
/**
4+
* Plugin for Fresh linting rules.
5+
*
6+
* For a full list of rules, see {@linkcode rules}.
7+
*
8+
* Enable lint rules by updating `deno.json`, each rule
9+
* should be prefixed with `fresh/<rule_name>`.
10+
*
11+
* @example
12+
* ```json deno.json
13+
* {
14+
* "lint": {
15+
* "plugins": ["@fresh/lint"],
16+
* "rules": {
17+
* "include": ["fresh/test"]
18+
* }
19+
* }
20+
* }
21+
* ```
22+
*/
23+
const plugin: Deno.lint.Plugin = {
24+
name: "fresh",
25+
rules,
26+
};
27+
28+
export default plugin;

lint/src/rules.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import * as test from "./rules/test-rule.ts";
2+
3+
export const rules: Deno.lint.Plugin["rules"] = {
4+
[test.RULE_NAME]: test.rule,
5+
};

lint/src/rules/test-rule.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { expect } from "@std/expect";
2+
import { rule, RULE_NAME } from "./test-rule.ts";
3+
4+
const testPlugin: Deno.lint.Plugin = {
5+
name: "fresh",
6+
rules: { [RULE_NAME]: rule },
7+
};
8+
9+
Deno.test("fresh/test - disallow 'test' const", () => {
10+
const diagnostics = Deno.lint.runPlugin(
11+
testPlugin,
12+
"main.ts",
13+
"const _a = 'a';\n\nconst test = 2;\n",
14+
);
15+
16+
const d = diagnostics[0];
17+
18+
expect(diagnostics.length).toBe(1);
19+
expect(d.id).toBe("fresh/test");
20+
expect(d.range).toEqual([23, 27]);
21+
expect(d.message).toBe("Do not use 'test' as a variable name.");
22+
});

lint/src/rules/test-rule.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* This rule is just a test.
3+
*
4+
* @module
5+
*/
6+
7+
export const RULE_NAME = "test";
8+
9+
export const rule: Deno.lint.Rule = {
10+
create(ctx) {
11+
const bannedVarName = "test";
12+
const selector =
13+
`VariableDeclaration > VariableDeclarator > Identifier[name="${bannedVarName}"]`;
14+
15+
return {
16+
[selector](node: Deno.lint.Identifier) {
17+
ctx.report({
18+
message: `Do not use '${bannedVarName}' as a variable name.`,
19+
node,
20+
range: node.range,
21+
});
22+
},
23+
};
24+
},
25+
};

www/deno.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@
33
"start": "deno run -A --watch=static/,routes/,../src,../docs dev.ts",
44
"build": "deno run -A dev.ts build",
55
"preview": "deno serve -A _fresh/server.js"
6+
},
7+
"lint": {
8+
"plugins": ["../lint/src/mod.ts"]
69
}
710
}

0 commit comments

Comments
 (0)