[
  {
    "path": ".eslintignore",
    "content": "test/packages\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true,\n    \"mocha\": true,\n    \"es6\": true\n  },\n  \"parserOptions\": {\n    \"ecmaVersion\": 2017\n  },\n  \"plugins\": [\"prettier\"],\n  \"extends\": [\"eslint:recommended\"],\n  \"rules\": {\n    \"prettier/prettier\": [\"warn\", {\n      \"singleQuote\": true,\n      \"tabWidth\": 4,\n      \"printWidth\": 100,\n      \"bracketSpacing\": false\n    }],\n    \"no-console\": \"error\"\n  },\n  \"overrides\": [\n    {\n      \"files\": \"*.mjs\",\n      \"parserOptions\": {\n        \"sourceType\": \"module\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/node.js.yml",
    "content": "# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node\n# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions\n\nname: Build\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [18.x, 20.x]\n        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/\n\n    steps:\n    - uses: actions/checkout@v3\n    - name: Use Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v3\n      with:\n        node-version: ${{ matrix.node-version }}\n        cache: 'npm'\n    - run: npm ci\n    - run: npm run lint\n    - run: npm run test\n    - run: npm run integration ci 7-legacy 8-legacy 8 9 # eslint versions\n    - run: npm run integration test 7-legacy 8-legacy 8 9 # eslint versions\n    - name: Upload coverage to Codecov\n      uses: codecov/codecov-action@v2\n      with:\n        verbose: true\n        directory: coverage\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nprivate\ntmp\ncoverage\n.nyc_output\nexample/package-lock.json\n.vscode/\n.idea/\n"
  },
  {
    "path": ".npmignore",
    "content": "test\nexamples\nprivate\ntmp\ncoverage\n.npmignore\n.eslintrc\n.github\n.vscode\n.nycrc\n.eslintignore\nvendor\n"
  },
  {
    "path": ".nycrc",
    "content": "{\n  \"all\": true,\n  \"include\": [\"src\"],\n  \"reporter\": [\"text\", \"text-summary\", \"lcov\"]\n}\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "The MIT License (MIT)\nCopyright (c) 2015-2021 Azeem Bande-Ali\n\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\nOR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# eslint-plugin-json\n\n[![npm](https://img.shields.io/npm/v/eslint-plugin-json.svg)](https://www.npmjs.com/package/eslint-plugin-json)\n[![Build](https://github.com/azeemba/eslint-plugin-json/workflows/Build/badge.svg)](https://github.com/azeemba/eslint-plugin-json/actions/workflows/node.js.yml)\n[![codecov](https://codecov.io/gh/azeemba/eslint-plugin-json/branch/master/graph/badge.svg)](https://codecov.io/gh/azeemba/eslint-plugin-json)\n[![Code Climate](https://codeclimate.com/github/azeemba/eslint-plugin-json/badges/gpa.svg)](https://codeclimate.com/github/azeemba/eslint-plugin-json)\n\n> Eslint plugin for JSON files\n\n:warning: If you are using eslint v9 or newer, use eslint-plugin-json v4 or newer.\n\n## Installation\n\nInstall `eslint-plugin-json` along [`eslint`](http://eslint.org):\n\n```shell\n$ npm install --save-dev eslint eslint-plugin-json\n# or\n$ yarn add --dev eslint eslint-plugin-json\n```\n\n**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-json` globally.\n\n## Usage\n\n### Basic configuration (Flat Config ESLint Format)\n\nThe `json` plugin ship with two recommended config you can use to easily activate it via the `extends` key.\nIt comes in two flavor: one strict (`recommended`) and one allowing comments `recommended-with-comments`.\n\n\n```js\nimport json from 'eslint-plugin-json';\n\nexport default [\n  {\n    files: [\"**/*.json\"],\n    ...json.configs[\"recommended\"]\n  }\n];\n```\n\n### Basic configuration (Legacy ESLint Format)\n\nThe `json` plugin ship with two recommended config you can use to easily activate it via the `extends` key.\nIt comes in two flavor: one strict (`recommended-legacy`) and one allowing comments `recommended-with-comments-legacy`.\n\n\n```json\n{\n    \"extends\": [\"plugin:json/recommended-legacy\"]\n}\n```\n\nYou can run ESLint on individual JSON files or you can use the `--ext` flag to add JSON files to the list.\n\n```\neslint . --ext .json,.js\neslint example.json\n```\n\n### Custom Configuration (Flat Config ESLint Format)\n\nIf you want more granular control over which rules, and which severity you want.\n\nIf you want them all, add the `json/json` rule (or its alias `json/*`). (this is what the `recommended` config does)\n\n#### Global rules\nThe global rules (`json/json` or its alias `json/*`) activate all the rules.\nNote it can be configured to ignore errors cause by comments.\nTo do so, add option `'allowComments'` or `{allowComments: true}`\n\nFor instance:\n```js\nimport json from \"eslint-plugin-json\";\n\nexport default [\n  {\n    files: [\"**/*.json\"],\n    plugins: { json },\n    processor: \"json/json\"\n    \"rules\": {\n      \"json/*\": [\"error\", \"allowComments\"],\n      // or the equivalent:\n      \"json/*\": [\"error\", {\"allowComments\": true}]\n    }\n  },\n];\n```\n\n### Custom Configuration (Legacy ESLint Format)\n\nIf you want more granular control over which rules, and which severity you want.\n\nAdd `json` to the list of plugins (You can omit the `eslint-plugin-` prefix)\nThen pick your rules.\n\nIf you want them all, add the `json/json` rule (or its alias `json/*`). (this is what the `recommended-legacy` config does)\n\n#### Global rules\nThe global rules (`json/json` or its alias `json/*`) activate all the rules.\nNote it can be configured to ignore errors cause by comments.\nTo do so, add option `'allowComments'` or `{allowComments: true}`\n\nFor instance:\n```json\n{\n    \"plugins\": [\n        \"json\"\n    ],\n    \"rules\": {\n        \"json/*\": [\"error\", \"allowComments\"],\n        // or the equivalent:\n        \"json/*\": [\"error\", {\"allowComments\": true}]\n    }\n}\n```\n\n#### Individual Rules\nHere is the list of individual rules (with name in `kebab-case`)in case you want granular error/warning level:\n- `json/undefined`\n- `json/enum-value-mismatch`\n- `json/unexpected-end-of-comment`\n- `json/unexpected-end-of-string`\n- `json/unexpected-end-of-number`\n- `json/invalid-unicode`\n- `json/invalid-escape-character`\n- `json/invalid-character`\n- `json/property-expected`\n- `json/comma-expected`\n- `json/colon-expected`\n- `json/value-expected`\n- `json/comma-or-close-backet-expected`\n- `json/comma-or-close-brace-expected`\n- `json/trailing-comma`\n- `json/duplicate-key`\n- `json/comment-not-permitted`\n- `json/schema-resolve-error`\n- `json/unknown` (error that does not match previous ones)\n\n## FAQs\n\n\n#### How does eslint-plugin-json work?\n\nStarting from version 1.3, this plugin relies on what [VSCode](https://github.com/Microsoft/vscode-json-languageservice)\nuses for its implementation of JSON validation.\n\nOriginaly this plugin used to use JSHint, however due to heavy dependencies, it was replaced.\n\n#### Why doesn't this plugin use `eslint` itself or just `JSON.parse`?\n\n`eslint`'s parser is a JavaScript parser. JSON is a stricter subset and things\nthat are valid JavaScript are not valid JSON. This is why something more specific\nis more appropriate.\n\nWhile `JSON.parse` seems ideal, it is not designed to continue after the first error.\nSo if you have a missing trailing comma in the start of the file, the rest of the file\nwill go unlinted. A smarter parser that can self-correct after seeing errors is needed\nwhich the VSCode implementation provides by leveraging the\n[jsonc-parser](https://www.npmjs.com/package/jsonc-parser) module.\n\n\n#### Will this plugin provide more configuration?\n\nIt is now possible as you can see in the [Configuration section](#custom-configuration).\n\nAdditionally, support for autofixing common errors could be added in the feature.\n\n#### Is `eslint` really the best tool to lint my JSON?\n\nNot really. `eslint` plugin interface wasn't designed to lint a completely different language but\nits interface is flexible enough to allow it. So this plugin is certainly unusual.\n\nIdeally, your editor would natively supports linting JSON. If it doesn't though, then might as well\nuse this plugin. Hacky linting is better than no linting :).\n"
  },
  {
    "path": "examples/.eslintrc",
    "content": "{\n  \"plugins\": [\"json\"],\n  \"rules\": {\n      \"json/*\": [\"warn\"],\n      \"json/duplicate-key\": \"error\",\n      \"json/trailing-comma\": \"error\"\n    },\n    \"overrides\": [\n        {\n            \"files\": [\"samples/json-with-comments.json\"],\n            \"rules\": {\n                \"json/*\": [\"warn\", {\"allowComments\": true}]\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "examples/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json-example\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Some example of usage of plugin\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"lint\": \"eslint\",\n    \"test\": \"node integration-test.js\"\n  },\n  \"keywords\": [],\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"eslint\": \"^6.3.0\",\n    \"eslint-plugin-json\": \"..\"\n  }\n}\n"
  },
  {
    "path": "examples/samples/duplicate-keys.json",
    "content": "{\n    \"iam\": \"here\",\n    \"iam\": \"and here\"\n}\n"
  },
  {
    "path": "examples/samples/good-json.json",
    "content": "{\n    \"hello\": \"world\"\n}\n"
  },
  {
    "path": "examples/samples/json-with-comments.json",
    "content": "{\n    \"hello\": \"world\" // with a comment\n}\n"
  },
  {
    "path": "examples/samples/whole-mess.json",
    "content": "{\n    \"iam\": \"here\",\n    \"iam\": \"and here\", // COMMENT\n}\n"
  },
  {
    "path": "examples/samples/wrong-syntax.json",
    "content": "{\n    \"oops\":\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json\",\n  \"version\": \"4.0.1\",\n  \"description\": \"eslint plugin for JSON files\",\n  \"keywords\": [\n    \"eslint\",\n    \"eslintplugin\",\n    \"eslint-plugin\",\n    \"json\",\n    \"eslint-plugin-json\"\n  ],\n  \"author\": \"Azeem Bande-Ali <a.bandeali@gmail.com>\",\n  \"contributors\": [\n    \"Adriean Khisbe <adriean.khisbe@live.fr> (https://github.com/AdrieanKhisbe/)\"\n  ],\n  \"main\": \"src/index.js\",\n  \"scripts\": {\n    \"integration\": \"test/integration-across-eslint-majors.sh\",\n    \"test\": \"nyc mocha test/unit.test.js\",\n    \"lint\": \"eslint src test\",\n    \"eslint\": \"eslint\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/azeemba/eslint-plugin-json.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/azeemba/eslint-plugin-json/issues\"\n  },\n  \"dependencies\": {\n    \"lodash\": \"^4.17.21\",\n    \"vscode-json-languageservice\": \"^4.1.6\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.3.4\",\n    \"codecov\": \"^3.8.3\",\n    \"eslint\": \"^8.0.0\",\n    \"eslint-config-prettier\": \"^8.3.0\",\n    \"eslint-plugin-prettier\": \"^3.4.1\",\n    \"eslint-plugin-self\": \"file:vendor/eslint-plugin-self\",\n    \"mocha\": \"^10.4.0\",\n    \"nyc\": \"^15.1.0\",\n    \"prettier\": \"^2.3.2\"\n  },\n  \"engines\": {\n    \"node\": \">=18.0\"\n  },\n  \"url\": \"https://github.com/azeemba/eslint-plugin-json\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "const _ = require('lodash/fp');\nconst jsonService = require('vscode-json-languageservice');\n\nconst jsonServiceHandle = jsonService.getLanguageService({});\n\nconst ErrorCodes = {\n    Undefined: 0,\n    EnumValueMismatch: 1,\n    UnexpectedEndOfComment: 0x101,\n    UnexpectedEndOfString: 0x102,\n    UnexpectedEndOfNumber: 0x103,\n    InvalidUnicode: 0x104,\n    InvalidEscapeCharacter: 0x105,\n    InvalidCharacter: 0x106,\n    PropertyExpected: 0x201,\n    CommaExpected: 0x202,\n    ColonExpected: 0x203,\n    ValueExpected: 0x204,\n    CommaOrCloseBacketExpected: 0x205,\n    CommaOrCloseBraceExpected: 0x206,\n    TrailingComma: 0x207,\n    DuplicateKey: 0x208,\n    CommentNotPermitted: 0x209,\n    SchemaResolveError: 0x300,\n};\n\nconst AllErrorCodes = _.values(ErrorCodes);\nconst AllowComments = 'allowComments';\n\nconst fileLintResults = {};\nconst fileComments = {};\nconst fileDocuments = {};\n\nconst getSignature = (problem) =>\n    `${problem.range.start.line} ${problem.range.start.character} ${problem.message}`;\n\nfunction getDiagnostics(jsonDocument) {\n    return _.pipe(\n        _.map((problem) => [getSignature(problem), problem]),\n        _.reverse, // reverse ensure fromPairs keep first signature occurence of problem\n        _.fromPairs\n    )(jsonDocument.syntaxErrors);\n}\nconst reportError = (filter) => (errorName, context) => {\n    _.filter(filter, fileLintResults[context.getFilename()]).forEach((error) => {\n        context.report({\n            ruleId: `json/${errorName}`,\n            message: error.message,\n            loc: {\n                start: {line: error.range.start.line + 1, column: error.range.start.character},\n                end: {line: error.range.end.line + 1, column: error.range.end.character},\n            },\n            // later: see how to add fix\n        });\n    });\n};\nconst reportComment = (errorName, context) => {\n    const ruleOption = _.head(context.options);\n    if (ruleOption === AllowComments || _.get(AllowComments, ruleOption)) return;\n\n    _.forEach((comment) => {\n        context.report({\n            ruleId: errorName,\n            message: 'Comment not allowed',\n            loc: {\n                start: {line: comment.start.line + 1, column: comment.start.character},\n                end: {line: comment.end.line + 1, column: comment.end.character},\n            },\n        });\n    }, fileComments[context.getFilename()]);\n};\n\nconst ruleSchema = [\n    {\n        anyOf: [\n            {\n                enum: ['allowComments'],\n            },\n            {\n                type: 'object',\n                properties: {\n                    allowComments: {type: 'boolean'},\n                },\n                additionalProperties: false,\n            },\n        ],\n    },\n];\n\nconst makeRule = (errorName, reporters) => ({\n    meta: {schema: ruleSchema},\n    create(context) {\n        return {\n            Program() {\n                _.flatten([reporters]).map((reporter) => reporter(errorName, context));\n            },\n        };\n    },\n});\n\nconst rules = _.pipe(\n    _.mapKeys(_.kebabCase),\n    _.toPairs,\n    _.map(([errorName, errorCode]) => [\n        errorName,\n        makeRule(\n            errorName,\n            reportError((err) => err.code === errorCode)\n        ),\n    ]),\n    _.fromPairs,\n    _.assign({\n        '*': makeRule('*', [reportError(_.constant(true)), reportComment]),\n        json: makeRule('json', [reportError(_.constant(true)), reportComment]),\n        unknown: makeRule('unknown', reportError(_.negate(AllErrorCodes.includes))),\n        'comment-not-permitted': makeRule('comment-not-permitted', reportComment),\n    })\n)(ErrorCodes);\n\nconst errorSignature = (err) =>\n    ['message', 'line', 'column', 'endLine', 'endColumn'].map((field) => err[field]).join('::');\n\nconst getErrorCode = _.pipe(_.get('ruleId'), _.split('/'), _.last);\n\nconst meta = {\n    name: 'eslint-plugin-json',\n    version: '3.1.0',\n};\n\nconst jsonProcessor = {\n    preprocess: function (text, fileName) {\n        const textDocument = jsonService.TextDocument.create(fileName, 'json', 1, text);\n        fileDocuments[fileName] = textDocument;\n        const parsed = jsonServiceHandle.parseJSONDocument(textDocument);\n        fileLintResults[fileName] = getDiagnostics(parsed);\n        fileComments[fileName] = parsed.comments;\n        return ['']; // sorry nothing ;)\n    },\n    postprocess: function (messages, fileName) {\n        const textDocument = fileDocuments[fileName];\n        delete fileLintResults[fileName];\n        delete fileComments[fileName];\n        return _.pipe(\n            _.first,\n            _.groupBy(errorSignature),\n            _.mapValues((errors) => {\n                if (errors.length === 1) return _.first(errors);\n                // Otherwise there is two errors: the generic and specific one\n                // json/* or json/json and json/some-code\n                const firstErrorCode = getErrorCode(errors[0]);\n                const isFirstGeneric = ['*', 'json'].includes(firstErrorCode);\n                const genericError = errors[isFirstGeneric ? 0 : 1];\n                const specificError = errors[isFirstGeneric ? 1 : 0];\n                return genericError.severity > specificError.severity\n                    ? genericError\n                    : specificError;\n            }),\n            _.mapValues((error) => {\n                const source = textDocument.getText({\n                    start: {line: error.line - 1, character: error.column},\n                    end: {line: error.endLine - 1, character: error.endColumn},\n                });\n                return _.assign(error, {\n                    source,\n                    column: error.column + 1,\n                    endColumn: error.endColumn + 1,\n                });\n            }),\n            _.values\n        )(messages);\n    },\n};\n\nconst processors = {\n    // Supports old config.\n    '.json': jsonProcessor,\n    // Supports new config.\n    json: jsonProcessor,\n};\n\nconst configs = {\n    'recommended-legacy': {\n        plugins: ['json'],\n        rules: {\n            'json/*': 'error',\n        },\n    },\n    'recommended-with-comments-legacy': {\n        plugins: ['json'],\n        rules: {\n            'json/*': ['error', {allowComments: true}],\n        },\n    },\n};\n\nconst json = {meta, rules, configs, processors};\n\njson.configs['recommended'] = {\n    files: ['**/*.json'],\n    plugins: {\n        json,\n    },\n    rules: {\n        'json/*': 'error',\n    },\n    processor: 'json/json',\n};\njson.configs['recommended-with-comments'] = {\n    files: ['**/*.json'],\n    plugins: {\n        json,\n    },\n    rules: {\n        'json/*': ['error', {allowComments: true}],\n    },\n    processor: 'json/json',\n};\n\nmodule.exports = json;\n"
  },
  {
    "path": "test/.eslintrc.with-recommended-comments-config.mjs",
    "content": "import json from '../src/index.js';\n\nexport default [json.configs['recommended-with-comments']];\n"
  },
  {
    "path": "test/.eslintrc.with-recommended-comments-legacy-config.json",
    "content": "{\n  \"extends\": [\"plugin:self/recommended-with-comments-legacy\"]\n}\n"
  },
  {
    "path": "test/.eslintrc.with-recommended-config.mjs",
    "content": "import json from '../src/index.js';\n\nexport default [json.configs['recommended']];\n"
  },
  {
    "path": "test/.eslintrc.with-recommended-legacy-config.json",
    "content": "{\n    \"extends\": [\"plugin:self/recommended-legacy\"]\n}\n"
  },
  {
    "path": "test/custom.eslintrc-legacy.json",
    "content": "{\n  \"plugins\": [\"self\"],\n  \"rules\": {\n      \"self/*\": \"warn\",\n      \"self/duplicate-key\": \"error\",\n      \"self/trailing-comma\": \"error\"\n    },\n    \"overrides\": [\n        {\n            \"files\": [\"samples/json-with-comments.json\"],\n            \"rules\": {\n                \"self/*\": [\"warn\", {\"allowComments\": true}]\n            }\n        },\n        {\n            \"files\": [\"samples/wrong-syntax.json\"],\n            \"rules\": {\n                \"self/*\": \"error\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "test/custom.eslintrc.config.mjs",
    "content": "import json from '../src/index.js';\n\nexport default [\n    {\n        files: ['**/*.json'],\n        plugins: {json},\n        processor: 'json/json',\n        rules: {\n            'json/*': 'warn',\n            'json/duplicate-key': 'error',\n            'json/trailing-comma': 'error',\n        },\n    },\n    {\n        files: ['samples/json-with-comments.json'],\n        plugins: {json},\n        rules: {\n            'json/*': ['warn', {allowComments: true}],\n        },\n    },\n    {\n        files: ['samples/wrong-syntax.json'],\n        plugins: {json},\n        rules: {\n            'json/*': 'error',\n        },\n    },\n];\n"
  },
  {
    "path": "test/integration-across-eslint-majors.sh",
    "content": "#!/usr/bin/env bash\nset -e\ncmd=\"$1\"\nshift\n\ncase \"$cmd\" in\n  test|install|ci);;\n  *)\n    echo \"Unknown integration subcommand $cmd\"\n    exit 2\n  ;;\nesac\n\nif [[ -z \"$@\" ]]; then\n  echo \"No eslint major versions were provided\"\n  exit 2\nfi\n\necho \"Will perform $cmd for following eslint majors lines: $@\"\n\nfor version in $@; do\n    (cd test/packages/eslint-v$version && npm $cmd)\ndone\n"
  },
  {
    "path": "test/integration-legacy.test.js",
    "content": "const {execFileSync} = require('child_process');\nconst {expect} = require('chai');\nconst _ = require('lodash/fp');\n\nconst SCOPE = 'self'; // (for test purpose only, relying the the eslint-plugin-self for tests)\nconst scoped = (rule) => `${SCOPE}/${rule}`;\n\nfunction getLintResults(filename, eslintConfig) {\n    try {\n        const results = execFileSync(\n            'eslint',\n            [\n                '--config',\n                eslintConfig || 'custom.eslintrc-legacy.json',\n                '--format',\n                'json',\n                filename,\n            ],\n            {\n                encoding: 'utf8',\n                stdio: 'pipe',\n                cwd: __dirname,\n            }\n        );\n        return JSON.parse(results)[0];\n    } catch (err) {\n        if (err.status !== 1 && err.status !== 0)\n            throw new Error(`The lint command itself failed: ${err.status}, ${err.message}`);\n        return JSON.parse(err.stdout)[0];\n    }\n}\n\nfunction groupInfringementsByRules(fileResults) {\n    const errors = {};\n    const warnings = {};\n    for (const infringement of fileResults.messages) {\n        const counter = infringement.severity === 1 ? warnings : errors;\n        counter[infringement.ruleId] = (counter[infringement.ruleId] || 0) + 1;\n    }\n    return {errors, warnings};\n}\nfunction validateInfringementExpectation(expected, actualSituation) {\n    if (_.isEmpty(expected)) return;\n    for (const someExpected of expected || []) {\n        const [rule, expectedCount] = someExpected.split(':');\n        if (expectedCount)\n            expect(actualSituation[scoped(rule)]).to.equal(\n                Number(expectedCount),\n                `unexpected count of rule ${rule}`\n            );\n        else expect(actualSituation).to.have.property(scoped(rule));\n    }\n    const allExpectedErrors = expected.map(_.pipe(_.split(':'), _.head, scoped));\n    expect(_.xor(_.keys(actualSituation), allExpectedErrors)).to.have.length(\n        0,\n        'Extra errors found'\n    );\n}\n\nfunction validateFile(filename, expectations = {}) {\n    const results = getLintResults(`samples/${filename}.json`, expectations.eslintrc);\n    const resultIndex = groupInfringementsByRules(results);\n    validateInfringementExpectation(expectations.errors, resultIndex.errors, 'errors');\n    validateInfringementExpectation(expectations.warnings, resultIndex.warnings, 'warnings');\n\n    if (expectations.errorCount !== undefined)\n        expect(results.errorCount).to.equal(expectations.errorCount, 'invalid count of errors');\n    if (expectations.warningCount !== undefined)\n        expect(results.warningCount).to.equal(\n            expectations.warningCount,\n            'invalid count of warnings'\n        );\n}\n\ndescribe('Integrations tests', function () {\n    it('validate correct json', function () {\n        validateFile('good-json', {errorCount: 0, warningCount: 0});\n    });\n    it('detect duplicate keys', function () {\n        validateFile('duplicate-keys', {\n            errors: ['duplicate-key:2'],\n        }); // FIXME: give error count!\n    });\n    it('handle comments in json', function () {\n        validateFile('json-with-comments', {errorCount: 0, warningCount: 0});\n    });\n    it('detect wrong syntax', function () {\n        validateFile('wrong-syntax', {errorCount: 1, warningCount: 0});\n    });\n    it('detect many infringements in messy json', function () {\n        validateFile('whole-mess', {\n            errors: ['duplicate-key:2', 'trailing-comma'],\n            warnings: ['*'],\n        });\n    });\n});\n\ndescribe('Integrations tests with config', function () {\n    describe('recommended', function () {\n        it('detect many infringements in messy json', function () {\n            validateFile('whole-mess', {\n                eslintrc: '.eslintrc.with-recommended-legacy-config.json',\n                errors: ['*:4'],\n            });\n        });\n\n        it('handle comments in json', function () {\n            validateFile('json-with-comments', {\n                eslintrc: '.eslintrc.with-recommended-legacy-config.json',\n                errorCount: 1, // comment-not-permitted under the '*' glob\n            });\n        });\n    });\n    describe('recommended-with-comments', function () {\n        it('detect many infringements in messy json', function () {\n            validateFile('whole-mess', {\n                eslintrc: '.eslintrc.with-recommended-comments-legacy-config.json',\n                errors: ['*:3'],\n            });\n        });\n\n        it('handle comments in json', function () {\n            validateFile('json-with-comments', {\n                eslintrc: '.eslintrc.with-recommended-comments-legacy-config.json',\n                errorCount: 0,\n                warningCount: 0,\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/integration.test.js",
    "content": "const {execFileSync} = require('child_process');\nconst {expect} = require('chai');\nconst _ = require('lodash/fp');\n\nconst SCOPE = 'json'; // (for test purpose only)\nconst scoped = (rule) => `${SCOPE}/${rule}`;\n\nfunction getLintResults(filename, eslintConfig) {\n    try {\n        const results = execFileSync(\n            'eslint',\n            [\n                '--config',\n                eslintConfig || 'custom.eslintrc.config.mjs',\n                '--format',\n                'json',\n                filename,\n            ],\n            {\n                encoding: 'utf8',\n                stdio: 'pipe',\n                cwd: __dirname,\n            }\n        );\n        return JSON.parse(results)[0];\n    } catch (err) {\n        if (err.status !== 1 && err.status !== 0)\n            throw new Error(`The lint command itself failed: ${err.status}, ${err.message}`);\n        return JSON.parse(err.stdout)[0];\n    }\n}\n\nfunction groupInfringementsByRules(fileResults) {\n    const errors = {};\n    const warnings = {};\n    for (const infringement of fileResults.messages) {\n        const counter = infringement.severity === 1 ? warnings : errors;\n        counter[infringement.ruleId] = (counter[infringement.ruleId] || 0) + 1;\n    }\n    return {errors, warnings};\n}\nfunction validateInfringementExpectation(expected, actualSituation) {\n    if (_.isEmpty(expected)) return;\n    for (const someExpected of expected || []) {\n        const [rule, expectedCount] = someExpected.split(':');\n        if (expectedCount)\n            expect(actualSituation[scoped(rule)]).to.equal(\n                Number(expectedCount),\n                `unexpected count of rule ${rule}`\n            );\n        else expect(actualSituation).to.have.property(scoped(rule));\n    }\n    const allExpectedErrors = expected.map(_.pipe(_.split(':'), _.head, scoped));\n    expect(_.xor(_.keys(actualSituation), allExpectedErrors)).to.have.length(\n        0,\n        'Extra errors found'\n    );\n}\n\nfunction validateFile(filename, expectations = {}) {\n    const results = getLintResults(`samples/${filename}.json`, expectations.eslintrc);\n    const resultIndex = groupInfringementsByRules(results);\n    validateInfringementExpectation(expectations.errors, resultIndex.errors, 'errors');\n    validateInfringementExpectation(expectations.warnings, resultIndex.warnings, 'warnings');\n\n    if (expectations.errorCount !== undefined)\n        expect(results.errorCount).to.equal(expectations.errorCount, 'invalid count of errors');\n    if (expectations.warningCount !== undefined)\n        expect(results.warningCount).to.equal(\n            expectations.warningCount,\n            'invalid count of warnings'\n        );\n}\n\ndescribe('Integrations tests', function () {\n    it('validate correct json', function () {\n        validateFile('good-json', {errorCount: 0, warningCount: 0});\n    });\n    it('detect duplicate keys', function () {\n        validateFile('duplicate-keys', {\n            errors: ['duplicate-key:2'],\n        }); // FIXME: give error count!\n    });\n    it('handle comments in json', function () {\n        validateFile('json-with-comments', {errorCount: 0, warningCount: 0});\n    });\n    it('detect wrong syntax', function () {\n        validateFile('wrong-syntax', {errorCount: 1, warningCount: 0});\n    });\n    it('detect many infringements in messy json', function () {\n        validateFile('whole-mess', {\n            errors: ['duplicate-key:2', 'trailing-comma'],\n            warnings: ['*'],\n        });\n    });\n});\n\ndescribe('Integrations tests with config', function () {\n    describe('recommended', function () {\n        it('detect many infringements in messy json', function () {\n            validateFile('whole-mess', {\n                eslintrc: '.eslintrc.with-recommended-config.mjs',\n                errors: ['*:4'],\n            });\n        });\n\n        it('handle comments in json', function () {\n            validateFile('json-with-comments', {\n                eslintrc: '.eslintrc.with-recommended-config.mjs',\n                errorCount: 1, // comment-not-permitted under the '*' glob\n            });\n        });\n    });\n    describe('recommended-with-comments', function () {\n        it('detect many infringements in messy json', function () {\n            validateFile('whole-mess', {\n                eslintrc: '.eslintrc.with-recommended-comments-config.mjs',\n                errors: ['*:3'],\n            });\n        });\n\n        it('handle comments in json', function () {\n            validateFile('json-with-comments', {\n                eslintrc: '.eslintrc.with-recommended-comments-config.mjs',\n                errorCount: 0,\n                warningCount: 0,\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/packages/eslint-v7-legacy/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json-v7\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Integration for eslint-plugin-json against ESLint v7\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"pretest\": \"eslint --version\",\n    \"test\": \"../../../node_modules/.bin/mocha test/integration-legacy.test.js\"\n  },\n  \"keywords\": [\n    \"eslint\",\n    \"eslint-plugin\",\n    \"eslint-plugin-json\",\n    \"integration-tests\"\n  ],\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"eslint\": \"^7.32.0\",\n    \"mocha\": \"^10.4.0\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "test/packages/eslint-v8/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json-v8\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Integration for eslint-plugin-json against ESLint v8\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"pretest\": \"eslint --version\",\n    \"test\": \"ESLINT_USE_FLAT_CONFIG=true ../../../node_modules/.bin/mocha test/integration.test.js\"\n  },\n  \"keywords\": [\n    \"eslint\",\n    \"eslint-plugin\",\n    \"eslint-plugin-json\",\n    \"integration-tests\"\n  ],\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"eslint\": \"^8.57.0\",\n    \"mocha\": \"^10.4.0\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "test/packages/eslint-v8-legacy/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json-v8\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Integration for eslint-plugin-json against ESLint v8\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"pretest\": \"eslint --version\",\n    \"test\": \"../../../node_modules/.bin/mocha test/integration-legacy.test.js\"\n  },\n  \"keywords\": [\n    \"eslint\",\n    \"eslint-plugin\",\n    \"eslint-plugin-json\",\n    \"integration-tests\"\n  ],\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"eslint\": \"^8.0.0\",\n    \"mocha\": \"^9.0.3\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "test/packages/eslint-v9/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-json-v9\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Integration for eslint-plugin-json against ESLint v9\",\n  \"private\": true,\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"pretest\": \"eslint --version\",\n    \"test\": \"node_modules/.bin/mocha test/integration.test.js\"\n  },\n  \"keywords\": [\n    \"eslint\",\n    \"eslint-plugin\",\n    \"eslint-plugin-json\",\n    \"integration-tests\"\n  ],\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"eslint\": \"9.1.0\",\n    \"mocha\": \"^10.4.0\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "test/unit.test.js",
    "content": "const plugin = require('../src');\nconst {assert} = require('chai');\nconst _ = require('lodash/fp');\n\ndescribe('plugin', function () {\n    describe('structure', function () {\n        it('should contain processors object', function () {\n            assert.property(plugin, 'processors', '.processors property is not defined');\n        });\n        it('should contain .json property', function () {\n            assert.property(plugin.processors, '.json', '.json property is not defined');\n        });\n        it('should contain .json.preprocess property', function () {\n            assert.property(\n                plugin.processors['.json'],\n                'preprocess',\n                '.json.preprocess is not defined'\n            );\n        });\n        it('should contain .json.postprocess property', function () {\n            assert.property(\n                plugin.processors['.json'],\n                'postprocess',\n                '.json.postprocess is not defined'\n            );\n        });\n    });\n    describe('preprocess', function () {\n        const preprocess = plugin.processors['.json'].preprocess;\n        it('should return the same text', function () {\n            const fileName = 'whatever-the-name.js';\n\n            const newText = preprocess('whatever', fileName);\n            assert.isArray(newText, 'preprocess should return array');\n            assert.strictEqual(newText[0], '');\n        });\n    });\n    describe('postprocess', function () {\n        const preprocess = plugin.processors['.json'].preprocess;\n        const postprocess = plugin.processors['.json'].postprocess;\n\n        const messageErrorFieldFromContextError = {\n            ruleId: _.get('ruleId'),\n            severity: _.getOr(1, 'severity'),\n            message: _.get('message'),\n            line: _.get('loc.start.line'),\n            column: _.get('loc.start.column'),\n            nodeType: _.getOr(null, 'nodeType'),\n            endLine: _.get('loc.end.line'),\n            endColumn: _.get('loc.end.column'),\n        };\n        const convertContextErrorToMessageError = (err) =>\n            _.mapValues((extractor) => extractor(err), messageErrorFieldFromContextError);\n        const fakeApplyRule = (rules) => (file) => {\n            const errors = [];\n            rules.forEach((rule) => {\n                const xxx = rule.create({\n                    getFilename() {\n                        return file;\n                    },\n                    report(err) {\n                        errors.push(err);\n                    },\n                });\n                xxx.Program();\n            });\n            return [errors.map(convertContextErrorToMessageError)];\n        };\n\n        const singleQuotes = {\n            fileName: 'singleQuotes.json',\n            text: \"{'x': 0}\",\n        };\n        const trailingCommas = {\n            fileName: 'trailing.json',\n            text: '{ \"x\": 0, }',\n        };\n        const multipleErrors = {\n            fileName: 'multipleErrors.json',\n            text: \"{ x: 200, 'what': 0 }\",\n        };\n        const trailingText = {\n            fileName: 'trailingtext.json',\n            text: '{ \"my_string\": \"hello world\" }' + ' \\n' + 'bad_text',\n        };\n\n        const good = {\n            fileName: 'good.json',\n            text: JSON.stringify({a: [1, 2, 3], b: 'cat', c: {x: 1}}),\n        };\n\n        const rules = ['undefined', 'trailing-comma'];\n        const lintFile = fakeApplyRule(rules.map((rule) => plugin.rules[rule]));\n        const samples = [singleQuotes, trailingCommas, multipleErrors, trailingText, good];\n        samples.forEach((sample) => preprocess(sample.text, sample.fileName));\n\n        const errorsByFile = _.fromPairs(\n            samples.map((sample) => [sample.fileName, lintFile(sample.fileName)])\n        );\n\n        it('should return an error for the single quotes', function () {\n            const errors = postprocess(errorsByFile[singleQuotes.fileName], singleQuotes.fileName);\n            assert.isArray(errors, 'should return an array');\n            assert.lengthOf(errors, 1, 'should return one error');\n\n            const error = errors[0];\n            assert.strictEqual(error.ruleId, 'json/undefined', 'should have a string ID');\n            assert.strictEqual(error.severity, 1, 'should have a numeric severity');\n            assert.strictEqual(\n                error.message,\n                'Property keys must be doublequoted',\n                'should have a message'\n            );\n            assert.strictEqual(error.line, 1, 'should point to first line');\n            assert.strictEqual(error.column, 2, 'should point to second character');\n        });\n\n        it('should return an error for trailing commas', function () {\n            const errors = postprocess(\n                errorsByFile[trailingCommas.fileName],\n                trailingCommas.fileName\n            );\n            assert.isArray(errors, 'should return an array');\n            assert.lengthOf(errors, 1, 'should return one error');\n\n            const error = errors[0];\n            assert.strictEqual(error.ruleId, 'json/trailing-comma', 'should have a string ID');\n            assert.strictEqual(error.line, 1, 'should point to the first line');\n            assert.strictEqual(error.column, 9, 'should point to the 9th character');\n        });\n\n        it('should report unrecoverable syntax error', function () {\n            const errors = postprocess(errorsByFile[trailingText.fileName], trailingText.fileName);\n            assert.isArray(errors, 'should return an array');\n            assert.lengthOf(errors, 1, 'should return one error');\n            assert.isString(errors[0].message, 'should have a valid message');\n\n            // we don't validate the line/column numbers since they don't actually\n            // mean anything for this error. JSHint just bails on the file.\n        });\n\n        it('should return multiple errors for multiple errors', function () {\n            const errors = postprocess(\n                errorsByFile[multipleErrors.fileName],\n                multipleErrors.fileName\n            );\n            assert.isArray(errors, 'should return an array');\n            assert.lengthOf(errors, 2, 'should return one error');\n        });\n\n        it('should return no errors for good json', function () {\n            const errors = postprocess(errorsByFile[good.fileName], good.fileName);\n            assert.isArray(errors, 'should return an array');\n            assert.lengthOf(errors, 0, \"good json shouldn't have any errors\");\n        });\n    });\n});\n"
  },
  {
    "path": "vendor/eslint-plugin-self/CHANGELOG.md",
    "content": "# Changelog\n\n## v1.2.1 (2020-05-27)\n\n* Support overrides having no rules :see_no_evil: ([#5](https://github.com/not-an-aardvark/eslint-plugin-self/issues/5)) ([e266543](https://github.com/not-an-aardvark/eslint-plugin-self/commit/e266543e50d062251755dd488abae31be7644bb1))\n\n## v1.2.0 (2019-03-04)\n\n* Support redefining plugins, overrides and rules with a \"/\" in them ([#2](https://github.com/not-an-aardvark/eslint-plugin-self/issues/2)) ([428664e](https://github.com/not-an-aardvark/eslint-plugin-self/commit/428664e1cf8f3726e0bb3b10bb3e137d271749c2))\n\n## v1.1.0 (2018-07-06)\n\n* Chore: add release script ([983a7d0](https://github.com/not-an-aardvark/eslint-plugin-self/commit/983a7d05c48bccc125f8d89fae1109a0c5a1d670))\n* Update: Add support for @scoped packages ([#1](https://github.com/not-an-aardvark/eslint-plugin-self/issues/1)) ([c57a01b](https://github.com/not-an-aardvark/eslint-plugin-self/commit/c57a01bbf922b82d09a0cceba6b5e845fab7d23a))\n\n## v1.0.1 (2017-07-02)\n\n* Fix: transform references to own rules in configs to use `self` prefix ([2dce85e](https://github.com/not-an-aardvark/eslint-plugin-self/commit/2dce85e445a7604f5fd963d1366509fa7a66d420))\n\n\n"
  },
  {
    "path": "vendor/eslint-plugin-self/LICENSE.md",
    "content": "The MIT License (MIT)\n=====================\n\nCopyright © 2017 Teddy Katz\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the “Software”), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "vendor/eslint-plugin-self/README.md",
    "content": "# eslint-plugin-self\n\nWhen writing an ESLint plugin, it's often useful to use the plugin's rules to lint the plugin's own codebase. You can use `eslint-plugin-self` to do that.\n\n## Usage\n\n```\nnpm install eslint-plugin-self --save-dev\n```\n\nNote: `eslint-plugin-self` must be installed locally (it will not work if installed globally), and the project that installs it must be a functioning ESLint plugin.\n\nAdd the following to your config file:\n\n```json\n{\n  \"plugins\": [\n    \"self\"\n  ]\n}\n```\n\nThen you can use your plugin's rules, with the `self/` prefix:\n\n```json\n{\n  \"rules\": {\n    \"self/my-custom-rule\": \"error\"\n  }\n}\n```\n\nYou can also use your plugin's configs, or anything else exported by your plugin:\n\n```json\n{\n  \"extends\": [\n    \"plugin:self/some-config\"\n  ]\n}\n```\n"
  },
  {
    "path": "vendor/eslint-plugin-self/index.js",
    "content": "'use strict';\n\nconst plugin = require('../..');\nconst selfPlugin = Object.assign({}, plugin);\n\nconst pkgName = require('../../package.json').name;\nlet pluginName;\nif (pkgName[0] === \"@\") {\n  const matches = pkgName.match(/^(@[^/]+)\\/eslint-plugin(?:-(.*))?$/);\n  pluginName = matches.slice(1, 3).filter(Boolean).join('/');\n} else {\n  pluginName = pkgName.replace(/^eslint-plugin-/, '');\n}\n\nfunction createRuleset(rules) {\n  return Object.keys(rules).reduce((newRules, oldRuleName) => {\n    const newRuleName = oldRuleName.startsWith(`${pluginName}/`)\n      ? `self${oldRuleName.slice(oldRuleName.indexOf('/'))}`\n      : oldRuleName;\n\n    newRules[newRuleName] = rules[oldRuleName];\n    return newRules;\n  }, {});\n}\n\nif (plugin.configs) {\n  selfPlugin.configs = Object.assign({}, plugin.configs);\n\n  Object.keys(plugin.configs).forEach(configName => {\n    const config = plugin.configs[configName];\n    selfPlugin.configs[configName] = Object.assign({}, config);\n    if (config.extends) {\n      selfPlugin.configs[configName].extends = [].concat(config.extends)\n        .map(extendsName => extendsName.replace(`plugin:${pluginName}/`, 'plugin:self/'));\n    }\n    // The Array.isArray avoids attempting to change the plugins property for\n    // eslint v9 based configurations.\n    if (config.plugins && Array.isArray(config.plugins)) {\n      selfPlugin.configs[configName].plugins = [].concat(config.plugins)\n        .map(enabledPluginName => enabledPluginName.replace(pluginName, 'self'));\n    }\n    if (config.rules) {\n      selfPlugin.configs[configName].rules = createRuleset(config.rules);\n    }\n    if (config.overrides) {\n      selfPlugin.configs[configName].overrides = [].concat(config.overrides)\n        .map((override) => {\n          if (!override.rules) return override;\n          return Object.assign(\n            {},\n            override,\n            {rules: createRuleset(override.rules)}\n          );\n        })\n    }\n  });\n}\n\nmodule.exports = selfPlugin;\n"
  },
  {
    "path": "vendor/eslint-plugin-self/package.json",
    "content": "{\n  \"name\": \"eslint-plugin-self\",\n  \"version\": \"1.2.1\",\n  \"description\": \"Allows ESLint plugins to be run on themselves\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"generate-release\": \"node-release-script\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/not-an-aardvark/eslint-plugin-self.git\"\n  },\n  \"keywords\": [\n    \"eslint-plugin\",\n    \"eslintplugin\"\n  ],\n  \"author\": \"Teddy Katz\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/not-an-aardvark/eslint-plugin-self/issues\"\n  },\n  \"homepage\": \"https://github.com/not-an-aardvark/eslint-plugin-self#readme\",\n  \"devDependencies\": {\n    \"@not-an-aardvark/node-release-script\": \"^0.1.0\"\n  }\n}\n"
  }
]