├── .coffeelintignore ├── .github ├── no-response.yml └── workflows │ └── main.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── coffeelint.json ├── grammars ├── json.cson └── tree-sitter-json.cson ├── package-lock.json ├── package.json ├── settings └── language-json.cson └── spec └── json-spec.coffee /.coffeelintignore: -------------------------------------------------------------------------------- 1 | spec/fixtures 2 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an issue is closed for lack of response 4 | daysUntilClose: 28 5 | 6 | # Label requiring a response 7 | responseRequiredLabel: more-information-needed 8 | 9 | # Comment to post when closing an issue for lack of response. Set to `false` to disable. 10 | closeComment: > 11 | This issue has been automatically closed because there has been no response 12 | to our request for more information from the original author. With only the 13 | information that is currently in the issue, we don't have enough information 14 | to take action. Please reach out if you have or find the answers we need so 15 | that we can investigate further. 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | env: 6 | CI: true 7 | 8 | jobs: 9 | Test: 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest, windows-latest] 13 | channel: [stable, beta] 14 | runs-on: ${{ matrix.os }} 15 | steps: 16 | - uses: actions/checkout@v1 17 | - uses: UziTech/action-setup-atom@v2 18 | with: 19 | version: ${{ matrix.channel }} 20 | - name: Install windows-build-tools 21 | if: ${{ matrix.os == 'windows-latest' }} 22 | run: | 23 | npm i windows-build-tools@4.0.0 24 | - name: Install dependencies 25 | run: apm install 26 | - name: Run tests 27 | run: atom --test spec 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See the [Atom contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) 2 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Prerequisites 10 | 11 | * [ ] Put an X between the brackets on this line if you have done all of the following: 12 | * Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode 13 | * Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/ 14 | * Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq 15 | * Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom 16 | * Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages 17 | 18 | ### Description 19 | 20 | [Description of the issue] 21 | 22 | ### Steps to Reproduce 23 | 24 | 1. [First Step] 25 | 2. [Second Step] 26 | 3. [and so on...] 27 | 28 | **Expected behavior:** [What you expect to happen] 29 | 30 | **Actual behavior:** [What actually happens] 31 | 32 | **Reproduces how often:** [What percentage of the time does it reproduce?] 33 | 34 | ### Versions 35 | 36 | You can get this information from copy and pasting the output of `atom --version` and `apm --version` from the command line. Also, please include the OS and what version of the OS you're running. 37 | 38 | ### Additional Information 39 | 40 | Any additional information, configuration or data that might be necessary to reproduce the issue. 41 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 GitHub Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------- 23 | 24 | This package was derived from a TextMate bundle located at 25 | https://github.com/textmate/json.tmbundle and distributed under the following 26 | license, located in `README.mdown`: 27 | 28 | Permission to copy, use, modify, sell and distribute this 29 | software is granted. This software is provided "as is" without 30 | express or implied warranty, and with no claim as to its 31 | suitability for any purpose. 32 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Requirements 2 | 3 | * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. 4 | * All new code requires tests to ensure against regressions 5 | 6 | ### Description of the Change 7 | 8 | 13 | 14 | ### Alternate Designs 15 | 16 | 17 | 18 | ### Benefits 19 | 20 | 21 | 22 | ### Possible Drawbacks 23 | 24 | 25 | 26 | ### Applicable Issues 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) 2 | # JSON language support in Atom 3 | ![CI Status](https://github.com/atom/language-json/actions/workflows/main.yml/badge.svg) 4 | 5 | Adds syntax highlighting of JSON files in Atom. 6 | 7 | Originally [converted](http://flight-manual.atom.io/hacking-atom/sections/converting-from-textmate) from the [JSON TextMate bundle](https://github.com/textmate/json.tmbundle). 8 | 9 | Contributions are greatly appreciated. Please fork this repository and open a pull request to add snippets, make grammar tweaks, etc. 10 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_line_length": { 3 | "level": "ignore" 4 | }, 5 | "no_empty_param_list": { 6 | "level": "error" 7 | }, 8 | "arrow_spacing": { 9 | "level": "error" 10 | }, 11 | "no_interpolation_in_single_quotes": { 12 | "level": "error" 13 | }, 14 | "no_debugger": { 15 | "level": "error" 16 | }, 17 | "prefer_english_operator": { 18 | "level": "error" 19 | }, 20 | "colon_assignment_spacing": { 21 | "spacing": { 22 | "left": 0, 23 | "right": 1 24 | }, 25 | "level": "error" 26 | }, 27 | "braces_spacing": { 28 | "spaces": 0, 29 | "level": "error" 30 | }, 31 | "spacing_after_comma": { 32 | "level": "error" 33 | }, 34 | "no_stand_alone_at": { 35 | "level": "error" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /grammars/json.cson: -------------------------------------------------------------------------------- 1 | 'scopeName': 'source.json' 2 | 'name': 'JSON' 3 | 'fileTypes': [ 4 | 'avsc' 5 | 'babelrc' 6 | 'bowerrc' 7 | 'composer.lock' 8 | 'geojson' 9 | 'gltf' 10 | 'htmlhintrc' 11 | 'ipynb' 12 | 'jscsrc' 13 | 'jshintrc' 14 | 'jslintrc' 15 | 'json' 16 | 'jsonl' 17 | 'jsonld' 18 | 'languagebabel' 19 | 'ldj' 20 | 'ldjson' 21 | 'Pipfile.lock' 22 | 'schema' 23 | 'stylintrc' 24 | 'template' 25 | 'tern-config' 26 | 'tern-project' 27 | 'tfstate' 28 | 'tfstate.backup' 29 | 'topojson' 30 | 'webapp' 31 | 'webmanifest' 32 | ] 33 | 'patterns': [ 34 | { 35 | 'include': '#value' 36 | } 37 | ] 38 | 'repository': 39 | 'array': 40 | 'begin': '\\[' 41 | 'beginCaptures': 42 | '0': 43 | 'name': 'punctuation.definition.array.begin.json' 44 | 'end': '(,)?[\\s\\n]*(\\])' 45 | 'endCaptures': 46 | '1': 47 | 'name': 'invalid.illegal.trailing-array-separator.json' 48 | '2': 49 | 'name': 'punctuation.definition.array.end.json' 50 | 'name': 'meta.structure.array.json' 51 | 'patterns': [ 52 | { 53 | 'include': '#value' 54 | } 55 | { 56 | 'match': ',' 57 | 'name': 'punctuation.separator.array.json' 58 | } 59 | { 60 | 'match': '[^\\s\\]]' 61 | 'name': 'invalid.illegal.expected-array-separator.json' 62 | } 63 | ] 64 | 'constant': 65 | 'match': '\\b(true|false|null)\\b' 66 | 'name': 'constant.language.json' 67 | 'number': 68 | 'match': '-?(?=[1-9]|0(?!\\d))\\d+(\\.\\d+)?([eE][+-]?\\d+)?' 69 | 'name': 'constant.numeric.json' 70 | 'object': 71 | 'begin': '{' 72 | 'beginCaptures': 73 | '0': 74 | 'name': 'punctuation.definition.dictionary.begin.json' 75 | 'end': '}' 76 | 'endCaptures': 77 | '0': 78 | 'name': 'punctuation.definition.dictionary.end.json' 79 | 'name': 'meta.structure.dictionary.json' 80 | 'patterns': [ 81 | { 82 | # the key 83 | 'begin': '(?=")' 84 | 'end': '(?<=")' 85 | 'name': 'meta.structure.dictionary.key.json' 86 | 'patterns': [ 87 | { 88 | 'include': '#string' 89 | } 90 | ] 91 | } 92 | { 93 | 'begin': ':' 94 | 'beginCaptures': 95 | '0': 96 | 'name': 'punctuation.separator.dictionary.key-value.json' 97 | 'end': '(,)(?=[\\s\\n]*})|(,)|(?=})' 98 | 'endCaptures': 99 | '1': 100 | 'name': 'invalid.illegal.trailing-dictionary-separator.json' 101 | '2': 102 | 'name': 'punctuation.separator.dictionary.pair.json' 103 | 'name': 'meta.structure.dictionary.value.json' 104 | 'patterns': [ 105 | { 106 | # the value 107 | 'include': '#value' 108 | } 109 | { 110 | 'match': '[^\\s,]' 111 | 'name': 'invalid.illegal.expected-dictionary-separator.json' 112 | } 113 | ] 114 | } 115 | { 116 | 'match': '[^\\s}]' 117 | 'name': 'invalid.illegal.expected-dictionary-separator.json' 118 | } 119 | ] 120 | 'string': 121 | 'begin': '"' 122 | 'beginCaptures': 123 | '0': 124 | 'name': 'punctuation.definition.string.begin.json' 125 | 'end': '"' 126 | 'endCaptures': 127 | '0': 128 | 'name': 'punctuation.definition.string.end.json' 129 | 'name': 'string.quoted.double.json' 130 | 'patterns': [ 131 | { 132 | 'match': '''(?x) 133 | \\\\ # a literal backslash 134 | ( # followed by 135 | ["\\\\/bfnrt] # one of these characters 136 | | # or 137 | u[0-9a-fA-F]{4} # a u and four hex digits 138 | ) 139 | ''' 140 | 'name': 'constant.character.escape.json' 141 | } 142 | { 143 | 'match': '\\\\.' 144 | 'name': 'invalid.illegal.unrecognized-string-escape.json' 145 | } 146 | ] 147 | 'value': 148 | # the 'value' diagram at http://json.org 149 | 'patterns': [ 150 | { 151 | 'include': '#constant' 152 | } 153 | { 154 | 'include': '#number' 155 | } 156 | { 157 | 'include': '#string' 158 | } 159 | { 160 | 'include': '#array' 161 | } 162 | { 163 | 'include': '#object' 164 | } 165 | ] 166 | -------------------------------------------------------------------------------- /grammars/tree-sitter-json.cson: -------------------------------------------------------------------------------- 1 | name: 'JSON' 2 | scopeName: 'source.json' 3 | type: 'tree-sitter' 4 | parser: 'tree-sitter-json' 5 | 6 | fileTypes: [ 7 | 'avsc' 8 | 'babelrc' 9 | 'bowerrc' 10 | 'composer.lock' 11 | 'geojson' 12 | 'gltf' 13 | 'htmlhintrc' 14 | 'ipynb' 15 | 'jscsrc' 16 | 'jshintrc' 17 | 'jslintrc' 18 | 'json' 19 | 'jsonl' 20 | 'jsonld' 21 | 'languagebabel' 22 | 'ldj' 23 | 'ldjson' 24 | 'Pipfile.lock' 25 | 'schema' 26 | 'stylintrc' 27 | 'template' 28 | 'tern-config' 29 | 'tern-project' 30 | 'tfstate' 31 | 'tfstate.backup' 32 | 'topojson' 33 | 'webapp' 34 | 'webmanifest' 35 | ] 36 | 37 | folds: [ 38 | { 39 | start: {index: 0, type: '{'} 40 | end: {index: -1, type: '}'} 41 | } 42 | { 43 | start: {index: 0, type: '['} 44 | end: {index: -1, type: ']'} 45 | } 46 | ] 47 | 48 | scopes: 49 | 'value': 'source.json' 50 | 51 | 'object': 'meta.structure.dictionary.json' 52 | 53 | 'string': 'string.quoted.double' 54 | 55 | 'string_content': [ 56 | { match: "^http:\/\/", scopes: 'markup.underline.link.http.hyperlink' } 57 | { match: "^https:\/\/", scopes: 'markup.underline.link.https.hyperlink' } 58 | ] 59 | 60 | 'pair > string:nth-child(0)': 'string.quoted.double.dictionary.key.json' 61 | 62 | 'escape_sequence': 'constant.character.escape' 63 | 64 | 'number': 'constant.numeric' 65 | 'true': 'constant.language' 66 | 'false': 'constant.language' 67 | 'null': 'constant.language' 68 | 69 | '"{"': 'punctuation.definition.dictionary.begin' 70 | '"}"': 'punctuation.definition.dictionary.end' 71 | '":"': 'punctuation.separator.dictionary.key-value' 72 | 'object > ","': 'punctuation.separator.dictionary.pair' 73 | 'array > ","': 'punctuation.separator.array' 74 | '"["': 'punctuation.definition.array.begin' 75 | '"]"': 'punctuation.definition.array.end' 76 | '"\\""': 'punctuation.definition.string.json' 77 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-json", 3 | "version": "1.0.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "balanced-match": { 8 | "version": "1.0.0", 9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 11 | "dev": true 12 | }, 13 | "brace-expansion": { 14 | "version": "1.1.11", 15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 16 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 17 | "dev": true, 18 | "requires": { 19 | "balanced-match": "^1.0.0", 20 | "concat-map": "0.0.1" 21 | } 22 | }, 23 | "coffee-script": { 24 | "version": "1.11.1", 25 | "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.11.1.tgz", 26 | "integrity": "sha1-vxxHrWREOg2V0S3ysUfMCk2q1uk=", 27 | "dev": true 28 | }, 29 | "coffeelint": { 30 | "version": "1.16.2", 31 | "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-1.16.2.tgz", 32 | "integrity": "sha512-6mzgOo4zb17WfdrSui/cSUEgQ0AQkW3gXDht+6lHkfkqGUtSYKwGdGcXsDfAyuScVzTlTtKdfwkAlJWfqul7zg==", 33 | "dev": true, 34 | "requires": { 35 | "coffee-script": "~1.11.0", 36 | "glob": "^7.0.6", 37 | "ignore": "^3.0.9", 38 | "optimist": "^0.6.1", 39 | "resolve": "^0.6.3", 40 | "strip-json-comments": "^1.0.2" 41 | } 42 | }, 43 | "concat-map": { 44 | "version": "0.0.1", 45 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 46 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 47 | "dev": true 48 | }, 49 | "fs.realpath": { 50 | "version": "1.0.0", 51 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 52 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 53 | "dev": true 54 | }, 55 | "glob": { 56 | "version": "7.1.4", 57 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 58 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 59 | "dev": true, 60 | "requires": { 61 | "fs.realpath": "^1.0.0", 62 | "inflight": "^1.0.4", 63 | "inherits": "2", 64 | "minimatch": "^3.0.4", 65 | "once": "^1.3.0", 66 | "path-is-absolute": "^1.0.0" 67 | } 68 | }, 69 | "ignore": { 70 | "version": "3.3.10", 71 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 72 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 73 | "dev": true 74 | }, 75 | "inflight": { 76 | "version": "1.0.6", 77 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 78 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 79 | "dev": true, 80 | "requires": { 81 | "once": "^1.3.0", 82 | "wrappy": "1" 83 | } 84 | }, 85 | "inherits": { 86 | "version": "2.0.3", 87 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 88 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 89 | "dev": true 90 | }, 91 | "minimatch": { 92 | "version": "3.0.4", 93 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 94 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 95 | "dev": true, 96 | "requires": { 97 | "brace-expansion": "^1.1.7" 98 | } 99 | }, 100 | "minimist": { 101 | "version": "0.0.10", 102 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 103 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", 104 | "dev": true 105 | }, 106 | "nan": { 107 | "version": "2.14.0", 108 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", 109 | "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" 110 | }, 111 | "once": { 112 | "version": "1.4.0", 113 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 114 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 115 | "dev": true, 116 | "requires": { 117 | "wrappy": "1" 118 | } 119 | }, 120 | "optimist": { 121 | "version": "0.6.1", 122 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 123 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 124 | "dev": true, 125 | "requires": { 126 | "minimist": "~0.0.1", 127 | "wordwrap": "~0.0.2" 128 | } 129 | }, 130 | "path-is-absolute": { 131 | "version": "1.0.1", 132 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 133 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 134 | "dev": true 135 | }, 136 | "resolve": { 137 | "version": "0.6.3", 138 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", 139 | "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", 140 | "dev": true 141 | }, 142 | "strip-json-comments": { 143 | "version": "1.0.4", 144 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", 145 | "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", 146 | "dev": true 147 | }, 148 | "tree-sitter-json": { 149 | "version": "0.15.1", 150 | "resolved": "https://registry.npmjs.org/tree-sitter-json/-/tree-sitter-json-0.15.1.tgz", 151 | "integrity": "sha512-zSbxzlZlMuWEQ/WhyjR+AoECf/v9/dlE+6+0uxNgU5fb5m4kGc9Y0+HKWxLWZ4yhZNBdwCIrUQwo/oaBdmyXPg==", 152 | "requires": { 153 | "nan": "^2.0.0" 154 | } 155 | }, 156 | "wordwrap": { 157 | "version": "0.0.3", 158 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 159 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 160 | "dev": true 161 | }, 162 | "wrappy": { 163 | "version": "1.0.2", 164 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 165 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 166 | "dev": true 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-json", 3 | "version": "1.0.5", 4 | "description": "JSON language support in Atom", 5 | "engines": { 6 | "atom": "*", 7 | "node": "*" 8 | }, 9 | "homepage": "http://atom.github.io/language-json", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/atom/language-json.git" 13 | }, 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/atom/language-json/issues" 17 | }, 18 | "devDependencies": { 19 | "coffeelint": "^1.10.1" 20 | }, 21 | "dependencies": { 22 | "tree-sitter-json": "^0.15.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /settings/language-json.cson: -------------------------------------------------------------------------------- 1 | '.source.json': 2 | 'editor': 3 | 'foldEndPattern': '(?x: # turn on extended mode\n\t ^ # a line beginning with\n\t \\s* # some optional space\n\t [}\\]] # and the close of an object or array\n\t )' 4 | 'increaseIndentPattern': '^.*(\\{[^}]*|\\[[^\\]]*)$' 5 | 'decreaseIndentPattern': '^\\s*[}\\]],?\\s*$' 6 | -------------------------------------------------------------------------------- /spec/json-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "JSON grammar", -> 2 | grammar = null 3 | 4 | beforeEach -> 5 | atom.config.set('core.useTreeSitterParsers', false) 6 | 7 | waitsForPromise -> 8 | atom.packages.activatePackage('language-json') 9 | 10 | runs -> 11 | grammar = atom.grammars.grammarForScopeName('source.json') 12 | 13 | it "parses the grammar", -> 14 | expect(grammar).toBeDefined() 15 | expect(grammar.scopeName).toBe 'source.json' 16 | 17 | it "tokenizes arrays", -> 18 | baseScopes = ['source.json', 'meta.structure.array.json'] 19 | numericScopes = [baseScopes..., 'constant.numeric.json'] 20 | separatorScopes = [baseScopes..., 'punctuation.separator.array.json'] 21 | 22 | {tokens} = grammar.tokenizeLine('[1, 2, 3]') 23 | expect(tokens[0]).toEqual value: '[', scopes: [baseScopes..., 'punctuation.definition.array.begin.json'] 24 | expect(tokens[1]).toEqual value: '1', scopes: numericScopes 25 | expect(tokens[2]).toEqual value: ',', scopes: separatorScopes 26 | expect(tokens[3]).toEqual value: ' ', scopes: baseScopes 27 | expect(tokens[4]).toEqual value: '2', scopes: numericScopes 28 | expect(tokens[5]).toEqual value: ',', scopes: separatorScopes 29 | expect(tokens[6]).toEqual value: ' ', scopes: baseScopes 30 | expect(tokens[7]).toEqual value: '3', scopes: numericScopes 31 | expect(tokens[8]).toEqual value: ']', scopes: [baseScopes..., 'punctuation.definition.array.end.json'] 32 | 33 | it "identifies trailing commas in arrays", -> 34 | baseScopes = ['source.json', 'meta.structure.array.json'] 35 | numericScopes = [baseScopes..., 'constant.numeric.json'] 36 | separatorScopes = [baseScopes..., 'punctuation.separator.array.json'] 37 | 38 | {tokens} = grammar.tokenizeLine('[1, ]') 39 | expect(tokens[0]).toEqual value: '[', scopes: [baseScopes..., 'punctuation.definition.array.begin.json'] 40 | expect(tokens[1]).toEqual value: '1', scopes: numericScopes 41 | expect(tokens[2]).toEqual value: ',', scopes: [baseScopes..., 'invalid.illegal.trailing-array-separator.json'] 42 | expect(tokens[3]).toEqual value: ' ', scopes: baseScopes 43 | expect(tokens[4]).toEqual value: ']', scopes: [baseScopes..., 'punctuation.definition.array.end.json'] 44 | 45 | it "tokenizes objects", -> 46 | baseScopes = ['source.json', 'meta.structure.dictionary.json'] 47 | keyScopes = [baseScopes..., 'meta.structure.dictionary.key.json', 'string.quoted.double.json'] 48 | keyBeginScopes = [keyScopes..., 'punctuation.definition.string.begin.json'] 49 | keyEndScopes = [keyScopes..., 'punctuation.definition.string.end.json'] 50 | valueScopes = [baseScopes..., 'meta.structure.dictionary.value.json'] 51 | keyValueSeparatorScopes = [valueScopes..., 'punctuation.separator.dictionary.key-value.json'] 52 | pairSeparatorScopes = [valueScopes..., 'punctuation.separator.dictionary.pair.json'] 53 | stringValueScopes = [valueScopes..., 'string.quoted.double.json'] 54 | 55 | {tokens} = grammar.tokenizeLine('{"a": 1, "b": true, "foo": "bar"}') 56 | expect(tokens[0]).toEqual value: '{', scopes: [baseScopes..., 'punctuation.definition.dictionary.begin.json'] 57 | expect(tokens[1]).toEqual value: '"', scopes: keyBeginScopes 58 | expect(tokens[2]).toEqual value: 'a', scopes: keyScopes 59 | expect(tokens[3]).toEqual value: '"', scopes: keyEndScopes 60 | expect(tokens[4]).toEqual value: ':', scopes: keyValueSeparatorScopes 61 | expect(tokens[5]).toEqual value: ' ', scopes: valueScopes 62 | expect(tokens[6]).toEqual value: '1', scopes: [valueScopes..., 'constant.numeric.json'] 63 | expect(tokens[7]).toEqual value: ',', scopes: pairSeparatorScopes 64 | expect(tokens[8]).toEqual value: ' ', scopes: baseScopes 65 | expect(tokens[9]).toEqual value: '"', scopes: keyBeginScopes 66 | expect(tokens[10]).toEqual value: 'b', scopes: keyScopes 67 | expect(tokens[11]).toEqual value: '"', scopes: keyEndScopes 68 | expect(tokens[12]).toEqual value: ':', scopes: keyValueSeparatorScopes 69 | expect(tokens[13]).toEqual value: ' ', scopes: valueScopes 70 | expect(tokens[14]).toEqual value: 'true', scopes: [valueScopes..., 'constant.language.json'] 71 | expect(tokens[15]).toEqual value: ',', scopes: pairSeparatorScopes 72 | expect(tokens[16]).toEqual value: ' ', scopes: baseScopes 73 | expect(tokens[17]).toEqual value: '"', scopes: keyBeginScopes 74 | expect(tokens[18]).toEqual value: 'foo', scopes: keyScopes 75 | expect(tokens[19]).toEqual value: '"', scopes: keyEndScopes 76 | expect(tokens[20]).toEqual value: ':', scopes: keyValueSeparatorScopes 77 | expect(tokens[21]).toEqual value: ' ', scopes: valueScopes 78 | expect(tokens[22]).toEqual value: '"', scopes: [stringValueScopes..., 'punctuation.definition.string.begin.json'] 79 | expect(tokens[23]).toEqual value: 'bar', scopes: stringValueScopes 80 | expect(tokens[24]).toEqual value: '"', scopes: [stringValueScopes..., 'punctuation.definition.string.end.json'] 81 | expect(tokens[25]).toEqual value: '}', scopes: [baseScopes..., 'punctuation.definition.dictionary.end.json'] 82 | 83 | it "identifies trailing commas in objects", -> 84 | baseScopes = ['source.json', 'meta.structure.dictionary.json'] 85 | keyScopes = [baseScopes..., 'meta.structure.dictionary.key.json', 'string.quoted.double.json'] 86 | keyBeginScopes = [keyScopes..., 'punctuation.definition.string.begin.json'] 87 | keyEndScopes = [keyScopes..., 'punctuation.definition.string.end.json'] 88 | valueScopes = [baseScopes..., 'meta.structure.dictionary.value.json'] 89 | keyValueSeparatorScopes = [valueScopes..., 'punctuation.separator.dictionary.key-value.json'] 90 | pairSeparatorScopes = [valueScopes..., 'punctuation.separator.dictionary.pair.json'] 91 | 92 | {tokens} = grammar.tokenizeLine('{"a": 1, "b": 2, }') 93 | expect(tokens[0]).toEqual value: '{', scopes: [baseScopes..., 'punctuation.definition.dictionary.begin.json'] 94 | expect(tokens[1]).toEqual value: '"', scopes: keyBeginScopes 95 | expect(tokens[2]).toEqual value: 'a', scopes: keyScopes 96 | expect(tokens[3]).toEqual value: '"', scopes: keyEndScopes 97 | expect(tokens[4]).toEqual value: ':', scopes: keyValueSeparatorScopes 98 | expect(tokens[5]).toEqual value: ' ', scopes: valueScopes 99 | expect(tokens[6]).toEqual value: '1', scopes: [valueScopes..., 'constant.numeric.json'] 100 | expect(tokens[7]).toEqual value: ',', scopes: pairSeparatorScopes 101 | expect(tokens[8]).toEqual value: ' ', scopes: baseScopes 102 | expect(tokens[9]).toEqual value: '"', scopes: keyBeginScopes 103 | expect(tokens[10]).toEqual value: 'b', scopes: keyScopes 104 | expect(tokens[11]).toEqual value: '"', scopes: keyEndScopes 105 | expect(tokens[12]).toEqual value: ':', scopes: keyValueSeparatorScopes 106 | expect(tokens[13]).toEqual value: ' ', scopes: valueScopes 107 | expect(tokens[14]).toEqual value: '2', scopes: [valueScopes..., 'constant.numeric.json'] 108 | expect(tokens[15]).toEqual value: ',', scopes: [valueScopes..., 'invalid.illegal.trailing-dictionary-separator.json'] 109 | expect(tokens[16]).toEqual value: ' ', scopes: baseScopes 110 | expect(tokens[17]).toEqual value: '}', scopes: [baseScopes..., 'punctuation.definition.dictionary.end.json'] 111 | --------------------------------------------------------------------------------