├── .all-contributorsrc
├── .bettercodehub.yml
├── .codecov.yml
├── .eslintignore
├── .eslintrc.json
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── BUG.md
│ ├── DOCS.md
│ ├── FEATURE.md
│ ├── QUESTION.md
│ ├── REGRESSION.md
│ └── SECURITY.md
├── PULL_REQUEST_TEMPLATE.md
├── config.yml
├── eslint-disable-bot.yml
├── issue-states.yml
├── issue_label_bot.yaml
├── stale.yml
└── workflows
│ ├── nodejs.yml
│ ├── semantic-pr.yml
│ ├── semantic-release.yml
│ └── snyk.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .releaserc
├── .remarkignore
├── .remarkrc
├── .snyk
├── CHANGELOG.md
├── LICENSE
├── README.md
├── index.js
├── package-lock.json
├── package.json
├── src
├── __tests__
│ ├── index.js
│ ├── intact.js
│ ├── more.js
│ └── utils.js
├── fixer.js
├── json.pegjs
├── json.pjs
├── test.utils.js
├── transform.js
└── utils.js
└── test
├── samples
├── b.json
├── bin.json
├── comment.json
├── concat.json
├── doublyMissingQuotes.json
├── doublyMissingQuotesMin.json
├── exp.json
├── extraBrackets.json
├── extraChar.json
├── fp.json
├── hex.json
├── issue31.json
├── lefty1.json
├── lefty2.json
├── leftyO.json
├── missing.json
├── missingLHQuotes.json
├── missingQuotes.json
├── monOps.json
├── multiComment.json
├── multiOps.json
├── newLines.json
├── noLHQuotes.json
├── noQuotes.json
├── normal.json
├── notCurly.json
├── notSquare.json
├── o.json
├── oct.json
├── ops.json
├── quoteInQuotes.json
├── singleQuote.json
├── smComment.json
├── tab.json
├── tabs.json
├── threeErrs.json
├── trailingChar.json
├── trailingComma.json
├── trailingDot.json
├── twoErrs.json
└── x.json
└── sandbox.js
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "json-fixer",
3 | "projectOwner": "Berkmann18",
4 | "repoType": "github",
5 | "repoHost": "https://github.com",
6 | "files": [
7 | "README.md"
8 | ],
9 | "imageSize": 100,
10 | "commit": true,
11 | "commitConvention": "angular",
12 | "contributors": [
13 | {
14 | "login": "Berkmann18",
15 | "name": "Maximilian Berkmann",
16 | "avatar_url": "https://avatars0.githubusercontent.com/u/8260834?v=4",
17 | "profile": "http://maxcubing.wordpress.com",
18 | "contributions": [
19 | "code",
20 | "doc",
21 | "ideas",
22 | "maintenance",
23 | "test",
24 | "security"
25 | ]
26 | },
27 | {
28 | "login": "semantic-release-bot",
29 | "name": "Semantic Release Bot",
30 | "avatar_url": "https://avatars1.githubusercontent.com/u/32174276?v=4",
31 | "profile": "http://semantic-release.org/",
32 | "contributions": [
33 | "platform",
34 | "doc"
35 | ]
36 | },
37 | {
38 | "login": "all-contributors[bot]",
39 | "name": "all-contributors[bot]",
40 | "avatar_url": "https://avatars1.githubusercontent.com/u/649578?v=4",
41 | "profile": "https://github.com/apps/all-contributors",
42 | "contributions": [
43 | "doc"
44 | ]
45 | },
46 | {
47 | "login": "Bkucera",
48 | "name": "Ben Kucera",
49 | "avatar_url": "https://avatars0.githubusercontent.com/u/14625260?v=4",
50 | "profile": "https://github.com/Bkucera",
51 | "contributions": [
52 | "code"
53 | ]
54 | },
55 | {
56 | "login": "SvetozarMateev",
57 | "name": "Svetozar Mateev",
58 | "avatar_url": "https://avatars3.githubusercontent.com/u/25162335?v=4",
59 | "profile": "https://github.com/SvetozarMateev",
60 | "contributions": [
61 | "bug",
62 | "code"
63 | ]
64 | },
65 | {
66 | "login": "andre-paulo98",
67 | "name": "André Paulo",
68 | "avatar_url": "https://avatars1.githubusercontent.com/u/19685105?v=4",
69 | "profile": "https://andrepaulo.me",
70 | "contributions": [
71 | "bug"
72 | ]
73 | },
74 | {
75 | "login": "Erkin97",
76 | "name": "Erkin Matkaziev",
77 | "avatar_url": "https://avatars2.githubusercontent.com/u/22586805?v=4",
78 | "profile": "https://www.linkedin.com/in/erkinmatkaziev/",
79 | "contributions": [
80 | "bug"
81 | ]
82 | },
83 | {
84 | "login": "codacy-badger",
85 | "name": "Codacy Badger",
86 | "avatar_url": "https://avatars3.githubusercontent.com/u/23704769?v=4",
87 | "profile": "https://www.codacy.com/",
88 | "contributions": [
89 | "infra",
90 | "doc"
91 | ]
92 | },
93 | {
94 | "login": "GiraffeKey",
95 | "name": "GiraffeKey",
96 | "avatar_url": "https://avatars2.githubusercontent.com/u/11844126?v=4",
97 | "profile": "https://github.com/GiraffeKey",
98 | "contributions": [
99 | "code",
100 | "test"
101 | ]
102 | },
103 | {
104 | "login": "jonasmaertens",
105 | "name": "jonasmaertens",
106 | "avatar_url": "https://avatars3.githubusercontent.com/u/71458938?v=4",
107 | "profile": "https://github.com/jonasmaertens",
108 | "contributions": [
109 | "bug"
110 | ]
111 | },
112 | {
113 | "login": "Geoxor",
114 | "name": "George Tsotsos",
115 | "avatar_url": "https://avatars.githubusercontent.com/u/34042825?v=4",
116 | "profile": "https://geoxor.moe",
117 | "contributions": [
118 | "code"
119 | ]
120 | }
121 | ],
122 | "contributorsPerLine": 7,
123 | "skipCi": true
124 | }
125 |
--------------------------------------------------------------------------------
/.bettercodehub.yml:
--------------------------------------------------------------------------------
1 | exclude:
2 | - /dist/.*
3 |
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project: off
4 | changes: on
5 | patch:
6 | default:
7 | target: auto
8 | base: pr
9 |
10 | comment: off
11 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | test/samples/*.json
2 | test/sandbox.js
3 | src/json.js
4 | dist
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "es6": true,
5 | "jest": true
6 | },
7 | "plugins": [
8 | "standard",
9 | "node",
10 | "security",
11 | "jest",
12 | "jquery"
13 | ],
14 | "extends": [
15 | "eslint:recommended",
16 | "plugin:security/recommended",
17 | "plugin:node/recommended",
18 | "plugin:you-dont-need-lodash-underscore/compatible"
19 | ],
20 | "rules": {
21 | "indent": [
22 | "error",
23 | 2
24 | ],
25 | "linebreak-style": [
26 | "error"
27 | ],
28 | "no-console": "off",
29 | "no-extra-semi": "off",
30 | "no-process-exit": "warn",
31 | "prefer-const": "warn",
32 | "no-trailing-spaces": [
33 | "error"
34 | ],
35 | "semi": "off",
36 | "symbol-description": [
37 | "warn"
38 | ],
39 | "jest/no-disabled-tests": "error",
40 | "jest/no-focused-tests": "error",
41 | "jest/no-identical-title": "error",
42 | "node/no-unsupported-features": "off",
43 | "node/no-unsupported-features/es-syntax": "off",
44 | "node/no-unpublished-require": "off"
45 | },
46 | "parserOptions": {
47 | "ecmaVersion": 9,
48 | "ecmaFeatures": {
49 | "impliedStrict": true
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: Berkmann18
2 | patreon: berkmann18
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug report
3 | about: Create a report to help us improve
4 | labels: 'Type: Bug :bug:, Priority: Medium'
5 | ---
6 |
7 |
8 |
9 | ## Expected behaviour
10 |
11 | ## Actual behaviour
12 |
13 | ## How to reproduce
14 |
15 |
16 |
17 | ## Possible solution(s)
18 |
19 |
20 |
21 | ## Environment
22 |
23 | - Version:
24 | - OS(s):
25 | - Browser(s) (if applicable):
26 | - Node version:
27 | - NPM version:
28 |
29 | ## Link or repo
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/DOCS.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 📖 Documentation issue
3 | about: Create a report to improve the documentation
4 | labels: 'Type: Documentation :book:, Priority: Medium'
5 | ---
6 |
7 |
8 |
9 | ## Expected information
10 |
11 | ## Actual information
12 |
13 | ## Possible solutions
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature request
3 | about: Submit a proposal for a feature request
4 | labels: 'Type: Enhancement :bulb:, Priority: Low'
5 | ---
6 |
7 |
8 |
9 | ## Proposal
10 |
11 | ## Motivation
12 |
13 | ## Use cases and examples
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/QUESTION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💬 Question
3 | about: Need support or a question in mind?
4 | labels: 'Type: Question :grey_question:, Priority: Low'
5 | ---
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/REGRESSION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💥 Regression Report
3 | about: Report unexpected behaviour that worked in previous versions
4 | labels: 'Type: Regression :boom:, Priority: Medium'
5 | ---
6 |
7 |
8 |
9 | ## Expected behaviour
10 |
11 |
12 |
13 | ## Versions
14 |
15 | It worked up to:
16 | It stopped working in version:
17 |
18 | ## How to reproduce
19 |
20 |
21 |
22 | ## Environment
23 |
24 | - Version:
25 | - OS(s):
26 | - Browser(s) (if applicable):
27 | - Node version:
28 | - NPM version:
29 |
30 | ## Link or repo
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SECURITY.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ⚠️ Security issue disclosure
3 | about: Report a security issue
4 | title: 'Security vulnerability'
5 | labels: 'Type: Vulnerability :warning:, Priority: High'
6 | ---
7 |
8 | Please email us/me in order to report the security vulnerability.
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Checklist
2 |
3 | - [ ] The PR follows the [guidelines](CONTRIBUTING.md)
4 | - [ ] Passes all the tests (including added/updated ones)
5 | - [ ] Contains a valid documentation
6 | - [ ] It's not a duplicate from another PR
7 |
8 | ## Changes
9 |
10 | This PR implements:
11 |
12 | - [ ] Bugfix
13 | - [ ] Feature
14 | - [ ] Refactoring
15 | - [ ] Documentation/wiki/tutorial update
16 | - [ ] Code style update
17 | - [ ] Build related change
18 | - [ ] Other, please specify:
19 |
20 | ## Details
21 |
22 | What does this PR implement exactly?
23 |
24 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | ## Configuration for request-info - https://github.com/behaviorbot/request-info
2 |
3 | # *Required* Comment to reply with
4 | #requestInfoReplyComment: >
5 | # We would appreciate it if you could provide us with more info about this issue/PR!
6 |
7 | # *OPTIONAL* default titles to check against for lack of descriptiveness
8 | # MUST BE ALL LOWERCASE
9 | requestInfoDefaultTitles:
10 | - update readme.md
11 | - updates
12 | - error
13 | - issue
14 |
15 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
16 | requestInfoLabelToAdd: needs-more-info
17 |
18 | requestInfoReplyComment: >
19 | We would appreciate it if you could provide us with more info about this
20 | issue/PR!
21 |
22 | ## Configuration for todo - https://github.com/jasonetco/todo
23 | todo:
24 | keyword: '@makeAnIssue'
25 |
26 | # Configuration for welcome - https://github.com/behaviorbot/welcome
27 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
28 |
29 | # Comment to be posted to on first time issues
30 | newIssueWelcomeComment: >
31 | Thanks for opening your first issue here! Be sure to follow the issue
32 | templates :simple_smile: !
33 |
34 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
35 |
36 | # Comment to be posted to on PRs from first time contributors in your repository
37 | newPRWelcomeComment: >
38 | Thanks for opening this PR (Pull Request)! Please check out our [contributing
39 | guidelines](https://github.com/Berkmann18/community-starter-kit/blob/master/CONTRIBUTING.md).
40 |
41 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
42 |
43 | # Comment to be posted to on pull requests merged by a first time user
44 | firstPRMergeComment: >
45 | :tada: Congrats on merging your first PR! We are proud of you!
46 |
47 | #requestInfoLabelToAdd: request-info
48 |
49 | # Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot
50 |
51 | # *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic
52 | # Anything higher than this threshold will be marked as toxic and commented on
53 | sentimentBotToxicityThreshold: .7
54 |
55 | # *Required* Comment to reply with
56 | sentimentBotReplyComment: >
57 | Please be sure to review the code of conduct and be respectful of other users.
58 | cc/ @Berkmann18
59 |
60 | # Configuration for issuelabeler - https://riyadhalnur.github.io/issuelabeler/
61 | # Number of labels to fetch (optional). Defaults to 20
62 | numLabels: 40
63 | # These labels will not be used even if the issue contains them (optional).
64 | # Pass a blank array if no labels are to be excluded.
65 | excludeLabels: []
66 |
--------------------------------------------------------------------------------
/.github/eslint-disable-bot.yml:
--------------------------------------------------------------------------------
1 | # Change this to set the number of comments the watcher should comment on a given PR.
2 | commentLimit: 20
3 | # The message the bot will post on any lines containing a eslint disable comment.
4 | commentMessage: "Please don't disable eslint rules :pray:"
5 | # A optional regular expression that will match against the branch name and not comment on it if it matches.
6 | skipBranchMatching: null
7 |
--------------------------------------------------------------------------------
/.github/issue-states.yml:
--------------------------------------------------------------------------------
1 | # Configuration for issue-states - https://github.com/dessant/issue-states
2 |
3 | # Open issues that are moved to these project columns. Set to `[]` to disable
4 | openIssueColumns:
5 | - To do
6 | - In Progress
7 | - Needs review
8 | - Reviewer approved
9 |
10 | # Close issues that are moved to these project columns. Set to `[]` to disable
11 | closedIssueColumns:
12 | - Closed
13 | - Done
14 | # Repository to extend settings from
15 | # _extends: repo
16 |
--------------------------------------------------------------------------------
/.github/issue_label_bot.yaml:
--------------------------------------------------------------------------------
1 | label-alias:
2 | bug: 'Type: Bug :bug:'
3 | feature_request: 'Type: Enhancement :bulb:'
4 | question: 'Type: Question :grey_question:'
5 | doc: 'Type: Documentation :book:'
6 | regression: 'Type: Regression :boom:'
7 | security: 'Type: Vulnerability :warning:'
8 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-stale - https://github.com/probot/stale
2 |
3 | # Number of days of inactivity before an Issue or Pull Request becomes stale
4 | daysUntilStale: 60
5 |
6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
8 | daysUntilClose: 14
9 |
10 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
11 | exemptLabels:
12 | - 'Status: On Hold :stop_sign:'
13 | - 'Type: Vulnerability :warning'
14 | - security
15 | - 'Status: Accepted :heavy_check_mark:'
16 |
17 | # Set to true to ignore issues in a project (defaults to false)
18 | exemptProjects: false
19 |
20 | # Set to true to ignore issues in a milestone (defaults to false)
21 | exemptMilestones: false
22 |
23 | # Label to use when marking as stale
24 | staleLabel: 'Status: Left Out :left_luggage:'
25 |
26 | # Comment to post when marking as stale. Set to `false` to disable
27 | markComment: >
28 | This issue has been automatically marked as stale because it has not had
29 | recent activity. It will be closed if no further activity occurs. Thank you
30 | for your contributions.
31 |
32 | # Comment to post when removing the stale label.
33 | unmarkComment: >
34 | This issue is no longer stale.
35 |
36 | # Comment to post when closing a stale Issue or Pull Request.
37 | closeComment: >
38 | This issue has been stale for 14 days so I'm closing it.
39 |
40 | # Limit the number of actions per hour, from 1-30. Default is 30
41 | limitPerRun: 30
42 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on:
4 | push:
5 | branches: [master, dev]
6 | pull_request:
7 | branches: [master]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | strategy:
14 | matrix:
15 | node-version: ['lts/*', 'node']
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Set up Node ${{ matrix.node-version }} using nvm
20 | uses: dcodeIO/setup-node-nvm@master
21 | with:
22 | node-version: ${{ matrix.node-version }}
23 | - run: |
24 | npm ci
25 | npm run lint
26 | npm run build --if-present
27 | - run: npm t
28 | env:
29 | CI: true
30 | - name: Codecov
31 | uses: codecov/codecov-action@v1.0.7
32 |
--------------------------------------------------------------------------------
/.github/workflows/semantic-pr.yml:
--------------------------------------------------------------------------------
1 | name: Lint PR
2 |
3 | on:
4 | pull_request:
5 | types:
6 | - opened
7 | - edited
8 | - synchronize
9 |
10 | jobs:
11 | main:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: amannn/action-semantic-pull-request@v1.1.1
15 | env:
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 |
--------------------------------------------------------------------------------
/.github/workflows/semantic-release.yml:
--------------------------------------------------------------------------------
1 | name: Semantic Release
2 |
3 | on:
4 | push:
5 | branches: [master]
6 |
7 | jobs:
8 | build-and-deploy:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v2
13 | - name: Setup Node
14 | uses: actions/setup-node@v1
15 | with:
16 | node-version: '12.x'
17 | - run: |
18 | npm ci
19 | npm run build
20 | - name: Semantic Release
21 | uses: cycjimmy/semantic-release-action@v2
22 | env:
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
25 |
--------------------------------------------------------------------------------
/.github/workflows/snyk.yml:
--------------------------------------------------------------------------------
1 | name: So Now You Know
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | branches: [master]
8 |
9 | jobs:
10 | security:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@master
14 | - name: Run Snyk to check for vulnerabilities
15 | uses: snyk/actions/node@master
16 | env:
17 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
18 | with:
19 | command: monitor
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | # Editors
64 | .idea
65 | .vscode
66 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | test
2 | .github
3 | .prettierignore
4 | .vscode
5 | **/*.spec.*
6 | coverage
7 | .nyc_output
8 | *.log
9 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 8.14.0
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | coverage/
3 | test/samples/*.json
4 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "tabWidth": 2,
4 | "singleQuote": true,
5 | "semi": true,
6 | "trailingComma": "none",
7 | "useTabs": false,
8 | "bracketSpacing": true
9 | }
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "@semantic-release/commit-analyzer",
4 | "@semantic-release/release-notes-generator",
5 | ["@semantic-release/changelog", {
6 | "changelogFile": "CHANGELOG.md"
7 | }],
8 | "@semantic-release/npm",
9 | "@semantic-release/github",
10 | ["@semantic-release/git", {
11 | "assets": ["src/*.{js,pjs}", "!src/test.utils.js", "index.js", "package.json", "package-lock.json", "LICENSE", "README.md", "CHANGELOG.md"],
12 | "message": "chore: release ${nextRelease.version} :tada: [skip ci]\n\n${nextRelease.notes}"
13 | }]
14 | ]
15 | }
--------------------------------------------------------------------------------
/.remarkignore:
--------------------------------------------------------------------------------
1 | CHANGELOG.md
--------------------------------------------------------------------------------
/.remarkrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "remark-preset-lint-recommended",
4 | "remark-preset-lint-consistent"
5 | ]
6 | }
--------------------------------------------------------------------------------
/.snyk:
--------------------------------------------------------------------------------
1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
2 | version: v1.14.1
3 | ignore: {}
4 | patch: {}
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.6.15](https://github.com/Berkmann18/json-fixer/compare/v1.6.14...v1.6.15) (2022-09-06)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * upgrade @babel/runtime from 7.17.9 to 7.18.9 ([85d95e5](https://github.com/Berkmann18/json-fixer/commit/85d95e5f5656a2a3783f507fd069c35d9f13f478))
7 |
8 | ## [1.6.14](https://github.com/Berkmann18/json-fixer/compare/v1.6.13...v1.6.14) (2022-08-16)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * upgrade @babel/runtime from 7.14.6 to 7.17.9 ([18b13f3](https://github.com/Berkmann18/json-fixer/commit/18b13f38c76e2972221aaa83145b3ff76fadfadf))
14 |
15 | ## [1.6.13](https://github.com/Berkmann18/json-fixer/compare/v1.6.12...v1.6.13) (2021-11-29)
16 |
17 |
18 | ### Bug Fixes
19 |
20 | * upgrade chalk from 4.1.1 to 4.1.2 ([2e67a23](https://github.com/Berkmann18/json-fixer/commit/2e67a235950e18006f13b344deca56a47410689d))
21 |
22 | ## [1.6.12](https://github.com/Berkmann18/json-fixer/compare/v1.6.11...v1.6.12) (2021-07-12)
23 |
24 |
25 | ### Bug Fixes
26 |
27 | * upgrade @babel/runtime from 7.14.5 to 7.14.6 ([daa5e08](https://github.com/Berkmann18/json-fixer/commit/daa5e0801998edb1a1f2b244eb7f0e024e99327d))
28 |
29 | ## [1.6.11](https://github.com/Berkmann18/json-fixer/compare/v1.6.10...v1.6.11) (2021-07-07)
30 |
31 |
32 | ### Bug Fixes
33 |
34 | * upgrade @babel/runtime from 7.14.0 to 7.14.5 ([319709b](https://github.com/Berkmann18/json-fixer/commit/319709bc2d122d8c2c70ae4c01da7ffea1bcf9b6))
35 |
36 | ## [1.6.10](https://github.com/Berkmann18/json-fixer/compare/v1.6.9...v1.6.10) (2021-06-03)
37 |
38 |
39 | ### Bug Fixes
40 |
41 | * upgrade @babel/runtime from 7.12.5 to 7.14.0 ([dbfd063](https://github.com/Berkmann18/json-fixer/commit/dbfd063ef5313fc707e982414423c6e0c8c99411))
42 |
43 | ## [1.6.9](https://github.com/Berkmann18/json-fixer/compare/v1.6.8...v1.6.9) (2021-05-14)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * upgrade chalk from 4.1.0 to 4.1.1 ([549ea47](https://github.com/Berkmann18/json-fixer/commit/549ea4702a2ff3dc5bcb537385196720a2790c01))
49 |
50 | ## [1.6.8](https://github.com/Berkmann18/json-fixer/compare/v1.6.7...v1.6.8) (2020-11-25)
51 |
52 |
53 | ### Bug Fixes
54 |
55 | * upgrade @babel/runtime from 7.12.1 to 7.12.5 ([d77dc09](https://github.com/Berkmann18/json-fixer/commit/d77dc09d01b936f6919f8f91d87662050056ec48))
56 |
57 | ## [1.6.7](https://github.com/Berkmann18/json-fixer/compare/v1.6.6...v1.6.7) (2020-11-08)
58 |
59 |
60 | ### Bug Fixes
61 |
62 | * upgrade @babel/runtime from 7.12.0 to 7.12.1 ([116409f](https://github.com/Berkmann18/json-fixer/commit/116409fffa8b7ebf793e289c62910c6ab940833c))
63 |
64 | ## [1.6.6](https://github.com/Berkmann18/json-fixer/compare/v1.6.5...v1.6.6) (2020-11-07)
65 |
66 |
67 | ### Bug Fixes
68 |
69 | * upgrade @babel/runtime from 7.11.2 to 7.12.0 ([5949534](https://github.com/Berkmann18/json-fixer/commit/594953453acacd14d77eab6402fb98c5ce302bc8))
70 |
71 | ## [1.6.5](https://github.com/Berkmann18/json-fixer/compare/v1.6.4...v1.6.5) (2020-10-08)
72 |
73 |
74 | ### Bug Fixes
75 |
76 | * **fixer:** addressed DeepScan's issue ([2c5868d](https://github.com/Berkmann18/json-fixer/commit/2c5868d3d89fcde097ddbe7a5be9410f551701ee))
77 | * **fixer:** removed futile LOC ([56f23a1](https://github.com/Berkmann18/json-fixer/commit/56f23a1cee0cfa6546dc212ee6b471b80a7e7529))
78 | * fixes special characters ([4e804e5](https://github.com/Berkmann18/json-fixer/commit/4e804e5e041fd7e75d2a6a95dcedca6011acefea))
79 |
80 | ## [1.6.4](https://github.com/Berkmann18/json-fixer/compare/v1.6.3...v1.6.4) (2020-10-08)
81 |
82 |
83 | ### Bug Fixes
84 |
85 | * upgrade @babel/runtime from 7.11.0 to 7.11.2 ([73e644e](https://github.com/Berkmann18/json-fixer/commit/73e644edde358afbd9a582cec5755a7797a64671))
86 |
87 | ## [1.6.3](https://github.com/Berkmann18/json-fixer/compare/v1.6.2...v1.6.3) (2020-08-26)
88 |
89 |
90 | ### Bug Fixes
91 |
92 | * upgrade @babel/runtime from 7.10.5 to 7.11.0 ([4cc9017](https://github.com/Berkmann18/json-fixer/commit/4cc90175f75b230d28bb737c9d0cb6384f0ed7b6))
93 |
94 | ## [1.6.2](https://github.com/Berkmann18/json-fixer/compare/v1.6.1...v1.6.2) (2020-08-26)
95 |
96 |
97 | ### Bug Fixes
98 |
99 | * **lockfile:** security update ([54c3bf0](https://github.com/Berkmann18/json-fixer/commit/54c3bf0532be98126e2f6b6b04707a7f5c2a8b73))
100 | * **lockfile:** vulnerability fix ([4b501a8](https://github.com/Berkmann18/json-fixer/commit/4b501a8ee6c9c3b015f43651b43bef4f6a08056d))
101 |
102 | ## [1.6.1](https://github.com/Berkmann18/json-fixer/compare/v1.6.0...v1.6.1) (2020-08-24)
103 |
104 |
105 | ### Bug Fixes
106 |
107 | * upgrade @babel/runtime from 7.10.4 to 7.10.5 ([cf9367b](https://github.com/Berkmann18/json-fixer/commit/cf9367b18e8551e47eee381b65103f920b81ed82))
108 |
109 | # [1.6.0](https://github.com/Berkmann18/json-fixer/compare/v1.5.4...v1.6.0) (2020-08-24)
110 |
111 |
112 | ### Features
113 |
114 | * **extra-brackets:** fix extra brackets ([6958b4b](https://github.com/Berkmann18/json-fixer/commit/6958b4b7d209fd128c1241ab4868190195defaab))
115 |
116 | ## [1.5.4](https://github.com/Berkmann18/json-fixer/compare/v1.5.3...v1.5.4) (2020-07-22)
117 |
118 |
119 | ### Bug Fixes
120 |
121 | * upgrade @babel/runtime from 7.10.3 to 7.10.4 ([11ec2a7](https://github.com/Berkmann18/json-fixer/commit/11ec2a7bafa7a945db0228f33cd191b3075528c4))
122 |
123 | ## [1.5.3](https://github.com/Berkmann18/json-fixer/compare/v1.5.2...v1.5.3) (2020-07-11)
124 |
125 |
126 | ### Bug Fixes
127 |
128 | * upgrade @babel/runtime from 7.10.2 to 7.10.3 ([a643b9b](https://github.com/Berkmann18/json-fixer/commit/a643b9b49f6a3d6591c8700c7d3f1815e7d9c51a))
129 |
130 | ## [1.5.2](https://github.com/Berkmann18/json-fixer/compare/v1.5.1...v1.5.2) (2020-07-01)
131 |
132 |
133 | ### Bug Fixes
134 |
135 | * upgrade chalk from 4.0.0 to 4.1.0 ([21f39eb](https://github.com/Berkmann18/json-fixer/commit/21f39ebd909f218aa59ef3320e9b4c2016207040))
136 |
137 | ## [1.5.1](https://github.com/Berkmann18/json-fixer/compare/v1.5.0...v1.5.1) (2020-06-27)
138 |
139 |
140 | ### Bug Fixes
141 |
142 | * security fix ([a306d58](https://github.com/Berkmann18/json-fixer/commit/a306d586dcd4ac09611adbc02a270b3bc186c8cf))
143 |
144 | # [1.5.0](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.5.0) (2020-06-27)
145 |
146 |
147 | ### Bug Fixes
148 |
149 | * **fixer:** fixing missing LHS quotes with 1-2 chars ([e2f8b9d](https://github.com/Berkmann18/json-fixer/commit/e2f8b9d2ae0f7c0f8bd79c11851a22628e0c5061))
150 | * **fixer:** lint fix ([bbf3ed9](https://github.com/Berkmann18/json-fixer/commit/bbf3ed9947b568dda5ad44e3f976a0900a1b7d72))
151 | * **fixer:** wrongly added missing quote ([2ee5e4f](https://github.com/Berkmann18/json-fixer/commit/2ee5e4f299b6d654a3066ed43066196054adaee9)), closes [#31](https://github.com/Berkmann18/json-fixer/issues/31)
152 | * **index:** not applying trailing-char fixes on LHS issues ([253ebfc](https://github.com/Berkmann18/json-fixer/commit/253ebfced66db18e883d22b63e019967629d1212)), closes [#38](https://github.com/Berkmann18/json-fixer/issues/38)
153 | * missing quote fixer failure ([60a5fff](https://github.com/Berkmann18/json-fixer/commit/60a5fff5be2683732a1996fe8c10179ac83f534c))
154 | * security fix ([067bd46](https://github.com/Berkmann18/json-fixer/commit/067bd46695aa540b517b620987d4506b82050c25))
155 | * **lockfile:** security fix ([cade206](https://github.com/Berkmann18/json-fixer/commit/cade206a43f05ebd3c16f96c2d44e22c368277b8))
156 |
157 |
158 | ### Features
159 |
160 | * **fixer:** trailing char fixer simplification ([5899676](https://github.com/Berkmann18/json-fixer/commit/5899676ae39de659b1ccf77705a6161e22143b21))
161 |
162 | ## [1.4.2](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.4.2) (2020-06-18)
163 |
164 |
165 | ### Bug Fixes
166 |
167 | * missing quote fixer failure ([60a5fff](https://github.com/Berkmann18/json-fixer/commit/60a5fff5be2683732a1996fe8c10179ac83f534c))
168 | * **fixer:** lint fix ([bbf3ed9](https://github.com/Berkmann18/json-fixer/commit/bbf3ed9947b568dda5ad44e3f976a0900a1b7d72))
169 | * security fix ([067bd46](https://github.com/Berkmann18/json-fixer/commit/067bd46695aa540b517b620987d4506b82050c25))
170 | * **fixer:** wrongly added missing quote ([2ee5e4f](https://github.com/Berkmann18/json-fixer/commit/2ee5e4f299b6d654a3066ed43066196054adaee9)), closes [#31](https://github.com/Berkmann18/json-fixer/issues/31)
171 | * **lockfile:** security fix ([cade206](https://github.com/Berkmann18/json-fixer/commit/cade206a43f05ebd3c16f96c2d44e22c368277b8))
172 |
173 | ## [1.4.2](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.4.2) (2020-06-17)
174 |
175 |
176 | ### Bug Fixes
177 |
178 | * missing quote fixer failure ([60a5fff](https://github.com/Berkmann18/json-fixer/commit/60a5fff5be2683732a1996fe8c10179ac83f534c))
179 | * **fixer:** lint fix ([bbf3ed9](https://github.com/Berkmann18/json-fixer/commit/bbf3ed9947b568dda5ad44e3f976a0900a1b7d72))
180 | * security fix ([067bd46](https://github.com/Berkmann18/json-fixer/commit/067bd46695aa540b517b620987d4506b82050c25))
181 | * **fixer:** wrongly added missing quote ([2ee5e4f](https://github.com/Berkmann18/json-fixer/commit/2ee5e4f299b6d654a3066ed43066196054adaee9)), closes [#31](https://github.com/Berkmann18/json-fixer/issues/31)
182 | * **lockfile:** security fix ([cade206](https://github.com/Berkmann18/json-fixer/commit/cade206a43f05ebd3c16f96c2d44e22c368277b8))
183 |
184 | ## [1.4.2](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.4.2) (2020-06-17)
185 |
186 |
187 | ### Bug Fixes
188 |
189 | * missing quote fixer failure ([60a5fff](https://github.com/Berkmann18/json-fixer/commit/60a5fff5be2683732a1996fe8c10179ac83f534c))
190 | * **fixer:** lint fix ([bbf3ed9](https://github.com/Berkmann18/json-fixer/commit/bbf3ed9947b568dda5ad44e3f976a0900a1b7d72))
191 | * security fix ([067bd46](https://github.com/Berkmann18/json-fixer/commit/067bd46695aa540b517b620987d4506b82050c25))
192 | * **fixer:** wrongly added missing quote ([2ee5e4f](https://github.com/Berkmann18/json-fixer/commit/2ee5e4f299b6d654a3066ed43066196054adaee9)), closes [#31](https://github.com/Berkmann18/json-fixer/issues/31)
193 | * **lockfile:** security fix ([cade206](https://github.com/Berkmann18/json-fixer/commit/cade206a43f05ebd3c16f96c2d44e22c368277b8))
194 |
195 | ## [1.4.3](https://github.com/Berkmann18/json-fixer/compare/v1.4.2...v1.4.3) (2020-06-17)
196 |
197 |
198 | ### Bug Fixes
199 |
200 | * missing quote fixer failure ([60a5fff](https://github.com/Berkmann18/json-fixer/commit/60a5fff5be2683732a1996fe8c10179ac83f534c))
201 | * **fixer:** lint fix ([bbf3ed9](https://github.com/Berkmann18/json-fixer/commit/bbf3ed9947b568dda5ad44e3f976a0900a1b7d72))
202 |
203 | ## ~[1.4.2](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.4.2)~ (2020-06-08)
204 |
205 |
206 | ### Bug Fixes
207 |
208 | * security fix ([067bd46](https://github.com/Berkmann18/json-fixer/commit/067bd46695aa540b517b620987d4506b82050c25))
209 |
210 | ## [1.4.2](https://github.com/Berkmann18/json-fixer/compare/v1.4.1...v1.4.2) (2020-06-07)
211 |
212 |
213 | ### Bug Fixes
214 |
215 | * **fixer:** wrongly added missing quote ([2ee5e4f](https://github.com/Berkmann18/json-fixer/commit/2ee5e4f299b6d654a3066ed43066196054adaee9)), closes [#31](https://github.com/Berkmann18/json-fixer/issues/31)
216 | * **lockfile:** security fix ([cade206](https://github.com/Berkmann18/json-fixer/commit/cade206a43f05ebd3c16f96c2d44e22c368277b8))
217 |
218 | ## [1.4.1](https://github.com/Berkmann18/json-fixer/compare/v1.4.0...v1.4.1) (2020-04-04)
219 |
220 |
221 | ### Bug Fixes
222 |
223 | * **package:** vulnerability fix ([7914f15](https://github.com/Berkmann18/json-fixer/commit/7914f156e9554000b1cb753aaccf07b77e3aadb7))
224 |
225 | # [1.4.0](https://github.com/Berkmann18/json-fixer/compare/v1.3.2...v1.4.0) (2019-12-15)
226 |
227 |
228 | ### Bug Fixes
229 |
230 | * **fixer:** improved trailing character fixer ([d671f0c](https://github.com/Berkmann18/json-fixer/commit/d671f0c68d62bbb11919fdad3bf128f71fb20d84)), closes [#18](https://github.com/Berkmann18/json-fixer/issues/18)
231 | * **package-lock:** vulnerability fix ([a61b48a](https://github.com/Berkmann18/json-fixer/commit/a61b48abd7ebe3a6fb429e6934329a32e10d2100))
232 | * **security:** bumped outdated packages + fixed vulnerabilities ([78bf487](https://github.com/Berkmann18/json-fixer/commit/78bf48760143eff21316faaa95ed8307a72f4d49))
233 |
234 |
235 | ### Features
236 |
237 | * added options object with parse option ([#21](https://github.com/Berkmann18/json-fixer/issues/21)) ([22874df](https://github.com/Berkmann18/json-fixer/commit/22874dfa67135a2bf6e8d84e8d01b37a708e58eb))
238 |
239 | ## [1.3.3](https://github.com/Berkmann18/json-fixer/compare/v1.3.2...v1.3.3) (2019-09-18)
240 |
241 | ### Bug Fixes
242 |
243 | - **fixer:** improved trailing character fixer ([d671f0c](https://github.com/Berkmann18/json-fixer/commit/d671f0c))
244 |
245 | ## [1.3.2](https://github.com/Berkmann18/json-fixer/compare/v1.3.1...v1.3.2) (2019-09-02)
246 |
247 | ### Bug Fixes
248 |
249 | - **security:** vulnerability fix ([8dc1f81](https://github.com/Berkmann18/json-fixer/commit/8dc1f81))
250 |
251 | ### Performance Improvements
252 |
253 | - **package:** reduce bundle size by 99.2% ([#15](https://github.com/Berkmann18/json-fixer/issues/15)) ([f915ee9](https://github.com/Berkmann18/json-fixer/commit/f915ee9))
254 |
255 | ## [1.3.1](https://github.com/Berkmann18/json-fixer/compare/v1.3.0...v1.3.1) (2019-05-31)
256 |
257 | ### Bug Fixes
258 |
259 | - **security:** security update ([3083a68](https://github.com/Berkmann18/json-fixer/commit/3083a68))
260 |
261 | # [1.3.0](https://github.com/Berkmann18/json-fixer/compare/v1.2.0...v1.3.0) (2019-05-19)
262 |
263 | ### Features
264 |
265 | - added concatenation support ([730d813](https://github.com/Berkmann18/json-fixer/commit/730d813))
266 | - operations support + refactoring ([191a6b0](https://github.com/Berkmann18/json-fixer/commit/191a6b0)), closes [#10](https://github.com/Berkmann18/json-fixer/issues/10)
267 | - **index:** round fix + improved quote fixer ([6ecb55e](https://github.com/Berkmann18/json-fixer/commit/6ecb55e))
268 |
269 | # [1.2.0](https://github.com/Berkmann18/json-fixer/compare/v1.1.0...v1.2.0) (2019-05-17)
270 |
271 | ### Features
272 |
273 | - **index:** added comment removers ([12bd10d](https://github.com/Berkmann18/json-fixer/commit/12bd10d))
274 |
275 | # [1.1.0](https://github.com/Berkmann18/json-fixer/compare/v1.0.0...v1.1.0) (2019-05-17)
276 |
277 | ### Features
278 |
279 | - **index:** added a square->curly brackets fixer ([9017579](https://github.com/Berkmann18/json-fixer/commit/9017579))
280 | - added verbosity and _LHS no quote_ support ([5b1504f](https://github.com/Berkmann18/json-fixer/commit/5b1504f))
281 |
282 | # 1.0.0 (2019-05-17)
283 |
284 | ### Features
285 |
286 | - **index:** add a _missing comma_ fixer ([1f8a535](https://github.com/Berkmann18/json-fixer/commit/1f8a535))
287 | - **index:** add a _missing quote_ fixer ([bc53b96](https://github.com/Berkmann18/json-fixer/commit/bc53b96))
288 | - **index:** added a single->double quote fixer ([b39844a](https://github.com/Berkmann18/json-fixer/commit/b39844a))
289 | - **index:** added a trailing dot fixer ([13f4931](https://github.com/Berkmann18/json-fixer/commit/13f4931))
290 | - **index:** generalised trailing dot ([280b845](https://github.com/Berkmann18/json-fixer/commit/280b845))
291 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Maximilian Berkmann
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - [json-fixer](#json-fixer)
6 | - [Usage](#usage)
7 | - [Contributors ✨](#contributors-)
8 |
9 |
10 |
11 | # json-fixer
12 |
13 | [](https://nodei.co/npm/json-fixer/)
14 |
15 | [](https://github.com/Berkmann18/json-fixer)
16 | [](https://david-dm.org/berkmann18/json-fixer?type=dev)
17 | [](https://david-dm.org/berkmann18/json-fixer)
18 |
19 | [](https://github.com/Berkmann18/json-fixer/network/members)
20 | [](https://github.com/Berkmann18/json-fixer/graphs/commit-activity)
21 | [](https://github.com/Berkmann18/json-fixer/graphs/contributors)
22 | [](https://github.com/Berkmann18/json-fixer/graphs/traffic)
23 |
24 | [](https://travis-ci.org/Berkmann18/json-fixer)
25 | [](https://codecov.io/github/Berkmann18/json-fixer?branch=master)
26 | [](https://github.com/facebook/jest)
27 | [](https://snyk.io/test/github/Berkmann18/json-fixer?targetFile=package.json)
28 |
29 | [](https://github.com/Berkmann18/json-fixer/blob/master/LICENSE)
30 | [](https://github.com/Berkmann18/json-fixer/issues)
31 | [](http://commitizen.github.io/cz-cli/)
32 |
33 | [](https://github.com/Berkmann18/json-fixer)
34 | [](https://github.com/Berkmann18/json-fixer)
35 | [](https://github.com/Berkmann18/json-fixer)
36 |
37 | [](https://bettercodehub.com/results/Berkmann18/json-fixer)
38 | [](https://app.codacy.com/manual/maxieberkmann/json-fixer?utm_source=github.com&utm_medium=referral&utm_content=Berkmann18/json-fixer&utm_campaign=Badge_Grade_Dashboard)
39 |
40 | A JSON file fixer primarly focused to be used in a NodeJS file.
41 |
42 | ## Usage
43 |
44 | - In NodeJS
45 |
46 | ```js
47 | const jsonFix = require('json-fixer')
48 | const fs = require('fs')
49 |
50 | // Get the (potentially malformed) JSON data ready
51 | const jsonContent = fs.readFileSync('config.json', 'utf-8')
52 |
53 | const {data, changed} = jsonFix(jsonContent) // Lint (and fix) it
54 |
55 | if (changed) {
56 | // Do something with `data` which is the fixed JSON parsed data from `jsonContent`
57 | // e.g. `fs.writeFileSync(configPath, JSON.stringify(data, null, 2))`
58 | }
59 | ```
60 |
61 | - In the CLI
62 | _Not supported yet_ (PR welcome).
63 |
64 | ## Contributors ✨
65 |
66 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
67 |
68 |
69 |
70 |
71 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
95 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 | const { parse } = require('./src/json.pjs');
3 | const { psw, removeLinebreak, verboseLog } = require('./src/utils');
4 | const fixer = require('./src/fixer');
5 |
6 | let fixRounds = 0;
7 | let roundThreshold = 20;
8 |
9 | const setFixThreshold = (data) => {
10 | const lineCount = data.split('\n').length;
11 | roundThreshold = Math.max(data.length / lineCount, lineCount);
12 | };
13 |
14 | const doubleCheck = (data, options = {}) => {
15 | /* eslint-disable no-console */
16 | const verbose = options.verbose;
17 | try {
18 | const res = parse(data);
19 | if (verbose) psw(`\n${chalk.cyan('The JSON data was fixed!')}`);
20 | if (res) return options.parse ? res : data;
21 | } catch (err) {
22 | if (verbose) {
23 | psw('Nearly fixed data:');
24 | data.split('\n').forEach((l, i) => psw(`${chalk.yellow(i)} ${l}`));
25 | }
26 | // eslint-disable-next-line no-use-before-define
27 | if (fixRounds < roundThreshold) return fixJson(err, data, options);
28 | console.error(chalk.red("There's still an error!"));
29 | throw new Error(err.message);
30 | }
31 | /* eslint-enable no-console */
32 | };
33 |
34 | const extraChar = (err) => err.expected[0].type === 'other' && ['}', ']'].includes(err.found);
35 |
36 | const trailingChar = (err) => {
37 | const literal = err.expected[0].type === 'literal' && err.expected[0].text !== ':';
38 | return ['.', ',', 'x', 'b', 'o'].includes(err.found) && literal;
39 | };
40 |
41 | const missingChar = (err) => err.expected[0].text === ',' && ['"', '[', '{'].includes(err.found);
42 |
43 | const singleQuotes = (err) => err.found === "'";
44 |
45 | const missingQuotes = (err) =>
46 | /\w/.test(err.found) && err.expected.find((el) => el.description === 'string');
47 |
48 | const notSquare = (err) => err.found === ':' && [',', ']'].includes(err.expected[0].text);
49 |
50 | const notCurly = (err) => err.found === ',' && err.expected[0].text === ':';
51 |
52 | const comment = (err) => err.found === '/';
53 |
54 | const ops = (err) => ['+', '-', '*', '/', '>', '<', '~', '|', '&', '^'].includes(err.found);
55 |
56 | const extraBrackets = (err) => err.found === '}';
57 |
58 | const specialChar = (err) => err.found === '"';
59 |
60 | const runFixer = ({ verbose, lines, start, err }) => {
61 | /* eslint-disable security/detect-object-injection */
62 | let fixedData = [...lines];
63 | const targetLine = start.line - 2;
64 |
65 | if (extraChar(err)) {
66 | fixedData = fixer.fixExtraChar({ fixedData, verbose, targetLine });
67 | } else if (trailingChar(err)) {
68 | fixedData = fixer.fixTrailingChar({ start, fixedData, verbose });
69 | } else if (missingChar(err)) {
70 | if (verbose) psw(chalk.magenta('Missing character'));
71 | const brokenLine = removeLinebreak(lines[targetLine]);
72 | fixedData[targetLine] = `${brokenLine},`;
73 | } else if (singleQuotes(err)) {
74 | fixedData = fixer.fixSingleQuotes({ start, fixedData, verbose });
75 | } else if (missingQuotes(err)) {
76 | fixedData = fixer.fixMissingQuotes({ start, fixedData, verbose });
77 | } else if (notSquare(err)) {
78 | fixedData = fixer.fixSquareBrackets({ start, fixedData, verbose, targetLine });
79 | } else if (notCurly(err)) {
80 | fixedData = fixer.fixCurlyBrackets({ fixedData, verbose, targetLine });
81 | } else if (comment(err)) {
82 | fixedData = fixer.fixComment({ start, fixedData, verbose });
83 | } else if (ops(err)) {
84 | fixedData = fixer.fixOpConcat({ start, fixedData, verbose });
85 | } else if (extraBrackets(err)) {
86 | fixedData = fixer.fixExtraCurlyBrackets({ start, fixedData, verbose });
87 | } else if (specialChar(err)) {
88 | fixedData = fixer.fixSpecialChar({ start, fixedData, verbose });
89 | } else throw new Error(`Unsupported issue: ${err.message} (please open an issue at the repo)`);
90 | return fixedData;
91 | };
92 |
93 | /*eslint-disable no-console */
94 | const fixJson = (err, data, options) => {
95 | ++fixRounds;
96 | const lines = data.split('\n');
97 | const verbose = options.verbose;
98 | verboseLog({ verbose, lines, err });
99 |
100 | const start = err.location.start;
101 | const fixedData = runFixer({ verbose, lines, start, err });
102 |
103 | return doubleCheck(fixedData.join('\n'), options);
104 | };
105 | /*eslint-enable no-console */
106 |
107 | const fixingTime = ({ data, err, optionsCopy }) => {
108 | fixRounds = 0;
109 | setFixThreshold(data);
110 | return {
111 | data: fixJson(err, data, optionsCopy),
112 | changed: true
113 | };
114 | };
115 |
116 | /**
117 | * @param {string} data JSON string data to check (and fix).
118 | * @param {{verbose:boolean, parse:boolean}} options configuration object which specifies verbosity and whether the object should be parsed or returned as fixed string
119 | * @returns {{data: (Object|string|Array), changed: boolean}} Result
120 | */
121 | const checkJson = (data, options) => {
122 | //inspired by https://jsontuneup.com/
123 | let optionsCopy;
124 | if (!options || typeof options === 'boolean') {
125 | optionsCopy = {};
126 | optionsCopy.verbose = options;
127 | } else {
128 | optionsCopy = JSON.parse(JSON.stringify(options));
129 | }
130 |
131 | if (optionsCopy.parse === undefined || optionsCopy.parse === null) {
132 | optionsCopy.parse = true;
133 | }
134 |
135 | try {
136 | const res = parse(data);
137 | if (res) {
138 | return {
139 | data: optionsCopy.parse ? res : data,
140 | changed: false
141 | };
142 | }
143 | } catch (err) {
144 | return fixingTime({ data, err, optionsCopy });
145 | }
146 | };
147 |
148 | module.exports = checkJson;
149 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "json-fixer",
3 | "version": "1.6.15",
4 | "description": "A JSON fixer",
5 | "main": "index.js",
6 | "repository": "https://github.com/Berkmann18/json-fixer.git",
7 | "files": [
8 | "src"
9 | ],
10 | "engines": {
11 | "node": ">=10"
12 | },
13 | "bugs": {
14 | "url": "https://github.com/Berkmann18/json-fixer/issues"
15 | },
16 | "homepage": "https://github.com/Berkmann18/json-fixer#readme",
17 | "author": {
18 | "name": "Maximilian Berkmann",
19 | "email": "maxieberkmann@gmail.com"
20 | },
21 | "license": "MIT",
22 | "private": false,
23 | "scripts": {
24 | "lint": "eslint . && npm run lint:lockfile && npm run lint:md",
25 | "lint:fix": "eslint . --fix",
26 | "lint:lockfile": "lockfile-lint --path package-lock.json --type npm --validate-https --allowed-hosts npm yarn",
27 | "lint:md": "remark . .github",
28 | "format": "prettier --write 'src/*.js' index.js",
29 | "test": "jest",
30 | "test:watch": "jest --watch",
31 | "sec": "snyk test",
32 | "commit": "git-cz",
33 | "generate": "pegjs src/json.pegjs",
34 | "prepare": "snyk protect",
35 | "sr": "semantic-release",
36 | "build": "echo 0",
37 | "sandbox": "node test/sandbox"
38 | },
39 | "husky": {
40 | "hooks": {
41 | "commit-msg": "commitlint --env HUSKY_GIT_PARAMS",
42 | "pre-commit": "lint-staged",
43 | "post-merge": "npm i",
44 | "pre-push": "npm run lint && npm t"
45 | }
46 | },
47 | "lint-staged": {
48 | "*.js": [
49 | "npm run format"
50 | ],
51 | "*.md": [
52 | "remark"
53 | ]
54 | },
55 | "keywords": [
56 | "json",
57 | "fix",
58 | "lint",
59 | "check"
60 | ],
61 | "dependencies": {
62 | "@babel/runtime": "^7.26.10",
63 | "chalk": "^4.1.2",
64 | "pegjs": "^0.10.0"
65 | },
66 | "devDependencies": {
67 | "@commitlint/cli": "^8.3.5",
68 | "@commitlint/config-conventional": "^8.3.4",
69 | "@semantic-release/changelog": "^5.0.1",
70 | "@semantic-release/git": "^9.0.0",
71 | "@semantic-release/npm": "^7.0.5",
72 | "codecov": "^3.7.0",
73 | "cz-conventional-changelog": "^3.2.0",
74 | "eslint": "^7.2.0",
75 | "eslint-plugin-jest": "^23.13.2",
76 | "eslint-plugin-jquery": "^1.5.1",
77 | "eslint-plugin-node": "^11.0.0",
78 | "eslint-plugin-security": "^1.4.0",
79 | "eslint-plugin-standard": "^4.0.0",
80 | "eslint-plugin-you-dont-need-lodash-underscore": "^6.8.0",
81 | "git-cz": "^4.6.2",
82 | "husky": "^4.2.5",
83 | "jest": "^26.0.1",
84 | "lint-staged": "^10.2.9",
85 | "lockfile-lint": "^4.2.2",
86 | "prettier": "^2.0.5",
87 | "remark-cli": "^8.0.0",
88 | "remark-preset-lint-consistent": "^3.0.0",
89 | "remark-preset-lint-recommended": "^4.0.0",
90 | "semantic-release": "^17.0.8",
91 | "snyk": "^1.336.0"
92 | },
93 | "config": {
94 | "commitizen": {
95 | "path": "cz-conventional-changelog"
96 | }
97 | },
98 | "commitlint": {
99 | "extends": [
100 | "@commitlint/config-conventional"
101 | ]
102 | },
103 | "jest": {
104 | "testEnvironment": "node",
105 | "verbose": true,
106 | "notify": true,
107 | "collectCoverage": true,
108 | "coverageThreshold": {
109 | "global": {
110 | "branches": 50,
111 | "functions": 40,
112 | "lines": 50,
113 | "statements": 50
114 | }
115 | },
116 | "testPathIgnorePatterns": [
117 | "/__tests__/.*/__fixtures__/.*"
118 | ],
119 | "collectCoverageFrom": [
120 | "index.js",
121 | "src/**/*.{js,ts}",
122 | "!src/test.utils.js"
123 | ]
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/__tests__/index.js:
--------------------------------------------------------------------------------
1 | const { exam } = require('../test.utils');
2 |
3 | const shouldHaveChanged = (sampleName, expectedOutput, fixerOptions = {}) => {
4 | exam({ sampleName, expectedOutput, fixerOptions, expectedChange: true });
5 | };
6 |
7 | it('fix single quotes', () => {
8 | shouldHaveChanged('singleQuote', {
9 | name: 'sample #1',
10 | type: 'JSON',
11 | error: 'single quote',
12 | version: '1'
13 | });
14 | });
15 |
16 | describe('fix missing quotes', () => {
17 | it('RHS: one word', () => {
18 | shouldHaveChanged('noQuotes', {
19 | name: 'sample #10',
20 | type: 'JSON',
21 | error: 'missing quotes',
22 | version: 'one'
23 | });
24 | });
25 |
26 | it('RHS: one word (verbose)', () => {
27 | shouldHaveChanged(
28 | 'noQuotes',
29 | {
30 | name: 'sample #10',
31 | type: 'JSON',
32 | error: 'missing quotes',
33 | version: 'one'
34 | },
35 | { verbose: true }
36 | );
37 | });
38 |
39 | it('RHS: several words', () => {
40 | shouldHaveChanged('missingQuotes', {
41 | name: 'sample #11',
42 | type: 'JSON',
43 | error: 'missing quotes',
44 | version: 'a string'
45 | });
46 | });
47 |
48 | it('LHS: one word', () => {
49 | shouldHaveChanged('noLHQuotes', {
50 | name: 'sample #13',
51 | type: 'JSON',
52 | error: 'missing quotes',
53 | version: 'a string'
54 | });
55 | });
56 |
57 | it('LHS: 2 chars', () => {
58 | shouldHaveChanged('lefty2', {
59 | ix: 1
60 | });
61 | });
62 |
63 | it('LHS: 1 char', () => {
64 | shouldHaveChanged('lefty1', {
65 | t: 42
66 | });
67 | });
68 |
69 | it('LHS: not an octet', () => {
70 | shouldHaveChanged('leftyO', {
71 | o: 1
72 | });
73 | });
74 |
75 | it('LHS: one word (verbose)', () => {
76 | shouldHaveChanged(
77 | 'noLHQuotes',
78 | {
79 | name: 'sample #13',
80 | type: 'JSON',
81 | error: 'missing quotes',
82 | version: 'a string'
83 | },
84 | { verbose: true }
85 | );
86 | });
87 |
88 | it('LHS: several words', () => {
89 | shouldHaveChanged('missingLHQuotes', {
90 | name: 'sample #14',
91 | type: 'JSON',
92 | error: 'missing quotes',
93 | 'long content': 'a string'
94 | });
95 | });
96 |
97 | it('LHS: complicated RHS', () => {
98 | shouldHaveChanged('issue31', {
99 | something: 'string:string'
100 | });
101 | });
102 |
103 | it('Both sides', () => {
104 | shouldHaveChanged('doublyMissingQuotes', {
105 | field: 'value'
106 | });
107 | });
108 |
109 | it('Both sides (minified)', () => {
110 | shouldHaveChanged('doublyMissingQuotesMin', {
111 | field: 'value'
112 | });
113 | });
114 | });
115 |
116 | describe('fix trailing characters', () => {
117 | it('dots', () => {
118 | shouldHaveChanged('trailingDot', {
119 | name: 'sample #3',
120 | type: 'JSON',
121 | error: 'trailing dot',
122 | version: 0.3
123 | });
124 | });
125 |
126 | it('commas', () => {
127 | shouldHaveChanged('trailingComma', {
128 | name: 'sample #6',
129 | type: 'JSON',
130 | error: 'trailing comma',
131 | version: 0.6
132 | });
133 | });
134 |
135 | it('chars', () => {
136 | shouldHaveChanged('trailingChar', [
137 | {
138 | test1: '1',
139 | test2: {
140 | a: 'b',
141 | c: {}
142 | }
143 | }
144 | ]);
145 | });
146 |
147 | it('hex\'s "x"', () => {
148 | shouldHaveChanged('x', {
149 | name: 'sample #7',
150 | type: 'JSON',
151 | error: 'trailing x',
152 | version: 0x7
153 | });
154 | });
155 |
156 | it('hex\'s "x" (verbose)', () => {
157 | shouldHaveChanged(
158 | 'x',
159 | {
160 | name: 'sample #7',
161 | type: 'JSON',
162 | error: 'trailing x',
163 | version: 0x7
164 | },
165 | { verbose: true }
166 | );
167 | });
168 |
169 | it('hex\'s "0x"', () => {
170 | shouldHaveChanged('hex', {
171 | name: 'sample #22',
172 | type: 'JSON',
173 | error: 'hex number',
174 | version: 0x16
175 | });
176 | });
177 |
178 | it('hex\'s "0x" (verbose)', () => {
179 | shouldHaveChanged(
180 | 'hex',
181 | {
182 | name: 'sample #22',
183 | type: 'JSON',
184 | error: 'hex number',
185 | version: 0x16
186 | },
187 | { verbose: true }
188 | );
189 | });
190 |
191 | it('binary\'s "b"', () => {
192 | shouldHaveChanged('b', {
193 | name: 'sample #8',
194 | type: 'JSON',
195 | error: 'trailing b',
196 | version: 0b1000
197 | });
198 | });
199 |
200 | it('binary\'s "0b"', () => {
201 | shouldHaveChanged('bin', {
202 | name: 'sample #23',
203 | type: 'JSON',
204 | error: 'binary number',
205 | version: 0b10111
206 | });
207 | });
208 |
209 | it('octal\'s "o"', () => {
210 | shouldHaveChanged('o', {
211 | name: 'sample #9',
212 | type: 'JSON',
213 | error: 'trailing o',
214 | version: 0o11
215 | });
216 | });
217 |
218 | it('octal\'s "0o"', () => {
219 | shouldHaveChanged('oct', {
220 | name: 'sample #24',
221 | type: 'JSON',
222 | error: 'octal number',
223 | version: 0o30
224 | });
225 | });
226 | });
227 |
228 | it('fix extra characters', () => {
229 | shouldHaveChanged('extraChar', {
230 | name: 'sample #4',
231 | type: 'JSON',
232 | error: 'trailing error',
233 | version: 4
234 | });
235 | });
236 |
237 | it('fix missing commas', () => {
238 | shouldHaveChanged('missing', {
239 | name: 'sample #5',
240 | type: 'JSON',
241 | error: 'missing comma',
242 | version: 5
243 | });
244 | });
245 |
246 | describe('fix wrong brackets', () => {
247 | it('square brackets', () => {
248 | shouldHaveChanged('notSquare', {
249 | name: 'sample #12',
250 | error: 'wrong brackets',
251 | info: {
252 | type: 'JSON',
253 | version: 12
254 | }
255 | });
256 | });
257 |
258 | it('square brackets (verbose)', () => {
259 | shouldHaveChanged(
260 | 'notSquare',
261 | {
262 | name: 'sample #12',
263 | error: 'wrong brackets',
264 | info: {
265 | type: 'JSON',
266 | version: 12
267 | }
268 | },
269 | { verbose: true }
270 | );
271 | });
272 |
273 | it('curly brackets', () => {
274 | shouldHaveChanged('notCurly', {
275 | name: 'sample #15',
276 | error: 'wrong brackets',
277 | info: ['one', 'two']
278 | });
279 | });
280 |
281 | it('curly brackets (verbose)', () => {
282 | shouldHaveChanged(
283 | 'notCurly',
284 | {
285 | name: 'sample #15',
286 | error: 'wrong brackets',
287 | info: ['one', 'two']
288 | },
289 | { verbose: true }
290 | );
291 | });
292 |
293 | it('extra brackets', () => {
294 | shouldHaveChanged('extraBrackets', {
295 | error: 'extra brackets'
296 | });
297 | });
298 | });
299 |
300 | describe('comments', () => {
301 | it('inline line', () => {
302 | shouldHaveChanged('comment', {
303 | name: 'sample #16',
304 | type: 'JSON',
305 | error: 'comment',
306 | version: '0x10'
307 | });
308 | });
309 |
310 | it('single line', () => {
311 | shouldHaveChanged('smComment', {
312 | name: 'sample #17',
313 | type: 'JSON',
314 | error: 'multi-comment',
315 | version: '0x10'
316 | });
317 | });
318 |
319 | it('multi line', () => {
320 | shouldHaveChanged('multiComment', {
321 | name: 'sample #18',
322 | type: 'JSON',
323 | error: 'multi-comment',
324 | version: 18
325 | });
326 | });
327 | });
328 |
329 | describe('fix operations', () => {
330 | it('simple', () => {
331 | shouldHaveChanged('ops', {
332 | name: 'sample #20',
333 | type: 'JSON',
334 | error: 'operations',
335 | version: 20
336 | });
337 | });
338 |
339 | it('unary', () => {
340 | shouldHaveChanged('monOps', {
341 | name: 'sample #26',
342 | type: 'JSON',
343 | error: 'unary operations',
344 | version: -7
345 | });
346 | });
347 |
348 | it('multi', () => {
349 | shouldHaveChanged('multiOps', {
350 | name: 'sample #27',
351 | type: 'JSON',
352 | error: 'multi operations',
353 | version: 7
354 | });
355 | });
356 | });
357 |
358 | describe('fix concatenations', () => {
359 | it('simple', () => {
360 | shouldHaveChanged('concat', {
361 | name: 'sample #25',
362 | type: 'JSON',
363 | error: 'concat',
364 | version: 25
365 | });
366 | });
367 |
368 | it('verbose', () => {
369 | shouldHaveChanged(
370 | 'concat',
371 | {
372 | name: 'sample #25',
373 | type: 'JSON',
374 | error: 'concat',
375 | version: 25
376 | },
377 | { verbose: true }
378 | );
379 | });
380 | });
381 |
382 | describe('multi rounds', () => {
383 | it('x2', () => {
384 | shouldHaveChanged('twoErrs', {
385 | name: 'sample #19',
386 | type: 'JSON',
387 | error: '2 errors',
388 | version: 19
389 | });
390 | });
391 |
392 | it('x2 (verbose)', () => {
393 | shouldHaveChanged(
394 | 'twoErrs',
395 | {
396 | name: 'sample #19',
397 | type: 'JSON',
398 | error: '2 errors',
399 | version: 19
400 | },
401 | { verbose: true }
402 | );
403 | });
404 |
405 | it('x3', () => {
406 | shouldHaveChanged('threeErrs', {
407 | name: 'sample #21',
408 | type: 'JSON',
409 | error: '3 errors',
410 | version: 21
411 | });
412 | });
413 | });
414 |
415 | describe('special chars', () => {
416 | it('tab', () => {
417 | shouldHaveChanged('tab', {
418 | Test: '\t'
419 | });
420 | });
421 |
422 | it('formatted tab', () => {
423 | shouldHaveChanged('tabs', {
424 | Test: '\t'
425 | });
426 | });
427 |
428 | it('new line', () => {
429 | shouldHaveChanged('newLines', {
430 | Broken: '\n'
431 | });
432 | });
433 | });
434 |
--------------------------------------------------------------------------------
/src/__tests__/intact.js:
--------------------------------------------------------------------------------
1 | const { exam } = require('../test.utils');
2 |
3 | describe('keeps a correct file intact', () => {
4 | it('normal file', () => {
5 | exam({
6 | sampleName: 'normal',
7 | expectedOutput: {
8 | name: 'sample #0',
9 | type: 'JSON',
10 | version: 0
11 | }
12 | });
13 | });
14 |
15 | it('floating points', () => {
16 | exam({
17 | sampleName: 'fp',
18 | expectedOutput: {
19 | name: 'sample #2',
20 | type: 'JSON',
21 | version: 2.0
22 | }
23 | });
24 | });
25 | });
26 |
27 | test('boolean option', () => {
28 | exam({
29 | sampleName: 'normal',
30 | expectedOutput: {
31 | name: 'sample #0',
32 | type: 'JSON',
33 | version: 0
34 | },
35 | fixerOptions: true
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/src/__tests__/more.js:
--------------------------------------------------------------------------------
1 | const { readFileSync } = require('fs');
2 | const jf = require('../..');
3 |
4 | describe('returns the json as fixed string', () => {
5 | it('normal file', () => {
6 | const json = readFileSync('./test/samples/normal.json', 'utf-8');
7 | const { data } = jf(json, { parse: false });
8 | expect(typeof data).toBe('string');
9 | expect(typeof JSON.parse(data)).toBe('object');
10 | });
11 | });
12 |
13 | test('Unsupported error', () => {
14 | const json = readFileSync('./test/samples/quoteInQuotes.json', 'utf-8');
15 | expect(() => jf(json)).toThrowError(
16 | 'Unsupported issue: Expected "," or "}" but "M" found. (please open an issue at the repo)'
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/src/__tests__/utils.js:
--------------------------------------------------------------------------------
1 | const { removeLinebreak, replaceChar, curlyBracesIncluded } = require('../utils');
2 |
3 | test('No line breaks', () => {
4 | expect(removeLinebreak(`a\nnew\nline`)).toEqual('anewline');
5 | });
6 |
7 | test('Spaces there', () => {
8 | expect(removeLinebreak('not the same ')).toEqual('not the same ');
9 | });
10 |
11 | test('Char replaced', () => {
12 | expect(replaceChar('Hi$mate', 2, ' ')).toEqual('Hi mate');
13 | });
14 |
15 | test('Char !not replaced', () => {
16 | expect(replaceChar('Hi$mate', -1, ' ')).toEqual(' Hi$mate');
17 | });
18 |
19 | describe('Inlined braces', () => {
20 | it('{ ... }', () => {
21 | expect(curlyBracesIncluded('{ a: "thing }')).toBeTruthy();
22 | });
23 |
24 | it('[ ... ]', () => {
25 | expect(curlyBracesIncluded('[ 0, 1 ]')).toBeFalsy();
26 | });
27 | });
28 |
29 | describe('Outlined braces', () => {
30 | it('{ ... }', () => {
31 | expect(curlyBracesIncluded('a: "thing\n')).toBeFalsy();
32 | });
33 |
34 | it('[ ... ]', () => {
35 | expect(curlyBracesIncluded('0, 1')).toBeFalsy();
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/src/fixer.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 | const { psw, removeLinebreak, replaceChar, curlyBracesIncluded } = require('./utils');
3 | const { quotify, numberify, baseNumify } = require('./transform');
4 | const { parse } = require('./json.pjs');
5 |
6 | const fixExtraChar = ({ fixedData, verbose, targetLine }) => {
7 | /* eslint-disable security/detect-object-injection */
8 | if (verbose) psw(chalk.magenta('Extra character'));
9 | if (fixedData[targetLine] === '') --targetLine;
10 | const brokenLine = removeLinebreak(fixedData[targetLine]);
11 |
12 | let fixedLine = brokenLine.trimEnd();
13 | fixedLine = fixedLine.substr(0, fixedLine.length - 1);
14 | fixedData[targetLine] = fixedLine;
15 | return fixedData;
16 | };
17 |
18 | const fixSingleQuotes = ({ start, fixedData, verbose }) => {
19 | if (verbose) psw(chalk.magenta('Single quotes'));
20 | const targetLine = start.line - 1;
21 | const brokenLine = removeLinebreak(fixedData[targetLine]);
22 | const fixedLine = brokenLine.replace(/(":\s*)'(.*?)'/g, '$1"$2"');
23 | fixedData[targetLine] = fixedLine;
24 | return fixedData;
25 | };
26 |
27 | const fixTrailingChar = ({ start, fixedData, verbose }) => {
28 | if (verbose) psw(chalk.magenta('Trailing character'));
29 | const targetLine = start.line - 1;
30 | const brokenLine = removeLinebreak(fixedData[targetLine]);
31 | const fixedLine = brokenLine.replace(/(":\s*)[.,](\d*)/g, '$10.$2');
32 | const unquotedWord = /(":\s*)(\S*)/g.exec(fixedLine);
33 | // if (unquotedWord === null) throw new Error('Unquoted word expected!');
34 | const NN = Number.isNaN(Number(unquotedWord[2]));
35 | if (NN && !/([xbo][0-9a-fA-F]+)/.test(unquotedWord[2])) {
36 | return quotify({ fixedData, targetLine, fixedLine, verbose });
37 | }
38 | if (!NN && !/\0([xbo][0-9a-fA-F]+)/.test(unquotedWord[2])) {
39 | return numberify({ fixedData, targetLine, fixedLine, unquotedWord, verbose });
40 | }
41 | let baseNumber = fixedLine.replace(/(":\s*)([xbo][0-9a-fA-F]*)/g, '$1"0$2"');
42 | if (baseNumber !== fixedLine) {
43 | baseNumber = baseNumify({ baseNumber, verbose });
44 | }
45 |
46 | fixedData[targetLine] = baseNumber;
47 | return fixedData;
48 | };
49 |
50 | const fixMissingQuotes = ({ start, fixedData, verbose }) => {
51 | /* eslint-disable security/detect-object-injection */
52 | if (verbose) psw(chalk.magenta('Missing quotes'));
53 | const targetLine = start.line - 1;
54 | let brokenLine = removeLinebreak(fixedData[targetLine]);
55 | const seCurlyBraces = curlyBracesIncluded(brokenLine);
56 | if (seCurlyBraces) {
57 | brokenLine = brokenLine.substring(1, brokenLine.length - 1);
58 | }
59 | const NO_RH_QUOTES = /(":\s*)([^,{}[\]]+)/;
60 | const NO_LH_QUOTES = /(^[^"][\S\s]*)(:\s*["\w{[])/;
61 | const RH = NO_RH_QUOTES.test(brokenLine);
62 | let fixedLine = RH ? brokenLine.replace(NO_RH_QUOTES, '$1"$2"') : brokenLine;
63 | const leftSpace = fixedLine.match(/^(\s+)/);
64 | fixedLine = fixedLine.trimStart();
65 | if (NO_LH_QUOTES.test(fixedLine)) {
66 | const firstColon = fixedLine.indexOf(':');
67 | const leftHand = fixedLine.substring(0, firstColon);
68 | fixedLine = `"${leftHand}"${fixedLine.substring(firstColon)}`;
69 | }
70 | fixedData[targetLine] = `${leftSpace === null ? '' : leftSpace[0]}${fixedLine}`;
71 | if (seCurlyBraces) {
72 | fixedData[targetLine] = `{${fixedData[targetLine]}}`;
73 | }
74 |
75 | return fixedData;
76 | };
77 |
78 | const fixSquareBrackets = ({ start, fixedData, verbose, targetLine }) => {
79 | /* eslint-disable security/detect-object-injection */
80 | if (verbose) psw(chalk.magenta('Square brackets instead of curly ones'));
81 | const lineToChange = fixedData[targetLine].includes('[')
82 | ? fixedData[targetLine]
83 | : fixedData[++targetLine];
84 | const brokenLine = removeLinebreak(lineToChange);
85 | const fixedLine = replaceChar(brokenLine, start.column - 1, '{');
86 | fixedData[targetLine] = fixedLine;
87 |
88 | try {
89 | parse(fixedData.join('\n'));
90 | } catch (e) {
91 | targetLine = e.location.start.line - 1;
92 | const newLine = removeLinebreak(fixedData[targetLine]).replace(']', '}');
93 | fixedData[targetLine] = newLine;
94 | }
95 | return fixedData;
96 | };
97 |
98 | const fixCurlyBrackets = ({ fixedData, verbose, targetLine }) => {
99 | if (verbose) psw(chalk.magenta('Curly brackets instead of square ones'));
100 | const brokenLine = removeLinebreak(
101 | fixedData[targetLine].includes('{') ? fixedData[targetLine] : fixedData[++targetLine]
102 | );
103 | const fixedLine = replaceChar(brokenLine, brokenLine.indexOf('{'), '[');
104 | fixedData[targetLine] = fixedLine;
105 |
106 | try {
107 | parse(fixedData.join('\n'));
108 | } catch (e) {
109 | targetLine = e.location.start.line - 1;
110 | const newLine = removeLinebreak(fixedData[targetLine]).replace('}', ']');
111 | fixedData[targetLine] = newLine;
112 | }
113 |
114 | return fixedData;
115 | };
116 |
117 | const fixMultilineComment = ({ fixedData, targetLine }) => {
118 | let end = targetLine + 1;
119 | while (end <= fixedData.length && !fixedData[end].includes('*/')) ++end;
120 | for (let i = targetLine + 1; i <= end; ++i) fixedData[i] = '#RM';
121 | fixedData[targetLine] = fixedData[targetLine].replace(/\s*\/\*+.*/g, '#RM');
122 | return fixedData.filter((l) => l !== '#RM');
123 | };
124 |
125 | const fixComment = ({ start, fixedData, verbose }) => {
126 | if (verbose) psw(chalk.magenta('Comment'));
127 | const targetLine = start.line - 1;
128 | const brokenLine = removeLinebreak(fixedData[targetLine]);
129 | const fixedLine = brokenLine.replace(/(\s*)(\/\/.*|\/\*+.*?\*+\/)/g, '');
130 | if (fixedLine.includes('/*')) {
131 | return fixMultilineComment({ fixedData, targetLine });
132 | }
133 | fixedData[targetLine] = fixedLine;
134 | return fixedData;
135 | };
136 |
137 | const fixOpConcat = ({ start, fixedData, verbose }) => {
138 | if (verbose) psw(chalk.magenta('Operations/Concatenations'));
139 | psw(
140 | chalk.yellow(
141 | 'Please note: calculations made here may not be entirely correct on complex operations'
142 | )
143 | );
144 | const targetLine = start.line - 1;
145 | const brokenLine = removeLinebreak(fixedData[targetLine]);
146 | const fixedLine = brokenLine
147 | /* eslint-disable no-eval, security/detect-eval-with-expression */
148 | .replace(
149 | /(\d+)\s*([+\-*/%&|^><]|\*\*|>{2,3}|<<|[=!><]=|[=!]==)\s*(\d+)\s*([+\-*/%&|^><]|\*\*|>{2,3}|<<|[=!><]=|[=!]==)*\s*(\d+)*/g,
150 | (eq) => eval(eq)
151 | )
152 | .replace(/[~!+-]\(?(\d+)\)?/g, (eq) => eval(eq))
153 | .replace(/(":\s*)"(.*?)"\s*\+\s*"(.*?)"/g, '$1"$2$3"');
154 | /* eslint-enable no-eval */
155 | fixedData[targetLine] = fixedLine;
156 | return fixedData;
157 | };
158 |
159 | const fixExtraCurlyBrackets = ({ start, fixedData, verbose }) => {
160 | if (verbose) psw(chalk.magenta('Extra curly brackets'));
161 |
162 | const targetLine = start.line - 1;
163 | const fullData = fixedData.join('\n');
164 | let fixedLine = removeLinebreak(fixedData[targetLine]);
165 |
166 | const data = fullData.split('');
167 | const openingCount = data.filter((c) => c === '{').length;
168 | const closingCount = data.filter((c) => c === '}').length;
169 | const bracketDiff = closingCount - openingCount;
170 |
171 | for (let i = 0; i < bracketDiff; i++) {
172 | const index = fixedLine.lastIndexOf('}');
173 | fixedLine = fixedLine.slice(0, index) + fixedLine.slice(index + 1);
174 | }
175 |
176 | fixedData[targetLine] = fixedLine;
177 | return fixedData;
178 | };
179 |
180 | const fixSpecialChar = ({ start, fixedData, verbose }) => {
181 | if (verbose) psw(chalk.magenta('Special character'));
182 | const targetLine = start.line - 1;
183 | const brokenLine = fixedData[targetLine];
184 |
185 | let fixedLine = brokenLine
186 | .replace(/\f/g, '\\f')
187 | .replace(/\n/g, '\\n')
188 | .replace(/\r/g, '\\r')
189 | .replace(/\t/g, '\\t');
190 |
191 | if (brokenLine.endsWith('"') && brokenLine[start.column] === undefined) {
192 | if (verbose) psw(chalk.magenta('New line'));
193 | const removedIndex = targetLine + 1;
194 | const continuation = fixedData[removedIndex];
195 | fixedLine = `${brokenLine}\\n${continuation}`;
196 | fixedData.splice(removedIndex, 1);
197 | }
198 |
199 | fixedData[targetLine] = fixedLine;
200 | return fixedData;
201 | };
202 |
203 | module.exports = {
204 | fixExtraChar,
205 | fixSingleQuotes,
206 | fixTrailingChar,
207 | fixMissingQuotes,
208 | fixSquareBrackets,
209 | fixCurlyBrackets,
210 | fixComment,
211 | fixOpConcat,
212 | fixExtraCurlyBrackets,
213 | fixSpecialChar
214 | };
215 |
--------------------------------------------------------------------------------
/src/json.pegjs:
--------------------------------------------------------------------------------
1 | // JSON Grammar
2 | // ============
3 | //
4 | // Based on the grammar from RFC 7159 [1].
5 | //
6 | // Note that JSON is also specified in ECMA-262 [2], ECMA-404 [3], and on the
7 | // JSON website [4] (somewhat informally). The RFC seems the most authoritative
8 | // source, which is confirmed e.g. by [5].
9 | //
10 | // [1] http://tools.ietf.org/html/rfc7159
11 | // [2] http://www.ecma-international.org/publications/standards/Ecma-262.htm
12 | // [3] http://www.ecma-international.org/publications/standards/Ecma-404.htm
13 | // [4] http://json.org/
14 | // [5] https://www.tbray.org/ongoing/When/201x/2014/03/05/RFC7159-JSON
15 |
16 | // ----- 2. JSON Grammar -----
17 |
18 | JSON_text
19 | = ws value:value ws { return value; }
20 |
21 | begin_array = ws "[" ws
22 | begin_object = ws "{" ws
23 | end_array = ws "]" ws
24 | end_object = ws "}" ws
25 | name_separator = ws ":" ws
26 | value_separator = ws "," ws
27 |
28 | ws "whitespace" = [ \t\n\r]*
29 |
30 | // ----- 3. Values -----
31 |
32 | value
33 | = false
34 | / null
35 | / true
36 | / object
37 | / array
38 | / number
39 | / string
40 |
41 | false = "false" { return false; }
42 | null = "null" { return null; }
43 | true = "true" { return true; }
44 |
45 | // ----- 4. Objects -----
46 |
47 | object
48 | = begin_object
49 | members:(
50 | head:member
51 | tail:(value_separator m:member { return m; })*
52 | {
53 | var result = {};
54 |
55 | [head].concat(tail).forEach(function(element) {
56 | result[element.name] = element.value;
57 | });
58 |
59 | return result;
60 | }
61 | )?
62 | end_object
63 | { return members !== null ? members: {}; }
64 |
65 | member
66 | = name:string name_separator value:value {
67 | return { name: name, value: value };
68 | }
69 |
70 | // ----- 5. Arrays -----
71 |
72 | array
73 | = begin_array
74 | values:(
75 | head:value
76 | tail:(value_separator v:value { return v; })*
77 | { return [head].concat(tail); }
78 | )?
79 | end_array
80 | { return values !== null ? values : []; }
81 |
82 | // ----- 6. Numbers -----
83 |
84 | number "number"
85 | = minus? int frac? exp? { return parseFloat(text()); }
86 |
87 | decimal_point
88 | = "."
89 |
90 | digit1_9
91 | = [1-9]
92 |
93 | e
94 | = [eE]
95 |
96 | exp
97 | = e (minus / plus)? DIGIT+
98 |
99 | frac
100 | = decimal_point DIGIT+
101 |
102 | int
103 | = zero / (digit1_9 DIGIT*)
104 |
105 | minus
106 | = "-"
107 |
108 | plus
109 | = "+"
110 |
111 | zero
112 | = "0"
113 |
114 | // ----- 7. Strings -----
115 |
116 | string "string"
117 | = quotation_mark chars:char* quotation_mark { return chars.join(""); }
118 |
119 | char
120 | = unescaped
121 | / escape
122 | sequence:(
123 | '"'
124 | / "\\"
125 | / "/"
126 | / "b" { return "\b"; }
127 | / "f" { return "\f"; }
128 | / "n" { return "\n"; }
129 | / "r" { return "\r"; }
130 | / "t" { return "\t"; }
131 | / "u" digits:$(HEXDIG HEXDIG HEXDIG HEXDIG) {
132 | return String.fromCharCode(parseInt(digits, 16));
133 | }
134 | )
135 | { return sequence; }
136 |
137 | escape
138 | = "\\"
139 |
140 | quotation_mark
141 | = '"'
142 |
143 | unescaped
144 | = [^\0-\x1F\x22\x5C]
145 |
146 | // ----- Core ABNF Rules -----
147 |
148 | // See RFC 4234, Appendix B (http://tools.ietf.org/html/rfc4234).
149 | DIGIT = [0-9]
150 | HEXDIG = [0-9a-f]i
151 |
--------------------------------------------------------------------------------
/src/json.pjs:
--------------------------------------------------------------------------------
1 | /*
2 | * Generated by PEG.js 0.10.0.
3 | *
4 | * http://pegjs.org/
5 | */
6 |
7 | 'use strict'
8 |
9 | function peg$subclass(child, parent) {
10 | function ctor() {
11 | this.constructor = child
12 | }
13 | ctor.prototype = parent.prototype
14 | child.prototype = new ctor()
15 | }
16 |
17 | function peg$SyntaxError(message, expected, found, location) {
18 | this.message = message
19 | this.expected = expected
20 | this.found = found
21 | this.location = location
22 | this.name = 'SyntaxError'
23 |
24 | if (typeof Error.captureStackTrace === 'function') {
25 | Error.captureStackTrace(this, peg$SyntaxError)
26 | }
27 | }
28 |
29 | peg$subclass(peg$SyntaxError, Error)
30 |
31 | peg$SyntaxError.buildMessage = function(expected, found) {
32 | var DESCRIBE_EXPECTATION_FNS = {
33 | literal: function(expectation) {
34 | return '"' + literalEscape(expectation.text) + '"'
35 | },
36 |
37 | class: function(expectation) {
38 | var escapedParts = '',
39 | i
40 |
41 | for (i = 0; i < expectation.parts.length; i++) {
42 | escapedParts +=
43 | expectation.parts[i] instanceof Array
44 | ? classEscape(expectation.parts[i][0]) +
45 | '-' +
46 | classEscape(expectation.parts[i][1])
47 | : classEscape(expectation.parts[i])
48 | }
49 |
50 | return '[' + (expectation.inverted ? '^' : '') + escapedParts + ']'
51 | },
52 |
53 | any: function(expectation) {
54 | return 'any character'
55 | },
56 |
57 | end: function(expectation) {
58 | return 'end of input'
59 | },
60 |
61 | other: function(expectation) {
62 | return expectation.description
63 | },
64 | }
65 |
66 | function hex(ch) {
67 | return ch
68 | .charCodeAt(0)
69 | .toString(16)
70 | .toUpperCase()
71 | }
72 |
73 | function literalEscape(s) {
74 | return s
75 | .replace(/\\/g, '\\\\')
76 | .replace(/"/g, '\\"')
77 | .replace(/\0/g, '\\0')
78 | .replace(/\t/g, '\\t')
79 | .replace(/\n/g, '\\n')
80 | .replace(/\r/g, '\\r')
81 | .replace(/[\x00-\x0F]/g, function(ch) {
82 | return '\\x0' + hex(ch)
83 | })
84 | .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
85 | return '\\x' + hex(ch)
86 | })
87 | }
88 |
89 | function classEscape(s) {
90 | return s
91 | .replace(/\\/g, '\\\\')
92 | .replace(/\]/g, '\\]')
93 | .replace(/\^/g, '\\^')
94 | .replace(/-/g, '\\-')
95 | .replace(/\0/g, '\\0')
96 | .replace(/\t/g, '\\t')
97 | .replace(/\n/g, '\\n')
98 | .replace(/\r/g, '\\r')
99 | .replace(/[\x00-\x0F]/g, function(ch) {
100 | return '\\x0' + hex(ch)
101 | })
102 | .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
103 | return '\\x' + hex(ch)
104 | })
105 | }
106 |
107 | function describeExpectation(expectation) {
108 | return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation)
109 | }
110 |
111 | function describeExpected(expected) {
112 | var descriptions = new Array(expected.length),
113 | i,
114 | j
115 |
116 | for (i = 0; i < expected.length; i++) {
117 | descriptions[i] = describeExpectation(expected[i])
118 | }
119 |
120 | descriptions.sort()
121 |
122 | if (descriptions.length > 0) {
123 | for (i = 1, j = 1; i < descriptions.length; i++) {
124 | if (descriptions[i - 1] !== descriptions[i]) {
125 | descriptions[j] = descriptions[i]
126 | j++
127 | }
128 | }
129 | descriptions.length = j
130 | }
131 |
132 | switch (descriptions.length) {
133 | case 1:
134 | return descriptions[0]
135 |
136 | case 2:
137 | return descriptions[0] + ' or ' + descriptions[1]
138 |
139 | default:
140 | return (
141 | descriptions.slice(0, -1).join(', ') +
142 | ', or ' +
143 | descriptions[descriptions.length - 1]
144 | )
145 | }
146 | }
147 |
148 | function describeFound(found) {
149 | return found ? '"' + literalEscape(found) + '"' : 'end of input'
150 | }
151 |
152 | return (
153 | 'Expected ' +
154 | describeExpected(expected) +
155 | ' but ' +
156 | describeFound(found) +
157 | ' found.'
158 | )
159 | }
160 |
161 | function peg$parse(input, options) {
162 | options = options !== void 0 ? options : {}
163 |
164 | var peg$FAILED = {},
165 | peg$startRuleFunctions = {JSON_text: peg$parseJSON_text},
166 | peg$startRuleFunction = peg$parseJSON_text,
167 | peg$c0 = function(value) {
168 | return value
169 | },
170 | peg$c1 = '[',
171 | peg$c2 = peg$literalExpectation('[', false),
172 | peg$c3 = '{',
173 | peg$c4 = peg$literalExpectation('{', false),
174 | peg$c5 = ']',
175 | peg$c6 = peg$literalExpectation(']', false),
176 | peg$c7 = '}',
177 | peg$c8 = peg$literalExpectation('}', false),
178 | peg$c9 = ':',
179 | peg$c10 = peg$literalExpectation(':', false),
180 | peg$c11 = ',',
181 | peg$c12 = peg$literalExpectation(',', false),
182 | peg$c13 = peg$otherExpectation('whitespace'),
183 | peg$c14 = /^[ \t\n\r]/,
184 | peg$c15 = peg$classExpectation([' ', '\t', '\n', '\r'], false, false),
185 | peg$c16 = 'false',
186 | peg$c17 = peg$literalExpectation('false', false),
187 | peg$c18 = function() {
188 | return false
189 | },
190 | peg$c19 = 'null',
191 | peg$c20 = peg$literalExpectation('null', false),
192 | peg$c21 = function() {
193 | return null
194 | },
195 | peg$c22 = 'true',
196 | peg$c23 = peg$literalExpectation('true', false),
197 | peg$c24 = function() {
198 | return true
199 | },
200 | peg$c25 = function(head, m) {
201 | return m
202 | },
203 | peg$c26 = function(head, tail) {
204 | var result = {}
205 |
206 | ;[head].concat(tail).forEach(function(element) {
207 | result[element.name] = element.value
208 | })
209 |
210 | return result
211 | },
212 | peg$c27 = function(members) {
213 | return members !== null ? members : {}
214 | },
215 | peg$c28 = function(name, value) {
216 | return {name: name, value: value}
217 | },
218 | peg$c29 = function(head, v) {
219 | return v
220 | },
221 | peg$c30 = function(head, tail) {
222 | return [head].concat(tail)
223 | },
224 | peg$c31 = function(values) {
225 | return values !== null ? values : []
226 | },
227 | peg$c32 = peg$otherExpectation('number'),
228 | peg$c33 = function() {
229 | return parseFloat(text())
230 | },
231 | peg$c34 = '.',
232 | peg$c35 = peg$literalExpectation('.', false),
233 | peg$c36 = /^[1-9]/,
234 | peg$c37 = peg$classExpectation([['1', '9']], false, false),
235 | peg$c38 = /^[eE]/,
236 | peg$c39 = peg$classExpectation(['e', 'E'], false, false),
237 | peg$c40 = '-',
238 | peg$c41 = peg$literalExpectation('-', false),
239 | peg$c42 = '+',
240 | peg$c43 = peg$literalExpectation('+', false),
241 | peg$c44 = '0',
242 | peg$c45 = peg$literalExpectation('0', false),
243 | peg$c46 = peg$otherExpectation('string'),
244 | peg$c47 = function(chars) {
245 | return chars.join('')
246 | },
247 | peg$c48 = '"',
248 | peg$c49 = peg$literalExpectation('"', false),
249 | peg$c50 = '\\',
250 | peg$c51 = peg$literalExpectation('\\', false),
251 | peg$c52 = '/',
252 | peg$c53 = peg$literalExpectation('/', false),
253 | peg$c54 = 'b',
254 | peg$c55 = peg$literalExpectation('b', false),
255 | peg$c56 = function() {
256 | return '\b'
257 | },
258 | peg$c57 = 'f',
259 | peg$c58 = peg$literalExpectation('f', false),
260 | peg$c59 = function() {
261 | return '\f'
262 | },
263 | peg$c60 = 'n',
264 | peg$c61 = peg$literalExpectation('n', false),
265 | peg$c62 = function() {
266 | return '\n'
267 | },
268 | peg$c63 = 'r',
269 | peg$c64 = peg$literalExpectation('r', false),
270 | peg$c65 = function() {
271 | return '\r'
272 | },
273 | peg$c66 = 't',
274 | peg$c67 = peg$literalExpectation('t', false),
275 | peg$c68 = function() {
276 | return '\t'
277 | },
278 | peg$c69 = 'u',
279 | peg$c70 = peg$literalExpectation('u', false),
280 | peg$c71 = function(digits) {
281 | return String.fromCharCode(parseInt(digits, 16))
282 | },
283 | peg$c72 = function(sequence) {
284 | return sequence
285 | },
286 | peg$c73 = /^[^\0-\x1F"\\]/,
287 | peg$c74 = peg$classExpectation([['\0', '\x1F'], '"', '\\'], true, false),
288 | peg$c75 = /^[0-9]/,
289 | peg$c76 = peg$classExpectation([['0', '9']], false, false),
290 | peg$c77 = /^[0-9a-f]/i,
291 | peg$c78 = peg$classExpectation([['0', '9'], ['a', 'f']], false, true),
292 | peg$currPos = 0,
293 | peg$savedPos = 0,
294 | peg$posDetailsCache = [{line: 1, column: 1}],
295 | peg$maxFailPos = 0,
296 | peg$maxFailExpected = [],
297 | peg$silentFails = 0,
298 | peg$result
299 |
300 | if ('startRule' in options) {
301 | if (!(options.startRule in peg$startRuleFunctions)) {
302 | throw new Error(
303 | 'Can\'t start parsing from rule "' + options.startRule + '".',
304 | )
305 | }
306 |
307 | peg$startRuleFunction = peg$startRuleFunctions[options.startRule]
308 | }
309 |
310 | function text() {
311 | return input.substring(peg$savedPos, peg$currPos)
312 | }
313 |
314 | function location() {
315 | return peg$computeLocation(peg$savedPos, peg$currPos)
316 | }
317 |
318 | function expected(description, location) {
319 | location =
320 | location !== void 0
321 | ? location
322 | : peg$computeLocation(peg$savedPos, peg$currPos)
323 |
324 | throw peg$buildStructuredError(
325 | [peg$otherExpectation(description)],
326 | input.substring(peg$savedPos, peg$currPos),
327 | location,
328 | )
329 | }
330 |
331 | function error(message, location) {
332 | location =
333 | location !== void 0
334 | ? location
335 | : peg$computeLocation(peg$savedPos, peg$currPos)
336 |
337 | throw peg$buildSimpleError(message, location)
338 | }
339 |
340 | function peg$literalExpectation(text, ignoreCase) {
341 | return {type: 'literal', text: text, ignoreCase: ignoreCase}
342 | }
343 |
344 | function peg$classExpectation(parts, inverted, ignoreCase) {
345 | return {
346 | type: 'class',
347 | parts: parts,
348 | inverted: inverted,
349 | ignoreCase: ignoreCase,
350 | }
351 | }
352 |
353 | function peg$anyExpectation() {
354 | return {type: 'any'}
355 | }
356 |
357 | function peg$endExpectation() {
358 | return {type: 'end'}
359 | }
360 |
361 | function peg$otherExpectation(description) {
362 | return {type: 'other', description: description}
363 | }
364 |
365 | function peg$computePosDetails(pos) {
366 | var details = peg$posDetailsCache[pos],
367 | p
368 |
369 | if (details) {
370 | return details
371 | } else {
372 | p = pos - 1
373 | while (!peg$posDetailsCache[p]) {
374 | p--
375 | }
376 |
377 | details = peg$posDetailsCache[p]
378 | details = {
379 | line: details.line,
380 | column: details.column,
381 | }
382 |
383 | while (p < pos) {
384 | if (input.charCodeAt(p) === 10) {
385 | details.line++
386 | details.column = 1
387 | } else {
388 | details.column++
389 | }
390 |
391 | p++
392 | }
393 |
394 | peg$posDetailsCache[pos] = details
395 | return details
396 | }
397 | }
398 |
399 | function peg$computeLocation(startPos, endPos) {
400 | var startPosDetails = peg$computePosDetails(startPos),
401 | endPosDetails = peg$computePosDetails(endPos)
402 |
403 | return {
404 | start: {
405 | offset: startPos,
406 | line: startPosDetails.line,
407 | column: startPosDetails.column,
408 | },
409 | end: {
410 | offset: endPos,
411 | line: endPosDetails.line,
412 | column: endPosDetails.column,
413 | },
414 | }
415 | }
416 |
417 | function peg$fail(expected) {
418 | if (peg$currPos < peg$maxFailPos) {
419 | return
420 | }
421 |
422 | if (peg$currPos > peg$maxFailPos) {
423 | peg$maxFailPos = peg$currPos
424 | peg$maxFailExpected = []
425 | }
426 |
427 | peg$maxFailExpected.push(expected)
428 | }
429 |
430 | function peg$buildSimpleError(message, location) {
431 | return new peg$SyntaxError(message, null, null, location)
432 | }
433 |
434 | function peg$buildStructuredError(expected, found, location) {
435 | return new peg$SyntaxError(
436 | peg$SyntaxError.buildMessage(expected, found),
437 | expected,
438 | found,
439 | location,
440 | )
441 | }
442 |
443 | function peg$parseJSON_text() {
444 | var s0, s1, s2, s3
445 |
446 | s0 = peg$currPos
447 | s1 = peg$parsews()
448 | if (s1 !== peg$FAILED) {
449 | s2 = peg$parsevalue()
450 | if (s2 !== peg$FAILED) {
451 | s3 = peg$parsews()
452 | if (s3 !== peg$FAILED) {
453 | peg$savedPos = s0
454 | s1 = peg$c0(s2)
455 | s0 = s1
456 | } else {
457 | peg$currPos = s0
458 | s0 = peg$FAILED
459 | }
460 | } else {
461 | peg$currPos = s0
462 | s0 = peg$FAILED
463 | }
464 | } else {
465 | peg$currPos = s0
466 | s0 = peg$FAILED
467 | }
468 |
469 | return s0
470 | }
471 |
472 | function peg$parsebegin_array() {
473 | var s0, s1, s2, s3
474 |
475 | s0 = peg$currPos
476 | s1 = peg$parsews()
477 | if (s1 !== peg$FAILED) {
478 | if (input.charCodeAt(peg$currPos) === 91) {
479 | s2 = peg$c1
480 | peg$currPos++
481 | } else {
482 | s2 = peg$FAILED
483 | if (peg$silentFails === 0) {
484 | peg$fail(peg$c2)
485 | }
486 | }
487 | if (s2 !== peg$FAILED) {
488 | s3 = peg$parsews()
489 | if (s3 !== peg$FAILED) {
490 | s1 = [s1, s2, s3]
491 | s0 = s1
492 | } else {
493 | peg$currPos = s0
494 | s0 = peg$FAILED
495 | }
496 | } else {
497 | peg$currPos = s0
498 | s0 = peg$FAILED
499 | }
500 | } else {
501 | peg$currPos = s0
502 | s0 = peg$FAILED
503 | }
504 |
505 | return s0
506 | }
507 |
508 | function peg$parsebegin_object() {
509 | var s0, s1, s2, s3
510 |
511 | s0 = peg$currPos
512 | s1 = peg$parsews()
513 | if (s1 !== peg$FAILED) {
514 | if (input.charCodeAt(peg$currPos) === 123) {
515 | s2 = peg$c3
516 | peg$currPos++
517 | } else {
518 | s2 = peg$FAILED
519 | if (peg$silentFails === 0) {
520 | peg$fail(peg$c4)
521 | }
522 | }
523 | if (s2 !== peg$FAILED) {
524 | s3 = peg$parsews()
525 | if (s3 !== peg$FAILED) {
526 | s1 = [s1, s2, s3]
527 | s0 = s1
528 | } else {
529 | peg$currPos = s0
530 | s0 = peg$FAILED
531 | }
532 | } else {
533 | peg$currPos = s0
534 | s0 = peg$FAILED
535 | }
536 | } else {
537 | peg$currPos = s0
538 | s0 = peg$FAILED
539 | }
540 |
541 | return s0
542 | }
543 |
544 | function peg$parseend_array() {
545 | var s0, s1, s2, s3
546 |
547 | s0 = peg$currPos
548 | s1 = peg$parsews()
549 | if (s1 !== peg$FAILED) {
550 | if (input.charCodeAt(peg$currPos) === 93) {
551 | s2 = peg$c5
552 | peg$currPos++
553 | } else {
554 | s2 = peg$FAILED
555 | if (peg$silentFails === 0) {
556 | peg$fail(peg$c6)
557 | }
558 | }
559 | if (s2 !== peg$FAILED) {
560 | s3 = peg$parsews()
561 | if (s3 !== peg$FAILED) {
562 | s1 = [s1, s2, s3]
563 | s0 = s1
564 | } else {
565 | peg$currPos = s0
566 | s0 = peg$FAILED
567 | }
568 | } else {
569 | peg$currPos = s0
570 | s0 = peg$FAILED
571 | }
572 | } else {
573 | peg$currPos = s0
574 | s0 = peg$FAILED
575 | }
576 |
577 | return s0
578 | }
579 |
580 | function peg$parseend_object() {
581 | var s0, s1, s2, s3
582 |
583 | s0 = peg$currPos
584 | s1 = peg$parsews()
585 | if (s1 !== peg$FAILED) {
586 | if (input.charCodeAt(peg$currPos) === 125) {
587 | s2 = peg$c7
588 | peg$currPos++
589 | } else {
590 | s2 = peg$FAILED
591 | if (peg$silentFails === 0) {
592 | peg$fail(peg$c8)
593 | }
594 | }
595 | if (s2 !== peg$FAILED) {
596 | s3 = peg$parsews()
597 | if (s3 !== peg$FAILED) {
598 | s1 = [s1, s2, s3]
599 | s0 = s1
600 | } else {
601 | peg$currPos = s0
602 | s0 = peg$FAILED
603 | }
604 | } else {
605 | peg$currPos = s0
606 | s0 = peg$FAILED
607 | }
608 | } else {
609 | peg$currPos = s0
610 | s0 = peg$FAILED
611 | }
612 |
613 | return s0
614 | }
615 |
616 | function peg$parsename_separator() {
617 | var s0, s1, s2, s3
618 |
619 | s0 = peg$currPos
620 | s1 = peg$parsews()
621 | if (s1 !== peg$FAILED) {
622 | if (input.charCodeAt(peg$currPos) === 58) {
623 | s2 = peg$c9
624 | peg$currPos++
625 | } else {
626 | s2 = peg$FAILED
627 | if (peg$silentFails === 0) {
628 | peg$fail(peg$c10)
629 | }
630 | }
631 | if (s2 !== peg$FAILED) {
632 | s3 = peg$parsews()
633 | if (s3 !== peg$FAILED) {
634 | s1 = [s1, s2, s3]
635 | s0 = s1
636 | } else {
637 | peg$currPos = s0
638 | s0 = peg$FAILED
639 | }
640 | } else {
641 | peg$currPos = s0
642 | s0 = peg$FAILED
643 | }
644 | } else {
645 | peg$currPos = s0
646 | s0 = peg$FAILED
647 | }
648 |
649 | return s0
650 | }
651 |
652 | function peg$parsevalue_separator() {
653 | var s0, s1, s2, s3
654 |
655 | s0 = peg$currPos
656 | s1 = peg$parsews()
657 | if (s1 !== peg$FAILED) {
658 | if (input.charCodeAt(peg$currPos) === 44) {
659 | s2 = peg$c11
660 | peg$currPos++
661 | } else {
662 | s2 = peg$FAILED
663 | if (peg$silentFails === 0) {
664 | peg$fail(peg$c12)
665 | }
666 | }
667 | if (s2 !== peg$FAILED) {
668 | s3 = peg$parsews()
669 | if (s3 !== peg$FAILED) {
670 | s1 = [s1, s2, s3]
671 | s0 = s1
672 | } else {
673 | peg$currPos = s0
674 | s0 = peg$FAILED
675 | }
676 | } else {
677 | peg$currPos = s0
678 | s0 = peg$FAILED
679 | }
680 | } else {
681 | peg$currPos = s0
682 | s0 = peg$FAILED
683 | }
684 |
685 | return s0
686 | }
687 |
688 | function peg$parsews() {
689 | var s0, s1
690 |
691 | peg$silentFails++
692 | s0 = []
693 | if (peg$c14.test(input.charAt(peg$currPos))) {
694 | s1 = input.charAt(peg$currPos)
695 | peg$currPos++
696 | } else {
697 | s1 = peg$FAILED
698 | if (peg$silentFails === 0) {
699 | peg$fail(peg$c15)
700 | }
701 | }
702 | while (s1 !== peg$FAILED) {
703 | s0.push(s1)
704 | if (peg$c14.test(input.charAt(peg$currPos))) {
705 | s1 = input.charAt(peg$currPos)
706 | peg$currPos++
707 | } else {
708 | s1 = peg$FAILED
709 | if (peg$silentFails === 0) {
710 | peg$fail(peg$c15)
711 | }
712 | }
713 | }
714 | peg$silentFails--
715 | if (s0 === peg$FAILED) {
716 | s1 = peg$FAILED
717 | if (peg$silentFails === 0) {
718 | peg$fail(peg$c13)
719 | }
720 | }
721 |
722 | return s0
723 | }
724 |
725 | function peg$parsevalue() {
726 | var s0
727 |
728 | s0 = peg$parsefalse()
729 | if (s0 === peg$FAILED) {
730 | s0 = peg$parsenull()
731 | if (s0 === peg$FAILED) {
732 | s0 = peg$parsetrue()
733 | if (s0 === peg$FAILED) {
734 | s0 = peg$parseobject()
735 | if (s0 === peg$FAILED) {
736 | s0 = peg$parsearray()
737 | if (s0 === peg$FAILED) {
738 | s0 = peg$parsenumber()
739 | if (s0 === peg$FAILED) {
740 | s0 = peg$parsestring()
741 | }
742 | }
743 | }
744 | }
745 | }
746 | }
747 |
748 | return s0
749 | }
750 |
751 | function peg$parsefalse() {
752 | var s0, s1
753 |
754 | s0 = peg$currPos
755 | if (input.substr(peg$currPos, 5) === peg$c16) {
756 | s1 = peg$c16
757 | peg$currPos += 5
758 | } else {
759 | s1 = peg$FAILED
760 | if (peg$silentFails === 0) {
761 | peg$fail(peg$c17)
762 | }
763 | }
764 | if (s1 !== peg$FAILED) {
765 | peg$savedPos = s0
766 | s1 = peg$c18()
767 | }
768 | s0 = s1
769 |
770 | return s0
771 | }
772 |
773 | function peg$parsenull() {
774 | var s0, s1
775 |
776 | s0 = peg$currPos
777 | if (input.substr(peg$currPos, 4) === peg$c19) {
778 | s1 = peg$c19
779 | peg$currPos += 4
780 | } else {
781 | s1 = peg$FAILED
782 | if (peg$silentFails === 0) {
783 | peg$fail(peg$c20)
784 | }
785 | }
786 | if (s1 !== peg$FAILED) {
787 | peg$savedPos = s0
788 | s1 = peg$c21()
789 | }
790 | s0 = s1
791 |
792 | return s0
793 | }
794 |
795 | function peg$parsetrue() {
796 | var s0, s1
797 |
798 | s0 = peg$currPos
799 | if (input.substr(peg$currPos, 4) === peg$c22) {
800 | s1 = peg$c22
801 | peg$currPos += 4
802 | } else {
803 | s1 = peg$FAILED
804 | if (peg$silentFails === 0) {
805 | peg$fail(peg$c23)
806 | }
807 | }
808 | if (s1 !== peg$FAILED) {
809 | peg$savedPos = s0
810 | s1 = peg$c24()
811 | }
812 | s0 = s1
813 |
814 | return s0
815 | }
816 |
817 | function peg$parseobject() {
818 | var s0, s1, s2, s3, s4, s5, s6, s7
819 |
820 | s0 = peg$currPos
821 | s1 = peg$parsebegin_object()
822 | if (s1 !== peg$FAILED) {
823 | s2 = peg$currPos
824 | s3 = peg$parsemember()
825 | if (s3 !== peg$FAILED) {
826 | s4 = []
827 | s5 = peg$currPos
828 | s6 = peg$parsevalue_separator()
829 | if (s6 !== peg$FAILED) {
830 | s7 = peg$parsemember()
831 | if (s7 !== peg$FAILED) {
832 | peg$savedPos = s5
833 | s6 = peg$c25(s3, s7)
834 | s5 = s6
835 | } else {
836 | peg$currPos = s5
837 | s5 = peg$FAILED
838 | }
839 | } else {
840 | peg$currPos = s5
841 | s5 = peg$FAILED
842 | }
843 | while (s5 !== peg$FAILED) {
844 | s4.push(s5)
845 | s5 = peg$currPos
846 | s6 = peg$parsevalue_separator()
847 | if (s6 !== peg$FAILED) {
848 | s7 = peg$parsemember()
849 | if (s7 !== peg$FAILED) {
850 | peg$savedPos = s5
851 | s6 = peg$c25(s3, s7)
852 | s5 = s6
853 | } else {
854 | peg$currPos = s5
855 | s5 = peg$FAILED
856 | }
857 | } else {
858 | peg$currPos = s5
859 | s5 = peg$FAILED
860 | }
861 | }
862 | if (s4 !== peg$FAILED) {
863 | peg$savedPos = s2
864 | s3 = peg$c26(s3, s4)
865 | s2 = s3
866 | } else {
867 | peg$currPos = s2
868 | s2 = peg$FAILED
869 | }
870 | } else {
871 | peg$currPos = s2
872 | s2 = peg$FAILED
873 | }
874 | if (s2 === peg$FAILED) {
875 | s2 = null
876 | }
877 | if (s2 !== peg$FAILED) {
878 | s3 = peg$parseend_object()
879 | if (s3 !== peg$FAILED) {
880 | peg$savedPos = s0
881 | s1 = peg$c27(s2)
882 | s0 = s1
883 | } else {
884 | peg$currPos = s0
885 | s0 = peg$FAILED
886 | }
887 | } else {
888 | peg$currPos = s0
889 | s0 = peg$FAILED
890 | }
891 | } else {
892 | peg$currPos = s0
893 | s0 = peg$FAILED
894 | }
895 |
896 | return s0
897 | }
898 |
899 | function peg$parsemember() {
900 | var s0, s1, s2, s3
901 |
902 | s0 = peg$currPos
903 | s1 = peg$parsestring()
904 | if (s1 !== peg$FAILED) {
905 | s2 = peg$parsename_separator()
906 | if (s2 !== peg$FAILED) {
907 | s3 = peg$parsevalue()
908 | if (s3 !== peg$FAILED) {
909 | peg$savedPos = s0
910 | s1 = peg$c28(s1, s3)
911 | s0 = s1
912 | } else {
913 | peg$currPos = s0
914 | s0 = peg$FAILED
915 | }
916 | } else {
917 | peg$currPos = s0
918 | s0 = peg$FAILED
919 | }
920 | } else {
921 | peg$currPos = s0
922 | s0 = peg$FAILED
923 | }
924 |
925 | return s0
926 | }
927 |
928 | function peg$parsearray() {
929 | var s0, s1, s2, s3, s4, s5, s6, s7
930 |
931 | s0 = peg$currPos
932 | s1 = peg$parsebegin_array()
933 | if (s1 !== peg$FAILED) {
934 | s2 = peg$currPos
935 | s3 = peg$parsevalue()
936 | if (s3 !== peg$FAILED) {
937 | s4 = []
938 | s5 = peg$currPos
939 | s6 = peg$parsevalue_separator()
940 | if (s6 !== peg$FAILED) {
941 | s7 = peg$parsevalue()
942 | if (s7 !== peg$FAILED) {
943 | peg$savedPos = s5
944 | s6 = peg$c29(s3, s7)
945 | s5 = s6
946 | } else {
947 | peg$currPos = s5
948 | s5 = peg$FAILED
949 | }
950 | } else {
951 | peg$currPos = s5
952 | s5 = peg$FAILED
953 | }
954 | while (s5 !== peg$FAILED) {
955 | s4.push(s5)
956 | s5 = peg$currPos
957 | s6 = peg$parsevalue_separator()
958 | if (s6 !== peg$FAILED) {
959 | s7 = peg$parsevalue()
960 | if (s7 !== peg$FAILED) {
961 | peg$savedPos = s5
962 | s6 = peg$c29(s3, s7)
963 | s5 = s6
964 | } else {
965 | peg$currPos = s5
966 | s5 = peg$FAILED
967 | }
968 | } else {
969 | peg$currPos = s5
970 | s5 = peg$FAILED
971 | }
972 | }
973 | if (s4 !== peg$FAILED) {
974 | peg$savedPos = s2
975 | s3 = peg$c30(s3, s4)
976 | s2 = s3
977 | } else {
978 | peg$currPos = s2
979 | s2 = peg$FAILED
980 | }
981 | } else {
982 | peg$currPos = s2
983 | s2 = peg$FAILED
984 | }
985 | if (s2 === peg$FAILED) {
986 | s2 = null
987 | }
988 | if (s2 !== peg$FAILED) {
989 | s3 = peg$parseend_array()
990 | if (s3 !== peg$FAILED) {
991 | peg$savedPos = s0
992 | s1 = peg$c31(s2)
993 | s0 = s1
994 | } else {
995 | peg$currPos = s0
996 | s0 = peg$FAILED
997 | }
998 | } else {
999 | peg$currPos = s0
1000 | s0 = peg$FAILED
1001 | }
1002 | } else {
1003 | peg$currPos = s0
1004 | s0 = peg$FAILED
1005 | }
1006 |
1007 | return s0
1008 | }
1009 |
1010 | function peg$parsenumber() {
1011 | var s0, s1, s2, s3, s4
1012 |
1013 | peg$silentFails++
1014 | s0 = peg$currPos
1015 | s1 = peg$parseminus()
1016 | if (s1 === peg$FAILED) {
1017 | s1 = null
1018 | }
1019 | if (s1 !== peg$FAILED) {
1020 | s2 = peg$parseint()
1021 | if (s2 !== peg$FAILED) {
1022 | s3 = peg$parsefrac()
1023 | if (s3 === peg$FAILED) {
1024 | s3 = null
1025 | }
1026 | if (s3 !== peg$FAILED) {
1027 | s4 = peg$parseexp()
1028 | if (s4 === peg$FAILED) {
1029 | s4 = null
1030 | }
1031 | if (s4 !== peg$FAILED) {
1032 | peg$savedPos = s0
1033 | s1 = peg$c33()
1034 | s0 = s1
1035 | } else {
1036 | peg$currPos = s0
1037 | s0 = peg$FAILED
1038 | }
1039 | } else {
1040 | peg$currPos = s0
1041 | s0 = peg$FAILED
1042 | }
1043 | } else {
1044 | peg$currPos = s0
1045 | s0 = peg$FAILED
1046 | }
1047 | } else {
1048 | peg$currPos = s0
1049 | s0 = peg$FAILED
1050 | }
1051 | peg$silentFails--
1052 | if (s0 === peg$FAILED) {
1053 | s1 = peg$FAILED
1054 | if (peg$silentFails === 0) {
1055 | peg$fail(peg$c32)
1056 | }
1057 | }
1058 |
1059 | return s0
1060 | }
1061 |
1062 | function peg$parsedecimal_point() {
1063 | var s0
1064 |
1065 | if (input.charCodeAt(peg$currPos) === 46) {
1066 | s0 = peg$c34
1067 | peg$currPos++
1068 | } else {
1069 | s0 = peg$FAILED
1070 | if (peg$silentFails === 0) {
1071 | peg$fail(peg$c35)
1072 | }
1073 | }
1074 |
1075 | return s0
1076 | }
1077 |
1078 | function peg$parsedigit1_9() {
1079 | var s0
1080 |
1081 | if (peg$c36.test(input.charAt(peg$currPos))) {
1082 | s0 = input.charAt(peg$currPos)
1083 | peg$currPos++
1084 | } else {
1085 | s0 = peg$FAILED
1086 | if (peg$silentFails === 0) {
1087 | peg$fail(peg$c37)
1088 | }
1089 | }
1090 |
1091 | return s0
1092 | }
1093 |
1094 | function peg$parsee() {
1095 | var s0
1096 |
1097 | if (peg$c38.test(input.charAt(peg$currPos))) {
1098 | s0 = input.charAt(peg$currPos)
1099 | peg$currPos++
1100 | } else {
1101 | s0 = peg$FAILED
1102 | if (peg$silentFails === 0) {
1103 | peg$fail(peg$c39)
1104 | }
1105 | }
1106 |
1107 | return s0
1108 | }
1109 |
1110 | function peg$parseexp() {
1111 | var s0, s1, s2, s3, s4
1112 |
1113 | s0 = peg$currPos
1114 | s1 = peg$parsee()
1115 | if (s1 !== peg$FAILED) {
1116 | s2 = peg$parseminus()
1117 | if (s2 === peg$FAILED) {
1118 | s2 = peg$parseplus()
1119 | }
1120 | if (s2 === peg$FAILED) {
1121 | s2 = null
1122 | }
1123 | if (s2 !== peg$FAILED) {
1124 | s3 = []
1125 | s4 = peg$parseDIGIT()
1126 | if (s4 !== peg$FAILED) {
1127 | while (s4 !== peg$FAILED) {
1128 | s3.push(s4)
1129 | s4 = peg$parseDIGIT()
1130 | }
1131 | } else {
1132 | s3 = peg$FAILED
1133 | }
1134 | if (s3 !== peg$FAILED) {
1135 | s1 = [s1, s2, s3]
1136 | s0 = s1
1137 | } else {
1138 | peg$currPos = s0
1139 | s0 = peg$FAILED
1140 | }
1141 | } else {
1142 | peg$currPos = s0
1143 | s0 = peg$FAILED
1144 | }
1145 | } else {
1146 | peg$currPos = s0
1147 | s0 = peg$FAILED
1148 | }
1149 |
1150 | return s0
1151 | }
1152 |
1153 | function peg$parsefrac() {
1154 | var s0, s1, s2, s3
1155 |
1156 | s0 = peg$currPos
1157 | s1 = peg$parsedecimal_point()
1158 | if (s1 !== peg$FAILED) {
1159 | s2 = []
1160 | s3 = peg$parseDIGIT()
1161 | if (s3 !== peg$FAILED) {
1162 | while (s3 !== peg$FAILED) {
1163 | s2.push(s3)
1164 | s3 = peg$parseDIGIT()
1165 | }
1166 | } else {
1167 | s2 = peg$FAILED
1168 | }
1169 | if (s2 !== peg$FAILED) {
1170 | s1 = [s1, s2]
1171 | s0 = s1
1172 | } else {
1173 | peg$currPos = s0
1174 | s0 = peg$FAILED
1175 | }
1176 | } else {
1177 | peg$currPos = s0
1178 | s0 = peg$FAILED
1179 | }
1180 |
1181 | return s0
1182 | }
1183 |
1184 | function peg$parseint() {
1185 | var s0, s1, s2, s3
1186 |
1187 | s0 = peg$parsezero()
1188 | if (s0 === peg$FAILED) {
1189 | s0 = peg$currPos
1190 | s1 = peg$parsedigit1_9()
1191 | if (s1 !== peg$FAILED) {
1192 | s2 = []
1193 | s3 = peg$parseDIGIT()
1194 | while (s3 !== peg$FAILED) {
1195 | s2.push(s3)
1196 | s3 = peg$parseDIGIT()
1197 | }
1198 | if (s2 !== peg$FAILED) {
1199 | s1 = [s1, s2]
1200 | s0 = s1
1201 | } else {
1202 | peg$currPos = s0
1203 | s0 = peg$FAILED
1204 | }
1205 | } else {
1206 | peg$currPos = s0
1207 | s0 = peg$FAILED
1208 | }
1209 | }
1210 |
1211 | return s0
1212 | }
1213 |
1214 | function peg$parseminus() {
1215 | var s0
1216 |
1217 | if (input.charCodeAt(peg$currPos) === 45) {
1218 | s0 = peg$c40
1219 | peg$currPos++
1220 | } else {
1221 | s0 = peg$FAILED
1222 | if (peg$silentFails === 0) {
1223 | peg$fail(peg$c41)
1224 | }
1225 | }
1226 |
1227 | return s0
1228 | }
1229 |
1230 | function peg$parseplus() {
1231 | var s0
1232 |
1233 | if (input.charCodeAt(peg$currPos) === 43) {
1234 | s0 = peg$c42
1235 | peg$currPos++
1236 | } else {
1237 | s0 = peg$FAILED
1238 | if (peg$silentFails === 0) {
1239 | peg$fail(peg$c43)
1240 | }
1241 | }
1242 |
1243 | return s0
1244 | }
1245 |
1246 | function peg$parsezero() {
1247 | var s0
1248 |
1249 | if (input.charCodeAt(peg$currPos) === 48) {
1250 | s0 = peg$c44
1251 | peg$currPos++
1252 | } else {
1253 | s0 = peg$FAILED
1254 | if (peg$silentFails === 0) {
1255 | peg$fail(peg$c45)
1256 | }
1257 | }
1258 |
1259 | return s0
1260 | }
1261 |
1262 | function peg$parsestring() {
1263 | var s0, s1, s2, s3
1264 |
1265 | peg$silentFails++
1266 | s0 = peg$currPos
1267 | s1 = peg$parsequotation_mark()
1268 | if (s1 !== peg$FAILED) {
1269 | s2 = []
1270 | s3 = peg$parsechar()
1271 | while (s3 !== peg$FAILED) {
1272 | s2.push(s3)
1273 | s3 = peg$parsechar()
1274 | }
1275 | if (s2 !== peg$FAILED) {
1276 | s3 = peg$parsequotation_mark()
1277 | if (s3 !== peg$FAILED) {
1278 | peg$savedPos = s0
1279 | s1 = peg$c47(s2)
1280 | s0 = s1
1281 | } else {
1282 | peg$currPos = s0
1283 | s0 = peg$FAILED
1284 | }
1285 | } else {
1286 | peg$currPos = s0
1287 | s0 = peg$FAILED
1288 | }
1289 | } else {
1290 | peg$currPos = s0
1291 | s0 = peg$FAILED
1292 | }
1293 | peg$silentFails--
1294 | if (s0 === peg$FAILED) {
1295 | s1 = peg$FAILED
1296 | if (peg$silentFails === 0) {
1297 | peg$fail(peg$c46)
1298 | }
1299 | }
1300 |
1301 | return s0
1302 | }
1303 |
1304 | function peg$parsechar() {
1305 | var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9
1306 |
1307 | s0 = peg$parseunescaped()
1308 | if (s0 === peg$FAILED) {
1309 | s0 = peg$currPos
1310 | s1 = peg$parseescape()
1311 | if (s1 !== peg$FAILED) {
1312 | if (input.charCodeAt(peg$currPos) === 34) {
1313 | s2 = peg$c48
1314 | peg$currPos++
1315 | } else {
1316 | s2 = peg$FAILED
1317 | if (peg$silentFails === 0) {
1318 | peg$fail(peg$c49)
1319 | }
1320 | }
1321 | if (s2 === peg$FAILED) {
1322 | if (input.charCodeAt(peg$currPos) === 92) {
1323 | s2 = peg$c50
1324 | peg$currPos++
1325 | } else {
1326 | s2 = peg$FAILED
1327 | if (peg$silentFails === 0) {
1328 | peg$fail(peg$c51)
1329 | }
1330 | }
1331 | if (s2 === peg$FAILED) {
1332 | if (input.charCodeAt(peg$currPos) === 47) {
1333 | s2 = peg$c52
1334 | peg$currPos++
1335 | } else {
1336 | s2 = peg$FAILED
1337 | if (peg$silentFails === 0) {
1338 | peg$fail(peg$c53)
1339 | }
1340 | }
1341 | if (s2 === peg$FAILED) {
1342 | s2 = peg$currPos
1343 | if (input.charCodeAt(peg$currPos) === 98) {
1344 | s3 = peg$c54
1345 | peg$currPos++
1346 | } else {
1347 | s3 = peg$FAILED
1348 | if (peg$silentFails === 0) {
1349 | peg$fail(peg$c55)
1350 | }
1351 | }
1352 | if (s3 !== peg$FAILED) {
1353 | peg$savedPos = s2
1354 | s3 = peg$c56()
1355 | }
1356 | s2 = s3
1357 | if (s2 === peg$FAILED) {
1358 | s2 = peg$currPos
1359 | if (input.charCodeAt(peg$currPos) === 102) {
1360 | s3 = peg$c57
1361 | peg$currPos++
1362 | } else {
1363 | s3 = peg$FAILED
1364 | if (peg$silentFails === 0) {
1365 | peg$fail(peg$c58)
1366 | }
1367 | }
1368 | if (s3 !== peg$FAILED) {
1369 | peg$savedPos = s2
1370 | s3 = peg$c59()
1371 | }
1372 | s2 = s3
1373 | if (s2 === peg$FAILED) {
1374 | s2 = peg$currPos
1375 | if (input.charCodeAt(peg$currPos) === 110) {
1376 | s3 = peg$c60
1377 | peg$currPos++
1378 | } else {
1379 | s3 = peg$FAILED
1380 | if (peg$silentFails === 0) {
1381 | peg$fail(peg$c61)
1382 | }
1383 | }
1384 | if (s3 !== peg$FAILED) {
1385 | peg$savedPos = s2
1386 | s3 = peg$c62()
1387 | }
1388 | s2 = s3
1389 | if (s2 === peg$FAILED) {
1390 | s2 = peg$currPos
1391 | if (input.charCodeAt(peg$currPos) === 114) {
1392 | s3 = peg$c63
1393 | peg$currPos++
1394 | } else {
1395 | s3 = peg$FAILED
1396 | if (peg$silentFails === 0) {
1397 | peg$fail(peg$c64)
1398 | }
1399 | }
1400 | if (s3 !== peg$FAILED) {
1401 | peg$savedPos = s2
1402 | s3 = peg$c65()
1403 | }
1404 | s2 = s3
1405 | if (s2 === peg$FAILED) {
1406 | s2 = peg$currPos
1407 | if (input.charCodeAt(peg$currPos) === 116) {
1408 | s3 = peg$c66
1409 | peg$currPos++
1410 | } else {
1411 | s3 = peg$FAILED
1412 | if (peg$silentFails === 0) {
1413 | peg$fail(peg$c67)
1414 | }
1415 | }
1416 | if (s3 !== peg$FAILED) {
1417 | peg$savedPos = s2
1418 | s3 = peg$c68()
1419 | }
1420 | s2 = s3
1421 | if (s2 === peg$FAILED) {
1422 | s2 = peg$currPos
1423 | if (input.charCodeAt(peg$currPos) === 117) {
1424 | s3 = peg$c69
1425 | peg$currPos++
1426 | } else {
1427 | s3 = peg$FAILED
1428 | if (peg$silentFails === 0) {
1429 | peg$fail(peg$c70)
1430 | }
1431 | }
1432 | if (s3 !== peg$FAILED) {
1433 | s4 = peg$currPos
1434 | s5 = peg$currPos
1435 | s6 = peg$parseHEXDIG()
1436 | if (s6 !== peg$FAILED) {
1437 | s7 = peg$parseHEXDIG()
1438 | if (s7 !== peg$FAILED) {
1439 | s8 = peg$parseHEXDIG()
1440 | if (s8 !== peg$FAILED) {
1441 | s9 = peg$parseHEXDIG()
1442 | if (s9 !== peg$FAILED) {
1443 | s6 = [s6, s7, s8, s9]
1444 | s5 = s6
1445 | } else {
1446 | peg$currPos = s5
1447 | s5 = peg$FAILED
1448 | }
1449 | } else {
1450 | peg$currPos = s5
1451 | s5 = peg$FAILED
1452 | }
1453 | } else {
1454 | peg$currPos = s5
1455 | s5 = peg$FAILED
1456 | }
1457 | } else {
1458 | peg$currPos = s5
1459 | s5 = peg$FAILED
1460 | }
1461 | if (s5 !== peg$FAILED) {
1462 | s4 = input.substring(s4, peg$currPos)
1463 | } else {
1464 | s4 = s5
1465 | }
1466 | if (s4 !== peg$FAILED) {
1467 | peg$savedPos = s2
1468 | s3 = peg$c71(s4)
1469 | s2 = s3
1470 | } else {
1471 | peg$currPos = s2
1472 | s2 = peg$FAILED
1473 | }
1474 | } else {
1475 | peg$currPos = s2
1476 | s2 = peg$FAILED
1477 | }
1478 | }
1479 | }
1480 | }
1481 | }
1482 | }
1483 | }
1484 | }
1485 | }
1486 | if (s2 !== peg$FAILED) {
1487 | peg$savedPos = s0
1488 | s1 = peg$c72(s2)
1489 | s0 = s1
1490 | } else {
1491 | peg$currPos = s0
1492 | s0 = peg$FAILED
1493 | }
1494 | } else {
1495 | peg$currPos = s0
1496 | s0 = peg$FAILED
1497 | }
1498 | }
1499 |
1500 | return s0
1501 | }
1502 |
1503 | function peg$parseescape() {
1504 | var s0
1505 |
1506 | if (input.charCodeAt(peg$currPos) === 92) {
1507 | s0 = peg$c50
1508 | peg$currPos++
1509 | } else {
1510 | s0 = peg$FAILED
1511 | if (peg$silentFails === 0) {
1512 | peg$fail(peg$c51)
1513 | }
1514 | }
1515 |
1516 | return s0
1517 | }
1518 |
1519 | function peg$parsequotation_mark() {
1520 | var s0
1521 |
1522 | if (input.charCodeAt(peg$currPos) === 34) {
1523 | s0 = peg$c48
1524 | peg$currPos++
1525 | } else {
1526 | s0 = peg$FAILED
1527 | if (peg$silentFails === 0) {
1528 | peg$fail(peg$c49)
1529 | }
1530 | }
1531 |
1532 | return s0
1533 | }
1534 |
1535 | function peg$parseunescaped() {
1536 | var s0
1537 |
1538 | if (peg$c73.test(input.charAt(peg$currPos))) {
1539 | s0 = input.charAt(peg$currPos)
1540 | peg$currPos++
1541 | } else {
1542 | s0 = peg$FAILED
1543 | if (peg$silentFails === 0) {
1544 | peg$fail(peg$c74)
1545 | }
1546 | }
1547 |
1548 | return s0
1549 | }
1550 |
1551 | function peg$parseDIGIT() {
1552 | var s0
1553 |
1554 | if (peg$c75.test(input.charAt(peg$currPos))) {
1555 | s0 = input.charAt(peg$currPos)
1556 | peg$currPos++
1557 | } else {
1558 | s0 = peg$FAILED
1559 | if (peg$silentFails === 0) {
1560 | peg$fail(peg$c76)
1561 | }
1562 | }
1563 |
1564 | return s0
1565 | }
1566 |
1567 | function peg$parseHEXDIG() {
1568 | var s0
1569 |
1570 | if (peg$c77.test(input.charAt(peg$currPos))) {
1571 | s0 = input.charAt(peg$currPos)
1572 | peg$currPos++
1573 | } else {
1574 | s0 = peg$FAILED
1575 | if (peg$silentFails === 0) {
1576 | peg$fail(peg$c78)
1577 | }
1578 | }
1579 |
1580 | return s0
1581 | }
1582 |
1583 | peg$result = peg$startRuleFunction()
1584 |
1585 | if (peg$result !== peg$FAILED && peg$currPos === input.length) {
1586 | return peg$result
1587 | } else {
1588 | if (peg$result !== peg$FAILED && peg$currPos < input.length) {
1589 | peg$fail(peg$endExpectation())
1590 | }
1591 |
1592 | throw peg$buildStructuredError(
1593 | peg$maxFailExpected,
1594 | peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
1595 | peg$maxFailPos < input.length
1596 | ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
1597 | : peg$computeLocation(peg$maxFailPos, peg$maxFailPos),
1598 | )
1599 | }
1600 | }
1601 |
1602 | module.exports = {
1603 | SyntaxError: peg$SyntaxError,
1604 | parse: peg$parse,
1605 | }
1606 |
--------------------------------------------------------------------------------
/src/test.utils.js:
--------------------------------------------------------------------------------
1 | const { readFileSync } = require('fs');
2 | const jf = require('../');
3 |
4 | const exam = ({ sampleName, expectedOutput, fixerOptions = {}, expectedChange = false } = {}) => {
5 | // eslint-disable-next-line security/detect-non-literal-fs-filename
6 | const json = readFileSync(`./test/samples/${sampleName}.json`, 'utf-8');
7 | const { data, changed } = jf(json, fixerOptions);
8 | expect(changed).toEqual(expectedChange);
9 | expect(data).toEqual(expectedOutput);
10 | };
11 |
12 | module.exports = { exam };
13 |
--------------------------------------------------------------------------------
/src/transform.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable security/detect-object-injection */
2 | const { psw } = require('./utils');
3 | const chalk = require('chalk');
4 |
5 | const quotify = ({ fixedData, targetLine, fixedLine, verbose }) => {
6 | if (verbose) psw(chalk.magenta('Adding quotes...'));
7 | fixedData[targetLine] = fixedLine.replace(/(":\s*)(\S*)/g, '$1"$2"');
8 | return fixedData;
9 | };
10 |
11 | const numberify = ({ fixedData, targetLine, fixedLine, unquotedWord, verbose }) => {
12 | if (verbose) {
13 | psw(
14 | chalk.cyan(
15 | "Found a non base-10 number and since JSON doesn't support those numbers types. I will turn it into a base-10 number to keep the structure intact"
16 | )
17 | );
18 | }
19 | fixedData[targetLine] = fixedLine.replace(unquotedWord[2], Number(unquotedWord[2]));
20 | return fixedData;
21 | };
22 |
23 | const baseNumify = ({ baseNumber, verbose }) => {
24 | if (verbose) {
25 | psw(
26 | chalk.cyan(
27 | "Found a non base-10 number and since JSON doesn't support those numbers types. I will turn it into a base-10 number to keep the structure intact"
28 | )
29 | );
30 | }
31 | return baseNumber.replace(/"(0[xbo][0-9a-fA-F]*)"/g, (_, num) => Number(num)); //base-(16|2|8) -> base-10
32 | };
33 |
34 | module.exports = {
35 | quotify,
36 | numberify,
37 | baseNumify
38 | };
39 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 |
3 | const psw = (data) => process.stdout.write(`${data}\n`);
4 |
5 | const removeLinebreak = (line) => line.replace(/[\n\r]/g, '');
6 |
7 | const replaceChar = (str, idx, chr) => str.substring(0, idx) + chr + str.substring(idx + 1);
8 |
9 | const verboseLog = ({ verbose = false, lines = [], err }) => {
10 | if (!verbose) return;
11 | psw('Data:');
12 | lines.forEach((l, i) => psw(`${chalk.yellow(i)} ${l}`));
13 | psw(chalk.red('err='));
14 | console.dir(err);
15 | };
16 |
17 | const curlyBracesIncluded = (line) => {
18 | const l = line.trim();
19 | return l.startsWith('{') && l.endsWith('}');
20 | };
21 |
22 | module.exports = { psw, removeLinebreak, replaceChar, verboseLog, curlyBracesIncluded };
23 |
--------------------------------------------------------------------------------
/test/samples/b.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #8",
3 | "type": "JSON",
4 | "error": "trailing b",
5 | "version": b1000
6 | }
--------------------------------------------------------------------------------
/test/samples/bin.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #23",
3 | "type": "JSON",
4 | "error": "binary number",
5 | "version": 0b10111
6 | }
--------------------------------------------------------------------------------
/test/samples/comment.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #16",
3 | "type": "JSON",
4 | "error": "comment",
5 | "version": "0x10" //16
6 | }
--------------------------------------------------------------------------------
/test/samples/concat.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample " + "#25",
3 | "type": "JSON",
4 | "error": "concat",
5 | "version": 25
6 | }
--------------------------------------------------------------------------------
/test/samples/doublyMissingQuotes.json:
--------------------------------------------------------------------------------
1 | {
2 | field: value
3 | }
--------------------------------------------------------------------------------
/test/samples/doublyMissingQuotesMin.json:
--------------------------------------------------------------------------------
1 | {field: value}
--------------------------------------------------------------------------------
/test/samples/exp.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #28",
3 | "type": "JSON",
4 | "error": "exponents",
5 | "version": 1e3
6 | }
--------------------------------------------------------------------------------
/test/samples/extraBrackets.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": "extra brackets"
3 | }}}
--------------------------------------------------------------------------------
/test/samples/extraChar.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #4",
3 | "type": "JSON",
4 | "error": "trailing error",
5 | "version": 4,
6 | }
--------------------------------------------------------------------------------
/test/samples/fp.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #2",
3 | "type": "JSON",
4 | "version": 2.0
5 | }
--------------------------------------------------------------------------------
/test/samples/hex.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #22",
3 | "type": "JSON",
4 | "error": "hex number",
5 | "version": 0x16
6 | }
--------------------------------------------------------------------------------
/test/samples/issue31.json:
--------------------------------------------------------------------------------
1 | {
2 | something:"string:string"
3 | }
--------------------------------------------------------------------------------
/test/samples/lefty1.json:
--------------------------------------------------------------------------------
1 | { t: 42 }
--------------------------------------------------------------------------------
/test/samples/lefty2.json:
--------------------------------------------------------------------------------
1 | {
2 | ix: 1
3 | }
--------------------------------------------------------------------------------
/test/samples/leftyO.json:
--------------------------------------------------------------------------------
1 | {
2 | o: 1
3 | }
--------------------------------------------------------------------------------
/test/samples/missing.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #5",
3 | "type": "JSON",
4 | "error": "missing comma"
5 | "version": 5
6 | }
--------------------------------------------------------------------------------
/test/samples/missingLHQuotes.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #14",
3 | "type": "JSON",
4 | "error": "missing quotes",
5 | long content: "a string"
6 | }
--------------------------------------------------------------------------------
/test/samples/missingQuotes.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #11",
3 | "type": "JSON",
4 | "error": "missing quotes",
5 | "version": a string
6 | }
--------------------------------------------------------------------------------
/test/samples/monOps.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #26",
3 | "type": "JSON",
4 | "error": "unary operations",
5 | "version": ~6
6 | }
--------------------------------------------------------------------------------
/test/samples/multiComment.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #18",
3 | "type": "JSON",
4 | "error": "multi-comment",
5 | "version": 18
6 | /*
7 | lorem ipsum dolore sit amet
8 | */
9 | }
--------------------------------------------------------------------------------
/test/samples/multiOps.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #27",
3 | "type": "JSON",
4 | "error": "multi operations",
5 | "version": 1 + 2 * 3
6 | }
--------------------------------------------------------------------------------
/test/samples/newLines.json:
--------------------------------------------------------------------------------
1 | {"Broken": "
2 | "}
--------------------------------------------------------------------------------
/test/samples/noLHQuotes.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #13",
3 | "type": "JSON",
4 | "error": "missing quotes",
5 | version: "a string"
6 | }
--------------------------------------------------------------------------------
/test/samples/noQuotes.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #10",
3 | "type": "JSON",
4 | "error": "missing quotes",
5 | "version": one
6 | }
--------------------------------------------------------------------------------
/test/samples/normal.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #0",
3 | "type": "JSON",
4 | "version": 0
5 | }
--------------------------------------------------------------------------------
/test/samples/notCurly.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #15",
3 | "error": "wrong brackets",
4 | "info": { "one", "two" }
5 | }
--------------------------------------------------------------------------------
/test/samples/notSquare.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #12",
3 | "error": "wrong brackets",
4 | "info": [
5 | "type": "JSON",
6 | "version": 12
7 | ]
8 | }
--------------------------------------------------------------------------------
/test/samples/o.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #9",
3 | "type": "JSON",
4 | "error": "trailing o",
5 | "version": o11
6 | }
--------------------------------------------------------------------------------
/test/samples/oct.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #24",
3 | "type": "JSON",
4 | "error": "octal number",
5 | "version": 0o30
6 | }
--------------------------------------------------------------------------------
/test/samples/ops.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #20",
3 | "type": "JSON",
4 | "error": "operations",
5 | "version": 2 * 10
6 | }
--------------------------------------------------------------------------------
/test/samples/quoteInQuotes.json:
--------------------------------------------------------------------------------
1 | { "name": "Broadcast "Media" }
--------------------------------------------------------------------------------
/test/samples/singleQuote.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #1",
3 | "type": "JSON",
4 | "error": "single quote",
5 | "version": '1'
6 | }
--------------------------------------------------------------------------------
/test/samples/smComment.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #17",
3 | "type": "JSON",
4 | "error": "multi-comment",
5 | "version": "0x10" /* 16 in hex */
6 | }
--------------------------------------------------------------------------------
/test/samples/tab.json:
--------------------------------------------------------------------------------
1 | {"Test": " "}
--------------------------------------------------------------------------------
/test/samples/tabs.json:
--------------------------------------------------------------------------------
1 | {
2 | "Test": " "
3 | }
--------------------------------------------------------------------------------
/test/samples/threeErrs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #21",
3 | "type": JSON,
4 | "error": "3 errors"
5 | "version": x15
6 | }
--------------------------------------------------------------------------------
/test/samples/trailingChar.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "test1": "1",
4 | "test2": {
5 | "a": "b",
6 | "c": {
7 |
8 | },
9 |
10 | }
11 | }
12 | ]
--------------------------------------------------------------------------------
/test/samples/trailingComma.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #6",
3 | "type": "JSON",
4 | "error": "trailing comma",
5 | "version": ,6
6 | }
--------------------------------------------------------------------------------
/test/samples/trailingDot.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #3",
3 | "type": "JSON",
4 | "error": "trailing dot",
5 | "version": .3
6 | }
--------------------------------------------------------------------------------
/test/samples/twoErrs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #19",
3 | "type": 'JSON',
4 | "error": "2 errors",
5 | "version": 19 //16
6 | }
--------------------------------------------------------------------------------
/test/samples/x.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample #7",
3 | "type": "JSON",
4 | "error": "trailing x",
5 | "version": x7
6 | }
--------------------------------------------------------------------------------
/test/sandbox.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const chalk = require('chalk')
3 | const jsonFix = require('../')
4 | const args = process.argv.slice(2)
5 | const files = args.length ? args : ['s4']
6 |
7 | // Get the (potentially malformed) JSON data ready
8 | files.forEach(arg => {
9 | const file = `./test/samples/${arg}.json`
10 | const jsonContent = fs.readFileSync(file, 'utf-8')
11 |
12 | const {data, changed} = jsonFix(jsonContent, true) // Lint (and fix) it
13 |
14 | if (changed) {
15 | // Do something with `data` which is the fixed JSON data from `jsonContent`
16 | // e.g. `fs.writeFileSync(configPath, JSON.stringify(config, null, 2))`
17 | console.log(chalk.underline(`${file} changed:`))
18 | console.log(JSON.stringify(data, null, 2))
19 | } else console.log(chalk.underline(file, 'is correct'))
20 | })
21 |
--------------------------------------------------------------------------------