Skip to content

Commit

Permalink
feat: add support for flat config (#301)
Browse files Browse the repository at this point in the history
* feat: add support for flat config

* fix

* Create rare-coats-report.md

* fix test
  • Loading branch information
ota-meshi committed Mar 20, 2024
1 parent 81b901e commit f5464cc
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-coats-report.md
@@ -0,0 +1,5 @@
---
"eslint-plugin-json-schema-validator": minor
---

feat: add support for flat config
12 changes: 12 additions & 0 deletions .eslintrc.js
Expand Up @@ -188,5 +188,17 @@ module.exports = {
"eslint-plugin/require-meta-schema": "off",
},
},
{
files: ["*.mjs"],
parserOptions: {
sourceType: "module",
},
},
{
files: ["*.md/**", "**/*.md/**"],
rules: {
"n/no-missing-import": "off",
},
},
],
};
30 changes: 29 additions & 1 deletion README.md
Expand Up @@ -43,7 +43,35 @@ npm install --save-dev eslint eslint-plugin-jsonc eslint-plugin-json-schema-vali

### Configuration

Use `.eslintrc.*` file to configure rules. See also: [https://eslint.org/docs/user-guide/configuring](https://eslint.org/docs/user-guide/configuring).
#### New (ESLint>=v9) Config (Flat Config)

Use `eslint.config.js` file to configure rules. See also: <https://eslint.org/docs/latest/use/configure/configuration-files-new>.

Example **eslint.config.js**:

```mjs
import eslintPluginJsonSchemaValidator from 'eslint-plugin-json-schema-validator';
export default [
// add more generic rule sets here, such as:
// js.configs.recommended,
...eslintPluginJsonSchemaValidator.configs['flat/recommended'],
{
rules: {
// override/add rules settings here, such as:
// 'json-schema-validator/no-invalid': 'warn'
}
}
];
```

This plugin provides configs:

- `*.configs['flat/base']` ... Configuration to enable correct JSON, YAML and TOML parsing.
- `*.configs['flat/recommended']` ... Above, plus rule to validate with JSON Schema.

#### Legacy Config (ESLint<v9)

Use `.eslintrc.*` file to configure rules. See also: <https://eslint.org/docs/latest/use/configure/>.

Example **.eslintrc.js**:

Expand Down
30 changes: 29 additions & 1 deletion docs/user-guide/README.md
Expand Up @@ -18,7 +18,35 @@ npm install --save-dev eslint eslint-plugin-json-schema-validator

### Configuration

Use `.eslintrc.*` file to configure rules. See also: [https://eslint.org/docs/user-guide/configuring](https://eslint.org/docs/user-guide/configuring).
#### New (ESLint>=v9) Config (Flat Config)

Use `eslint.config.js` file to configure rules. See also: <https://eslint.org/docs/latest/use/configure/configuration-files-new>.

Example **eslint.config.js**:

```mjs
import eslintPluginJsonSchemaValidator from 'eslint-plugin-json-schema-validator';
export default [
// add more generic rule sets here, such as:
// js.configs.recommended,
...eslintPluginJsonSchemaValidator.configs['flat/recommended'],
{
rules: {
// override/add rules settings here, such as:
// 'json-schema-validator/no-invalid': 'warn'
}
}
];
```

This plugin provides configs:

- `*.configs['flat/base']` ... Configuration to enable correct JSON, YAML and TOML parsing.
- `*.configs['flat/recommended']` ... Above, plus rule to validate with JSON Schema.

#### Legacy Config (ESLint<v9)

Use `.eslintrc.*` file to configure rules. See also: <https://eslint.org/docs/latest/use/configure/>.

Example **.eslintrc.js**:

Expand Down
57 changes: 57 additions & 0 deletions src/configs/flat/base.ts
@@ -0,0 +1,57 @@
import type { ESLint } from "eslint";
import * as jsoncParser from "jsonc-eslint-parser";
import * as yamlParser from "yaml-eslint-parser";
import * as tomlParser from "toml-eslint-parser";
export default [
{
plugins: {
// eslint-disable-next-line @typescript-eslint/naming-convention -- plugin name
get "json-schema-validator"(): ESLint.Plugin {
// eslint-disable-next-line @typescript-eslint/no-require-imports -- ignore
return require("../../index");
},
},
},
{
files: [
"*.json",
"**/*.json",
"*.json5",
"**/*.json5",
"*.jsonc",
"**/*.jsonc",
],
languageOptions: {
parser: jsoncParser,
},
rules: {
// ESLint core rules known to cause problems with JSON.
strict: "off",
"no-unused-expressions": "off",
"no-unused-vars": "off",
},
},
{
files: ["*.yaml", "**/*.yaml", "*.yml", "**/*.yml"],
languageOptions: {
parser: yamlParser,
},
rules: {
// ESLint core rules known to cause problems with YAML.
"no-irregular-whitespace": "off",
"no-unused-vars": "off",
"spaced-comment": "off",
},
},
{
files: ["*.toml", "**/*.toml"],
languageOptions: {
parser: tomlParser,
},
rules: {
// ESLint core rules known to cause problems with TOML.
"no-irregular-whitespace": "off",
"spaced-comment": "off",
},
},
];
10 changes: 10 additions & 0 deletions src/configs/flat/recommended.ts
@@ -0,0 +1,10 @@
import base from "./base";
export default [
...base,
{
rules: {
// eslint-plugin-json-schema-validator rules
"json-schema-validator/no-invalid": "warn",
},
},
];
4 changes: 4 additions & 0 deletions src/index.ts
Expand Up @@ -2,11 +2,15 @@ import type { RuleModule } from "./types";
import { rules as ruleList } from "./utils/rules";
import base from "./configs/base";
import recommended from "./configs/recommended";
import flatBase from "./configs/flat/base";
import flatRecommended from "./configs/flat/recommended";
import * as meta from "./meta";

const configs = {
base,
recommended,
"flat/base": flatBase,
"flat/recommended": flatRecommended,
};

const rules = ruleList.reduce(
Expand Down
@@ -0,0 +1 @@
var a = {foo: 'bar'}
@@ -0,0 +1 @@
{"foo": "bar"}
36 changes: 29 additions & 7 deletions tests/src/eslint-plugin.ts
@@ -1,24 +1,46 @@
import path from "path";
import assert from "assert";
import plugin from "../../src/index";
import { getLegacyESLint } from "eslint-compat-utils/eslint";
import semver from "semver";
import { getLegacyESLint, getESLint } from "eslint-compat-utils/eslint";

// eslint-disable-next-line @typescript-eslint/naming-convention -- Class name
const ESLint = getLegacyESLint();
// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

const TEST_CWD = path.join(__dirname, "../fixtures/integrations/eslint-plugin");
const TEST_FIXTURES_ROOT = path.join(
__dirname,
"../fixtures/integrations/eslint-plugin",
);

describe("Integration with eslint-plugin-json-schema-validator", () => {
it("should lint without errors", async () => {
it("should lint without errors with legacy-config", async () => {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Class name
const ESLint = getLegacyESLint();
const engine = new ESLint({
cwd: TEST_CWD,
cwd: path.join(TEST_FIXTURES_ROOT, "legacy-config-test01"),
extensions: [".js", ".json"],
plugins: { "json-schema-validator": plugin as any },
});
const results = await engine.lintFiles(["test01/src"]);
const results = await engine.lintFiles(["src"]);
assert.strictEqual(results.length, 2);
assert.strictEqual(
results.reduce((s, r) => s + r.errorCount, 0),
0,
);
});
it("should lint without errors with flat-config", async () => {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Class name
const ESLint = getESLint();
if (semver.satisfies(ESLint.version, "<7.0.0")) return;
const engine = new ESLint({
cwd: path.join(TEST_FIXTURES_ROOT, "flat-config-test01"),
// @ts-expect-error -- typing bug
overrideConfigFile: true,
// @ts-expect-error -- typing bug
overrideConfig: plugin.configs["flat/recommended"],
});
const results = await engine.lintFiles(["src"]);
assert.strictEqual(results.length, 2);
assert.strictEqual(
results.reduce((s, r) => s + r.errorCount, 0),
Expand Down
41 changes: 41 additions & 0 deletions tools/update-rulesets.ts
Expand Up @@ -5,6 +5,9 @@ import os from "os";
import { rules } from "./lib/load-rules";
const isWin = os.platform().startsWith("win");

const FLAT_RULESET_NAME = {
recommended: "../src/configs/flat/recommended.ts",
};
const RULESET_NAME = {
recommended: "../src/configs/recommended.ts",
// standard: "../src/configs/standard.ts",
Expand Down Expand Up @@ -50,3 +53,41 @@ export = {
// Update file.
fs.writeFileSync(filePath, content);
}

for (const rec of ["recommended"] as const) {
let content = `
import base from './base';
export default [
...base,
{
rules: {
// eslint-plugin-json-schema-validator rules
${rules
.filter(
(rule) =>
rule.meta.docs.categories &&
!rule.meta.deprecated &&
rule.meta.docs.categories.includes(rec),
)
.map((rule) => {
const conf = rule.meta.docs.default || "error";
return `"${rule.meta.docs.ruleId}": "${conf}"`;
})
.join(",\n")}
},
}
]
`;

const filePath = path.resolve(__dirname, FLAT_RULESET_NAME[rec]);

if (isWin) {
content = content
.replace(/\r?\n/gu, "\n")
.replace(/\r/gu, "\n")
.replace(/\n/gu, "\r\n");
}

// Update file.
fs.writeFileSync(filePath, content);
}

0 comments on commit f5464cc

Please sign in to comment.