├── .github
├── FUNDING.yml
└── workflows
│ ├── format.yml
│ ├── GHPages.yml
│ ├── pkg.pr.new-comment.yml
│ ├── stale.yml
│ ├── pkg.pr.new.yml
│ └── Release.yml
├── .npmrc
├── tests
├── fixtures
│ ├── indent
│ │ ├── array-01.json
│ │ ├── object-01.json
│ │ └── vue-sfc-01.vue
│ ├── integrations
│ │ └── eslint-plugin
│ │ │ ├── test01
│ │ │ ├── src
│ │ │ │ ├── test.json
│ │ │ │ └── test.js
│ │ │ └── .eslintrc.json
│ │ │ ├── test-auto-rule01
│ │ │ ├── src
│ │ │ │ ├── test.json
│ │ │ │ └── test.js
│ │ │ └── .eslintrc.json
│ │ │ ├── test-auto-rule-with-flat-config01
│ │ │ ├── src
│ │ │ │ ├── test.json
│ │ │ │ └── test.js
│ │ │ └── eslint.config.js
│ │ │ └── test-as-parser01
│ │ │ ├── src
│ │ │ └── test.json6
│ │ │ └── .eslintrc.json
│ └── auto
│ │ ├── test02
│ │ └── .eslintrc.json
│ │ ├── test03
│ │ └── .eslintrc.json
│ │ └── test01
│ │ └── .eslintrc.json
└── lib
│ ├── test-lib
│ └── eslint-compat.ts
│ ├── rules
│ ├── no-nan.ts
│ ├── no-plus-sign.ts
│ ├── no-floating-decimal.ts
│ ├── no-infinity.ts
│ ├── no-octal-numeric-literals.ts
│ ├── no-binary-numeric-literals.ts
│ ├── no-octal.ts
│ ├── no-dupe-keys.ts
│ ├── no-hexadecimal-numeric-literals.ts
│ ├── no-escape-sequence-in-identifier.ts
│ ├── quote-props.ts
│ ├── no-number-props.ts
│ ├── object-curly-newline.ts
│ ├── no-octal-escape.ts
│ ├── no-regexp-literals.ts
│ ├── no-bigint-literals.ts
│ ├── key-spacing.ts
│ ├── no-multi-str.ts
│ ├── comma-dangle.ts
│ ├── no-binary-expression.ts
│ ├── no-comments.ts
│ ├── quotes.ts
│ ├── no-unicode-codepoint-escapes.ts
│ ├── array-element-newline.ts
│ ├── no-undefined-value.ts
│ ├── object-property-newline.ts
│ ├── no-numeric-separators.ts
│ ├── no-sparse-arrays.ts
│ ├── array-bracket-newline.ts
│ ├── no-useless-escape.ts
│ ├── no-template-literals.ts
│ ├── space-unary-ops.ts
│ └── no-parenthesized.ts
│ ├── meta.ts
│ ├── eslint-plugin.ts
│ ├── configs
│ ├── flat
│ │ └── base.ts
│ └── recommended-with-json.ts
│ └── as-parser.ts
├── logo.png
├── tests-integrations
├── fixtures
│ ├── vue-eslint-parser-option
│ │ ├── test.json
│ │ ├── .eslintrc.json
│ │ └── package.json
│ ├── eslint-plugin-markdown-nest-for-v6
│ │ ├── test.md
│ │ ├── .eslintrc.json
│ │ └── package.json
│ ├── eslint-plugin-markdown
│ │ ├── test.md
│ │ ├── .eslintrc.json
│ │ └── package.json
│ └── eslint-plugin-markdown-nest
│ │ ├── test.md
│ │ ├── .eslintrc.json
│ │ └── package.json
└── lib
│ ├── vue-eslint-parser-option.ts
│ ├── eslint-plugin-markdown.ts
│ └── eslint-plugin-markdown-nest-for-v6.ts
├── docs
├── .vitepress
│ ├── theme
│ │ ├── components
│ │ │ ├── state
│ │ │ │ ├── index.js
│ │ │ │ ├── deserialize.js
│ │ │ │ └── serialize.js
│ │ │ ├── components
│ │ │ │ └── PgEditor.vue
│ │ │ └── eslint-code-block.vue
│ │ ├── style.css
│ │ └── index.ts
│ ├── shim
│ │ ├── module.mjs
│ │ └── rules
│ │ │ └── auto.mjs
│ ├── build-system
│ │ ├── src
│ │ │ ├── events.mjs
│ │ │ └── vue-eslint-parser.mjs
│ │ └── build.ts
│ └── stylelint.config.js
├── playground
│ └── index.md
└── rules
│ ├── no-comments.md
│ ├── no-undefined-value.md
│ ├── no-regexp-literals.md
│ ├── no-nan.md
│ ├── no-bigint-literals.md
│ ├── no-infinity.md
│ ├── no-octal-escape.md
│ ├── no-multi-str.md
│ ├── no-binary-expression.md
│ ├── no-parenthesized.md
│ ├── vue-custom-block
│ └── no-parsing-error.md
│ ├── no-octal.md
│ ├── no-plus-sign.md
│ ├── no-template-literals.md
│ ├── no-unicode-codepoint-escapes.md
│ ├── no-number-props.md
│ ├── no-escape-sequence-in-identifier.md
│ ├── no-dupe-keys.md
│ ├── auto.md
│ ├── no-numeric-separators.md
│ ├── no-octal-numeric-literals.md
│ ├── no-binary-numeric-literals.md
│ ├── no-hexadecimal-numeric-literals.md
│ ├── no-useless-escape.md
│ ├── no-sparse-arrays.md
│ ├── space-unary-ops.md
│ ├── array-bracket-spacing.md
│ ├── object-curly-spacing.md
│ ├── array-element-newline.md
│ ├── comma-style.md
│ ├── indent.md
│ ├── no-floating-decimal.md
│ ├── object-curly-newline.md
│ ├── key-spacing.md
│ ├── key-name-casing.md
│ ├── array-bracket-newline.md
│ ├── no-irregular-whitespace.md
│ ├── object-property-newline.md
│ ├── valid-json-number.md
│ └── quotes.md
├── typings
└── espree
│ └── index.d.ts
├── tools
├── update.ts
├── lib
│ ├── changesets-util.ts
│ └── load-rules.ts
├── update-docs-rules-index.ts
├── update-meta.ts
└── update-rules.ts
├── lib
├── meta.ts
├── configs
│ ├── auto-config.ts
│ ├── base.ts
│ ├── flat
│ │ ├── all.ts
│ │ ├── base.ts
│ │ ├── prettier.ts
│ │ ├── recommended-with-json5.ts
│ │ ├── recommended-with-jsonc.ts
│ │ └── recommended-with-json.ts
│ ├── all.ts
│ ├── prettier.ts
│ ├── recommended-with-json5.ts
│ ├── recommended-with-jsonc.ts
│ └── recommended-with-json.ts
├── utils
│ ├── get-auto-jsonc-rules-config
│ │ ├── worker.ts
│ │ ├── calculate-config-for-file.ts
│ │ └── should-use-flat-config.ts
│ ├── eslint-string-utils.ts
│ └── eslint-keywords.ts
├── rules
│ ├── no-octal.ts
│ ├── no-sparse-arrays.ts
│ ├── no-octal-escape.ts
│ ├── no-dupe-keys.ts
│ ├── no-regexp-literals.ts
│ ├── no-bigint-literals.ts
│ ├── no-useless-escape.ts
│ ├── no-comments.ts
│ ├── no-floating-decimal.ts
│ ├── no-multi-str.ts
│ ├── no-undefined-value.ts
│ ├── no-nan.ts
│ ├── no-infinity.ts
│ ├── no-template-literals.ts
│ ├── no-irregular-whitespace.ts
│ ├── no-binary-expression.ts
│ ├── no-number-props.ts
│ ├── no-octal-numeric-literals.ts
│ ├── no-binary-numeric-literals.ts
│ ├── no-hexadecimal-numeric-literals.ts
│ ├── no-numeric-separators.ts
│ ├── no-plus-sign.ts
│ └── no-escape-sequence-in-identifier.ts
└── index.ts
├── .env-cmdrc
├── conf
├── eslint-all.js
├── eslint-recommended.js
└── rules.js
├── tsconfig.build.json
├── renovate.json
├── .eslintrc.for-vscode.mjs
├── .changeset
├── config.json
└── README.md
├── tsconfig.json
├── .vscode
└── settings.json
├── .devcontainer
└── devcontainer.json
└── LICENSE
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: ota-meshi
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 | force=true
--------------------------------------------------------------------------------
/tests/fixtures/indent/array-01.json:
--------------------------------------------------------------------------------
1 | /*{}*/
2 | [
3 | "value"
4 | ]
--------------------------------------------------------------------------------
/tests/fixtures/indent/object-01.json:
--------------------------------------------------------------------------------
1 | /*{}*/
2 | {
3 | "key": "value"
4 | }
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test01/src/test.json:
--------------------------------------------------------------------------------
1 | {"foo": "bar"}
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ota-meshi/eslint-plugin-jsonc/HEAD/logo.png
--------------------------------------------------------------------------------
/tests-integrations/fixtures/vue-eslint-parser-option/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "a": "b"
3 | }
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test01/src/test.js:
--------------------------------------------------------------------------------
1 | var a = {foo: 'bar'}
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule01/src/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar"
3 | }
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule01/src/test.js:
--------------------------------------------------------------------------------
1 | var a = {
2 | foo: 'bar'
3 | }
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule-with-flat-config01/src/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar"
3 | }
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/state/index.js:
--------------------------------------------------------------------------------
1 | export * from "./deserialize.js";
2 | export * from "./serialize.js";
3 |
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-as-parser01/src/test.json6:
--------------------------------------------------------------------------------
1 | {
2 | // comment
3 | "foo": "bar"
4 | }
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule-with-flat-config01/src/test.js:
--------------------------------------------------------------------------------
1 | var a = {
2 | foo: 'bar'
3 | }
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest-for-v6/test.md:
--------------------------------------------------------------------------------
1 | ```json
2 | {
3 | "quotes": 'value'
4 | }
5 | ```
6 |
--------------------------------------------------------------------------------
/tests/fixtures/auto/test02/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "rules": {
4 | "indent": "error"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown/test.md:
--------------------------------------------------------------------------------
1 |
2 | ```json
3 | {
4 | "arr": ["a", "b"
5 | ]
6 | }
7 | ```
8 |
--------------------------------------------------------------------------------
/docs/.vitepress/shim/module.mjs:
--------------------------------------------------------------------------------
1 | export function createRequire() {
2 | // noop
3 | }
4 | export default {
5 | createRequire,
6 | };
7 |
--------------------------------------------------------------------------------
/typings/espree/index.d.ts:
--------------------------------------------------------------------------------
1 | import type { Program } from "estree";
2 |
3 | export function parse(text: string, options?: any): Program;
4 |
--------------------------------------------------------------------------------
/docs/.vitepress/build-system/src/events.mjs:
--------------------------------------------------------------------------------
1 | import all from "events";
2 | export default all;
3 | export const EventEmitter = all.EventEmitter;
4 |
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test01/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["plugin:jsonc/recommended-with-jsonc"]
4 | }
5 |
--------------------------------------------------------------------------------
/tests/fixtures/auto/test03/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:all"],
4 | "rules": {
5 | "indent": ["off", 4]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/docs/.vitepress/build-system/src/vue-eslint-parser.mjs:
--------------------------------------------------------------------------------
1 | import all from "vue-eslint-parser";
2 | export default all;
3 | export const parseForESLint = all.parseForESLint;
4 |
--------------------------------------------------------------------------------
/tools/update.ts:
--------------------------------------------------------------------------------
1 | import "./update-rules";
2 | import "./update-rulesets";
3 | import "./update-docs";
4 | import "./update-readme";
5 | import "./update-docs-rules-index";
6 | import "./update-meta";
7 |
--------------------------------------------------------------------------------
/tests/lib/test-lib/eslint-compat.ts:
--------------------------------------------------------------------------------
1 | import { getLegacyESLint, getESLint } from "eslint-compat-utils/eslint";
2 |
3 | export const LegacyESLint = getLegacyESLint();
4 | export const ESLint = getESLint();
5 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest/test.md:
--------------------------------------------------------------------------------
1 | ```json
2 | {
3 | "quotes": 'value'
4 | }
5 | ```
6 |
7 | ````md
8 | ```json
9 | {
10 | "quotes": 'value'
11 | }
12 | ```
13 | ````
14 |
--------------------------------------------------------------------------------
/lib/meta.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | export const name = "eslint-plugin-jsonc" as const;
5 | export const version = "2.21.0" as const;
6 |
--------------------------------------------------------------------------------
/docs/playground/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "playground"
3 | ---
4 |
5 | # Playground
6 |
7 |
8 |
9 | The playground is [here](https://ota-meshi.github.io/eslint-plugin-jsonc/playground/)!!
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.env-cmdrc:
--------------------------------------------------------------------------------
1 | {
2 | "test": {
3 | "SYNCKIT_TS_RUNNER": "swc"
4 | },
5 | "version": {
6 | "IN_VERSION_SCRIPT": "true",
7 | "SYNCKIT_TS_RUNNER": "swc"
8 | },
9 | "version-ci": {
10 | "IN_VERSION_CI_SCRIPT": "true",
11 | "SYNCKIT_TS_RUNNER": "swc"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-as-parser01/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["plugin:jsonc/recommended-with-json"],
4 | "overrides": [
5 | {
6 | "files": ["*.json6"],
7 | "parser": "jsonc-eslint-parser"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/conf/eslint-all.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use strict";
3 |
4 | const getCoreRules = require("./rules");
5 |
6 | const allRules = {};
7 |
8 | for (const [ruleId, rule] of getCoreRules()) {
9 | if (!rule.meta.deprecated) {
10 | allRules[ruleId] = "error";
11 | }
12 | }
13 | module.exports = { rules: allRules };
14 |
--------------------------------------------------------------------------------
/docs/.vitepress/stylelint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["stylelint-config-standard-vue"],
3 | rules: {
4 | "no-descending-specificity": null,
5 | "selector-class-pattern": null,
6 | "value-keyword-case": null,
7 |
8 | // Conflict with Prettier
9 | indentation: null,
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": [
4 | "tests/**/*",
5 | "tests-integrations/lib/**/*",
6 | "tools/**/*",
7 | "typings/**/*",
8 | "docs/**/*"
9 | ],
10 | "compilerOptions": {
11 | "removeComments": true /* Do not emit comments to output. */
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/conf/eslint-recommended.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use strict";
3 |
4 | const getCoreRules = require("./rules");
5 |
6 | const rules = {};
7 |
8 | for (const [ruleId, rule] of getCoreRules()) {
9 | if (rule.meta.docs.recommended && !rule.meta.deprecated) {
10 | rules[ruleId] = "error";
11 | }
12 | }
13 | module.exports = {
14 | rules,
15 | };
16 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/vue-eslint-parser-option/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "plugins": ["jsonc"],
4 | "parser": "vue-eslint-parser",
5 | "parserOptions": {
6 | "parser": "jsonc-eslint-parser",
7 | "sourceType": "module",
8 | "ecmaVersion": 2015
9 | },
10 | "rules": {
11 | "jsonc/indent": "error"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/style.css:
--------------------------------------------------------------------------------
1 | a > img {
2 | display: inline-block;
3 | }
4 |
5 | /* Playground */
6 | .playground .VPDoc.has-aside .content-container,
7 | .playground .VPDoc:not(.has-sidebar) .content,
8 | .playground .VPDoc:not(.has-sidebar) .container {
9 | max-width: none;
10 | }
11 |
12 | .playground .VPDoc.has-aside .aside {
13 | display: none;
14 | }
15 |
--------------------------------------------------------------------------------
/lib/configs/auto-config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @deprecated Use the `jsonc/auto` rule instead.
3 | */
4 | import path from "path";
5 | const base = require.resolve("./base");
6 | const baseExtend =
7 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
8 | export = {
9 | extends: [baseExtend],
10 | rules: {
11 | "jsonc/auto": "error",
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | ":preserveSemverRanges",
5 | ":disableDependencyDashboard"
6 | ],
7 | "packageRules": [
8 | {
9 | "updateTypes": ["minor", "patch", "pin", "digest"],
10 | "automerge": true
11 | },
12 | {
13 | "depTypeList": ["devDependencies"],
14 | "automerge": true
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.eslintrc.for-vscode.mjs:
--------------------------------------------------------------------------------
1 | import base from "./eslint.config.mjs";
2 | import eslintRuleTester from "eslint-plugin-eslint-rule-tester";
3 |
4 | export default [
5 | ...base,
6 | {
7 | files: ["tests/lib/rules/**/*.ts"],
8 | plugins: { "eslint-rule-tester": eslintRuleTester },
9 | rules: {
10 | "eslint-rule-tester/valid-testcase": "error",
11 | },
12 | },
13 | ];
14 |
--------------------------------------------------------------------------------
/lib/utils/get-auto-jsonc-rules-config/worker.ts:
--------------------------------------------------------------------------------
1 | import { runAsWorker } from "synckit";
2 | import { getESLint } from "eslint-compat-utils/eslint";
3 | const ESLint = getESLint();
4 |
5 | runAsWorker(async (cwd: string, fileName: string) => {
6 | const eslint = new ESLint({ cwd });
7 | const config = await eslint.calculateConfigForFile(fileName);
8 | return { rules: config.rules };
9 | });
10 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parserOptions": {
4 | "sourceType": "module",
5 | "ecmaVersion": 2015
6 | },
7 | "extends": [
8 | "plugin:markdown/recommended",
9 | "plugin:jsonc/recommended-with-json"
10 | ],
11 | "rules": {
12 | "array-bracket-newline": "error",
13 | "jsonc/auto": "error"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule01/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["plugin:jsonc/base","eslint:recommended"],
4 | "rules": {
5 | "indent": "error",
6 | "no-unused-vars": "off",
7 | "no-multi-spaces": "error",
8 | "no-multiple-empty-lines": "error",
9 | "jsonc/auto": "error",
10 | "jsonc/no-comments": "error"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/configs/base.ts:
--------------------------------------------------------------------------------
1 | export = {
2 | plugins: ["jsonc"],
3 | overrides: [
4 | {
5 | files: ["*.json", "*.json5", "*.jsonc"],
6 | parser: require.resolve("jsonc-eslint-parser"),
7 | rules: {
8 | // ESLint core rules known to cause problems with JSON.
9 | strict: "off",
10 | "no-unused-expressions": "off",
11 | "no-unused-vars": "off",
12 | },
13 | },
14 | ],
15 | };
16 |
--------------------------------------------------------------------------------
/tools/lib/changesets-util.ts:
--------------------------------------------------------------------------------
1 | import getReleasePlan from "@changesets/get-release-plan";
2 | import path from "path";
3 |
4 | /** Get new version string from changesets */
5 | export async function getNewVersion(): Promise {
6 | const releasePlan = await getReleasePlan(path.resolve(__dirname, "../.."));
7 |
8 | return releasePlan.releases.find(
9 | ({ name }) => name === "eslint-plugin-jsonc",
10 | )!.newVersion;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/utils/get-auto-jsonc-rules-config/calculate-config-for-file.ts:
--------------------------------------------------------------------------------
1 | import type { Linter } from "eslint";
2 | import { createSyncFn } from "synckit";
3 |
4 | const getSync = createSyncFn(require.resolve("./worker"));
5 |
6 | /**
7 | * Synchronously calculateConfigForFile
8 | */
9 | export function calculateConfigForFile(
10 | cwd: string,
11 | fileName: string,
12 | ): Pick {
13 | return getSync(cwd, fileName);
14 | }
15 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config/schema.json",
3 | "changelog": [
4 | "@changesets/changelog-github",
5 | {
6 | "repo": "ota-meshi/eslint-plugin-jsonc"
7 | }
8 | ],
9 | "commit": false,
10 | "linked": [],
11 | "access": "restricted",
12 | "baseBranch": "main",
13 | "updateInternalDependencies": "patch",
14 | "bumpVersionsWithWorkspaceProtocolOnly": true,
15 | "ignore": []
16 | }
17 |
--------------------------------------------------------------------------------
/conf/rules.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use strict";
3 |
4 | let ruleMap;
5 |
6 | /** Get all rules */
7 | module.exports = function getCoreRules() {
8 | const eslint = require("eslint");
9 | try {
10 | return ruleMap || (ruleMap = new eslint.Linter().getRules());
11 | } catch {
12 | // getRules() is no longer available in flat config.
13 | }
14 |
15 | const { builtinRules } = require("eslint/use-at-your-own-risk");
16 | return builtinRules;
17 | };
18 |
--------------------------------------------------------------------------------
/lib/configs/flat/all.ts:
--------------------------------------------------------------------------------
1 | import { rules } from "../../utils/rules";
2 | import base from "./base";
3 | import type { Linter } from "eslint";
4 | const all: Linter.RulesRecord = {};
5 | for (const rule of rules) {
6 | if (rule.meta.docs.ruleId === "jsonc/sort-array-values") continue;
7 | all[rule.meta.docs.ruleId] = "error";
8 | }
9 |
10 | export default [
11 | ...base,
12 | {
13 | rules: {
14 | ...all,
15 | },
16 | },
17 | ] satisfies Linter.FlatConfig[];
18 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parserOptions": {
4 | "sourceType": "module",
5 | "ecmaVersion": 2015
6 | },
7 | "extends": ["plugin:markdown/recommended"],
8 | "rules": {
9 | "quotes": ["error", "single"]
10 | },
11 | "overrides": [
12 | {
13 | "files": ["*.json"],
14 | "extends": ["plugin:jsonc/recommended-with-json"],
15 | "rules": { "jsonc/auto": "error" }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest-for-v6/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parserOptions": {
4 | "sourceType": "module",
5 | "ecmaVersion": 2015
6 | },
7 | "extends": ["plugin:markdown/recommended"],
8 | "rules": {
9 | "quotes": ["error", "single"]
10 | },
11 | "overrides": [
12 | {
13 | "files": ["*.json"],
14 | "extends": ["plugin:jsonc/recommended-with-json"],
15 | "rules": { "jsonc/auto": "error" }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/lib/configs/all.ts:
--------------------------------------------------------------------------------
1 | import { rules } from "../utils/rules";
2 | import path from "path";
3 | const base = require.resolve("./base");
4 | const baseExtend =
5 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
6 |
7 | const all: Record = {};
8 | for (const rule of rules) {
9 | if (rule.meta.docs.ruleId === "jsonc/sort-array-values") continue;
10 | all[rule.meta.docs.ruleId] = "error";
11 | }
12 |
13 | export = {
14 | extends: [baseExtend],
15 | rules: {
16 | ...all,
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/tests/fixtures/indent/vue-sfc-01.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {
4 | "key": "value"
5 | }
6 |
7 |
8 | {
9 | "key": "value"
10 | }
11 |
12 |
13 | {
14 | "key": "value"
15 | }
16 |
17 |
18 | {
19 | key: "value",
20 | }
21 |
22 |
23 |
24 | {
25 | "key": "value"
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-for-eslint-plugin-jsonc-with-md",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "eslint": "^9.0.0",
14 | "eslint-plugin-jsonc": "file:../../../eslint-plugin-jsonc-2.16.0.tgz",
15 | "eslint-plugin-markdown": "^3.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/vue-eslint-parser-option/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-for-eslint-plugin-jsonc-with-vue",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "eslint": "^9.0.0",
14 | "eslint-plugin-jsonc": "file:../../../eslint-plugin-jsonc-2.16.0.tgz",
15 | "vue-eslint-parser": "^10.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-for-eslint-plugin-jsonc-with-md-nest",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "eslint": "^9.0.0",
14 | "eslint-plugin-jsonc": "file:../../../eslint-plugin-jsonc-2.16.0.tgz",
15 | "eslint-plugin-markdown": "^3.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests-integrations/fixtures/eslint-plugin-markdown-nest-for-v6/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-for-eslint-plugin-jsonc-with-md-nest",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "eslint": "^9.0.0",
14 | "eslint-plugin-jsonc": "file:../../../eslint-plugin-jsonc-2.16.0.tgz",
15 | "eslint-plugin-markdown": "^3.0.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-nan.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-nan";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | });
11 |
12 | tester.run("no-nan", rule, {
13 | valid: ["Infinity", "1234", '"foo"', "{NaN:42}"],
14 | invalid: [
15 | {
16 | code: `NaN`,
17 | errors: ["NaN should not be used."],
18 | },
19 | {
20 | code: `+NaN`,
21 | errors: ["NaN should not be used."],
22 | },
23 | {
24 | code: `-NaN`,
25 | errors: ["NaN should not be used."],
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-plus-sign.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-plus-sign";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | });
11 |
12 | tester.run("no-plus-sign", rule, {
13 | valid: ["42", "-42", "-42.0"],
14 | invalid: [
15 | {
16 | code: `+42`,
17 | output: `42`,
18 | errors: ["Plus sign should not be used."],
19 | },
20 | {
21 | code: `+ 42`,
22 | output: ` 42`,
23 | errors: ["Plus sign should not be used."],
24 | ignoreMomoa: true,
25 | },
26 | ],
27 | });
28 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-floating-decimal.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-floating-decimal";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | });
11 |
12 | tester.run("no-floating-decimal", rule, {
13 | valid: ["42", "42.0", "0.42"],
14 | invalid: [
15 | {
16 | code: `.42`,
17 | output: `0.42`,
18 | errors: ["A leading decimal point can be confused with a dot."],
19 | },
20 | {
21 | code: `42.`,
22 | output: `42.0`,
23 | errors: ["A trailing decimal point can be confused with a dot."],
24 | },
25 | ],
26 | });
27 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-infinity.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-infinity";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | });
11 |
12 | tester.run("no-infinity", rule, {
13 | valid: ["NaN", "42", '"foo"', "{Infinity:42}"],
14 | invalid: [
15 | {
16 | code: `Infinity`,
17 | errors: ["Infinity should not be used."],
18 | },
19 | {
20 | code: `+Infinity`,
21 | errors: ["Infinity should not be used."],
22 | },
23 | {
24 | code: `-Infinity`,
25 | errors: ["Infinity should not be used."],
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-octal-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-octal-numeric-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-octal-numeric-literals", rule, {
14 | valid: ["0", "777"],
15 | invalid: [
16 | {
17 | code: `0o777`,
18 | output: `511`,
19 | errors: ["Octal numeric literals should not be used."],
20 | },
21 | {
22 | code: `0O777`,
23 | output: `511`,
24 | errors: ["Octal numeric literals should not be used."],
25 | },
26 | ],
27 | });
28 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-binary-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-binary-numeric-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-binary-numeric-literals", rule, {
14 | valid: ["0", "1010"],
15 | invalid: [
16 | {
17 | code: `0b1010`,
18 | output: `10`,
19 | errors: ["Binary numeric literals should not be used."],
20 | },
21 | {
22 | code: `0B1010`,
23 | output: `10`,
24 | errors: ["Binary numeric literals should not be used."],
25 | },
26 | ],
27 | });
28 |
--------------------------------------------------------------------------------
/tests/fixtures/integrations/eslint-plugin/test-auto-rule-with-flat-config01/eslint.config.js:
--------------------------------------------------------------------------------
1 | let plugin;
2 | try {
3 | plugin = require("../../../../../lib/index");
4 | } catch (e) {
5 | // @ts-ignore -- ignore
6 | plugin = require("../../../../../dist/index");
7 | }
8 | const parser = require("jsonc-eslint-parser");
9 |
10 | module.exports = [
11 | {
12 | plugins: {
13 | jsonc: plugin,
14 | },
15 | rules: {
16 | indent: "error",
17 | "no-unused-vars": "off",
18 | "no-multi-spaces": "error",
19 | "no-multiple-empty-lines": "error",
20 | "jsonc/auto": "error",
21 | "jsonc/no-comments": "error",
22 | },
23 | },
24 | {
25 | files: ["**/*.json"],
26 | languageOptions: {
27 | parser,
28 | },
29 | },
30 | ];
31 |
--------------------------------------------------------------------------------
/tests/fixtures/auto/test01/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["eslint:recommended"],
4 | "rules": {
5 | "array-bracket-newline": "error",
6 | "array-bracket-spacing": "error",
7 | "array-element-newline": "error",
8 | "comma-dangle": "error",
9 | "comma-style": "error",
10 | "indent": "error",
11 | "key-spacing": "error",
12 | "no-dupe-keys": "error",
13 | "no-multi-str": "error",
14 | "no-octal-escape": "error",
15 | "no-sparse-arrays": "error",
16 | "no-useless-escape": "error",
17 | "object-curly-newline": "error",
18 | "object-curly-spacing": "error",
19 | "object-property-newline": "error",
20 | "quote-props": "error",
21 | "quotes": "error",
22 | "sort-keys": "error",
23 | "space-unary-ops": "error"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/rules/no-octal.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-octal");
3 |
4 | export default createRule("no-octal", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow legacy octal literals",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: coreRule.meta!.messages!,
17 | type: coreRule.meta!.type!,
18 | deprecated: false,
19 | replacedBy: [],
20 | },
21 | create(context) {
22 | return defineWrapperListener(coreRule, context, context.options);
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/components/PgEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
36 |
--------------------------------------------------------------------------------
/lib/rules/no-sparse-arrays.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-sparse-arrays");
3 |
4 | export default createRule("no-sparse-arrays", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow sparse arrays",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: coreRule.meta!.messages!,
17 | type: coreRule.meta!.type!,
18 | deprecated: false,
19 | replacedBy: [],
20 | },
21 | create(context) {
22 | return defineWrapperListener(coreRule, context, context.options);
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/lib/rules/no-octal-escape.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-octal-escape");
3 |
4 | export default createRule("no-octal-escape", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow octal escape sequences in string literals",
9 | recommended: null,
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: coreRule.meta!.messages!,
17 | type: coreRule.meta!.type!,
18 | deprecated: false,
19 | replacedBy: [],
20 | },
21 | create(context) {
22 | return defineWrapperListener(coreRule, context, context.options);
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2015",
4 | "module": "node16",
5 | "lib": ["es2022"],
6 | "allowJs": true,
7 | "checkJs": true,
8 | "outDir": "./dist",
9 | "strict": true,
10 | "noImplicitAny": true,
11 |
12 | "noUnusedLocals": true,
13 | "noUnusedParameters": true,
14 | "noImplicitReturns": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "baseUrl": ".",
17 | "paths": {
18 | "*": ["typings/*"]
19 | },
20 | "esModuleInterop": true,
21 | "resolveJsonModule": true,
22 |
23 | "skipLibCheck": true
24 | },
25 | "include": [
26 | "lib/**/*",
27 | "tests/lib/**/*",
28 | "tests-integrations/lib/**/*",
29 | "tools/**/*",
30 | "typings/**/*",
31 | "docs/.vitepress/**/*"
32 | ],
33 | "exclude": ["dist/**/*"]
34 | }
35 |
--------------------------------------------------------------------------------
/lib/configs/flat/base.ts:
--------------------------------------------------------------------------------
1 | import type { ESLint, Linter } from "eslint";
2 | import * as parser from "jsonc-eslint-parser";
3 | export default [
4 | {
5 | plugins: {
6 | get jsonc(): ESLint.Plugin {
7 | // eslint-disable-next-line @typescript-eslint/no-require-imports -- ignore
8 | return require("../../index");
9 | },
10 | },
11 | },
12 | {
13 | files: [
14 | "*.json",
15 | "**/*.json",
16 | "*.json5",
17 | "**/*.json5",
18 | "*.jsonc",
19 | "**/*.jsonc",
20 | ],
21 | languageOptions: {
22 | parser,
23 | },
24 | rules: {
25 | // ESLint core rules known to cause problems with JSON.
26 | strict: "off",
27 | "no-unused-expressions": "off",
28 | "no-unused-vars": "off",
29 | },
30 | },
31 | ] satisfies Linter.FlatConfig[];
32 |
--------------------------------------------------------------------------------
/lib/rules/no-dupe-keys.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-dupe-keys");
3 |
4 | export default createRule("no-dupe-keys", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow duplicate keys in object literals",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: coreRule.meta!.messages!,
17 | type: coreRule.meta!.type!,
18 | deprecated: false,
19 | replacedBy: [],
20 | },
21 | create(context) {
22 | return defineWrapperListener(coreRule, context, context.options);
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/lib/rules/no-regexp-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-regexp-literals", {
4 | meta: {
5 | docs: {
6 | description: "disallow RegExp literals",
7 | recommended: ["json", "jsonc", "json5"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | schema: [],
12 | messages: {
13 | unexpected: "RegExp literals are not allowed.",
14 | },
15 | type: "problem",
16 | },
17 | create(context) {
18 | if (!context.sourceCode.parserServices.isJSON) {
19 | return {};
20 | }
21 | return {
22 | JSONLiteral(node) {
23 | if (node.regex) {
24 | context.report({
25 | loc: node.loc,
26 | messageId: "unexpected",
27 | });
28 | }
29 | },
30 | };
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/lib/rules/no-bigint-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-bigint-literals", {
4 | meta: {
5 | docs: {
6 | description: "disallow BigInt literals",
7 | recommended: ["json", "jsonc", "json5"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | schema: [],
12 | messages: {
13 | unexpected: "BigInt literals are not allowed.",
14 | },
15 | type: "problem",
16 | },
17 | create(context) {
18 | if (!context.sourceCode.parserServices.isJSON) {
19 | return {};
20 | }
21 | return {
22 | JSONLiteral(node) {
23 | if (node.bigint != null) {
24 | context.report({
25 | loc: node.loc,
26 | messageId: "unexpected",
27 | });
28 | }
29 | },
30 | };
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/lib/rules/no-useless-escape.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-useless-escape");
3 |
4 | export default createRule("no-useless-escape", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow unnecessary escape usage",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: coreRule.meta!.messages!,
17 | type: coreRule.meta!.type!,
18 | deprecated: false,
19 | replacedBy: [],
20 | },
21 | create(context) {
22 | return defineWrapperListener(coreRule, context, context.options);
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | if (typeof globalThis !== "undefined") {
2 | if (typeof require === "undefined") {
3 | (globalThis as any).require = () => {
4 | const e = new Error("require is not defined");
5 | (e as any).code = "MODULE_NOT_FOUND";
6 | throw e;
7 | };
8 | }
9 | }
10 | import type { Theme } from "vitepress";
11 | import DefaultTheme from "vitepress/theme";
12 | import ESLintCodeBlock from "./components/eslint-code-block.vue";
13 | import PlaygroundBlock from "./components/playground-block.vue";
14 | import "./style.css";
15 |
16 | const theme: Theme = {
17 | extends: DefaultTheme,
18 | enhanceApp(ctx) {
19 | DefaultTheme.enhanceApp(ctx);
20 | ctx.app.component("eslint-code-block", ESLintCodeBlock);
21 | ctx.app.component("playground-block", PlaygroundBlock);
22 | },
23 | };
24 | export default theme;
25 |
--------------------------------------------------------------------------------
/lib/rules/no-comments.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-comments", {
4 | meta: {
5 | docs: {
6 | description: "disallow comments",
7 | recommended: ["json"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | schema: [],
12 | messages: {
13 | unexpected: "Unexpected comment.",
14 | },
15 | type: "problem",
16 | },
17 | create(context) {
18 | const sourceCode = context.sourceCode;
19 | if (!sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | Program() {
24 | for (const comment of sourceCode.getAllComments()) {
25 | context.report({
26 | loc: comment.loc!,
27 | messageId: "unexpected",
28 | });
29 | }
30 | },
31 | };
32 | },
33 | });
34 |
--------------------------------------------------------------------------------
/tools/update-docs-rules-index.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import fs from "fs";
3 | import renderRulesTableContent from "./render-rules";
4 |
5 | // -----------------------------------------------------------------------------
6 | const readmeFilePath = path.resolve(__dirname, "../docs/rules/index.md");
7 | fs.writeFileSync(
8 | readmeFilePath,
9 | `---
10 | sidebarDepth: 0
11 | ---
12 |
13 | # Available Rules
14 |
15 | The \`--fix\` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) automatically fixes problems reported by rules which have a wrench :wrench: below.
16 | The rules with the following star :star: are included in the \`plugin:jsonc/recommended\` config.
17 |
18 |
19 | ${renderRulesTableContent(1)}`,
20 | );
21 |
--------------------------------------------------------------------------------
/lib/rules/no-floating-decimal.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-floating-decimal");
3 |
4 | export default createRule("no-floating-decimal", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description:
9 | "disallow leading or trailing decimal points in numeric literals",
10 | recommended: ["json", "jsonc"],
11 | extensionRule: true,
12 | layout: true,
13 | },
14 | fixable: coreRule.meta?.fixable,
15 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
16 | schema: coreRule.meta!.schema!,
17 | messages: coreRule.meta!.messages!,
18 | type: coreRule.meta!.type!,
19 | deprecated: false,
20 | replacedBy: [],
21 | },
22 | create(context) {
23 | return defineWrapperListener(coreRule, context, context.options);
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-octal.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-octal";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-octal", rule, {
14 | valid: ["0", "1", "9"],
15 | invalid: [
16 | {
17 | code: `01`,
18 | errors: ["Octal literals should not be used."],
19 | ...({
20 | languageOptions: {
21 | sourceType: "script",
22 | },
23 | } as any),
24 | },
25 | {
26 | code: `09`,
27 | errors: ["Octal literals should not be used."],
28 | ...({
29 | languageOptions: {
30 | sourceType: "script",
31 | },
32 | } as any),
33 | },
34 | ],
35 | });
36 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.validate": [
3 | "javascript",
4 | "javascriptreact",
5 | "vue",
6 | "typescript",
7 | "jsonc",
8 | "json",
9 | "markdown",
10 | "yaml"
11 | ],
12 | "eslint.options": {
13 | "overrideConfigFile": "./.eslintrc.for-vscode.mjs"
14 | },
15 | "typescript.validate.enable": true,
16 | "javascript.validate.enable": false,
17 | "vetur.validation.script": false,
18 | "vetur.validation.style": false,
19 | "css.validate": false,
20 | "typescript.tsdk": "node_modules/typescript/lib",
21 | "editor.codeActionsOnSave": {
22 | "source.fixAll.eslint": "explicit",
23 | "source.fixAll.stylelint": "explicit"
24 | },
25 | "stylelint.validate": [
26 | "css",
27 | "html",
28 | "less",
29 | "postcss",
30 | "sass",
31 | "scss",
32 | "vue",
33 | "vue-html",
34 | "vue-postcss",
35 | "stylus"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/lib/rules/no-multi-str.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-multi-str");
3 |
4 | export default createRule("no-multi-str", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow multiline strings",
9 | recommended: ["json", "jsonc"],
10 | extensionRule: true,
11 | layout: false,
12 | },
13 | fixable: coreRule.meta?.fixable,
14 | hasSuggestions: (coreRule.meta as any).hasSuggestions,
15 | schema: coreRule.meta!.schema!,
16 | messages: {
17 | ...coreRule.meta!.messages!,
18 | multilineString: "Multiline support is limited to JSON5 only.",
19 | },
20 | type: coreRule.meta!.type!,
21 | deprecated: false,
22 | replacedBy: [],
23 | },
24 | create(context) {
25 | return defineWrapperListener(coreRule, context, context.options);
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-dupe-keys.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-dupe-keys";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("no-dupe-keys", rule, {
13 | valid: ['{"key": "value"}', '{"key": "value", "key2": "value"}'],
14 | invalid: [
15 | {
16 | code: '{"key": "value", "key": "value"}',
17 | errors: ["Duplicate key 'key'."],
18 | },
19 | {
20 | filename: "test.vue",
21 | code: `{"key": "value", "key": "value"}`,
22 | errors: ["Duplicate key 'key'."],
23 | ...({
24 | languageOptions: {
25 | parser: vueParser,
26 | },
27 | } as any),
28 | },
29 | ],
30 | });
31 |
--------------------------------------------------------------------------------
/lib/rules/no-undefined-value.ts:
--------------------------------------------------------------------------------
1 | import { isUndefinedIdentifier } from "jsonc-eslint-parser";
2 | import { createRule } from "../utils";
3 |
4 | export default createRule("no-undefined-value", {
5 | meta: {
6 | docs: {
7 | description: "disallow `undefined`",
8 | recommended: ["json", "jsonc", "json5"],
9 | extensionRule: false,
10 | layout: false,
11 | },
12 | schema: [],
13 | messages: {
14 | unexpected: "`undefined` is not allowed.",
15 | },
16 | type: "problem",
17 | },
18 | create(context) {
19 | if (!context.sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | JSONIdentifier(node) {
24 | if (!isUndefinedIdentifier(node)) {
25 | return;
26 | }
27 | context.report({
28 | loc: node.loc,
29 | messageId: "unexpected",
30 | });
31 | },
32 | };
33 | },
34 | });
35 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-hexadecimal-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-hexadecimal-numeric-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | });
11 |
12 | tester.run("no-hexadecimal-numeric-literals", rule, {
13 | valid: ["0", "777", '"FFF"'],
14 | invalid: [
15 | {
16 | code: `0x777`,
17 | output: `1911`,
18 | errors: ["Hexadecimal numeric literals should not be used."],
19 | },
20 | {
21 | code: `0X777`,
22 | output: `1911`,
23 | errors: ["Hexadecimal numeric literals should not be used."],
24 | },
25 | {
26 | code: `0xFFFF`,
27 | output: `65535`,
28 | errors: ["Hexadecimal numeric literals should not be used."],
29 | },
30 | ],
31 | });
32 |
--------------------------------------------------------------------------------
/docs/.vitepress/shim/rules/auto.mjs:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line n/no-missing-import -- The file path used is the actual rule path
2 | import { createRule } from "../utils";
3 | export default createRule("auto", {
4 | meta: {
5 | docs: {
6 | description:
7 | "apply jsonc rules similar to your configured ESLint core rules",
8 | recommended: null,
9 | extensionRule: false,
10 | layout: false,
11 | },
12 | fixable: "code",
13 | schema: [],
14 | messages: {},
15 | type: "suggestion",
16 | },
17 | create(context) {
18 | const sourceCode = context.sourceCode;
19 | if (!sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | context.report({
23 | node: sourceCode.ast,
24 | loc: {
25 | line: 1,
26 | column: 0,
27 | },
28 | message: "The `auto` rule does not work in browsers.",
29 | });
30 | return {};
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/lib/rules/no-nan.ts:
--------------------------------------------------------------------------------
1 | import { isNumberIdentifier } from "jsonc-eslint-parser";
2 | import { createRule } from "../utils";
3 |
4 | export default createRule("no-nan", {
5 | meta: {
6 | docs: {
7 | description: "disallow NaN",
8 | recommended: ["json", "jsonc"],
9 | extensionRule: false,
10 | layout: false,
11 | },
12 | messages: {
13 | disallow: "NaN should not be used.",
14 | },
15 | schema: [],
16 | type: "problem",
17 | },
18 | create(context) {
19 | if (!context.sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | JSONIdentifier(node) {
24 | if (!isNumberIdentifier(node)) {
25 | return;
26 | }
27 | if (node.name === "NaN") {
28 | context.report({
29 | loc: node.loc,
30 | messageId: "disallow",
31 | });
32 | }
33 | },
34 | };
35 | },
36 | });
37 |
--------------------------------------------------------------------------------
/tests/lib/meta.ts:
--------------------------------------------------------------------------------
1 | import assert from "assert";
2 | import plugin from "../../lib";
3 | import { version } from "../../package.json";
4 | const expectedMeta = {
5 | name: "eslint-plugin-jsonc",
6 | version,
7 | };
8 |
9 | describe("Test for meta object", () => {
10 | it("A plugin should have a meta object.", () => {
11 | assert.strictEqual(plugin.meta.name, expectedMeta.name);
12 | assert.strictEqual(typeof plugin.meta.version, "string");
13 | });
14 |
15 | for (const [name, processor] of Object.entries(
16 | // @ts-expect-error -- missing processors
17 | plugin.processors || {},
18 | )) {
19 | it(`"${name}" processor should have a meta object.`, () => {
20 | // @ts-expect-error -- missing type
21 | assert.strictEqual(processor.meta.name, expectedMeta.name);
22 | // @ts-expect-error -- missing type
23 | assert.strictEqual(typeof processor.meta.version, "string");
24 | });
25 | }
26 | });
27 |
--------------------------------------------------------------------------------
/lib/rules/no-infinity.ts:
--------------------------------------------------------------------------------
1 | import { isNumberIdentifier } from "jsonc-eslint-parser";
2 | import { createRule } from "../utils";
3 |
4 | export default createRule("no-infinity", {
5 | meta: {
6 | docs: {
7 | description: "disallow Infinity",
8 | recommended: ["json", "jsonc"],
9 | extensionRule: false,
10 | layout: false,
11 | },
12 | messages: {
13 | disallow: "Infinity should not be used.",
14 | },
15 | schema: [],
16 | type: "problem",
17 | },
18 | create(context) {
19 | if (!context.sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | JSONIdentifier(node) {
24 | if (!isNumberIdentifier(node)) {
25 | return;
26 | }
27 | if (node.name === "Infinity") {
28 | context.report({
29 | loc: node.loc,
30 | messageId: "disallow",
31 | });
32 | }
33 | },
34 | };
35 | },
36 | });
37 |
--------------------------------------------------------------------------------
/lib/configs/flat/prettier.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import type { Linter } from "eslint";
5 | import base from "./base";
6 | export default [
7 | ...base,
8 | {
9 | rules: {
10 | // eslint-plugin-jsonc rules
11 | "jsonc/array-bracket-newline": "off",
12 | "jsonc/array-bracket-spacing": "off",
13 | "jsonc/array-element-newline": "off",
14 | "jsonc/comma-dangle": "off",
15 | "jsonc/comma-style": "off",
16 | "jsonc/indent": "off",
17 | "jsonc/key-spacing": "off",
18 | "jsonc/no-floating-decimal": "off",
19 | "jsonc/object-curly-newline": "off",
20 | "jsonc/object-curly-spacing": "off",
21 | "jsonc/object-property-newline": "off",
22 | "jsonc/quote-props": "off",
23 | "jsonc/quotes": "off",
24 | "jsonc/space-unary-ops": "off",
25 | },
26 | },
27 | ] satisfies Linter.FlatConfig[];
28 |
--------------------------------------------------------------------------------
/.github/workflows/format.yml:
--------------------------------------------------------------------------------
1 | name: 👔 Format
2 |
3 | on:
4 | workflow_dispatch: null
5 |
6 | jobs:
7 | format:
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - name: Checkout repo
12 | uses: actions/checkout@v4
13 | - name: Setup node
14 | uses: actions/setup-node@v5
15 | - name: Install deps
16 | run: npm install -f
17 | - name: Format
18 | run: npm run eslint-fix
19 | - name: Commit
20 | run: |
21 | git config --local user.email "github-actions[bot]@users.noreply.github.com"
22 | git config --local user.name "github-actions[bot]"
23 |
24 | git add .
25 | if [ -z "$(git status --porcelain)" ]; then
26 | echo "no formatting changed"
27 | exit 0
28 | fi
29 | git commit -m "chore: format"
30 | git push
31 | echo "pushed formatting changes https://github.com/$GITHUB_REPOSITORY/commit/$(git rev-parse HEAD)"
32 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-escape-sequence-in-identifier.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-escape-sequence-in-identifier";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-escape-sequence-in-identifier", rule, {
14 | valid: ["{key: 42}"],
15 | invalid: [
16 | {
17 | code: `{\\u0041_\\u{42}: "\\u0043\\u{44}"}`,
18 | output: `{A_B: "\\u0043\\u{44}"}`,
19 | errors: [
20 | {
21 | message: "Escape sequence in identifiers should not be used.",
22 | line: 1,
23 | column: 2,
24 | },
25 | {
26 | message: "Escape sequence in identifiers should not be used.",
27 | line: 1,
28 | column: 9,
29 | },
30 | ],
31 | },
32 | ],
33 | });
34 |
--------------------------------------------------------------------------------
/lib/configs/prettier.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import path from "path";
5 | const base = require.resolve("./base");
6 | const baseExtend =
7 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
8 | export = {
9 | extends: [baseExtend],
10 | rules: {
11 | // eslint-plugin-jsonc rules
12 | "jsonc/array-bracket-newline": "off",
13 | "jsonc/array-bracket-spacing": "off",
14 | "jsonc/array-element-newline": "off",
15 | "jsonc/comma-dangle": "off",
16 | "jsonc/comma-style": "off",
17 | "jsonc/indent": "off",
18 | "jsonc/key-spacing": "off",
19 | "jsonc/no-floating-decimal": "off",
20 | "jsonc/object-curly-newline": "off",
21 | "jsonc/object-curly-spacing": "off",
22 | "jsonc/object-property-newline": "off",
23 | "jsonc/quote-props": "off",
24 | "jsonc/quotes": "off",
25 | "jsonc/space-unary-ops": "off",
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/lib/rules/no-template-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-template-literals", {
4 | meta: {
5 | docs: {
6 | description: "disallow template literals",
7 | recommended: ["json", "jsonc", "json5"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | fixable: "code",
12 | schema: [],
13 | messages: {
14 | unexpected: "The template literals are not allowed.",
15 | },
16 | type: "problem",
17 | },
18 | create(context) {
19 | if (!context.sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | JSONTemplateLiteral(node) {
24 | context.report({
25 | loc: node.loc,
26 | messageId: "unexpected",
27 | fix(fixer) {
28 | const s = node.quasis[0].value.cooked;
29 | return fixer.replaceTextRange(node.range, JSON.stringify(s));
30 | },
31 | });
32 | },
33 | };
34 | },
35 | });
36 |
--------------------------------------------------------------------------------
/tests/lib/rules/quote-props.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/quote-props";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("quote-props", rule, {
13 | valid: ['{"key": "value"}', '"string"', '["element"]'],
14 | invalid: [
15 | {
16 | code: '{key: "value"}',
17 | output: '{"key": "value"}',
18 | errors: ["Unquoted property 'key' found."],
19 | },
20 | {
21 | filename: "test.vue",
22 | code: `{key: "value"}`,
23 | output: `{"key": "value"}`,
24 | errors: ["Unquoted property 'key' found."],
25 | ...({
26 | languageOptions: {
27 | parser: vueParser,
28 | },
29 | } as any),
30 | },
31 | ],
32 | });
33 |
--------------------------------------------------------------------------------
/lib/rules/no-irregular-whitespace.ts:
--------------------------------------------------------------------------------
1 | import { createRule, defineWrapperListener, getCoreRule } from "../utils";
2 | const coreRule = getCoreRule("no-irregular-whitespace");
3 |
4 | export default createRule("no-irregular-whitespace", {
5 | meta: {
6 | ...coreRule.meta,
7 | docs: {
8 | description: "disallow irregular whitespace",
9 | // TODO: We will switch this in the next major version.
10 | recommended: null,
11 | // recommended: ["json", "jsonc", "json5"], // TODO: We need to turn off core `no-irregular-whitespace` rule in shared config.
12 | extensionRule: true,
13 | layout: false,
14 | },
15 | fixable: coreRule.meta?.fixable,
16 | hasSuggestions: (coreRule.meta as any)?.hasSuggestions,
17 | schema: coreRule.meta!.schema!,
18 | messages: coreRule.meta!.messages!,
19 | type: coreRule.meta!.type!,
20 | deprecated: false,
21 | replacedBy: [],
22 | },
23 | create(context) {
24 | return defineWrapperListener(coreRule, context, context.options);
25 | },
26 | });
27 |
--------------------------------------------------------------------------------
/docs/rules/no-comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-comments"
5 | description: "disallow comments"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/no-comments
10 |
11 | > disallow comments
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports comments.
18 |
19 | Cannot use comments when in JSON.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-comments: 'error' */
27 | {
28 | /* ✗ BAD */
29 | // ✗ BAD
30 | }
31 | ```
32 |
33 |
34 |
35 | ## :wrench: Options
36 |
37 | Nothing.
38 |
39 | ## :rocket: Version
40 |
41 | This rule was introduced in eslint-plugin-jsonc v0.1.0
42 |
43 | ## :mag: Implementation
44 |
45 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-comments.ts)
46 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-comments.ts)
47 |
--------------------------------------------------------------------------------
/tests/lib/eslint-plugin.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import assert from "assert";
3 | import plugin from "../../lib/index";
4 | import { getLegacyESLint } from "eslint-compat-utils/eslint";
5 | const ESLint = getLegacyESLint();
6 |
7 | // -----------------------------------------------------------------------------
8 | // Tests
9 | // -----------------------------------------------------------------------------
10 |
11 | const TEST_CWD = path.join(__dirname, "../fixtures/integrations/eslint-plugin");
12 |
13 | describe("Integration with eslint-plugin-jsonc", () => {
14 | it("should lint without errors", async () => {
15 | const engine = new ESLint({
16 | cwd: TEST_CWD,
17 | extensions: [".js", ".json"],
18 | plugins: {
19 | "eslint-plugin-jsonc": plugin as never,
20 | },
21 | });
22 | const results = await engine.lintFiles(["test01/src"]);
23 | assert.strictEqual(results.length, 2);
24 | assert.strictEqual(
25 | results.reduce((s, m) => s + m.errorCount, 0),
26 | 0,
27 | );
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-number-props.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-number-props";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-number-props", rule, {
14 | valid: ['{"key": 123}', "{key: 123}", "123", "[123]"],
15 | invalid: [
16 | {
17 | code: "{123: 123}",
18 | output: '{"123": 123}',
19 | errors: ["The number property keys are not allowed."],
20 | },
21 | {
22 | filename: "test.vue",
23 | code: `{123: 123}`,
24 | output: `{"123": 123}`,
25 | errors: ["The number property keys are not allowed."],
26 | ...({
27 | languageOptions: {
28 | parser: vueParser,
29 | },
30 | } as any),
31 | },
32 | ],
33 | });
34 |
--------------------------------------------------------------------------------
/tests/lib/rules/object-curly-newline.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/object-curly-newline";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("object-curly-newline", rule, {
13 | valid: ['{"key": "value"}', '{\n"key": "value"\n}'],
14 | invalid: [
15 | {
16 | code: '{\n"key": "value"}',
17 | output: '{"key": "value"}',
18 | errors: ["Unexpected line break after this opening brace."],
19 | },
20 | {
21 | filename: "test.vue",
22 | code: `{\n"key": "value"}`,
23 | output: `{"key": "value"}`,
24 | errors: ["Unexpected line break after this opening brace."],
25 | ...({
26 | languageOptions: {
27 | parser: vueParser,
28 | },
29 | } as any),
30 | },
31 | ],
32 | });
33 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2 | // README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
3 | {
4 | "name": "Node.js & TypeScript",
5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6 | "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",
7 |
8 | // Features to add to the dev container. More info: https://containers.dev/features.
9 | // "features": {},
10 |
11 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
12 | // "forwardPorts": [],
13 |
14 | // Use 'postCreateCommand' to run commands after the container is created.
15 | "postCreateCommand": "npm install",
16 |
17 | // Configure tool-specific properties.
18 | "customizations": {
19 | "vscode": {
20 | "extensions": ["dbaeumer.vscode-eslint"]
21 | }
22 | }
23 |
24 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
25 | // "remoteUser": "root"
26 | }
27 |
--------------------------------------------------------------------------------
/lib/rules/no-binary-expression.ts:
--------------------------------------------------------------------------------
1 | import { getStaticJSONValue } from "jsonc-eslint-parser";
2 | import { createRule } from "../utils";
3 |
4 | export default createRule("no-binary-expression", {
5 | meta: {
6 | docs: {
7 | description: "disallow binary expression",
8 | recommended: ["json", "jsonc", "json5"],
9 | extensionRule: false,
10 | layout: false,
11 | },
12 | fixable: "code",
13 | hasSuggestions: false,
14 | schema: [],
15 | messages: {
16 | disallow: "The binary expressions are not allowed.",
17 | },
18 | type: "problem",
19 | },
20 | create(context) {
21 | if (!context.sourceCode.parserServices.isJSON) {
22 | return {};
23 | }
24 |
25 | return {
26 | JSONBinaryExpression(node) {
27 | context.report({
28 | loc: node.loc,
29 | messageId: "disallow",
30 | fix(fixer) {
31 | const value = getStaticJSONValue(node);
32 | return fixer.replaceTextRange(node.range, JSON.stringify(value));
33 | },
34 | });
35 | },
36 | };
37 | },
38 | });
39 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-octal-escape.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-octal-escape";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("no-octal-escape", rule, {
13 | valid: ['{"GOOD": "Copyright \\u00A9"}'],
14 | invalid: [
15 | {
16 | code: '{"BAD": "Copyright \\251"}',
17 | errors: ["Don't use octal: '\\251'. Use '\\u....' instead."],
18 | ...({
19 | languageOptions: {
20 | sourceType: "script",
21 | },
22 | } as any),
23 | },
24 | {
25 | filename: "test.vue",
26 | code: `{"BAD": "Copyright \\251"}`,
27 | errors: ["Don't use octal: '\\251'. Use '\\u....' instead."],
28 | ...({
29 | languageOptions: {
30 | sourceType: "script",
31 | parser: vueParser,
32 | },
33 | } as any),
34 | },
35 | ],
36 | });
37 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-regexp-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-regexp-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-regexp-literals", rule, {
14 | valid: ['{"key": "value"}', '"string"', '["element"]'],
15 | invalid: [
16 | {
17 | code: "/reg/",
18 | errors: ["RegExp literals are not allowed."],
19 | },
20 | {
21 | code: "[/reg/, {'/val/': /reg/}]",
22 | errors: [
23 | "RegExp literals are not allowed.",
24 | "RegExp literals are not allowed.",
25 | ],
26 | },
27 | {
28 | filename: "test.vue",
29 | code: `/reg/`,
30 | errors: ["RegExp literals are not allowed."],
31 | ...({
32 | languageOptions: {
33 | parser: vueParser,
34 | },
35 | } as any),
36 | },
37 | ],
38 | });
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Yosuke Ota
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-bigint-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-bigint-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | ecmaVersion: 2020,
10 | },
11 | ignoreMomoa: true,
12 | });
13 |
14 | tester.run("no-bigint-literals", rule, {
15 | valid: ['{"key": "value"}', '"string"', '["element"]'],
16 | invalid: [
17 | {
18 | code: "42n",
19 | errors: ["BigInt literals are not allowed."],
20 | },
21 | {
22 | code: "[1n, {'2n': 3n}]",
23 | errors: [
24 | "BigInt literals are not allowed.",
25 | "BigInt literals are not allowed.",
26 | ],
27 | },
28 | {
29 | filename: "test.vue",
30 | code: `42n`,
31 | errors: ["BigInt literals are not allowed."],
32 | ...({
33 | languageOptions: {
34 | parser: vueParser,
35 | },
36 | } as any),
37 | },
38 | ],
39 | });
40 |
--------------------------------------------------------------------------------
/tests/lib/configs/flat/base.ts:
--------------------------------------------------------------------------------
1 | import assert from "assert";
2 | import plugin from "../../../../lib/index";
3 | import { ESLint } from "../../test-lib/eslint-compat";
4 |
5 | const code = `{ foo: 42 }`;
6 | describe("`flat/base` config", () => {
7 | it("`flat/base` config should work. ", async () => {
8 | const linter = new ESLint({
9 | overrideConfigFile: true as never,
10 | overrideConfig: plugin.configs["flat/base"] as never,
11 | });
12 | const result = await linter.lintText(code, { filePath: "test.json" });
13 | const messages = result[0].messages;
14 |
15 | assert.deepStrictEqual(
16 | messages.map((m) => ({
17 | ruleId: m.ruleId,
18 | line: m.line,
19 | message: m.message,
20 | })),
21 | [],
22 | );
23 |
24 | const resultWithJs = await linter.lintText(";", { filePath: "test.js" });
25 | const messagesWithJs = resultWithJs[0].messages;
26 |
27 | assert.deepStrictEqual(
28 | messagesWithJs.map((m) => ({
29 | ruleId: m.ruleId,
30 | line: m.line,
31 | message: m.message,
32 | })),
33 | [],
34 | );
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/lib/rules/no-number-props.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-number-props", {
4 | meta: {
5 | docs: {
6 | description: "disallow number property keys",
7 | recommended: ["json", "jsonc", "json5"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | fixable: "code",
12 | schema: [],
13 | messages: {
14 | unexpected: "The number property keys are not allowed.",
15 | },
16 | type: "problem",
17 | },
18 | create(context) {
19 | if (!context.sourceCode.parserServices.isJSON) {
20 | return {};
21 | }
22 | return {
23 | JSONProperty(node) {
24 | if (node.key.type !== "JSONLiteral") {
25 | return;
26 | }
27 | if (typeof node.key.value === "number") {
28 | const raw = node.key.raw;
29 | context.report({
30 | loc: node.key.loc,
31 | messageId: "unexpected",
32 | fix(fixer) {
33 | return fixer.replaceTextRange(node.key.range, `"${raw}"`);
34 | },
35 | });
36 | }
37 | },
38 | };
39 | },
40 | });
41 |
--------------------------------------------------------------------------------
/tests/lib/rules/key-spacing.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/key-spacing";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("key-spacing", rule, {
13 | valid: ['{"key": "value"}'],
14 | invalid: [
15 | {
16 | code: '{"key" :"value"}',
17 | output: '{"key": "value"}',
18 | errors: [
19 | "Extra space after key 'key'.",
20 | "Missing space before value for key 'key'.",
21 | ],
22 | },
23 | {
24 | filename: "test.vue",
25 | code: `{"key" :"value"}`,
26 | output: `{"key": "value"}`,
27 | errors: [
28 | "Extra space after key 'key'.",
29 | "Missing space before value for key 'key'.",
30 | ],
31 | ...({
32 | languageOptions: {
33 | parser: vueParser,
34 | },
35 | } as any),
36 | },
37 | ],
38 | });
39 |
--------------------------------------------------------------------------------
/tests/lib/as-parser.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import assert from "assert";
3 | import plugin from "../../lib/index";
4 | import { getLegacyESLint } from "eslint-compat-utils/eslint";
5 | const ESLint = getLegacyESLint();
6 |
7 | // -----------------------------------------------------------------------------
8 | // Tests
9 | // -----------------------------------------------------------------------------
10 |
11 | const TEST_CWD = path.join(__dirname, "../fixtures/integrations/eslint-plugin");
12 |
13 | describe("eslint-plugin-jsonc as parser", () => {
14 | it("should parse '.json6'", async () => {
15 | const engine = new ESLint({
16 | cwd: TEST_CWD,
17 | extensions: [".js", ".json6"],
18 | plugins: {
19 | "eslint-plugin-jsonc": plugin as never,
20 | },
21 | });
22 | const results = await engine.lintFiles(["test-as-parser01/src"]);
23 | assert.strictEqual(results.length, 1);
24 | assert.strictEqual(path.basename(results[0].filePath), "test.json6");
25 | assert.strictEqual(results[0].messages.length, 1);
26 | assert.strictEqual(results[0].messages[0].ruleId, "jsonc/no-comments");
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/lib/utils/eslint-string-utils.ts:
--------------------------------------------------------------------------------
1 | // Most source code was copied from ESLint v8.
2 | // MIT License. Copyright OpenJS Foundation and other contributors,
3 | /**
4 | * @fileoverview Utilities to operate on strings.
5 | * @author Stephen Wade
6 | */
7 |
8 | import Graphemer from "graphemer";
9 | // eslint-disable-next-line no-control-regex -- intentionally including control characters
10 | const ASCII_REGEX = /^[\u0000-\u007f]*$/u;
11 | let segmenter: Intl.Segmenter | undefined;
12 | let splitter: Graphemer | undefined;
13 |
14 | /**
15 | * Counts graphemes in a given string.
16 | * @param value A string to count graphemes.
17 | * @returns The number of graphemes in `value`.
18 | */
19 | export function getGraphemeCount(value: string): number {
20 | if (ASCII_REGEX.test(value)) return value.length;
21 |
22 | try {
23 | if (!segmenter) segmenter = new Intl.Segmenter();
24 |
25 | return [...segmenter.segment(value)].length;
26 | } catch {
27 | // ignore
28 | }
29 | if (!splitter)
30 | // @ts-expect-error CJS interop
31 | splitter = new (Graphemer.default || Graphemer)();
32 | return splitter!.countGraphemes(value);
33 | }
34 |
--------------------------------------------------------------------------------
/tools/update-meta.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | import path from "path";
3 | import { ESLint } from "eslint";
4 | import { name, version } from "../package.json";
5 | import { getNewVersion } from "./lib/changesets-util";
6 |
7 | const META_PATH = path.join(__dirname, "../lib/meta.ts");
8 |
9 | void main();
10 |
11 | /** main */
12 | async function main() {
13 | if (!fs.existsSync(META_PATH)) {
14 | fs.writeFileSync(META_PATH, "", "utf8");
15 | }
16 | const eslint = new ESLint({ fix: true });
17 | const [result] = await eslint.lintText(
18 | `/*
19 | * IMPORTANT!
20 | * This file has been automatically generated,
21 | * in order to update its content execute "npm run update"
22 | */
23 | export const name = ${JSON.stringify(name)} as const;
24 | export const version = ${JSON.stringify(await getVersion())} as const;
25 | `,
26 | { filePath: META_PATH },
27 | );
28 | fs.writeFileSync(META_PATH, result.output!);
29 | }
30 |
31 | /** Get version */
32 | function getVersion() {
33 | // eslint-disable-next-line no-process-env -- ignore
34 | if (process.env.IN_VERSION_CI_SCRIPT) {
35 | return getNewVersion();
36 | }
37 | return version;
38 | }
39 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-multi-str.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-multi-str";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("no-multi-str", rule, {
13 | valid: ['{"GOOD": "Line 1 \\nLine 2"}', '"Line 1 \\nLine 2"'],
14 | invalid: [
15 | {
16 | code: '{"GOOD": "Line 1 \\\nLine 2"}',
17 | errors: 1, // FIXME: drop supports eslint6 ["Multiline support is limited to JSON5 only."],
18 | },
19 | {
20 | filename: "test.json",
21 | code: '"Line 1 \\\nLine 2"',
22 | errors: 1, // FIXME: drop supports eslint6 ["Multiline support is limited to JSON5 only."],
23 | },
24 | {
25 | filename: "test.vue",
26 | code: `"Line 1 \\\nLine 2"`,
27 | errors: 1,
28 | languageOptions: {
29 | parser: vueParser,
30 | }, // FIXME: drop supports eslint6 ["Multiline support is limited to JSON5 only."],
31 | },
32 | ],
33 | });
34 |
--------------------------------------------------------------------------------
/lib/rules/no-octal-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | const octalNumericLiteralPattern = /^0o/iu;
4 |
5 | export default createRule("no-octal-numeric-literals", {
6 | meta: {
7 | docs: {
8 | description: "disallow octal numeric literals",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: false,
11 | layout: false,
12 | },
13 | fixable: "code",
14 | messages: {
15 | disallow: "Octal numeric literals should not be used.",
16 | },
17 | schema: [],
18 | type: "problem",
19 | },
20 | create(context) {
21 | if (!context.sourceCode.parserServices.isJSON) {
22 | return {};
23 | }
24 | return {
25 | JSONLiteral(node) {
26 | if (
27 | typeof node.value === "number" &&
28 | octalNumericLiteralPattern.test(node.raw)
29 | ) {
30 | context.report({
31 | loc: node.loc,
32 | messageId: "disallow",
33 | fix: (fixer) => {
34 | return fixer.replaceTextRange(node.range, `${node.value}`);
35 | },
36 | });
37 | }
38 | },
39 | };
40 | },
41 | });
42 |
--------------------------------------------------------------------------------
/.github/workflows/GHPages.yml:
--------------------------------------------------------------------------------
1 | name: GHPages
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | workflow_dispatch: null
7 |
8 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
9 | permissions:
10 | contents: read
11 | pages: write
12 | id-token: write
13 |
14 | # Allow one concurrent deployment
15 | concurrency:
16 | group: pages
17 | cancel-in-progress: true
18 |
19 | jobs:
20 | deploy:
21 | environment:
22 | name: github-pages
23 | url: ${{ steps.deployment.outputs.page_url }}
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Checkout
27 | uses: actions/checkout@v4
28 | - uses: actions/setup-node@v5
29 | - name: Install Packages
30 | run: npm install -f
31 | - name: Build docs
32 | run: |+
33 | npm run docs:build
34 | - name: Setup Pages
35 | uses: actions/configure-pages@v5
36 | - name: Upload artifact
37 | uses: actions/upload-pages-artifact@v3
38 | with:
39 | path: ./docs/.vitepress/dist/eslint-plugin-jsonc
40 | - name: Deploy to GitHub Pages
41 | id: deployment
42 | uses: actions/deploy-pages@v4
43 |
--------------------------------------------------------------------------------
/lib/rules/no-binary-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | const binaryNumericLiteralPattern = /^0b/iu;
4 |
5 | export default createRule("no-binary-numeric-literals", {
6 | meta: {
7 | docs: {
8 | description: "disallow binary numeric literals",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: false,
11 | layout: false,
12 | },
13 | fixable: "code",
14 | messages: {
15 | disallow: "Binary numeric literals should not be used.",
16 | },
17 | schema: [],
18 | type: "problem",
19 | },
20 | create(context) {
21 | if (!context.sourceCode.parserServices.isJSON) {
22 | return {};
23 | }
24 | return {
25 | JSONLiteral(node) {
26 | if (
27 | typeof node.value === "number" &&
28 | binaryNumericLiteralPattern.test(node.raw)
29 | ) {
30 | context.report({
31 | loc: node.loc,
32 | messageId: "disallow",
33 | fix: (fixer) => {
34 | return fixer.replaceTextRange(node.range, `${node.value}`);
35 | },
36 | });
37 | }
38 | },
39 | };
40 | },
41 | });
42 |
--------------------------------------------------------------------------------
/lib/rules/no-hexadecimal-numeric-literals.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | const hexadecimalNumericLiteralPattern = /^0x/iu;
4 |
5 | export default createRule("no-hexadecimal-numeric-literals", {
6 | meta: {
7 | docs: {
8 | description: "disallow hexadecimal numeric literals",
9 | recommended: ["json", "jsonc"],
10 | extensionRule: false,
11 | layout: false,
12 | },
13 | fixable: "code",
14 | messages: {
15 | disallow: "Hexadecimal numeric literals should not be used.",
16 | },
17 | schema: [],
18 | type: "problem",
19 | },
20 | create(context) {
21 | if (!context.sourceCode.parserServices.isJSON) {
22 | return {};
23 | }
24 | return {
25 | JSONLiteral(node) {
26 | if (
27 | typeof node.value === "number" &&
28 | hexadecimalNumericLiteralPattern.test(node.raw)
29 | ) {
30 | context.report({
31 | loc: node.loc,
32 | messageId: "disallow",
33 | fix: (fixer) => {
34 | return fixer.replaceTextRange(node.range, `${node.value}`);
35 | },
36 | });
37 | }
38 | },
39 | };
40 | },
41 | });
42 |
--------------------------------------------------------------------------------
/lib/rules/no-numeric-separators.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-numeric-separators", {
4 | meta: {
5 | docs: {
6 | description: "disallow numeric separators",
7 | recommended: ["json", "jsonc", "json5"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | fixable: "code",
12 | schema: [],
13 | messages: {
14 | unexpected: "Numeric separators are not allowed.",
15 | },
16 | type: "problem",
17 | },
18 | create(context) {
19 | const sourceCode = context.sourceCode;
20 | if (!sourceCode.parserServices.isJSON) {
21 | return {};
22 | }
23 | return {
24 | JSONLiteral(node) {
25 | if (typeof node.value !== "number") {
26 | return;
27 | }
28 | const text = sourceCode.text.slice(...node.range);
29 | if (text.includes("_")) {
30 | context.report({
31 | loc: node.loc,
32 | messageId: "unexpected",
33 | fix(fixer) {
34 | return fixer.replaceTextRange(node.range, text.replace(/_/g, ""));
35 | },
36 | });
37 | }
38 | },
39 | };
40 | },
41 | });
42 |
--------------------------------------------------------------------------------
/.github/workflows/pkg.pr.new-comment.yml:
--------------------------------------------------------------------------------
1 | name: Update pkg.pr.new comment
2 |
3 | on:
4 | workflow_run:
5 | workflows: [Publish to pkg.pr.new]
6 | types:
7 | - completed
8 |
9 | permissions:
10 | issues: write
11 | pull-requests: write
12 |
13 | jobs:
14 | build:
15 | if: github.repository == 'ota-meshi/eslint-plugin-jsonc'
16 | name: Update comment
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v5
20 | - name: Download artifact
21 | uses: actions/download-artifact@v5
22 | with:
23 | name: output
24 | github-token: ${{ secrets.GITHUB_TOKEN }}
25 | run-id: ${{ github.event.workflow_run.id }}
26 | - run: ls -R .
27 | - name: Post or update comment
28 | uses: actions/github-script@v8
29 | with:
30 | github-token: ${{ secrets.GITHUB_TOKEN }}
31 | script: |
32 | const fs = require('fs');
33 | const output = JSON.parse(fs.readFileSync('output.json', 'utf8'));
34 | const { default: process } = await import('${{ github.workspace }}/tools/pkg.pr.new-comment.mjs')
35 |
36 | await process({github, context, core, output})
37 |
--------------------------------------------------------------------------------
/docs/rules/no-undefined-value.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-undefined-value"
5 | description: "disallow `undefined`"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-undefined-value
10 |
11 | > disallow `undefined`
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports the use of `undefined`.
18 |
19 | JSON, JSONC and JSON5 do not allow `undefined`.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-undefined-value: 'error' */
27 | {
28 | /* ✗ BAD */
29 | "BAD": undefined
30 | }
31 | ```
32 |
33 |
34 |
35 | ## :wrench: Options
36 |
37 | Nothing.
38 |
39 | ## :rocket: Version
40 |
41 | This rule was introduced in eslint-plugin-jsonc v0.2.0
42 |
43 | ## :mag: Implementation
44 |
45 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-undefined-value.ts)
46 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-undefined-value.ts)
47 |
--------------------------------------------------------------------------------
/docs/rules/no-regexp-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-regexp-literals"
5 | description: "disallow RegExp literals"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-regexp-literals
10 |
11 | > disallow RegExp literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports the use of RegExp literals.
18 |
19 | JSON, JSONC and JSON5 do not allow RegExp literals.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-regexp-literals: 'error' */
27 | {
28 | /* ✗ BAD */
29 | "BAD": /foo/
30 | }
31 | ```
32 |
33 |
34 |
35 | ## :wrench: Options
36 |
37 | Nothing.
38 |
39 | ## :rocket: Version
40 |
41 | This rule was introduced in eslint-plugin-jsonc v0.2.0
42 |
43 | ## :mag: Implementation
44 |
45 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-regexp-literals.ts)
46 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-regexp-literals.ts)
47 |
--------------------------------------------------------------------------------
/docs/rules/no-nan.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-nan"
5 | description: "disallow NaN"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-nan
10 |
11 | > disallow NaN
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports the use of NaN.
18 |
19 | Cannot use NaN when in JSON and JSONC.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-nan: 'error' */
27 | {
28 | /* ✓ GOOD */
29 | "GOOD": 42,
30 |
31 | /* ✗ BAD */
32 | "BAD": NaN
33 | }
34 | ```
35 |
36 |
37 |
38 | ## :wrench: Options
39 |
40 | Nothing.
41 |
42 | ## :couple: Related rules
43 |
44 | - [jsonc/valid-json-number]
45 |
46 | [jsonc/valid-json-number]: ./valid-json-number.md
47 |
48 | ## :rocket: Version
49 |
50 | This rule was introduced in eslint-plugin-jsonc v1.1.0
51 |
52 | ## :mag: Implementation
53 |
54 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-nan.ts)
55 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-nan.ts)
56 |
--------------------------------------------------------------------------------
/lib/rules/no-plus-sign.ts:
--------------------------------------------------------------------------------
1 | import { createRule } from "../utils";
2 |
3 | export default createRule("no-plus-sign", {
4 | meta: {
5 | docs: {
6 | description: "disallow plus sign",
7 | recommended: ["json", "jsonc"],
8 | extensionRule: false,
9 | layout: false,
10 | },
11 | fixable: "code",
12 | messages: {
13 | disallow: "Plus sign should not be used.",
14 | },
15 | schema: [],
16 | type: "problem",
17 | },
18 | create(context) {
19 | const sourceCode = context.sourceCode;
20 | if (!sourceCode.parserServices.isJSON) {
21 | return {};
22 | }
23 | return {
24 | JSONUnaryExpression(node) {
25 | if (node.operator === "+") {
26 | const operator = sourceCode.getFirstToken(
27 | node as any,
28 | (token) =>
29 | token.type === "Punctuator" && token.value === node.operator,
30 | );
31 | context.report({
32 | loc: operator?.loc || node.loc,
33 | messageId: "disallow",
34 | fix(fixer) {
35 | return operator ? fixer.removeRange(operator.range) : null;
36 | },
37 | });
38 | }
39 | },
40 | };
41 | },
42 | });
43 |
--------------------------------------------------------------------------------
/lib/utils/eslint-keywords.ts:
--------------------------------------------------------------------------------
1 | // Most source code was copied from ESLint v8.
2 | // MIT License. Copyright OpenJS Foundation and other contributors,
3 | /**
4 | * @fileoverview A shared list of ES3 keywords.
5 | * @author Josh Perez
6 | */
7 |
8 | export const keywords = [
9 | "abstract",
10 | "boolean",
11 | "break",
12 | "byte",
13 | "case",
14 | "catch",
15 | "char",
16 | "class",
17 | "const",
18 | "continue",
19 | "debugger",
20 | "default",
21 | "delete",
22 | "do",
23 | "double",
24 | "else",
25 | "enum",
26 | "export",
27 | "extends",
28 | "false",
29 | "final",
30 | "finally",
31 | "float",
32 | "for",
33 | "function",
34 | "goto",
35 | "if",
36 | "implements",
37 | "import",
38 | "in",
39 | "instanceof",
40 | "int",
41 | "interface",
42 | "long",
43 | "native",
44 | "new",
45 | "null",
46 | "package",
47 | "private",
48 | "protected",
49 | "public",
50 | "return",
51 | "short",
52 | "static",
53 | "super",
54 | "switch",
55 | "synchronized",
56 | "this",
57 | "throw",
58 | "throws",
59 | "transient",
60 | "true",
61 | "try",
62 | "typeof",
63 | "var",
64 | "void",
65 | "volatile",
66 | "while",
67 | "with",
68 | ];
69 |
--------------------------------------------------------------------------------
/tools/update-rules.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import fs from "fs";
3 | import os from "os";
4 | // import eslint from "eslint"
5 | import { rules } from "./lib/load-rules";
6 | const isWin = os.platform().startsWith("win");
7 |
8 | /**
9 | * Convert text to camelCase
10 | */
11 | function camelCase(str: string) {
12 | return str.replace(/[-/_](\w)/gu, (_, c) => (c ? c.toUpperCase() : ""));
13 | }
14 |
15 | let content = `/*
16 | * IMPORTANT!
17 | * This file has been automatically generated,
18 | * in order to update its content execute "npm run update"
19 | */
20 | import type { RuleModule } from "../types"
21 | ${rules
22 | .map(
23 | (rule) =>
24 | `import ${camelCase(rule.meta.docs.ruleName)} from "../rules/${
25 | rule.meta.docs.ruleName
26 | }"`,
27 | )
28 | .join("\n")}
29 |
30 | export const rules = [
31 | ${rules.map((rule) => camelCase(rule.meta.docs.ruleName)).join(",")}
32 | ] as RuleModule[]
33 | `;
34 |
35 | const filePath = path.resolve(__dirname, "../lib/utils/rules.ts");
36 |
37 | if (isWin) {
38 | content = content
39 | .replace(/\r?\n/gu, "\n")
40 | .replace(/\r/gu, "\n")
41 | .replace(/\n/gu, "\r\n");
42 | }
43 |
44 | // Update file.
45 | fs.writeFileSync(filePath, content);
46 |
--------------------------------------------------------------------------------
/tests/lib/rules/comma-dangle.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/comma-dangle";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("comma-dangle", rule, {
13 | valid: ['{"key": "value"}'],
14 | invalid: [
15 | {
16 | code: '{"key": "value",}',
17 | output: '{"key": "value"}',
18 | errors: ["Unexpected trailing comma."],
19 | },
20 | {
21 | code: '{"key": [1,2],}',
22 | output: '{"key": [1,2,],}',
23 | options: [{ arrays: "always", objects: "never" }],
24 | errors: ["Missing trailing comma.", "Unexpected trailing comma."],
25 | },
26 | {
27 | filename: "test.vue",
28 | code: `{"key": "value",}{"key": "value",}`,
29 | output: `{"key": "value"}{"key": "value",}`,
30 | errors: ["Unexpected trailing comma."],
31 | ...({
32 | languageOptions: {
33 | parser: vueParser,
34 | },
35 | } as any),
36 | },
37 | ],
38 | });
39 |
--------------------------------------------------------------------------------
/lib/configs/flat/recommended-with-json5.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import type { Linter } from "eslint";
5 | import base from "./base";
6 | export default [
7 | ...base,
8 | {
9 | rules: {
10 | // eslint-plugin-jsonc rules
11 | "jsonc/no-bigint-literals": "error",
12 | "jsonc/no-binary-expression": "error",
13 | "jsonc/no-binary-numeric-literals": "error",
14 | "jsonc/no-dupe-keys": "error",
15 | "jsonc/no-escape-sequence-in-identifier": "error",
16 | "jsonc/no-number-props": "error",
17 | "jsonc/no-numeric-separators": "error",
18 | "jsonc/no-octal-numeric-literals": "error",
19 | "jsonc/no-octal": "error",
20 | "jsonc/no-parenthesized": "error",
21 | "jsonc/no-regexp-literals": "error",
22 | "jsonc/no-sparse-arrays": "error",
23 | "jsonc/no-template-literals": "error",
24 | "jsonc/no-undefined-value": "error",
25 | "jsonc/no-unicode-codepoint-escapes": "error",
26 | "jsonc/no-useless-escape": "error",
27 | "jsonc/space-unary-ops": "error",
28 | "jsonc/vue-custom-block/no-parsing-error": "error",
29 | },
30 | },
31 | ] satisfies Linter.FlatConfig[];
32 |
--------------------------------------------------------------------------------
/docs/rules/no-bigint-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-bigint-literals"
5 | description: "disallow BigInt literals"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-bigint-literals
10 |
11 | > disallow BigInt literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports the use of BigInt literals.
18 |
19 | JSON, JSONC and JSON5 do not allow BigInt literals.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-bigint-literals: 'error' */
27 | {
28 | /* ✓ GOOD */
29 | "GOOD": 42,
30 |
31 | /* ✗ BAD */
32 | "BAD": 42n
33 | }
34 | ```
35 |
36 |
37 |
38 | ## :wrench: Options
39 |
40 | Nothing.
41 |
42 | ## :rocket: Version
43 |
44 | This rule was introduced in eslint-plugin-jsonc v0.2.0
45 |
46 | ## :mag: Implementation
47 |
48 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-bigint-literals.ts)
49 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-bigint-literals.ts)
50 |
--------------------------------------------------------------------------------
/lib/configs/recommended-with-json5.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import path from "path";
5 | const base = require.resolve("./base");
6 | const baseExtend =
7 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
8 | export = {
9 | extends: [baseExtend],
10 | rules: {
11 | // eslint-plugin-jsonc rules
12 | "jsonc/no-bigint-literals": "error",
13 | "jsonc/no-binary-expression": "error",
14 | "jsonc/no-binary-numeric-literals": "error",
15 | "jsonc/no-dupe-keys": "error",
16 | "jsonc/no-escape-sequence-in-identifier": "error",
17 | "jsonc/no-number-props": "error",
18 | "jsonc/no-numeric-separators": "error",
19 | "jsonc/no-octal-numeric-literals": "error",
20 | "jsonc/no-octal": "error",
21 | "jsonc/no-parenthesized": "error",
22 | "jsonc/no-regexp-literals": "error",
23 | "jsonc/no-sparse-arrays": "error",
24 | "jsonc/no-template-literals": "error",
25 | "jsonc/no-undefined-value": "error",
26 | "jsonc/no-unicode-codepoint-escapes": "error",
27 | "jsonc/no-useless-escape": "error",
28 | "jsonc/space-unary-ops": "error",
29 | "jsonc/vue-custom-block/no-parsing-error": "error",
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-binary-expression.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-binary-expression";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-binary-expression", rule, {
14 | valid: ['{"42": 42}', "42", "[42]"],
15 | invalid: [
16 | {
17 | code: `[42-1, {"key": 42-1}]`,
18 | output: `[41, {"key": 41}]`,
19 | errors: [
20 | {
21 | message: "The binary expressions are not allowed.",
22 | line: 1,
23 | column: 2,
24 | },
25 | {
26 | message: "The binary expressions are not allowed.",
27 | line: 1,
28 | column: 16,
29 | },
30 | ],
31 | },
32 | {
33 | code: `42-1`,
34 | output: `41`,
35 | errors: ["The binary expressions are not allowed."],
36 | },
37 | {
38 | code: `[42 * (42 - 3)]`,
39 | output: `[1638]`,
40 | errors: [
41 | "The binary expressions are not allowed.",
42 | "The binary expressions are not allowed.",
43 | ],
44 | },
45 | ],
46 | });
47 |
--------------------------------------------------------------------------------
/docs/rules/no-infinity.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-infinity"
5 | description: "disallow Infinity"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-infinity
10 |
11 | > disallow Infinity
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports the use of Infinity.
18 |
19 | Cannot use Infinity when in JSON and JSONC.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-infinity: 'error' */
27 | {
28 | /* ✓ GOOD */
29 | "GOOD": 42,
30 |
31 | /* ✗ BAD */
32 | "BAD": Infinity
33 | }
34 | ```
35 |
36 |
37 |
38 | ## :wrench: Options
39 |
40 | Nothing.
41 |
42 | ## :couple: Related rules
43 |
44 | - [jsonc/valid-json-number]
45 |
46 | [jsonc/valid-json-number]: ./valid-json-number.md
47 |
48 | ## :rocket: Version
49 |
50 | This rule was introduced in eslint-plugin-jsonc v1.1.0
51 |
52 | ## :mag: Implementation
53 |
54 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-infinity.ts)
55 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-infinity.ts)
56 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-comments.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-comments";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("no-comments", rule, {
13 | valid: ['{"key": "value"}', '"string"', '["element"]'],
14 | invalid: [
15 | {
16 | code: "{/* comment */}",
17 | errors: [
18 | {
19 | message: "Unexpected comment.",
20 | line: 1,
21 | column: 2,
22 | endLine: 1,
23 | endColumn: 15,
24 | },
25 | ],
26 | },
27 | {
28 | code: "{// comment\n}",
29 | errors: [
30 | {
31 | message: "Unexpected comment.",
32 | line: 1,
33 | column: 2,
34 | endLine: 1,
35 | endColumn: 12,
36 | },
37 | ],
38 | },
39 | {
40 | filename: "test.vue",
41 | code: `
42 | // comment
43 | "a"`,
44 | errors: ["Unexpected comment."],
45 | ...({
46 | languageOptions: {
47 | parser: vueParser,
48 | },
49 | } as any),
50 | },
51 | ],
52 | });
53 |
--------------------------------------------------------------------------------
/docs/rules/no-octal-escape.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-octal-escape"
5 | description: "disallow octal escape sequences in string literals"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/no-octal-escape
10 |
11 | > disallow octal escape sequences in string literals
12 |
13 | ## :book: Rule Details
14 |
15 | This rule disallows octal escape sequences in string literals.
16 |
17 |
18 |
19 |
20 |
21 | ```json5
22 | /* eslint jsonc/no-octal-escape: 'error' */
23 | {
24 | /* ✓ GOOD */
25 | "GOOD": "Copyright \u00A9",
26 |
27 | /* ✗ BAD */
28 | "BAD": "Copyright \251"
29 | }
30 | ```
31 |
32 |
33 |
34 | ## :wrench: Options
35 |
36 | Nothing.
37 |
38 | ## :couple: Related rules
39 |
40 | - [no-octal-escape]
41 |
42 | [no-octal-escape]: https://eslint.org/docs/rules/no-octal-escape
43 |
44 | ## :rocket: Version
45 |
46 | This rule was introduced in eslint-plugin-jsonc v0.1.0
47 |
48 | ## :mag: Implementation
49 |
50 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-octal-escape.ts)
51 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-octal-escape.ts)
52 |
53 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-octal-escape)
54 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/state/deserialize.js:
--------------------------------------------------------------------------------
1 | import pako from "pako";
2 |
3 | /**
4 | * Deserialize a given serialized string then update this object.
5 | * @param {string} serializedString A serialized string.
6 | * @returns {object} The deserialized state.
7 | */
8 | export function deserializeState(serializedString) {
9 | const state = {
10 | code: undefined,
11 | rules: undefined,
12 | };
13 |
14 | if (serializedString === "") {
15 | return state;
16 | }
17 |
18 | try {
19 | const compressedString = window.atob(serializedString);
20 | const uint8Arr = pako.inflate(
21 | Uint8Array.from(compressedString, (c) => c.charCodeAt(0)),
22 | );
23 |
24 | const jsonText = new TextDecoder().decode(uint8Arr);
25 | const json = JSON.parse(jsonText);
26 |
27 | if (typeof json === "object" && json != null) {
28 | if (typeof json.code === "string") {
29 | state.code = json.code;
30 | }
31 | if (typeof json.rules === "object" && json.rules != null) {
32 | state.rules = {};
33 | for (const id of Object.keys(json.rules)) {
34 | state.rules[id] = json.rules[id] === 2 ? "error" : "off";
35 | }
36 | }
37 | }
38 | } catch (error) {
39 | //eslint-disable-next-line no-console -- demo
40 | console.error(error);
41 | }
42 |
43 | return state;
44 | }
45 |
--------------------------------------------------------------------------------
/tests/lib/rules/quotes.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/quotes";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("quotes", rule, {
13 | valid: ['{"key": "value"}', '"string"', '["element"]'],
14 | invalid: [
15 | {
16 | code: "{'key': 'value'}",
17 | output: '{"key": "value"}',
18 | errors: [
19 | "Strings must use doublequote.",
20 | "Strings must use doublequote.",
21 | ],
22 | },
23 | {
24 | filename: "test.json",
25 | code: "'string'",
26 | output: '"string"',
27 | errors: ["Strings must use doublequote."],
28 | },
29 | {
30 | code: "['element']",
31 | output: '["element"]',
32 | errors: ["Strings must use doublequote."],
33 | },
34 | {
35 | filename: "test.vue",
36 | code: `['element']`,
37 | output: `["element"]`,
38 | errors: ["Strings must use doublequote."],
39 | ...({
40 | languageOptions: {
41 | parser: vueParser,
42 | },
43 | } as any),
44 | },
45 | ],
46 | });
47 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-unicode-codepoint-escapes.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-unicode-codepoint-escapes";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-unicode-codepoint-escapes", rule, {
14 | valid: ['"\\u0041"', '{"\\u0041": "string"}', "`\\u0042`"],
15 | invalid: [
16 | {
17 | code: `"\\u{41}"`,
18 | output: `"\\u0041"`,
19 | errors: ["Unicode code point escape sequence should not be used."],
20 | },
21 | {
22 | code: `{"\\u{41}": "string"}`,
23 | output: `{"\\u0041": "string"}`,
24 | errors: ["Unicode code point escape sequence should not be used."],
25 | },
26 | {
27 | code: `{a\\u{41}: "string"}`,
28 | output: `{a\\u0041: "string"}`,
29 | errors: ["Unicode code point escape sequence should not be used."],
30 | },
31 | {
32 | code: "`\\u{42}`",
33 | output: "`\\u0042`",
34 | errors: ["Unicode code point escape sequence should not be used."],
35 | },
36 | {
37 | code: '"\\u{20BB7}"',
38 | output: '"\\uD842\\uDFB7"',
39 | errors: ["Unicode code point escape sequence should not be used."],
40 | },
41 | ],
42 | });
43 |
--------------------------------------------------------------------------------
/docs/rules/no-multi-str.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-multi-str"
5 | description: "disallow multiline strings"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/no-multi-str
10 |
11 | > disallow multiline strings
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule is aimed at preventing the use of multiline strings.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/no-multi-str: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": "Line 1 \nLine 2",
28 |
29 | /* ✗ BAD */
30 | "BAD": "Line 1 \
31 | Line 2",
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [no-multi-str]
44 |
45 | [no-multi-str]: https://eslint.org/docs/rules/no-multi-str
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v0.1.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-multi-str.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-multi-str.ts)
55 |
56 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-multi-str)
57 |
--------------------------------------------------------------------------------
/docs/rules/no-binary-expression.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-binary-expression"
5 | description: "disallow binary expression"
6 | since: "v2.0.0"
7 | ---
8 |
9 | # jsonc/no-binary-expression
10 |
11 | > disallow binary expression
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow binary expressions.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-binary-expression: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": 86400,
29 |
30 | /* ✗ BAD */
31 | "BAD": 60 * 60 * 24
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :rocket: Version
42 |
43 | This rule was introduced in eslint-plugin-jsonc v2.0.0
44 |
45 | ## :mag: Implementation
46 |
47 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-binary-expression.ts)
48 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-binary-expression.ts)
49 |
--------------------------------------------------------------------------------
/tests/lib/rules/array-element-newline.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/array-element-newline";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("array-element-newline", rule, {
13 | valid: [
14 | `[1,
15 | 2,
16 | 3]`,
17 | ],
18 | invalid: [
19 | {
20 | code: "[1, 2, 3]",
21 | output: `[1,
22 | 2,
23 | 3]`,
24 | errors: [
25 | "There should be a linebreak after this element.",
26 | "There should be a linebreak after this element.",
27 | ],
28 | },
29 | {
30 | filename: "test.vue",
31 | code: `[1, 2, 3][1, 2, 3]`,
32 | output: `[1,
33 | 2,
34 | 3][1,
35 | 2,
36 | 3]`,
37 | errors: [
38 | "There should be a linebreak after this element.",
39 | "There should be a linebreak after this element.",
40 | "There should be a linebreak after this element.",
41 | "There should be a linebreak after this element.",
42 | ],
43 | ...({
44 | languageOptions: {
45 | parser: vueParser,
46 | },
47 | } as any),
48 | },
49 | ],
50 | });
51 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/state/serialize.js:
--------------------------------------------------------------------------------
1 | import pako from "pako";
2 |
3 | /**
4 | * Get only enabled rules to make the serialized data smaller.
5 | * @param {object} allRules The rule settings.
6 | * @returns {object} The rule settings for the enabled rules.
7 | */
8 | function getEnabledRules(allRules) {
9 | return Object.keys(allRules).reduce((map, id) => {
10 | if (allRules[id] === "error") {
11 | map[id] = 2;
12 | }
13 | return map;
14 | }, {});
15 | }
16 |
17 | /**
18 | * Serialize a given state as a base64 string.
19 | * @param {State} state The state to serialize.
20 | * @returns {string} The serialized string.
21 | */
22 | export function serializeState(state) {
23 | const saveData = {
24 | code: state.code,
25 | rules: state.rules ? getEnabledRules(state.rules) : undefined,
26 | };
27 | const jsonString = JSON.stringify(saveData);
28 |
29 | const uint8Arr = new TextEncoder().encode(jsonString);
30 | const compressedString = String.fromCharCode(...pako.deflate(uint8Arr));
31 | const base64 =
32 | (typeof window !== "undefined" && window.btoa(compressedString)) ||
33 | compressedString;
34 |
35 | //eslint-disable-next-line no-console -- demo
36 | console.log(
37 | `The compress rate of serialized string: ${(
38 | (100 * base64.length) /
39 | jsonString.length
40 | ).toFixed(1)}% (${jsonString.length}B → ${base64.length}B)`,
41 | );
42 |
43 | return base64;
44 | }
45 |
--------------------------------------------------------------------------------
/docs/rules/no-parenthesized.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-parenthesized"
5 | description: "disallow parentheses around the expression"
6 | since: "v2.0.0"
7 | ---
8 |
9 | # jsonc/no-parenthesized
10 |
11 | > disallow parentheses around the expression
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule always disallow parentheses around the expression.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-parenthesized: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": "foo",
29 |
30 | /* ✗ BAD */
31 | "BAD": ("bar")
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :rocket: Version
42 |
43 | This rule was introduced in eslint-plugin-jsonc v2.0.0
44 |
45 | ## :mag: Implementation
46 |
47 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-parenthesized.ts)
48 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-parenthesized.ts)
49 |
--------------------------------------------------------------------------------
/docs/rules/vue-custom-block/no-parsing-error.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/vue-custom-block/no-parsing-error"
5 | description: "disallow parsing errors in Vue custom blocks"
6 | since: "v0.8.0"
7 | ---
8 |
9 | # jsonc/vue-custom-block/no-parsing-error
10 |
11 | > disallow parsing errors in Vue custom blocks
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule reports JSON parsing errors in Vue custom blocks.
18 |
19 |
20 |
21 |
22 |
23 | ```vue
24 |
25 | { "foo": }
26 |
27 |
28 |
29 | { "foo": }
30 |
31 |
32 |
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :rocket: Version
44 |
45 | This rule was introduced in eslint-plugin-jsonc v0.8.0
46 |
47 | ## :mag: Implementation
48 |
49 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/vue-custom-block/no-parsing-error.ts)
50 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/vue-custom-block/no-parsing-error.ts)
51 |
--------------------------------------------------------------------------------
/docs/rules/no-octal.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-octal"
5 | description: "disallow legacy octal literals"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-octal
10 |
11 | > disallow legacy octal literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | The rule disallows legacy octal literals.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/no-octal: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": 777,
28 |
29 | /* ✗ BAD */
30 | "BAD": 0777
31 | }
32 | ```
33 |
34 |
35 |
36 | ## :wrench: Options
37 |
38 | Nothing.
39 |
40 | ## :couple: Related rules
41 |
42 | - [no-octal]
43 | - [jsonc/valid-json-number]
44 |
45 | [no-octal]: https://eslint.org/docs/rules/no-octal
46 | [jsonc/valid-json-number]: ./valid-json-number.md
47 |
48 | ## :rocket: Version
49 |
50 | This rule was introduced in eslint-plugin-jsonc v1.1.0
51 |
52 | ## :mag: Implementation
53 |
54 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-octal.ts)
55 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-octal.ts)
56 |
57 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-octal)
58 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-undefined-value.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-undefined-value";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-undefined-value", rule, {
14 | valid: ["null", "[1,,2]", "{undefined:1}"],
15 | invalid: [
16 | {
17 | code: "undefined",
18 | errors: ["`undefined` is not allowed."],
19 | },
20 | {
21 | code: `[
22 | undefined,
23 | {
24 | undefined: undefined
25 | }
26 | ]`,
27 | errors: [
28 | {
29 | message: "`undefined` is not allowed.",
30 | line: 2,
31 | column: 17,
32 | endColumn: 26,
33 | },
34 | {
35 | message: "`undefined` is not allowed.",
36 | line: 4,
37 | column: 32,
38 | endColumn: 41,
39 | },
40 | ],
41 | },
42 | {
43 | filename: "test.vue",
44 | code: `undefined`,
45 | errors: ["`undefined` is not allowed."],
46 | ...({
47 | languageOptions: {
48 | parser: vueParser,
49 | },
50 | } as any),
51 | },
52 | ],
53 | });
54 |
--------------------------------------------------------------------------------
/tests/lib/rules/object-property-newline.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/object-property-newline";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("object-property-newline", rule, {
13 | valid: [
14 | `
15 | {
16 | "foo": "foo",
17 | "bar": "bar",
18 | "baz": "baz"
19 | }
20 | `,
21 | ],
22 | invalid: [
23 | {
24 | code: `
25 | {
26 | "foo": "foo", "bar": "bar", "baz": "baz"
27 | }`,
28 | output: `
29 | {
30 | "foo": "foo",
31 | "bar": "bar",
32 | "baz": "baz"
33 | }`,
34 | errors: [
35 | "Object properties must go on a new line.",
36 | "Object properties must go on a new line.",
37 | ],
38 | },
39 | {
40 | filename: "test.vue",
41 | code: `{ "foo": "foo", "bar": "bar" }`,
42 | output: `{ "foo": "foo",\n"bar": "bar" }`,
43 | errors: ["Object properties must go on a new line."],
44 | ...({
45 | languageOptions: {
46 | parser: vueParser,
47 | },
48 | } as any),
49 | },
50 | ],
51 | });
52 |
--------------------------------------------------------------------------------
/docs/rules/no-plus-sign.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-plus-sign"
5 | description: "disallow plus sign"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-plus-sign
10 |
11 | > disallow plus sign
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow plus sign.
19 |
20 | Cannot use plus sign when in JSON and JSONC.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/no-plus-sign: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": 42,
31 |
32 | /* ✗ BAD */
33 | "BAD": +42
34 | }
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :couple: Related rules
44 |
45 | - [jsonc/valid-json-number]
46 |
47 | [jsonc/valid-json-number]: ./valid-json-number.md
48 |
49 | ## :rocket: Version
50 |
51 | This rule was introduced in eslint-plugin-jsonc v1.1.0
52 |
53 | ## :mag: Implementation
54 |
55 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-plus-sign.ts)
56 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-plus-sign.ts)
57 |
--------------------------------------------------------------------------------
/docs/rules/no-template-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-template-literals"
5 | description: "disallow template literals"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-template-literals
10 |
11 | > disallow template literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports the use of template literals.
19 |
20 | JSON, JSONC and JSON5 do not allow template literal.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/no-template-literals: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": "foo",
31 |
32 | /* ✗ BAD */
33 | "BAD": `bar`
34 | }
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :rocket: Version
44 |
45 | This rule was introduced in eslint-plugin-jsonc v0.2.0
46 |
47 | ## :mag: Implementation
48 |
49 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-template-literals.ts)
50 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-template-literals.ts)
51 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-numeric-separators.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-numeric-separators";
3 | import { Linter } from "eslint";
4 | import semver from "semver";
5 | import * as jsonParser from "jsonc-eslint-parser";
6 | import * as vueParser from "vue-eslint-parser";
7 |
8 | if (semver.gte(Linter.version, "7.3.0")) {
9 | const tester = new RuleTester({
10 | languageOptions: {
11 | ecmaVersion: 2021,
12 | parser: jsonParser,
13 | },
14 | ignoreMomoa: true,
15 | });
16 |
17 | tester.run("no-numeric-separators", rule, {
18 | valid: ['{"key": 1234}', "1234", "[1234]"],
19 | invalid: [
20 | {
21 | code: `{"key": 1_234}`,
22 | output: `{"key": 1234}`,
23 | errors: ["Numeric separators are not allowed."],
24 | },
25 | {
26 | code: `1_234`,
27 | output: `1234`,
28 | errors: ["Numeric separators are not allowed."],
29 | },
30 | {
31 | code: `[1_234]`,
32 | output: `[1234]`,
33 | errors: ["Numeric separators are not allowed."],
34 | },
35 | {
36 | filename: "test.vue",
37 | code: `{"a": 1_23}`,
38 | output: `{"a": 123}`,
39 | errors: ["Numeric separators are not allowed."],
40 | languageOptions: {
41 | parser: vueParser,
42 | },
43 | },
44 | ],
45 | });
46 | }
47 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-sparse-arrays.ts:
--------------------------------------------------------------------------------
1 | import { ESLint } from "../test-lib/eslint-compat";
2 | import { RuleTester } from "../test-lib/tester";
3 | import rule from "../../../lib/rules/no-sparse-arrays";
4 | import * as jsonParser from "jsonc-eslint-parser";
5 | import * as vueParser from "vue-eslint-parser";
6 | import semver from "semver";
7 |
8 | const tester = new RuleTester({
9 | languageOptions: {
10 | parser: jsonParser,
11 | },
12 | ignoreMomoa: true,
13 | });
14 |
15 | tester.run("no-sparse-arrays", rule, {
16 | valid: ["[1,2,3,4]", "[1,2,3,4,]"],
17 | invalid: [
18 | {
19 | code: "[1,,,4]",
20 | errors: semver.gte(ESLint.version, "9.5.0")
21 | ? [
22 | "Unexpected comma in middle of array.",
23 | "Unexpected comma in middle of array.",
24 | ]
25 | : ["Unexpected comma in middle of array."],
26 | },
27 | {
28 | code: "[,2,3,4]",
29 | errors: ["Unexpected comma in middle of array."],
30 | },
31 | {
32 | filename: "test.vue",
33 | code: `[,,]`,
34 | errors: semver.gte(ESLint.version, "9.5.0")
35 | ? [
36 | "Unexpected comma in middle of array.",
37 | "Unexpected comma in middle of array.",
38 | ]
39 | : ["Unexpected comma in middle of array."],
40 | ...({
41 | languageOptions: {
42 | parser: vueParser,
43 | },
44 | } as any),
45 | },
46 | ],
47 | });
48 |
--------------------------------------------------------------------------------
/tools/lib/load-rules.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import fs from "fs";
3 |
4 | /**
5 | * Get the all rules
6 | * @returns {Array} The all rules
7 | */
8 | function readRules() {
9 | const rules = [];
10 | const rulesLibRoot = path.resolve(__dirname, "../../lib/rules");
11 | for (const name of fs
12 | .readdirSync(rulesLibRoot)
13 | .filter((n) => n.endsWith(".ts"))) {
14 | const ruleName = name.replace(/\.ts$/u, "");
15 | const ruleId = `jsonc/${ruleName}`;
16 | // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires -- tool
17 | const rule = require(path.join(rulesLibRoot, name)).default;
18 |
19 | rule.meta.docs.ruleName = ruleName;
20 | rule.meta.docs.ruleId = ruleId;
21 |
22 | rules.push(rule);
23 | }
24 | const vueCustomBlockRulesLibRoot = path.resolve(
25 | __dirname,
26 | "../../lib/rules/vue-custom-block",
27 | );
28 | for (const name of fs.readdirSync(vueCustomBlockRulesLibRoot)) {
29 | const ruleName = `vue-custom-block/${name.replace(/\.ts$/u, "")}`;
30 | const ruleId = `jsonc/${ruleName}`;
31 | // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires -- tool
32 | const rule = require(path.join(vueCustomBlockRulesLibRoot, name)).default;
33 |
34 | rule.meta.docs.ruleName = ruleName;
35 | rule.meta.docs.ruleId = ruleId;
36 |
37 | rules.push(rule);
38 | }
39 | return rules;
40 | }
41 |
42 | export const rules = readRules();
43 |
--------------------------------------------------------------------------------
/tests/lib/rules/array-bracket-newline.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/array-bracket-newline";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("array-bracket-newline", rule, {
13 | valid: ["[]", "[\n1,\n2\n]"],
14 | invalid: [
15 | {
16 | code: "[\n1\n]",
17 | output: "[1]",
18 | errors: [
19 | "There should be no linebreak after '['.",
20 | "There should be no linebreak before ']'.",
21 | ],
22 | },
23 | {
24 | code: "[1,\n2]",
25 | output: "[\n1,\n2\n]",
26 | errors: [
27 | "A linebreak is required after '['.",
28 | "A linebreak is required before ']'.",
29 | ],
30 | },
31 | {
32 | filename: "test.vue",
33 | code: `[1,\n2][\n1\n]`,
34 | output: `[\n1,\n2\n][1]`,
35 | errors: [
36 | "A linebreak is required after '['.",
37 | "A linebreak is required before ']'.",
38 | "There should be no linebreak after '['.",
39 | "There should be no linebreak before ']'.",
40 | ],
41 | ...({
42 | languageOptions: {
43 | parser: vueParser,
44 | },
45 | } as any),
46 | },
47 | ],
48 | });
49 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: Close stale issues and PRs
2 | on:
3 | schedule:
4 | - cron: "30 1 * * *"
5 |
6 | permissions:
7 | issues: write
8 | pull-requests: write
9 |
10 | jobs:
11 | stale:
12 | if: github.repository == 'ota-meshi/eslint-plugin-jsonc'
13 | name: Close stale issues with missing information
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/stale@v9
17 | with:
18 | any-of-labels: "needs repro,needs info,needs more info"
19 | days-before-stale: 60
20 | days-before-close: 14
21 | stale-issue-message: This issue is is stale because it missing information and has been open for 60 days with no activity.
22 | stale-pr-message: This PR is is stale because it missing information and has been open for 60 days with no activity.
23 | close-issue-message: >
24 | This issue has been automatically closed because we haven't received a
25 | response from the original author 🙈. This automation helps keep the issue
26 | tracker clean from issues that aren't actionable. Please reach out if you
27 | have more information for us! 🙂
28 | close-pr-message: >
29 | This PR has been automatically closed because we haven't received a
30 | response from the original author 🙈. This automation helps keep the issue
31 | tracker clean from PRs that aren't actionable. Please reach out if you
32 | have more information for us! 🙂
33 |
--------------------------------------------------------------------------------
/docs/rules/no-unicode-codepoint-escapes.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-unicode-codepoint-escapes"
5 | description: "disallow Unicode code point escape sequences."
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-unicode-codepoint-escapes
10 |
11 | > disallow Unicode code point escape sequences.
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow Unicode code point escape sequences.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-unicode-codepoint-escapes: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": "\u0041",
29 |
30 | /* ✗ BAD */
31 | "BAD": "\u{41}"
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :rocket: Version
42 |
43 | This rule was introduced in eslint-plugin-jsonc v1.1.0
44 |
45 | ## :mag: Implementation
46 |
47 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-unicode-codepoint-escapes.ts)
48 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-unicode-codepoint-escapes.ts)
49 |
--------------------------------------------------------------------------------
/docs/rules/no-number-props.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-number-props"
5 | description: "disallow number property keys"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-number-props
10 |
11 | > disallow number property keys
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports the use of number property keys.
19 |
20 | JSON, JSONC and JSON5 do not allow number property keys.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/no-number-props: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": {
31 | "42": "foo"
32 | },
33 |
34 | /* ✗ BAD */
35 | "BAD": {
36 | 42: "foo"
37 | }
38 | }
39 | ```
40 |
41 |
42 |
43 | ## :wrench: Options
44 |
45 | Nothing.
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v0.2.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-number-props.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-number-props.ts)
55 |
--------------------------------------------------------------------------------
/.github/workflows/pkg.pr.new.yml:
--------------------------------------------------------------------------------
1 | name: Publish to pkg.pr.new
2 | on:
3 | pull_request:
4 | branches: [master]
5 | push:
6 | branches: [master]
7 | tags: ["!**"]
8 |
9 | jobs:
10 | build:
11 | if: github.repository == 'ota-meshi/eslint-plugin-jsonc'
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v5
16 | - uses: actions/setup-node@v5
17 | - name: Install Packages
18 | run: npm install -f
19 | - name: Build
20 | run: npm run build
21 | env:
22 | SYNCKIT_TS_RUNNER: oxc
23 | - run: npx pkg-pr-new publish --compact '.' --json output.json --comment=off
24 | - name: Add metadata to output
25 | uses: actions/github-script@v8
26 | with:
27 | github-token: ${{ secrets.GITHUB_TOKEN }}
28 | script: |
29 | const fs = require('fs');
30 | const output = JSON.parse(fs.readFileSync('output.json', 'utf8'));
31 | output.number = context.issue.number;
32 | output.event_name = context.eventName;
33 | output.ref = context.ref;
34 | output.sha = context.eventName === 'pull_request'
35 | ? context.payload.pull_request.head.sha
36 | : context.payload.after;
37 | fs.writeFileSync('output.json', JSON.stringify(output), 'utf8');
38 | - name: Upload output
39 | uses: actions/upload-artifact@v4
40 | with:
41 | name: output
42 | path: ./output.json
43 |
44 | - run: ls -R .
45 |
--------------------------------------------------------------------------------
/docs/rules/no-escape-sequence-in-identifier.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-escape-sequence-in-identifier"
5 | description: "disallow escape sequences in identifiers."
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-escape-sequence-in-identifier
10 |
11 | > disallow escape sequences in identifiers.
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports disallow escape sequences in identifiers.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-escape-sequence-in-identifier: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | GOOD: "GOOD",
29 |
30 | /* ✗ BAD */
31 | \u0042\u{41}\u{44}: "BAD"
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :rocket: Version
42 |
43 | This rule was introduced in eslint-plugin-jsonc v1.1.0
44 |
45 | ## :mag: Implementation
46 |
47 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-escape-sequence-in-identifier.ts)
48 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-escape-sequence-in-identifier.ts)
49 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-useless-escape.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-useless-escape";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("no-useless-escape", rule, {
13 | valid: ['"\\""'],
14 | invalid: [
15 | {
16 | filename: "test.json",
17 | code: '"hol\\a"',
18 | errors: [
19 | {
20 | message: "Unnecessary escape character: \\a.",
21 | suggestions: [
22 | { messageId: "removeEscape", output: `"hola"` },
23 | { messageId: "escapeBackslash", output: String.raw`"hol\\a"` },
24 | ],
25 | },
26 | ],
27 | },
28 | {
29 | filename: "test.vue",
30 | code: `"hol\\a"`,
31 | errors: [
32 | {
33 | message: "Unnecessary escape character: \\a.",
34 | suggestions: [
35 | {
36 | messageId: "removeEscape",
37 | output: `"hola"`,
38 | },
39 | {
40 | messageId: "escapeBackslash",
41 | output: String.raw`"hol\\a"`,
42 | },
43 | ],
44 | },
45 | ],
46 | languageOptions: {
47 | parser: vueParser,
48 | },
49 | },
50 | ],
51 | });
52 |
--------------------------------------------------------------------------------
/docs/rules/no-dupe-keys.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-dupe-keys"
5 | description: "disallow duplicate keys in object literals"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/no-dupe-keys
10 |
11 | > disallow duplicate keys in object literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule disallows duplicate keys in object literals.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/no-dupe-keys: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": {
28 | "foo": "val",
29 | "bar": "val"
30 | },
31 |
32 | /* ✗ BAD */
33 | "BAD": {
34 | "foo": "val",
35 | "foo": "val"
36 | }
37 | }
38 | ```
39 |
40 |
41 |
42 | ## :wrench: Options
43 |
44 | Nothing.
45 |
46 | ## :couple: Related rules
47 |
48 | - [no-dupe-keys]
49 |
50 | [no-dupe-keys]: https://eslint.org/docs/rules/no-dupe-keys
51 |
52 | ## :rocket: Version
53 |
54 | This rule was introduced in eslint-plugin-jsonc v0.1.0
55 |
56 | ## :mag: Implementation
57 |
58 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-dupe-keys.ts)
59 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-dupe-keys.ts)
60 |
61 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-dupe-keys)
62 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-template-literals.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-template-literals";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | ecmaVersion: 2020,
10 | },
11 | ignoreMomoa: true,
12 | });
13 |
14 | tester.run("no-template-literals", rule, {
15 | valid: ['{"key": "value"}', '"string"', '["element"]'],
16 | invalid: [
17 | {
18 | code: "`template`",
19 | output: '"template"',
20 | errors: ["The template literals are not allowed."],
21 | },
22 | {
23 | code: "[`template`]",
24 | output: '["template"]',
25 | errors: ["The template literals are not allowed."],
26 | },
27 | {
28 | code: '{"foo":`template`}',
29 | output: '{"foo":"template"}',
30 | errors: ["The template literals are not allowed."],
31 | },
32 | {
33 | code: "`temp\n\nlate`",
34 | output: '"temp\\n\\nlate"',
35 | errors: ["The template literals are not allowed."],
36 | },
37 | {
38 | filename: "test.vue",
39 | code: `{"foo":\`template\`}`,
40 | output: `{"foo":"template"}`,
41 | errors: ["The template literals are not allowed."],
42 | ...({
43 | languageOptions: {
44 | parser: vueParser,
45 | },
46 | } as any),
47 | },
48 | ],
49 | });
50 |
--------------------------------------------------------------------------------
/docs/rules/auto.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/auto"
5 | description: "apply jsonc rules similar to your configured ESLint core rules"
6 | since: "v0.8.0"
7 | ---
8 |
9 | # jsonc/auto
10 |
11 | > apply jsonc rules similar to your configured ESLint core rules
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | Automatically apply jsonc rules similar to your configured ESLint core rules to JSON.
18 |
19 | This rule checks the ESLint core rules you are already using in your configuration and automatically turns ON the equivalent [Extension Rules](./index.md#extension-rules) provided by this plugin.
20 |
21 | If you have already configured a particular jsonc rule, either explicitly or via a shared configuration, then that will take precedence over `jsonc/auto`. For example, if you use the `"plugin:jsonc/recommended-with-json"` configuration, the `auto` rule will not turn ON the `jsonc/comma-dangle` rule even if the `comma-dangle` rule is enabled in your core ESLint config.
22 |
23 | ## :wrench: Options
24 |
25 | Nothing.
26 |
27 | ## :rocket: Version
28 |
29 | This rule was introduced in eslint-plugin-jsonc v0.8.0
30 |
31 | ## :mag: Implementation
32 |
33 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/auto.ts)
34 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/auto.ts)
35 |
--------------------------------------------------------------------------------
/docs/rules/no-numeric-separators.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-numeric-separators"
5 | description: "disallow numeric separators"
6 | since: "v0.6.0"
7 | ---
8 |
9 | # jsonc/no-numeric-separators
10 |
11 | > disallow numeric separators
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports the use of numeric separators.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-numeric-separators: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": 1234567890,
29 |
30 | /* ✗ BAD */
31 | "BAD": 1_234_567_890
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [jsonc/valid-json-number]
44 |
45 | [jsonc/valid-json-number]: ./valid-json-number.md
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v0.6.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-numeric-separators.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-numeric-separators.ts)
55 |
--------------------------------------------------------------------------------
/docs/rules/no-octal-numeric-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-octal-numeric-literals"
5 | description: "disallow octal numeric literals"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-octal-numeric-literals
10 |
11 | > disallow octal numeric literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow octal numeric literals.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-octal-numeric-literals: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": 511,
29 |
30 | /* ✗ BAD */
31 | "BAD": 0o777
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [jsonc/valid-json-number]
44 |
45 | [jsonc/valid-json-number]: ./valid-json-number.md
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v1.1.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-octal-numeric-literals.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-octal-numeric-literals.ts)
55 |
--------------------------------------------------------------------------------
/docs/rules/no-binary-numeric-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-binary-numeric-literals"
5 | description: "disallow binary numeric literals"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-binary-numeric-literals
10 |
11 | > disallow binary numeric literals
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow binary numeric literals
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-binary-numeric-literals: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": 10,
29 |
30 | /* ✗ BAD */
31 | "BAD": 0b1010
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [jsonc/valid-json-number]
44 |
45 | [jsonc/valid-json-number]: ./valid-json-number.md
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v1.1.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-binary-numeric-literals.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-binary-numeric-literals.ts)
55 |
--------------------------------------------------------------------------------
/.github/workflows/Release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | release:
10 | # prevents this action from running on forks
11 | if: github.repository == 'ota-meshi/eslint-plugin-jsonc'
12 | permissions:
13 | id-token: write # Required for OIDC
14 | contents: write # to create release (changesets/action)
15 | pull-requests: write # to create pull request (changesets/action)
16 | name: Release
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: Checkout Repo
20 | uses: actions/checkout@v4
21 | with:
22 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
23 | fetch-depth: 0
24 | - name: Setup Node.js
25 | uses: actions/setup-node@v5
26 | with:
27 | node-version: 24
28 | - name: Install Dependencies
29 | run: npm install -f
30 | - name: Create Release Pull Request or Publish to npm
31 | id: changesets
32 | uses: changesets/action@v1
33 | with:
34 | # this expects you to have a npm script called version that runs some logic and then calls `changeset version`.
35 | version: npm run version:ci
36 | # This expects you to have a script called release which does a build for your packages and calls changeset publish
37 | publish: npm run release
38 | commit: "chore: release eslint-plugin-jsonc"
39 | title: "chore: release eslint-plugin-jsonc"
40 | env:
41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42 |
--------------------------------------------------------------------------------
/lib/configs/recommended-with-jsonc.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import path from "path";
5 | const base = require.resolve("./base");
6 | const baseExtend =
7 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
8 | export = {
9 | extends: [baseExtend],
10 | rules: {
11 | // eslint-plugin-jsonc rules
12 | "jsonc/no-bigint-literals": "error",
13 | "jsonc/no-binary-expression": "error",
14 | "jsonc/no-binary-numeric-literals": "error",
15 | "jsonc/no-dupe-keys": "error",
16 | "jsonc/no-escape-sequence-in-identifier": "error",
17 | "jsonc/no-floating-decimal": "error",
18 | "jsonc/no-hexadecimal-numeric-literals": "error",
19 | "jsonc/no-infinity": "error",
20 | "jsonc/no-multi-str": "error",
21 | "jsonc/no-nan": "error",
22 | "jsonc/no-number-props": "error",
23 | "jsonc/no-numeric-separators": "error",
24 | "jsonc/no-octal-numeric-literals": "error",
25 | "jsonc/no-octal": "error",
26 | "jsonc/no-parenthesized": "error",
27 | "jsonc/no-plus-sign": "error",
28 | "jsonc/no-regexp-literals": "error",
29 | "jsonc/no-sparse-arrays": "error",
30 | "jsonc/no-template-literals": "error",
31 | "jsonc/no-undefined-value": "error",
32 | "jsonc/no-unicode-codepoint-escapes": "error",
33 | "jsonc/no-useless-escape": "error",
34 | "jsonc/quote-props": "error",
35 | "jsonc/quotes": "error",
36 | "jsonc/space-unary-ops": "error",
37 | "jsonc/valid-json-number": "error",
38 | "jsonc/vue-custom-block/no-parsing-error": "error",
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/lib/configs/flat/recommended-with-jsonc.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import type { Linter } from "eslint";
5 | import base from "./base";
6 | export default [
7 | ...base,
8 | {
9 | rules: {
10 | // eslint-plugin-jsonc rules
11 | "jsonc/no-bigint-literals": "error",
12 | "jsonc/no-binary-expression": "error",
13 | "jsonc/no-binary-numeric-literals": "error",
14 | "jsonc/no-dupe-keys": "error",
15 | "jsonc/no-escape-sequence-in-identifier": "error",
16 | "jsonc/no-floating-decimal": "error",
17 | "jsonc/no-hexadecimal-numeric-literals": "error",
18 | "jsonc/no-infinity": "error",
19 | "jsonc/no-multi-str": "error",
20 | "jsonc/no-nan": "error",
21 | "jsonc/no-number-props": "error",
22 | "jsonc/no-numeric-separators": "error",
23 | "jsonc/no-octal-numeric-literals": "error",
24 | "jsonc/no-octal": "error",
25 | "jsonc/no-parenthesized": "error",
26 | "jsonc/no-plus-sign": "error",
27 | "jsonc/no-regexp-literals": "error",
28 | "jsonc/no-sparse-arrays": "error",
29 | "jsonc/no-template-literals": "error",
30 | "jsonc/no-undefined-value": "error",
31 | "jsonc/no-unicode-codepoint-escapes": "error",
32 | "jsonc/no-useless-escape": "error",
33 | "jsonc/quote-props": "error",
34 | "jsonc/quotes": "error",
35 | "jsonc/space-unary-ops": "error",
36 | "jsonc/valid-json-number": "error",
37 | "jsonc/vue-custom-block/no-parsing-error": "error",
38 | },
39 | },
40 | ] satisfies Linter.FlatConfig[];
41 |
--------------------------------------------------------------------------------
/docs/rules/no-hexadecimal-numeric-literals.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-hexadecimal-numeric-literals"
5 | description: "disallow hexadecimal numeric literals"
6 | since: "v1.1.0"
7 | ---
8 |
9 | # jsonc/no-hexadecimal-numeric-literals
10 |
11 | > disallow hexadecimal numeric literals
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule disallow hexadecimal numeric literals.
19 |
20 | Cannot use hexadecimal numeric literals when in JSON and JSONC.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/no-hexadecimal-numeric-literals: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": 65535,
31 |
32 | /* ✗ BAD */
33 | "BAD": 0xFFFF
34 | }
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :couple: Related rules
44 |
45 | - [jsonc/valid-json-number]
46 |
47 | [jsonc/valid-json-number]: ./valid-json-number.md
48 |
49 | ## :rocket: Version
50 |
51 | This rule was introduced in eslint-plugin-jsonc v1.1.0
52 |
53 | ## :mag: Implementation
54 |
55 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-hexadecimal-numeric-literals.ts)
56 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-hexadecimal-numeric-literals.ts)
57 |
--------------------------------------------------------------------------------
/docs/rules/no-useless-escape.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-useless-escape"
5 | description: "disallow unnecessary escape usage"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/no-useless-escape
10 |
11 | > disallow unnecessary escape usage
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
15 |
16 | ## :book: Rule Details
17 |
18 | This rule flags escapes that can be safely removed without changing behavior.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/no-useless-escape: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": "\"",
29 |
30 | /* ✗ BAD */
31 | "BAD": "hol\a"
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [no-useless-escape]
44 |
45 | [no-useless-escape]: https://eslint.org/docs/rules/no-useless-escape
46 |
47 | ## :rocket: Version
48 |
49 | This rule was introduced in eslint-plugin-jsonc v0.1.0
50 |
51 | ## :mag: Implementation
52 |
53 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-useless-escape.ts)
54 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-useless-escape.ts)
55 |
56 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-useless-escape)
57 |
--------------------------------------------------------------------------------
/docs/rules/no-sparse-arrays.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-sparse-arrays"
5 | description: "disallow sparse arrays"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/no-sparse-arrays
10 |
11 | > disallow sparse arrays
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule disallows sparse array literals which have "holes" where commas are not preceded by elements. It does not apply to a trailing comma following the last element.
18 |
19 | JSON, JSONC and JSON5 do not allow arrays contain empty slots.
20 |
21 |
22 |
23 |
24 |
25 | ```json5
26 | /* eslint jsonc/no-sparse-arrays: 'error' */
27 | {
28 | /* ✓ GOOD */
29 | "GOOD": [1, 2, 3, 4],
30 | "GOOD": [1, 2, 3, 4,],
31 |
32 | /* ✗ BAD */
33 | "BAD": [1, , , 4],
34 | "BAD": [, 2, 3, 4]
35 | }
36 | ```
37 |
38 |
39 |
40 | ## :wrench: Options
41 |
42 | Nothing.
43 |
44 | ## :couple: Related rules
45 |
46 | - [no-sparse-arrays]
47 |
48 | [no-sparse-arrays]: https://eslint.org/docs/rules/no-sparse-arrays
49 |
50 | ## :rocket: Version
51 |
52 | This rule was introduced in eslint-plugin-jsonc v0.2.0
53 |
54 | ## :mag: Implementation
55 |
56 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-sparse-arrays.ts)
57 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-sparse-arrays.ts)
58 |
59 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-sparse-arrays)
60 |
--------------------------------------------------------------------------------
/tests/lib/rules/space-unary-ops.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/space-unary-ops";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 | import * as vueParser from "vue-eslint-parser";
5 |
6 | const tester = new RuleTester({
7 | languageOptions: {
8 | parser: jsonParser,
9 | },
10 | });
11 |
12 | tester.run("space-unary-ops", rule, {
13 | valid: ["-1", "+1", "-0", "+0"],
14 | invalid: [
15 | {
16 | code: "[- 1, + 1, - 0, + 0]",
17 | output: "[-1, +1, -0, +0]",
18 | errors: [
19 | {
20 | message: "Unexpected space after unary operator '-'.",
21 | line: 1,
22 | column: 2,
23 | endColumn: 5,
24 | },
25 | {
26 | message: "Unexpected space after unary operator '+'.",
27 | line: 1,
28 | column: 7,
29 | endColumn: 11,
30 | },
31 | {
32 | message: "Unexpected space after unary operator '-'.",
33 | line: 1,
34 | column: 13,
35 | endColumn: 17,
36 | },
37 | {
38 | message: "Unexpected space after unary operator '+'.",
39 | line: 1,
40 | column: 19,
41 | endColumn: 23,
42 | },
43 | ],
44 | ignoreMomoa: true,
45 | },
46 | {
47 | filename: "test.vue",
48 | code: `- 1`,
49 | output: `-1`,
50 | errors: ["Unexpected space after unary operator '-'."],
51 | ...({
52 | languageOptions: {
53 | parser: vueParser,
54 | },
55 | } as any),
56 | },
57 | ],
58 | });
59 |
--------------------------------------------------------------------------------
/lib/configs/recommended-with-json.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import path from "path";
5 | const base = require.resolve("./base");
6 | const baseExtend =
7 | path.extname(`${base}`) === ".ts" ? "plugin:jsonc/base" : base;
8 | export = {
9 | extends: [baseExtend],
10 | rules: {
11 | // eslint-plugin-jsonc rules
12 | "jsonc/comma-dangle": "error",
13 | "jsonc/no-bigint-literals": "error",
14 | "jsonc/no-binary-expression": "error",
15 | "jsonc/no-binary-numeric-literals": "error",
16 | "jsonc/no-comments": "error",
17 | "jsonc/no-dupe-keys": "error",
18 | "jsonc/no-escape-sequence-in-identifier": "error",
19 | "jsonc/no-floating-decimal": "error",
20 | "jsonc/no-hexadecimal-numeric-literals": "error",
21 | "jsonc/no-infinity": "error",
22 | "jsonc/no-multi-str": "error",
23 | "jsonc/no-nan": "error",
24 | "jsonc/no-number-props": "error",
25 | "jsonc/no-numeric-separators": "error",
26 | "jsonc/no-octal-numeric-literals": "error",
27 | "jsonc/no-octal": "error",
28 | "jsonc/no-parenthesized": "error",
29 | "jsonc/no-plus-sign": "error",
30 | "jsonc/no-regexp-literals": "error",
31 | "jsonc/no-sparse-arrays": "error",
32 | "jsonc/no-template-literals": "error",
33 | "jsonc/no-undefined-value": "error",
34 | "jsonc/no-unicode-codepoint-escapes": "error",
35 | "jsonc/no-useless-escape": "error",
36 | "jsonc/quote-props": "error",
37 | "jsonc/quotes": "error",
38 | "jsonc/space-unary-ops": "error",
39 | "jsonc/valid-json-number": "error",
40 | "jsonc/vue-custom-block/no-parsing-error": "error",
41 | },
42 | };
43 |
--------------------------------------------------------------------------------
/lib/configs/flat/recommended-with-json.ts:
--------------------------------------------------------------------------------
1 | // IMPORTANT!
2 | // This file has been automatically generated,
3 | // in order to update its content execute "npm run update"
4 | import type { Linter } from "eslint";
5 | import base from "./base";
6 | export default [
7 | ...base,
8 | {
9 | rules: {
10 | // eslint-plugin-jsonc rules
11 | "jsonc/comma-dangle": "error",
12 | "jsonc/no-bigint-literals": "error",
13 | "jsonc/no-binary-expression": "error",
14 | "jsonc/no-binary-numeric-literals": "error",
15 | "jsonc/no-comments": "error",
16 | "jsonc/no-dupe-keys": "error",
17 | "jsonc/no-escape-sequence-in-identifier": "error",
18 | "jsonc/no-floating-decimal": "error",
19 | "jsonc/no-hexadecimal-numeric-literals": "error",
20 | "jsonc/no-infinity": "error",
21 | "jsonc/no-multi-str": "error",
22 | "jsonc/no-nan": "error",
23 | "jsonc/no-number-props": "error",
24 | "jsonc/no-numeric-separators": "error",
25 | "jsonc/no-octal-numeric-literals": "error",
26 | "jsonc/no-octal": "error",
27 | "jsonc/no-parenthesized": "error",
28 | "jsonc/no-plus-sign": "error",
29 | "jsonc/no-regexp-literals": "error",
30 | "jsonc/no-sparse-arrays": "error",
31 | "jsonc/no-template-literals": "error",
32 | "jsonc/no-undefined-value": "error",
33 | "jsonc/no-unicode-codepoint-escapes": "error",
34 | "jsonc/no-useless-escape": "error",
35 | "jsonc/quote-props": "error",
36 | "jsonc/quotes": "error",
37 | "jsonc/space-unary-ops": "error",
38 | "jsonc/valid-json-number": "error",
39 | "jsonc/vue-custom-block/no-parsing-error": "error",
40 | },
41 | },
42 | ] satisfies Linter.FlatConfig[];
43 |
--------------------------------------------------------------------------------
/tests-integrations/lib/vue-eslint-parser-option.ts:
--------------------------------------------------------------------------------
1 | import cp from "child_process";
2 | import assert from "assert";
3 | import path from "path";
4 | import { version } from "../../package.json";
5 |
6 | // -----------------------------------------------------------------------------
7 | // Tests
8 | // -----------------------------------------------------------------------------
9 |
10 | const TEST_CWD = path.join(__dirname, "../fixtures/vue-eslint-parser-option");
11 | const ESLINT = path.join(TEST_CWD, `./node_modules/.bin/eslint`);
12 |
13 | describe("Integration with vue-eslint-parser with option", () => {
14 | let originalCwd: string;
15 |
16 | before(() => {
17 | originalCwd = process.cwd();
18 | process.chdir(TEST_CWD);
19 | cp.execSync(`npm i -D ../../../eslint-plugin-jsonc-${version}.tgz`, {
20 | stdio: "inherit",
21 | });
22 | cp.execSync("npm i", { stdio: "inherit" });
23 | });
24 | after(() => {
25 | process.chdir(originalCwd);
26 | });
27 |
28 | it("should lint errors", () => {
29 | try {
30 | const res = cp.execSync(`${ESLINT} "./test.json" --format json`, {
31 | env: {
32 | // eslint-disable-next-line no-process-env -- Legacy Config test
33 | ...process.env,
34 | ESLINT_USE_FLAT_CONFIG: "false",
35 | },
36 | });
37 | console.log(`${res}`);
38 | } catch (e: any) {
39 | const results = JSON.parse(`${e.stdout}`);
40 |
41 | assert.strictEqual(results.length, 1);
42 | assert.strictEqual(results[0].messages.length, 1);
43 | assert.strictEqual(
44 | results[0].messages[0].message,
45 | "Expected indentation of 4 spaces but found 0.",
46 | );
47 | return;
48 | }
49 | assert.fail("Expect error");
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/tests-integrations/lib/eslint-plugin-markdown.ts:
--------------------------------------------------------------------------------
1 | import cp from "child_process";
2 | import assert from "assert";
3 | import path from "path";
4 | import { version } from "../../package.json";
5 |
6 | // -----------------------------------------------------------------------------
7 | // Tests
8 | // -----------------------------------------------------------------------------
9 |
10 | const TEST_CWD = path.join(__dirname, "../fixtures/eslint-plugin-markdown");
11 | const ESLINT = path.join(TEST_CWD, `./node_modules/.bin/eslint`);
12 |
13 | describe("Integration with eslint-plugin-markdown", () => {
14 | let originalCwd: string;
15 |
16 | before(() => {
17 | originalCwd = process.cwd();
18 | process.chdir(TEST_CWD);
19 | cp.execSync(`npm i -D ../../../eslint-plugin-jsonc-${version}.tgz`, {
20 | stdio: "inherit",
21 | });
22 | cp.execSync("npm i", { stdio: "inherit" });
23 | });
24 | after(() => {
25 | process.chdir(originalCwd);
26 | });
27 |
28 | it("should lint errors", () => {
29 | try {
30 | const res = cp.execSync(`${ESLINT} "./test.md" --format json`, {
31 | env: {
32 | // eslint-disable-next-line no-process-env -- Legacy Config test
33 | ...process.env,
34 | ESLINT_USE_FLAT_CONFIG: "false",
35 | },
36 | });
37 | console.log(`${res}`);
38 | } catch (e: any) {
39 | const results = JSON.parse(`${e.stdout}`);
40 |
41 | assert.strictEqual(results.length, 1);
42 | assert.strictEqual(results[0].messages.length, 1);
43 | assert.strictEqual(
44 | results[0].messages[0].message,
45 | "[jsonc/array-bracket-newline] There should be no linebreak before ']'.",
46 | );
47 | return;
48 | }
49 | assert.fail("Expect error");
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/docs/rules/space-unary-ops.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/space-unary-ops"
5 | description: "disallow spaces after unary operators"
6 | since: "v0.2.0"
7 | ---
8 |
9 | # jsonc/space-unary-ops
10 |
11 | > disallow spaces after unary operators
12 |
13 | - :gear: This rule is included in all of `"plugin:jsonc/recommended-with-json"`, `"plugin:jsonc/recommended-with-json5"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports the space after the sign operator.
19 |
20 | JSON, JSONC and JSON5 do not allow spaces after the sign.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/space-unary-ops: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": -42,
31 |
32 | /* ✗ BAD */
33 | "BAD": - 42
34 | }
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :couple: Related rules
44 |
45 | - [space-unary-ops]
46 | - [jsonc/valid-json-number]
47 |
48 | [space-unary-ops]: https://eslint.org/docs/rules/space-unary-ops
49 | [jsonc/valid-json-number]: ./valid-json-number.md
50 |
51 | ## :rocket: Version
52 |
53 | This rule was introduced in eslint-plugin-jsonc v0.2.0
54 |
55 | ## :mag: Implementation
56 |
57 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/space-unary-ops.ts)
58 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/space-unary-ops.ts)
59 |
60 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/space-unary-ops)
61 |
--------------------------------------------------------------------------------
/docs/rules/array-bracket-spacing.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/array-bracket-spacing"
5 | description: "disallow or enforce spaces inside of brackets"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/array-bracket-spacing
10 |
11 | > disallow or enforce spaces inside of brackets
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces consistent spacing inside array brackets.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/array-bracket-spacing: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": [1, 2, 3],
28 |
29 | /* ✗ BAD */
30 | "BAD": [ 1, 2, 3 ]
31 | }
32 | ```
33 |
34 |
35 |
36 | ## :wrench: Options
37 |
38 | ```json
39 | {
40 | "jsonc/array-bracket-spacing": ["error",
41 | "never"
42 | ]
43 | }
44 | ```
45 |
46 | Same as [array-bracket-spacing] rule option. See [here](https://eslint.org/docs/rules/array-bracket-spacing#options) for details.
47 |
48 | ## :couple: Related rules
49 |
50 | - [array-bracket-spacing]
51 |
52 | [array-bracket-spacing]: https://eslint.org/docs/rules/array-bracket-spacing
53 |
54 | ## :rocket: Version
55 |
56 | This rule was introduced in eslint-plugin-jsonc v0.1.0
57 |
58 | ## :mag: Implementation
59 |
60 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/array-bracket-spacing.ts)
61 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/array-bracket-spacing.ts)
62 |
63 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/array-bracket-spacing)
64 |
--------------------------------------------------------------------------------
/docs/rules/object-curly-spacing.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/object-curly-spacing"
5 | description: "enforce consistent spacing inside braces"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/object-curly-spacing
10 |
11 | > enforce consistent spacing inside braces
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces consistent spacing inside braces of object literals.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/object-curly-spacing: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": {"foo": "bar"},
28 |
29 | /* ✗ BAD */
30 | "BAD": { "foo": "bar" },
31 | }
32 | ```
33 |
34 |
35 |
36 | ## :wrench: Options
37 |
38 | ```json
39 | {
40 | "jsonc/object-curly-spacing": ["error",
41 | "never"
42 | ]
43 | }
44 | ```
45 |
46 | Same as [object-curly-spacing] rule option. See [here](https://eslint.org/docs/rules/object-curly-spacing#options) for details.
47 |
48 | ## :couple: Related rules
49 |
50 | - [object-curly-spacing]
51 |
52 | [object-curly-spacing]: https://eslint.org/docs/rules/object-curly-spacing
53 |
54 | ## :rocket: Version
55 |
56 | This rule was introduced in eslint-plugin-jsonc v0.1.0
57 |
58 | ## :mag: Implementation
59 |
60 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/object-curly-spacing.ts)
61 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/object-curly-spacing.ts)
62 |
63 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/object-curly-spacing)
64 |
--------------------------------------------------------------------------------
/docs/rules/array-element-newline.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/array-element-newline"
5 | description: "enforce line breaks between array elements"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/array-element-newline
10 |
11 | > enforce line breaks between array elements
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces line breaks between array elements.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/array-element-newline: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": [1,
28 | 2,
29 | 3],
30 |
31 | /* ✗ BAD */
32 | "BAD": [1, 2, 3]
33 | }
34 | ```
35 |
36 |
37 |
38 | ## :wrench: Options
39 |
40 | ```json
41 | {
42 | "jsonc/array-element-newline": ["error",
43 | "always"
44 | ]
45 | }
46 | ```
47 |
48 | Same as [array-element-newline] rule option. See [here](https://eslint.org/docs/rules/array-element-newline#options) for details.
49 |
50 | ## :couple: Related rules
51 |
52 | - [array-element-newline]
53 |
54 | [array-element-newline]: https://eslint.org/docs/rules/array-element-newline
55 |
56 | ## :rocket: Version
57 |
58 | This rule was introduced in eslint-plugin-jsonc v0.1.0
59 |
60 | ## :mag: Implementation
61 |
62 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/array-element-newline.ts)
63 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/array-element-newline.ts)
64 |
65 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/array-element-newline)
66 |
--------------------------------------------------------------------------------
/docs/rules/comma-style.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/comma-style"
5 | description: "enforce consistent comma style"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/comma-style
10 |
11 | > enforce consistent comma style
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforce consistent comma style in array literals and object literals.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/comma-style: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": ["apples",
28 | "oranges"],
29 | "GOOD": {
30 | "a": 1,
31 | "b": 2
32 | },
33 |
34 | /* ✗ BAD */
35 | "BAD": ["apples"
36 | , "oranges"]
37 | ,"BAD": {
38 | "a": 1
39 | , "b": 2
40 | }
41 | }
42 | ```
43 |
44 |
45 |
46 | ## :wrench: Options
47 |
48 | ```json
49 | {
50 | "jsonc/comma-style": ["error",
51 | "last"
52 | ]
53 | }
54 | ```
55 |
56 | Same as [comma-style] rule option. See [here](https://eslint.org/docs/rules/comma-style#options) for details.
57 |
58 | ## :couple: Related rules
59 |
60 | - [comma-style]
61 |
62 | [comma-style]: https://eslint.org/docs/rules/comma-style
63 |
64 | ## :rocket: Version
65 |
66 | This rule was introduced in eslint-plugin-jsonc v0.1.0
67 |
68 | ## :mag: Implementation
69 |
70 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/comma-style.ts)
71 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/comma-style.ts)
72 |
73 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/comma-style)
74 |
--------------------------------------------------------------------------------
/docs/rules/indent.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/indent"
5 | description: "enforce consistent indentation"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/indent
10 |
11 | > enforce consistent indentation
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces a consistent indentation style. The default style is `4 spaces`.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/indent: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": {
28 | "GOOD": "foo"
29 | },
30 |
31 | /* ✗ BAD */
32 | "BAD": {
33 | "BAD": "bar"
34 | }
35 | }
36 | ```
37 |
38 |
39 |
40 | ## :wrench: Options
41 |
42 | ```json
43 | {
44 | "jsonc/indent": ["error",
45 | 4,
46 | {}
47 | ]
48 | }
49 | ```
50 |
51 | Same as [indent] rule option. See [here](https://eslint.org/docs/rules/indent#options) for details.
52 |
53 | - First option ... Sets the indentation style. default `4`
54 | Set to `2` if you prefer 2 spaces indentation.
55 | Set to `"tab"` if you prefer tab indentation.
56 | - Second option ... You can set the object to customize it further.
57 |
58 | ## :couple: Related rules
59 |
60 | - [indent]
61 |
62 | [indent]: https://eslint.org/docs/rules/indent
63 |
64 | ## :rocket: Version
65 |
66 | This rule was introduced in eslint-plugin-jsonc v0.1.0
67 |
68 | ## :mag: Implementation
69 |
70 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/indent.ts)
71 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/indent.ts)
72 |
73 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/indent)
74 |
--------------------------------------------------------------------------------
/docs/rules/no-floating-decimal.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-floating-decimal"
5 | description: "disallow leading or trailing decimal points in numeric literals"
6 | since: "v0.9.0"
7 | ---
8 |
9 | # jsonc/no-floating-decimal
10 |
11 | > disallow leading or trailing decimal points in numeric literals
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule is aimed at eliminating floating decimal points and will warn whenever a numeric value has a decimal point but is missing a number either before or after it.
19 |
20 | Cannot use floating decimal points when in JSON and JSONC.
21 |
22 |
23 |
24 |
25 |
26 | ```json5
27 | /* eslint jsonc/no-floating-decimal: 'error' */
28 | {
29 | /* ✓ GOOD */
30 | "GOOD": 42.0,
31 |
32 | /* ✗ BAD */
33 | "BAD": 42.
34 | }
35 | ```
36 |
37 |
38 |
39 | ## :wrench: Options
40 |
41 | Nothing.
42 |
43 | ## :couple: Related rules
44 |
45 | - [no-floating-decimal]
46 | - [jsonc/valid-json-number]
47 |
48 | [no-floating-decimal]: https://eslint.org/docs/rules/no-floating-decimal
49 | [jsonc/valid-json-number]: ./valid-json-number.md
50 |
51 | ## :rocket: Version
52 |
53 | This rule was introduced in eslint-plugin-jsonc v0.9.0
54 |
55 | ## :mag: Implementation
56 |
57 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-floating-decimal.ts)
58 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-floating-decimal.ts)
59 |
60 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-floating-decimal)
61 |
--------------------------------------------------------------------------------
/docs/.vitepress/build-system/build.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Pre-build cjs packages that cannot be bundled well.
3 | */
4 | import esbuild from "esbuild";
5 | import path from "path";
6 | import fs from "fs";
7 | import { fileURLToPath } from "url";
8 |
9 | const dirname = path.dirname(
10 | fileURLToPath(
11 | // @ts-expect-error -- Cannot change `module` option
12 | import.meta.url,
13 | ),
14 | );
15 |
16 | build(
17 | path.join(dirname, "./src/vue-eslint-parser.mjs"),
18 | path.join(dirname, "./shim/vue-eslint-parser.mjs"),
19 | ["eslint", "path", "module", "events"],
20 | );
21 | build(
22 | path.join(dirname, "./src/events.mjs"),
23 | path.join(dirname, "./shim/events.mjs"),
24 | [],
25 | );
26 |
27 | function build(input: string, out: string, injects: string[] = []) {
28 | // eslint-disable-next-line no-console -- ignore
29 | console.log(`build@ ${input}`);
30 | let code = bundle(input, injects);
31 | code = transform(code, injects);
32 | fs.mkdirSync(path.dirname(out), { recursive: true });
33 | fs.writeFileSync(out, code, "utf8");
34 | }
35 |
36 | function bundle(entryPoint: string, externals: string[]) {
37 | const result = esbuild.buildSync({
38 | entryPoints: [entryPoint],
39 | format: "esm",
40 | bundle: true,
41 | external: externals,
42 | write: false,
43 | });
44 |
45 | return `${result.outputFiles[0].text}`;
46 | }
47 |
48 | function transform(code: string, injects: string[]) {
49 | const newCode = code.replace(/"[a-z]+" = "[a-z]+";/u, "");
50 | return `
51 | ${injects
52 | .map(
53 | (inject) =>
54 | `import $inject_${inject.replace(/-/gu, "_")}$ from '${inject}';`,
55 | )
56 | .join("\n")}
57 | const $_injects_$ = {${injects
58 | .map((inject) => `${inject.replace(/-/gu, "_")}:$inject_${inject}$`)
59 | .join(",\n")}};
60 | function require(module, ...args) {
61 | return $_injects_$[module] || {}
62 | }
63 | ${newCode}
64 |
65 | if (typeof __require !== 'undefined') __require.cache = {};
66 | `;
67 | }
68 |
--------------------------------------------------------------------------------
/docs/rules/object-curly-newline.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/object-curly-newline"
5 | description: "enforce consistent line breaks inside braces"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/object-curly-newline
10 |
11 | > enforce consistent line breaks inside braces
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces consistent line breaks inside braces of object literals.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/object-curly-newline: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": {"foo": "bar"},
28 | "GOOD": {
29 | "foo": "bar"
30 | },
31 |
32 | /* ✗ BAD */
33 | "BAD": {"foo": "bar"
34 | },
35 | "BAD": {
36 | "foo": "bar"}
37 | }
38 | ```
39 |
40 |
41 |
42 | ## :wrench: Options
43 |
44 | ```json
45 | {
46 | "jsonc/object-curly-newline": ["error",
47 | {
48 | "consistent": true
49 | }
50 | ]
51 | }
52 | ```
53 |
54 | Same as [object-curly-newline] rule option. See [here](https://eslint.org/docs/rules/object-curly-newline#options) for details.
55 |
56 | ## :couple: Related rules
57 |
58 | - [object-curly-newline]
59 |
60 | [object-curly-newline]: https://eslint.org/docs/rules/object-curly-newline
61 |
62 | ## :rocket: Version
63 |
64 | This rule was introduced in eslint-plugin-jsonc v0.1.0
65 |
66 | ## :mag: Implementation
67 |
68 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/object-curly-newline.ts)
69 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/object-curly-newline.ts)
70 |
71 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/object-curly-newline)
72 |
--------------------------------------------------------------------------------
/docs/rules/key-spacing.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/key-spacing"
5 | description: "enforce consistent spacing between keys and values in object literal properties"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/key-spacing
10 |
11 | > enforce consistent spacing between keys and values in object literal properties
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces consistent spacing between keys and values in object literal properties. In the case of long lines, it is acceptable to add a new line wherever whitespace is allowed.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/key-spacing: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": "foo",
28 |
29 | /* ✗ BAD */
30 | "BAD" :"bar"
31 | }
32 | ```
33 |
34 |
35 |
36 | ## :wrench: Options
37 |
38 | ```json
39 | {
40 | "jsonc/key-spacing": ["error",
41 | {
42 | "beforeColon": false,
43 | "afterColon": true,
44 | "mode": "strict"
45 | }
46 | ]
47 | }
48 | ```
49 |
50 | Same as [key-spacing] rule option. See [here](https://eslint.org/docs/rules/key-spacing#options) for details.
51 |
52 | ## :couple: Related rules
53 |
54 | - [key-spacing]
55 |
56 | [key-spacing]: https://eslint.org/docs/rules/key-spacing
57 |
58 | ## :rocket: Version
59 |
60 | This rule was introduced in eslint-plugin-jsonc v0.1.0
61 |
62 | ## :mag: Implementation
63 |
64 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/key-spacing.ts)
65 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/key-spacing.ts)
66 |
67 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/key-spacing)
68 |
--------------------------------------------------------------------------------
/docs/rules/key-name-casing.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/key-name-casing"
5 | description: "enforce naming convention to property key names"
6 | since: "v0.8.0"
7 | ---
8 |
9 | # jsonc/key-name-casing
10 |
11 | > enforce naming convention to property key names
12 |
13 | ## :book: Rule Details
14 |
15 | This rule enforces a naming convention to property key names.
16 |
17 |
18 |
19 |
20 |
21 | ```json5
22 | /* eslint jsonc/key-name-casing: 'error' */
23 | {
24 | /* ✓ GOOD */
25 | "camelCase": "camelCase",
26 |
27 | /* ✗ BAD */
28 | "PascalCase": "PascalCase",
29 | "SCREAMING_SNAKE_CASE": "SCREAMING_SNAKE_CASE",
30 | "kebab-case": "kebab-case",
31 | "snake_case": "snake_case"
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | ```json5
40 | {
41 | "jsonc/key-name-casing": ["error",
42 | {
43 | "camelCase": true,
44 | "PascalCase": false,
45 | "SCREAMING_SNAKE_CASE": false,
46 | "kebab-case": false,
47 | "snake_case": false,
48 | "ignores": []
49 | }
50 | ]
51 | }
52 | ```
53 |
54 | - `"camelCase"` ... if `true`, allows camelCase naming. default `true`
55 | - `"PascalCase"` ... if `true`, allows PascalCase naming. default `false`
56 | - `"SCREAMING_SNAKE_CASE"` ... if `true`, allows SCREAMING_SNAKE_CASE naming. default `false`
57 | - `"kebab-case"` ... if `true`, allows kebab-case naming. default `false`
58 | - `"snake_case"` ... if `true`, allows snake_case naming. default `false`
59 | - `"ignores"` ... you can specify the patterns to ignore in the array.
60 |
61 | ## :rocket: Version
62 |
63 | This rule was introduced in eslint-plugin-jsonc v0.8.0
64 |
65 | ## :mag: Implementation
66 |
67 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/key-name-casing.ts)
68 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/key-name-casing.ts)
69 |
--------------------------------------------------------------------------------
/docs/rules/array-bracket-newline.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/array-bracket-newline"
5 | description: "enforce line breaks after opening and before closing array brackets"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/array-bracket-newline
10 |
11 | > enforce line breaks after opening and before closing array brackets
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule enforces line breaks after opening and before closing array brackets.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/array-bracket-newline: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": [1, 2, 3],
28 | "GOOD": [
29 | 1,
30 | 2,
31 | 3
32 | ],
33 |
34 | /* ✗ BAD */
35 | "BAD": [
36 | 1, 2, 3
37 | ],
38 | "BAD": [1,
39 | 2, 3]
40 | }
41 | ```
42 |
43 |
44 |
45 | ## :wrench: Options
46 |
47 | ```json
48 | {
49 | "jsonc/array-bracket-newline": ["error",
50 | {
51 | "multiline": true,
52 | "minItems": null
53 | }
54 | ]
55 | }
56 | ```
57 |
58 | Same as [array-bracket-newline] rule option. See [here](https://eslint.org/docs/rules/array-bracket-newline#options) for details.
59 |
60 | ## :couple: Related rules
61 |
62 | - [array-bracket-newline]
63 |
64 | [array-bracket-newline]: https://eslint.org/docs/rules/array-bracket-newline
65 |
66 | ## :rocket: Version
67 |
68 | This rule was introduced in eslint-plugin-jsonc v0.1.0
69 |
70 | ## :mag: Implementation
71 |
72 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/array-bracket-newline.ts)
73 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/array-bracket-newline.ts)
74 |
75 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/array-bracket-newline)
76 |
--------------------------------------------------------------------------------
/lib/rules/no-escape-sequence-in-identifier.ts:
--------------------------------------------------------------------------------
1 | import type { AST } from "jsonc-eslint-parser";
2 | import { createRule } from "../utils";
3 | import { PatternMatcher } from "@eslint-community/eslint-utils";
4 |
5 | export default createRule("no-escape-sequence-in-identifier", {
6 | meta: {
7 | docs: {
8 | description: "disallow escape sequences in identifiers.",
9 | recommended: ["json", "jsonc", "json5"],
10 | extensionRule: false,
11 | layout: false,
12 | },
13 | fixable: "code",
14 | messages: {
15 | disallow: "Escape sequence in identifiers should not be used.",
16 | },
17 | schema: [],
18 | type: "problem",
19 | },
20 | create(context) {
21 | const sourceCode = context.sourceCode;
22 | if (!sourceCode.parserServices.isJSON) {
23 | return {};
24 | }
25 | return {
26 | JSONIdentifier(node) {
27 | verify(node);
28 | },
29 | };
30 |
31 | /**
32 | * verify
33 | */
34 | function verify(node: AST.JSONIdentifier) {
35 | const escapeMatcher = new PatternMatcher(/\\u\{[\dA-Fa-f]+\}|\\u\d{4}/gu);
36 | const text = sourceCode.text.slice(...node.range);
37 | for (const match of escapeMatcher.execAll(text)) {
38 | const start = match.index;
39 | const end = start + match[0].length;
40 | const range: [number, number] = [
41 | start + node.range[0],
42 | end + node.range[0],
43 | ];
44 | context.report({
45 | loc: {
46 | start: sourceCode.getLocFromIndex(range[0]),
47 | end: sourceCode.getLocFromIndex(range[1]),
48 | },
49 | messageId: "disallow",
50 | fix(fixer) {
51 | const codePointStr =
52 | match[0][2] === "{"
53 | ? text.slice(start + 3, end - 1)
54 | : text.slice(start + 2, end);
55 | const codePoint = Number(`0x${codePointStr}`);
56 | return fixer.replaceTextRange(
57 | range,
58 | String.fromCodePoint(codePoint),
59 | );
60 | },
61 | });
62 | }
63 | }
64 | },
65 | });
66 |
--------------------------------------------------------------------------------
/docs/rules/no-irregular-whitespace.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/no-irregular-whitespace"
5 | description: "disallow irregular whitespace"
6 | since: "v2.5.0"
7 | ---
8 |
9 | # jsonc/no-irregular-whitespace
10 |
11 | > disallow irregular whitespace
12 |
13 | ## :book: Rule Details
14 |
15 | This rule is aimed at catching invalid whitespace that is not a normal tab and space.
16 |
17 |
18 |
19 |
20 |
21 | ```json
22 | /* eslint jsonc/no-irregular-whitespace: 'error' */
23 | {
24 | /* ✓ GOOD */
25 | "GOOD": "",
26 |
27 | /* ✗ BAD */
28 | "BAD": "foo",
29 | }
30 | ```
31 |
32 |
33 |
34 | ESLint core [no-irregular-whitespace] rule don't work well in JSON. Turn off that rule in JSON files and use `jsonc/no-irregular-whitespace` rule.
35 |
36 | ## :wrench: Options
37 |
38 | Nothing.
39 |
40 | ```json
41 | {
42 | "overrides": [
43 | {
44 | "files": ["*.json", "*.json5"],
45 | "rules": {
46 | "no-irregular-whitespace": "off",
47 | "jsonc/no-irregular-whitespace": [
48 | "error",
49 | {
50 | "skipStrings": true,
51 | "skipComments": false,
52 | "skipRegExps": false,
53 | "skipTemplates": false
54 | }
55 | ]
56 | }
57 | }
58 | ]
59 | }
60 | ```
61 |
62 | Same as [no-irregular-whitespace] rule option. See [here](https://eslint.org/docs/rules/no-irregular-whitespace#options) for details.
63 |
64 | ## :couple: Related rules
65 |
66 | - [no-irregular-whitespace]
67 |
68 | [no-irregular-whitespace]: https://eslint.org/docs/rules/no-irregular-whitespace
69 |
70 | ## :rocket: Version
71 |
72 | This rule was introduced in eslint-plugin-jsonc v2.5.0
73 |
74 | ## :mag: Implementation
75 |
76 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/no-irregular-whitespace.ts)
77 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/no-irregular-whitespace.ts)
78 |
79 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-irregular-whitespace)
80 |
--------------------------------------------------------------------------------
/lib/index.ts:
--------------------------------------------------------------------------------
1 | import type { RuleModule } from "./types";
2 | import { rules as ruleList } from "./utils/rules";
3 | import base from "./configs/base";
4 | import autoConfig from "./configs/auto-config";
5 | import recommendedWithJson from "./configs/recommended-with-json";
6 | import recommendedWithJsonc from "./configs/recommended-with-jsonc";
7 | import recommendedWithJson5 from "./configs/recommended-with-json5";
8 | import prettier from "./configs/prettier";
9 | import all from "./configs/all";
10 | import flatBase from "./configs/flat/base";
11 | import flatRecommendedWithJson from "./configs/flat/recommended-with-json";
12 | import flatRecommendedWithJsonc from "./configs/flat/recommended-with-jsonc";
13 | import flatRecommendedWithJson5 from "./configs/flat/recommended-with-json5";
14 | import flatPrettier from "./configs/flat/prettier";
15 | import flatAll from "./configs/flat/all";
16 | import * as meta from "./meta";
17 |
18 | import {
19 | parseForESLint,
20 | parseJSON,
21 | traverseNodes,
22 | AST,
23 | getStaticJSONValue,
24 | } from "jsonc-eslint-parser";
25 |
26 | const configs = {
27 | base,
28 | "auto-config": autoConfig,
29 | "recommended-with-json": recommendedWithJson,
30 | "recommended-with-jsonc": recommendedWithJsonc,
31 | "recommended-with-json5": recommendedWithJson5,
32 | prettier,
33 | all,
34 | "flat/base": flatBase,
35 | "flat/recommended-with-json": flatRecommendedWithJson,
36 | "flat/recommended-with-jsonc": flatRecommendedWithJsonc,
37 | "flat/recommended-with-json5": flatRecommendedWithJson5,
38 | "flat/prettier": flatPrettier,
39 | "flat/all": flatAll,
40 | };
41 |
42 | const rules = ruleList.reduce(
43 | (obj, r) => {
44 | obj[r.meta.docs.ruleName] = r;
45 | return obj;
46 | },
47 | {} as { [key: string]: RuleModule },
48 | );
49 |
50 | export default {
51 | meta,
52 | configs,
53 | rules,
54 |
55 | // backward compatibility
56 | parseForESLint,
57 | parseJSON,
58 | traverseNodes,
59 | getStaticJSONValue,
60 | };
61 | export {
62 | meta,
63 | configs,
64 | rules,
65 | // types
66 | AST,
67 |
68 | // backward compatibility
69 | parseForESLint,
70 | parseJSON,
71 | traverseNodes,
72 | getStaticJSONValue,
73 | };
74 |
--------------------------------------------------------------------------------
/lib/utils/get-auto-jsonc-rules-config/should-use-flat-config.ts:
--------------------------------------------------------------------------------
1 | /** copied from https://github.com/eslint/eslint/blob/v8.56.0/lib/eslint/flat-eslint.js#L1119 */
2 |
3 | import path from "path";
4 | import fs from "fs";
5 |
6 | const FLAT_CONFIG_FILENAMES = [
7 | "eslint.config.js",
8 | "eslint.config.mjs",
9 | "eslint.config.cjs",
10 | ];
11 | /**
12 | * Returns whether flat config should be used.
13 | * @returns {Promise} Whether flat config should be used.
14 | */
15 | export function shouldUseFlatConfig(cwd: string): boolean {
16 | // eslint-disable-next-line no-process-env -- ignore
17 | switch (process.env.ESLINT_USE_FLAT_CONFIG) {
18 | case "true":
19 | return true;
20 | case "false":
21 | return false;
22 | default:
23 | // If neither explicitly enabled nor disabled, then use the presence
24 | // of a flat config file to determine enablement.
25 | return Boolean(findFlatConfigFile(cwd));
26 | }
27 | }
28 |
29 | /**
30 | * Searches from the current working directory up until finding the
31 | * given flat config filename.
32 | * @param {string} cwd The current working directory to search from.
33 | * @returns {string|undefined} The filename if found or `undefined` if not.
34 | */
35 | function findFlatConfigFile(cwd: string) {
36 | return findUp(FLAT_CONFIG_FILENAMES, { cwd });
37 | }
38 |
39 | /** We used https://github.com/sindresorhus/find-up/blob/b733bb70d3aa21b22fa011be8089110d467c317f/index.js#L94 as a reference */
40 | function findUp(names: string[], options: { cwd: string }) {
41 | let directory = path.resolve(options.cwd);
42 | const { root } = path.parse(directory);
43 | const stopAt = path.resolve(directory, root);
44 |
45 | while (true) {
46 | for (const name of names) {
47 | const target = path.resolve(directory, name);
48 | const stat = fs.existsSync(target)
49 | ? fs.statSync(target, {
50 | throwIfNoEntry: false,
51 | })
52 | : null;
53 | if (stat?.isFile()) {
54 | return target;
55 | }
56 | }
57 |
58 | if (directory === stopAt) {
59 | break;
60 | }
61 |
62 | directory = path.dirname(directory);
63 | }
64 |
65 | return null;
66 | }
67 |
--------------------------------------------------------------------------------
/docs/rules/object-property-newline.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/object-property-newline"
5 | description: "enforce placing object properties on separate lines"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/object-property-newline
10 |
11 | > enforce placing object properties on separate lines
12 |
13 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14 |
15 | ## :book: Rule Details
16 |
17 | This rule permits you to restrict the locations of property specifications in object literals. You may prohibit any part of any property specification from appearing on the same line as any part of any other property specification. You may make this prohibition absolute, or, by invoking an object option, you may allow an exception, permitting an object literal to have all parts of all of its property specifications on a single line.
18 |
19 |
20 |
21 |
22 |
23 | ```json5
24 | /* eslint jsonc/object-property-newline: 'error' */
25 | {
26 | /* ✓ GOOD */
27 | "GOOD": {
28 | "foo": "foo",
29 | "bar": "bar",
30 | "baz": "baz"
31 | },
32 |
33 | /* ✗ BAD */
34 | "BAD": {
35 | "foo": "foo", "bar": "bar", "baz": "baz"
36 | }
37 | }
38 | ```
39 |
40 |
41 |
42 | ## :wrench: Options
43 |
44 | Same as [object-property-newline] rule option. See [here](https://eslint.org/docs/rules/object-property-newline#optional-exception) for details.
45 |
46 | ## :couple: Related rules
47 |
48 | - [object-property-newline]
49 |
50 | [object-property-newline]: https://eslint.org/docs/rules/object-property-newline
51 |
52 | ## :rocket: Version
53 |
54 | This rule was introduced in eslint-plugin-jsonc v0.1.0
55 |
56 | ## :mag: Implementation
57 |
58 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/object-property-newline.ts)
59 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/object-property-newline.ts)
60 |
61 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/object-property-newline)
62 |
--------------------------------------------------------------------------------
/tests/lib/configs/recommended-with-json.ts:
--------------------------------------------------------------------------------
1 | import assert from "assert";
2 | import plugin from "../../../lib/index";
3 | import { LegacyESLint, ESLint } from "../test-lib/eslint-compat";
4 |
5 | const code = `{ foo: 42 }`;
6 | describe("`recommended-with-json` config", () => {
7 | it("legacy `recommended-with-json` config should work. ", async () => {
8 | const linter = new LegacyESLint({
9 | plugins: {
10 | svelte: plugin as never,
11 | },
12 | baseConfig: {
13 | parserOptions: {
14 | ecmaVersion: 2020,
15 | },
16 | extends: ["plugin:jsonc/recommended-with-json"],
17 | },
18 | useEslintrc: false,
19 | });
20 | const result = await linter.lintText(code, { filePath: "test.json" });
21 | const messages = result[0].messages;
22 |
23 | assert.deepStrictEqual(
24 | messages.map((m) => ({
25 | ruleId: m.ruleId,
26 | line: m.line,
27 | message: m.message,
28 | })),
29 | [
30 | {
31 | message: "Unquoted property 'foo' found.",
32 | ruleId: "jsonc/quote-props",
33 | line: 1,
34 | },
35 | ],
36 | );
37 | });
38 | it("`flat/recommended-with-json` config should work. ", async () => {
39 | const linter = new ESLint({
40 | overrideConfigFile: true as never,
41 | overrideConfig: plugin.configs["flat/recommended-with-json"] as never,
42 | });
43 | const result = await linter.lintText(code, { filePath: "test.json" });
44 | const messages = result[0].messages;
45 |
46 | assert.deepStrictEqual(
47 | messages.map((m) => ({
48 | ruleId: m.ruleId,
49 | line: m.line,
50 | message: m.message,
51 | })),
52 | [
53 | {
54 | message: "Unquoted property 'foo' found.",
55 | ruleId: "jsonc/quote-props",
56 | line: 1,
57 | },
58 | ],
59 | );
60 |
61 | const resultWithJs = await linter.lintText(";", { filePath: "test.js" });
62 | const messagesWithJs = resultWithJs[0].messages;
63 |
64 | assert.deepStrictEqual(
65 | messagesWithJs.map((m) => ({
66 | ruleId: m.ruleId,
67 | line: m.line,
68 | message: m.message,
69 | })),
70 | [],
71 | );
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/docs/rules/valid-json-number.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/valid-json-number"
5 | description: "disallow invalid number for JSON"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/valid-json-number
10 |
11 | > disallow invalid number for JSON
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule reports numbers that cannot be parsed with JSON.
19 |
20 |
21 |
22 |
23 |
24 | ```json5
25 | /* eslint jsonc/valid-json-number: 'error' */
26 | {
27 | /* ✓ GOOD */
28 | "GOOD": [123, 0.4, -42],
29 |
30 | /* ✗ BAD */
31 | "BAD": [123., .4, +42, Infinity, NaN]
32 | }
33 | ```
34 |
35 |
36 |
37 | ## :wrench: Options
38 |
39 | Nothing.
40 |
41 | ## :couple: Related rules
42 |
43 | - [jsonc/no-binary-numeric-literals]
44 | - [jsonc/no-floating-decimal]
45 | - [jsonc/no-hexadecimal-numeric-literals]
46 | - [jsonc/no-infinity]
47 | - [jsonc/no-nan]
48 | - [jsonc/no-numeric-separators]
49 | - [jsonc/no-octal-numeric-literals]
50 | - [jsonc/no-octal]
51 | - [jsonc/no-plus-sign]
52 | - [jsonc/space-unary-ops]
53 |
54 | [jsonc/no-binary-numeric-literals]: ./no-binary-numeric-literals.md
55 | [jsonc/no-floating-decimal]: ./no-floating-decimal.md
56 | [jsonc/no-hexadecimal-numeric-literals]: ./no-hexadecimal-numeric-literals.md
57 | [jsonc/no-infinity]: ./no-infinity.md
58 | [jsonc/no-nan]: ./no-nan.md
59 | [jsonc/no-numeric-separators]: ./no-numeric-separators.md
60 | [jsonc/no-octal-numeric-literals]: ./no-octal-numeric-literals.md
61 | [jsonc/no-octal]: ./no-octal.md
62 | [jsonc/no-plus-sign]: ./no-plus-sign.md
63 | [jsonc/space-unary-ops]: ./space-unary-ops.md
64 |
65 | ## :rocket: Version
66 |
67 | This rule was introduced in eslint-plugin-jsonc v0.1.0
68 |
69 | ## :mag: Implementation
70 |
71 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/valid-json-number.ts)
72 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/valid-json-number.ts)
73 |
--------------------------------------------------------------------------------
/docs/rules/quotes.md:
--------------------------------------------------------------------------------
1 | ---
2 | pageClass: "rule-details"
3 | sidebarDepth: 0
4 | title: "jsonc/quotes"
5 | description: "enforce use of double or single quotes"
6 | since: "v0.1.0"
7 | ---
8 |
9 | # jsonc/quotes
10 |
11 | > enforce use of double or single quotes
12 |
13 | - :gear: This rule is included in `"plugin:jsonc/recommended-with-json"` and `"plugin:jsonc/recommended-with-jsonc"`.
14 | - :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
15 |
16 | ## :book: Rule Details
17 |
18 | This rule enforces the use of double or single quotes.
19 |
20 | JSON5 allows you to define a string in one of two ways: double quotes or single quotes.
21 | However, JSON and JSONC can only use double quotes.
22 |
23 |
24 |
25 |
26 |
27 | ```json5
28 | /* eslint jsonc/quotes: 'error' */
29 | {
30 | /* ✓ GOOD */
31 | "GOOD": "foo",
32 |
33 | /* ✗ BAD */
34 | 'BAD': 'bar'
35 | }
36 | ```
37 |
38 |
39 |
40 | ## :wrench: Options
41 |
42 | ```json
43 | {
44 | "jsonc/quotes": ["error",
45 | "double",
46 | {"avoidEscape": false}
47 | ]
48 | }
49 | ```
50 |
51 | This rule has two options, a string option and an object option.
52 |
53 | String option:
54 |
55 | - `"double"` (default) ... requires the use of double quotes wherever possible
56 | - `"single"` ... requires the use of single quotes wherever possible
57 |
58 | Object option:
59 |
60 | - `"avoidEscape"` ... if `true`, allows strings to use single-quotes or double-quotes so long as the string contains a quote that would have to be escaped otherwise. default `false`
61 |
62 | See [here](https://eslint.org/docs/rules/quotes#options) for details.
63 |
64 | ## :couple: Related rules
65 |
66 | - [quotes]
67 |
68 | [quotes]: https://eslint.org/docs/rules/quotes
69 |
70 | ## :rocket: Version
71 |
72 | This rule was introduced in eslint-plugin-jsonc v0.1.0
73 |
74 | ## :mag: Implementation
75 |
76 | - [Rule source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/lib/rules/quotes.ts)
77 | - [Test source](https://github.com/ota-meshi/eslint-plugin-jsonc/blob/master/tests/lib/rules/quotes.ts)
78 |
79 | Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/quotes)
80 |
--------------------------------------------------------------------------------
/tests/lib/rules/no-parenthesized.ts:
--------------------------------------------------------------------------------
1 | import { RuleTester } from "../test-lib/tester";
2 | import rule from "../../../lib/rules/no-parenthesized";
3 | import * as jsonParser from "jsonc-eslint-parser";
4 |
5 | const tester = new RuleTester({
6 | languageOptions: {
7 | parser: jsonParser,
8 | ecmaVersion: 2020,
9 | },
10 | ignoreMomoa: true,
11 | });
12 |
13 | tester.run("no-parenthesized", rule, {
14 | valid: ["{42: 42}", "42", "[42]"],
15 | invalid: [
16 | {
17 | code: `[(42), {key: (42)}]`,
18 | output: `[42, {key: 42}]`,
19 | errors: [
20 | {
21 | message: "Parentheses around expression should not be used.",
22 | line: 1,
23 | column: 2,
24 | },
25 | {
26 | message: "Parentheses around expression should not be used.",
27 | line: 1,
28 | column: 5,
29 | },
30 | {
31 | message: "Parentheses around expression should not be used.",
32 | line: 1,
33 | column: 14,
34 | },
35 | {
36 | message: "Parentheses around expression should not be used.",
37 | line: 1,
38 | column: 17,
39 | },
40 | ],
41 | },
42 | {
43 | code: `(42)`,
44 | output: `42`,
45 | errors: [
46 | {
47 | message: "Parentheses around expression should not be used.",
48 | line: 1,
49 | column: 1,
50 | },
51 | {
52 | message: "Parentheses around expression should not be used.",
53 | line: 1,
54 | column: 4,
55 | },
56 | ],
57 | },
58 | {
59 | code: `[-(42), 42 + (42 - 3)]`,
60 | output: null,
61 | errors: [
62 | {
63 | message: "Parentheses around expression should not be used.",
64 | line: 1,
65 | column: 3,
66 | },
67 | {
68 | message: "Parentheses around expression should not be used.",
69 | line: 1,
70 | column: 6,
71 | },
72 | {
73 | message: "Parentheses around expression should not be used.",
74 | line: 1,
75 | column: 14,
76 | },
77 | {
78 | message: "Parentheses around expression should not be used.",
79 | line: 1,
80 | column: 21,
81 | },
82 | ],
83 | },
84 | ],
85 | });
86 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/components/eslint-code-block.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
101 |
--------------------------------------------------------------------------------
/tests-integrations/lib/eslint-plugin-markdown-nest-for-v6.ts:
--------------------------------------------------------------------------------
1 | import cp from "child_process";
2 | import assert from "assert";
3 | import path from "path";
4 | import { version } from "../../package.json";
5 | import type { ESLint } from "eslint";
6 |
7 | // -----------------------------------------------------------------------------
8 | // Tests
9 | // -----------------------------------------------------------------------------
10 |
11 | const TEST_CWD = path.join(
12 | __dirname,
13 | "../fixtures/eslint-plugin-markdown-nest-for-v6",
14 | );
15 | const ESLINT = path.join(TEST_CWD, `./node_modules/.bin/eslint`);
16 |
17 | describe("Integration with eslint-plugin-markdown with nesting config with eslint v6", () => {
18 | let originalCwd: string;
19 |
20 | before(() => {
21 | originalCwd = process.cwd();
22 | // To test ESLint v6, remove `@eslint/eslintrc` module in the root.
23 | cp.execSync(`npx rimraf node_modules/@eslint/eslintrc`, {
24 | stdio: "inherit",
25 | });
26 |
27 | process.chdir(TEST_CWD);
28 | cp.execSync(`npm i -D ../../../eslint-plugin-jsonc-${version}.tgz`, {
29 | stdio: "inherit",
30 | });
31 | cp.execSync("npm i", { stdio: "inherit" });
32 | });
33 | after(() => {
34 | process.chdir(originalCwd);
35 |
36 | // `npm install` to get the removed module back.
37 | cp.execSync(`npm i`, {
38 | stdio: "inherit",
39 | });
40 | });
41 |
42 | it(`should lint errors`, () => {
43 | try {
44 | const res = cp.execSync(
45 | `${ESLINT} "./test.md" --format json --ext .md,.json`,
46 | {
47 | env: {
48 | // eslint-disable-next-line no-process-env -- Legacy Config test
49 | ...process.env,
50 | ESLINT_USE_FLAT_CONFIG: "false",
51 | },
52 | },
53 | );
54 | console.log(`${res}`);
55 | } catch (e: any) {
56 | const results: ESLint.LintResult[] = JSON.parse(`${e.stdout}`);
57 | assert.deepStrictEqual(
58 | results[0].messages.map((message) => ({
59 | message: message.message,
60 | ruleId: message.ruleId,
61 | line: message.line,
62 | })),
63 | [
64 | {
65 | message: "Strings must use doublequote.",
66 | ruleId: "jsonc/quotes",
67 | line: 3,
68 | },
69 | ],
70 | );
71 | return;
72 | }
73 | assert.fail("Expect error");
74 | });
75 | });
76 |
--------------------------------------------------------------------------------