diff --git a/JSON/Comments - JSON5.tmPreferences b/JSON/Comments - JSON5.tmPreferences
new file mode 100644
index 00000000000..75aac0ef338
--- /dev/null
+++ b/JSON/Comments - JSON5.tmPreferences
@@ -0,0 +1,25 @@
+
+
+
+ scope
+ source.json.json5
+ settings
+
+ shellVariables
+
+
+ nameTM_COMMENT_START
+ value//
+
+
+ nameTM_COMMENT_START_2
+ value/*
+
+
+ nameTM_COMMENT_END_2
+ value*/
+
+
+
+
+
diff --git a/JSON/Comments - JSONC.tmPreferences b/JSON/Comments - JSONC.tmPreferences
new file mode 100644
index 00000000000..1ee8dd7e2af
--- /dev/null
+++ b/JSON/Comments - JSONC.tmPreferences
@@ -0,0 +1,25 @@
+
+
+
+ scope
+ source.json.jsonc
+ settings
+
+ shellVariables
+
+
+ nameTM_COMMENT_START
+ value//
+
+
+ nameTM_COMMENT_START_2
+ value/*
+
+
+ nameTM_COMMENT_END_2
+ value*/
+
+
+
+
+
diff --git a/JSON/Comments.tmPreferences b/JSON/Comments.tmPreferences
deleted file mode 100644
index d9695e9cf24..00000000000
--- a/JSON/Comments.tmPreferences
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- scope
- source.json
- settings
-
- shellVariables
-
-
- name
- TM_COMMENT_START
- value
- //
-
-
- name
- TM_COMMENT_START_2
- value
- /*
-
-
- name
- TM_COMMENT_END_2
- value
- */
-
-
-
-
-
diff --git a/JSON/Default.sublime-keymap b/JSON/Default.sublime-keymap
index e11d9bce5c6..d710b8aab89 100644
--- a/JSON/Default.sublime-keymap
+++ b/JSON/Default.sublime-keymap
@@ -60,4 +60,4 @@
{ "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true }
]
},
-]
\ No newline at end of file
+]
diff --git a/JSON/JSON (Basic).sublime-syntax b/JSON/JSON (Basic).sublime-syntax
new file mode 100644
index 00000000000..e7e3cb7562d
--- /dev/null
+++ b/JSON/JSON (Basic).sublime-syntax
@@ -0,0 +1,352 @@
+%YAML 1.2
+---
+# https://yaml.org/spec/1.2/spec.html
+# https://www.sublimetext.com/docs/syntax.html#ver-dev
+# https://www.sublimetext.com/docs/syntax.html#testing:ver-dev
+# https://www.sublimetext.com/docs/scope_naming.html
+name: JSON (Basic)
+scope: source.json.basic
+version: 2
+hidden: true
+
+
+variables:
+ exponent: (?:[eE][-+]?\d+)
+ pos_integer_decimal: (?:0|[1-9]\d*)
+
+
+contexts:
+
+ prototype:
+ - include: comments
+
+ main:
+ - include: top-level-object
+ - include: arrays
+ # TODO: highlight other stuff as illegal
+
+ any:
+ - include: constants
+ - include: numbers
+ - include: strings
+ - include: arrays
+ - include: objects
+
+ eol-pop:
+ - match: '$\n?'
+ pop: 1
+
+
+####[ Comments ]########################################################################################################
+
+ comments:
+ - include: comment-line
+ - include: comment-doc-block
+ - include: comment-block
+
+ comment-line:
+ - match: '//'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_scope: invalid.illegal.comment.json
+ - meta_include_prototype: false
+ - include: eol-pop
+
+ comment-doc-block:
+ - match: '/\*\*(?!/)'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_scope: invalid.illegal.comment.json
+ - meta_include_prototype: false
+ - include: comment-block-end
+ - match: '^\s*(\*)(?!/)'
+ captures:
+ 1: invalid.illegal.comment.json
+
+ comment-block:
+ - match: '/\*'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_scope: invalid.illegal.comment.json
+ - meta_include_prototype: false
+ - include: comment-block-end
+
+ comment-block-end:
+ - match: '\*/'
+ scope: invalid.illegal.comment.json
+ pop: 1
+
+####[ Constants ]#######################################################################################################
+
+ constants:
+ - match: \b(?:null)\b
+ scope: constant.language.null.json
+ - match: \b(?:false|true)\b
+ scope: constant.language.boolean.json
+ # when for example typing "Null" or "NULL" instead of "null"
+ - match: \b(?i:null)\b
+ scope: invalid.illegal.expected-lower-case-null.json
+ - match: \b(?i:false|true)\b
+ scope: invalid.illegal.expected-lower-case-boolean.json
+
+####[ Numbers ]#########################################################################################################
+
+ numbers:
+ - include: floats
+ - include: integers
+
+ floats:
+ - include: decimal-floats
+
+ decimal-floats:
+ - match: |-
+ (?x:
+ (?:(-)|(\+))?
+ (
+ {{pos_integer_decimal}}
+ (?:
+ # 1.1 1.1e1 1.1e-1 1.1e+1
+ (\.)\d+ {{exponent}}?
+ # 1e1 1+e1 1-e1
+ | {{exponent}}
+ )
+ )
+ )
+ scope: meta.number.float.decimal.json
+ captures:
+ 1: constant.numeric.sign.json
+ 2: invalid.illegal.number-sign.json
+ 3: constant.numeric.value.json
+ 4: punctuation.separator.decimal.json
+
+ integers:
+ - include: decimal-integers
+
+ decimal-integers:
+ - match: (?:(-)|(\+))?({{pos_integer_decimal}})
+ scope: meta.number.integer.decimal.json
+ captures:
+ 1: constant.numeric.sign.json
+ 2: invalid.illegal.number-sign.json
+ 3: constant.numeric.value.json
+
+####[ Strings ]#########################################################################################################
+
+ strings:
+ - include: double-quoted-string-ahead
+
+ double-quoted-string-ahead:
+ - match: '(?=\")'
+ push: double-quoted-string
+
+ double-quoted-string:
+ - meta_scope: meta.string.json string.quoted.double.json
+ - match: '"'
+ scope: punctuation.definition.string.begin.json
+ set: inside-double-quoted-string
+
+ inside-double-quoted-string:
+ - meta_scope: meta.string.json string.quoted.double.json
+ - meta_include_prototype: false
+ - match: '"'
+ scope: punctuation.definition.string.end.json
+ pop: 1
+ - include: double-quoted-string-escape-characters
+ - match: \n
+ scope: invalid.illegal.unclosed-string.json
+ pop: 1
+
+ double-quoted-string-escape-characters:
+ - match: \\\"
+ scope: constant.character.escape.double-quote.json
+ - include: string-escape-characters
+
+ string-escape-characters:
+ - include: valid-string-escape-characters
+ - include: invalid-string-escape-characters
+
+ valid-string-escape-characters:
+ - match: \\\\
+ scope: constant.character.escape.back-slash.json
+ - match: \\\/
+ scope: constant.character.escape.forward-slash.json
+ - match: \\b
+ scope: constant.character.escape.backspace.json
+ - match: \\f
+ scope: constant.character.escape.form-feed.json
+ - match: \\n
+ scope: constant.character.escape.newline.json # linefeed
+ - match: \\r
+ scope: constant.character.escape.carriage-return.json
+ - match: \\t
+ scope: constant.character.escape.horizontal-tab.json
+ - match: \\u[0-9a-fA-F]{4}
+ scope: constant.character.escape.unicode-symbol.basic-multilingual-plane.json
+
+ invalid-string-escape-characters:
+ - match: \\.
+ scope: invalid.illegal.unrecognized-string-escape.json
+
+####[ Sequence ]########################################################################################################
+
+ # FIXME: trailing commas
+
+ arrays:
+ - include: empty-array
+ - match: \[
+ scope: punctuation.definition.sequence.begin.json
+ push: inside-array
+
+ empty-array:
+ - match: (\[)\s*(\])
+ scope: meta.sequence.list.empty.json
+ captures:
+ 1: punctuation.definition.sequence.begin.json
+ 2: punctuation.definition.sequence.end.json
+
+ inside-array:
+ - meta_scope: meta.sequence.list.json
+ - match: \]
+ scope: punctuation.definition.sequence.end.json
+ pop: 1
+ - match: (?=\S)
+ set: expect-sequence-first-item
+ # - match: '[^\s\]]'
+ # scope: invalid.illegal.expected-any-value.json
+
+ expect-sequence-first-item:
+ - meta_scope: meta.sequence.list.json
+ - match: \]
+ scope: punctuation.definition.sequence.end.json
+ pop: 1
+ - match: ','
+ scope: invalid.illegal.expected-any-value.json
+ - match: (?=\S)
+ set: sequence-first-item
+
+ sequence-first-item:
+ - meta_scope: meta.sequence.item.first.json
+ - include: any
+ - match: (?=\S)
+ set: expect-sequence-end-or-sequence-separator
+
+ expect-sequence-end-or-sequence-separator:
+ - meta_scope: meta.sequence.list.json
+ - match: \]
+ scope: punctuation.definition.sequence.end.json
+ pop: 1
+ - match: ','
+ scope: punctuation.separator.sequence.json
+ set: expect-sequence-item
+ - match: (?=\S)
+ scope: invalid.illegal.expected-sequence-separator.json
+ pop: 1
+
+ expect-sequence-item:
+ - meta_scope: meta.sequence.list.json
+ - match: ','
+ scope: invalid.illegal.expected-any-value.json
+ - match: (?=\S)
+ set: sequence-item
+
+ sequence-item:
+ - meta_scope: meta.sequence.item.json
+ - include: any
+ - match: (?=\S)
+ set: expect-sequence-end-or-sequence-separator
+
+####[ Mapping ]#########################################################################################################
+
+ # FIXME: leading separators
+ # FIXME: trailing commas
+
+ # The top-level contexts here are to ensure that we can apply `meta.toc-list`
+ # to the top-level object keys.
+
+ top-level-object:
+ - include: empty-object
+ - match: \{
+ scope: punctuation.definition.mapping.begin.json
+ push: top-level-meta-mapping
+
+ objects:
+ - include: empty-object
+ - match: \{
+ scope: punctuation.definition.mapping.begin.json
+ push: meta-mapping
+
+ empty-object:
+ - match: (\{)\s*(\})
+ scope: meta.mapping.empty.json
+ captures:
+ 1: punctuation.definition.mapping.begin.json
+ 2: punctuation.definition.mapping.end.json
+
+ top-level-meta-mapping:
+ - meta_scope: meta.mapping.json
+ - match: \}
+ scope: punctuation.definition.mapping.end.json
+ pop: 1
+ - include: top-level-mapping-key
+ - include: mapping-separator
+ - match: '[^\s\}]'
+ scope: invalid.illegal.expected-mapping-key.json
+
+ meta-mapping:
+ - meta_scope: meta.mapping.json
+ - match: \}
+ scope: punctuation.definition.mapping.end.json
+ pop: 1
+ - include: mapping-key
+ - include: mapping-separator
+ - match: '[^\s\}]'
+ scope: invalid.illegal.expected-mapping-key.json
+
+ top-level-mapping-key:
+ - match: '"'
+ scope: punctuation.definition.string.begin.json
+ push: top-level-mapping-key-double-quoted
+
+ mapping-key:
+ - match: '"'
+ scope: punctuation.definition.string.begin.json
+ push: mapping-key-double-quoted
+
+ top-level-mapping-key-double-quoted:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.key.json meta.toc-list.json meta.string.json string.quoted.double.json
+ - meta_include_prototype: false
+ - include: inside-double-quoted-string
+
+ mapping-key-double-quoted:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.key.json meta.string.json string.quoted.double.json
+ - meta_include_prototype: false
+ - include: inside-double-quoted-string
+
+ mapping-separator:
+ - match: ':'
+ scope: punctuation.separator.mapping.key-value.json
+ push: mapping-expect-value
+
+ mapping-expect-value:
+ - match: ',|\s?(?=\})'
+ scope: invalid.illegal.expected-mapping-value.json
+ pop: 1
+ - match: (?=\S)
+ set: mapping-value
+
+ mapping-value:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.value.json
+ - include: any
+ - match: ''
+ set:
+ - match: ','
+ scope: punctuation.separator.mapping.pair.json
+ pop: 1
+ - match: \s*(?=\})
+ pop: 1
+ - match: \s(?!/[/*])(?=[^\s,])|[^\s,]
+ scope: invalid.illegal.expected-mapping-separator.json
+ pop: 1
diff --git a/JSON/JSON.sublime-syntax b/JSON/JSON.sublime-syntax
index c391ca6687e..bc9f7f4ccfa 100644
--- a/JSON/JSON.sublime-syntax
+++ b/JSON/JSON.sublime-syntax
@@ -1,165 +1,123 @@
%YAML 1.2
---
+# https://yaml.org/spec/1.2/spec.html
+# https://www.sublimetext.com/docs/syntax.html#ver-dev
+# https://www.sublimetext.com/docs/syntax.html#testing:ver-dev
+# https://www.sublimetext.com/docs/scope_naming.html
name: JSON
scope: source.json
version: 2
+# https://www.sublimetext.com/docs/syntax.html#inheritance
+extends: 'Packages/JSON/JSON (Basic).sublime-syntax'
+
file_extensions:
- - json
- - sublime-build
- - sublime-color-scheme
- - sublime-commands
- - sublime-completions
- - sublime-keymap
- - sublime-macro
- - sublime-menu
- - sublime-mousemap
- - sublime-project
- - sublime-settings
- - sublime-theme
- - sublime-workspace
- - ipynb
+ # To not confuse beginners too much with comments being marked as invalid and
+ # not knowing where to change from `JSON` to `JSONC (JSON with Comments)`, it
+ # was decided by Jon to apply the `JSONC (JSON with Comments)` syntax by
+ # default to `*.json` files instead.
+ # See: https://github.com/sublimehq/Packages/issues/285
+
+ - .bowerrc
+ # Bower
+ # https://bower.io/docs/config/
+
+ - .htmlhintrc
+ # HTML hint
+ # https://htmlhint.com/docs/user-guide/getting-started
+
+ - .jscsrc
+ # JavaScript Code Style Configuration
+ # https://jscs-dev.github.io
+
+ - .jsfmtrc
+ # jsfmt Configuration
+ # https://github.com/rdio/jsfmt
+
+ - .tern-config
+ # Tern.js Server Configuration
+ # https://ternjs.net/doc/manual.html#server
+
+ - .tern-project
+ # Tern.js Project Configuration
+ # https://ternjs.net/doc/manual.html#configuration
+
+ - .watchmanconfig
+ # Facebook Watchman
+ # root specific configuration file
+ # https://facebook.github.io/watchman/docs/config.html
+
- Pipfile.lock
+ # Pipfile
+ # https://github.com/pypa/pipfile
+
+ - avsc
+ # Pure JavaScript implementation of the Avro specification
+ # https://github.com/mtth/avsc
+
+ - composer.lock
+ # Composer lock file
+ # https://getcomposer.org/doc/01-basic-usage.md
+
+ - css.map
+ # CSS Source Map
+
+ - geojson
+ # JSON for geographic data structures
+ # https://geojson.org
+ # https://datatracker.ietf.org/wg/geojson/charter/
+ # https://datatracker.ietf.org/doc/html/rfc7946
+
+ - gltf
+ # glTF Runtime 3D asset delivery
+ # https://www.khronos.com/gltf
+
+ - har
+ # HTTP Archive Format
+
+ - ipynb
+ # Jupyter Notebook, formerly known as iPython Notebook
+ # https://jupyter.org/documentation
+
+ - js.map
+ # JavaScript Source Map
+
+ - jsonld
+ # JSON for Linking Data
+ # https://json-ld.org
+
+ - ldjson
+ # JSON for Linking Data
+ # https://json-ld.org
+
+ - schema
+ # JSON Schema
+ # https://json-schema.org/learn
+
+ - tfstate
+ # Hashicorp Terraform State
+ # https://www.terraform.io/docs/language/state/index.html
+
+ - tfstate.backup
+ # Hashicorp Terraform State
+ # https://www.terraform.io/docs/language/state/index.html
+
+ - topojson
+ # TopoJSON, an extension to GeoJSON
+ # https://github.com/topojson/topojson-specification
+
+ - ts.map
+ # TypeScript Source Map
+
+ - webapp
+ # Web app manifests
+ # https://developer.mozilla.org/en-US/docs/Web/Manifest
+
+ - webmanifest
+ # Web app manifests
+ # https://developer.mozilla.org/en-US/docs/Web/Manifest
-contexts:
-
- prototype:
- - include: comments
-
- main:
- - include: value
-
- value:
- - include: constant
- - include: number
- - include: string
- - include: array
- - include: object
-
- array:
- - match: \[
- scope: punctuation.section.sequence.begin.json
- push:
- - meta_scope: meta.sequence.json
- - match: \]
- scope: punctuation.section.sequence.end.json
- pop: 1
- - include: value
- - match: ','
- scope: punctuation.separator.sequence.json
- - match: '[^\s\]]'
- scope: invalid.illegal.expected-sequence-separator.json
-
- comments:
- - match: /\*\*(?!/)
- scope: punctuation.definition.comment.json
- push:
- - meta_scope: comment.block.documentation.json
- - meta_include_prototype: false
- - match: \*/
- pop: 1
- - match: ^\s*(\*)(?!/)
- captures:
- 1: punctuation.definition.comment.json
- - match: /\*
- scope: punctuation.definition.comment.json
- push:
- - meta_scope: comment.block.json
- - meta_include_prototype: false
- - match: \*/
- pop: 1
- - match: (//).*$\n?
- scope: comment.line.double-slash.js
- captures:
- 1: punctuation.definition.comment.json
-
- constant:
- - match: \b(?:false|true)\b
- scope: constant.language.boolean.json
- - match: \bnull\b
- scope: constant.language.null.json
-
- number:
- # handles integer and decimal numbers
- - match: (-?)((?:0|[1-9]\d*)(?:(?:(\.)\d+)(?:[eE][-+]?\d+)?|(?:[eE][-+]?\d+)))
- scope: meta.number.float.decimal.json
- captures:
- 1: keyword.operator.arithmetic.json
- 2: constant.numeric.value.json
- 3: punctuation.separator.decimal.json
- - match: (-?)(0|[1-9]\d*)
- scope: meta.number.integer.decimal.json
- captures:
- 1: keyword.operator.arithmetic.json
- 2: constant.numeric.value.json
-
- object:
- # a JSON object
- - match: \{
- scope: punctuation.section.mapping.begin.json
- push:
- - meta_scope: meta.mapping.json
- - match: \}
- scope: punctuation.section.mapping.end.json
- pop: 1
- - match: \"
- scope: punctuation.definition.string.begin.json
- push:
- - clear_scopes: 1
- - meta_scope: meta.mapping.key.json string.quoted.double.json
- - meta_include_prototype: false
- - include: inside-string
- - match: ':'
- scope: punctuation.separator.mapping.key-value.json
- push:
- - match: ',|\s?(?=\})'
- scope: invalid.illegal.expected-mapping-value.json
- pop: 1
- - match: (?=\S)
- set:
- - clear_scopes: 1
- - meta_scope: meta.mapping.value.json
- - include: value
- - match: ''
- set:
- - match: ','
- scope: punctuation.separator.mapping.pair.json
- pop: 1
- - match: \s*(?=\})
- pop: 1
- - match: \s(?!/[/*])(?=[^\s,])|[^\s,]
- scope: invalid.illegal.expected-mapping-separator.json
- pop: 1
- - match: '[^\s\}]'
- scope: invalid.illegal.expected-mapping-key.json
-
- string:
- - match: \"
- scope: punctuation.definition.string.begin.json
- push: inside-string
-
- inside-string:
- - meta_scope: string.quoted.double.json
- - meta_include_prototype: false
- - match: \"
- scope: punctuation.definition.string.end.json
- pop: 1
- - include: string-escape
- - match: \n
- scope: invalid.illegal.unclosed-string.json
- pop: 1
-
- string-escape:
- - match: |-
- (?x: # turn on extended mode
- \\ # a literal backslash
- (?: # ...followed by...
- ["\\/bfnrt] # one of these characters
- | # ...or...
- u # a u
- [0-9a-fA-F]{4} # and four hex digits
- )
- )
- scope: constant.character.escape.json
- - match: \\.
- scope: invalid.illegal.unrecognized-string-escape.json
+first_line_match: |-
+ (?xi:
+ ^ \s* // .*? -\*- .*? \bjson\b .*? -\*- # editorconfig
+ )
diff --git a/JSON/JSON5.sublime-syntax b/JSON/JSON5.sublime-syntax
new file mode 100644
index 00000000000..80b834c4c79
--- /dev/null
+++ b/JSON/JSON5.sublime-syntax
@@ -0,0 +1,194 @@
+%YAML 1.2
+---
+# https://yaml.org/spec/1.2/spec.html
+# https://www.sublimetext.com/docs/syntax.html#ver-dev
+# https://www.sublimetext.com/docs/syntax.html#testing:ver-dev
+# https://www.sublimetext.com/docs/scope_naming.html
+name: JSON5
+scope: source.json.json5
+version: 2
+
+# https://www.sublimetext.com/docs/syntax.html#inheritance
+extends: Packages/JSON/JSONC.sublime-syntax
+
+file_extensions:
+
+ - json5
+ # https://json5.org/
+ # https://spec.json5.org/
+
+ - .babelrc
+ # Babel.js File-relative Configuration
+ # https://babeljs.io/docs/en/config-files
+
+ - .babelrc.json
+ # Babel.js File-relative Configuration
+ # https://babeljs.io/docs/en/config-files
+
+ - .jupyterlab-settings
+ # JupyterLab User Settings
+ # https://jupyterlab.readthedocs.io/en/stable/user/directories.html?highlight=json5#jupyterlab-user-settings-directory
+
+ - babel.config.json
+ # Babel.js Project-wide Configuration
+ # https://babeljs.io/docs/en/config-files
+
+ - next.config.json
+ # Vercel Next.js Configuration
+ # https://nextjs.org/docs/api-reference/next.config.js/introduction
+
+ - nextrc.json
+ # Vercel Next.js Configuration
+ # https://nextjs.org/docs/api-reference/next.config.js/introduction
+
+first_line_match: |-
+ (?xi:
+ ^ \s* // .*? -\*- .*? \bjson5\b .*? -\*- # editorconfig
+ )
+
+
+contexts:
+
+ # TODO: check whitespace valid chars
+
+####[ Numbers ]#########################################################################################################
+
+
+ # completely override original context
+ decimal-floats:
+ - match: |-
+ (?x:
+ ([-+]?)
+ (
+ {{pos_integer_decimal}}
+ (?:
+ # 1. 1.e1 1.e-1 1.e+1 1.1 1.1e1 1.1e-1 1.1e+1
+ (\.)\d* {{exponent}}?
+ # 1e1 1+e1 1-e1
+ | {{exponent}}
+ )
+ # .1 .1e1 .1e+1 .1e-1
+ | (\.)\d+ {{exponent}}?
+ )
+ )
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.numeric.value.json5
+ 3: punctuation.separator.decimal.json5
+ 4: punctuation.separator.decimal.json5
+ - match: ([-+]?)(Infinity)
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.language.infinity.json5
+ - match: ([-+]?)(NaN)
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.language.nan.json5
+
+ integers:
+ - meta_prepend: true
+ - include: hexadecimal-integers
+
+ # completely override original context
+ decimal-integers:
+ - match: ([-+]?)({{pos_integer_decimal}})
+ scope: meta.number.integer.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.numeric.value.json5
+
+ hexadecimal-integers:
+ - match: ([-+]?)(0[xX])(\h+)
+ scope: meta.number.integer.hexadecimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.numeric.base.json5
+ 3: constant.numeric.value.json5
+
+####[ Strings ]#########################################################################################################
+
+ # TODO: add multiline with new-line-escapes
+
+ strings:
+ - meta_append: true
+ - include: single-quoted-string-ahead
+
+ single-quoted-string-ahead:
+ - match: (?=')
+ push: single-quoted-string
+
+ single-quoted-string:
+ - meta_scope: meta.string.json5 string.quoted.single.json5
+ - match: "'"
+ scope: punctuation.definition.string.begin.json5
+ set: inside-single-quoted-string
+
+ inside-single-quoted-string:
+ - meta_scope: meta.string.json5 string.quoted.single.json5
+ - meta_include_prototype: false
+ - match: "'"
+ scope: punctuation.definition.string.end.json5
+ pop: 1
+ - include: single-quoted-string-escape-characters
+ - match: \n
+ scope: invalid.illegal.unclosed-string.json5
+ pop: 1
+
+ single-quoted-string-escape-characters:
+ - match: \\\'
+ scope: constant.character.escape.single-quote.json5
+ - include: string-escape-characters
+
+ valid-string-escape-characters:
+ - meta_prepend: true
+ - match: \\v
+ scope: constant.character.escape.vertical-tab.json5
+ - match: (\\0)([0-9])?
+ captures:
+ 1: constant.character.escape.null.json5
+ 2: invalid.illegal.expected-non-digit-char.json5
+ - match: \\\x{2028}
+ scope: constant.character.escape.line-separator.json5
+ - match: \\\x{2029}
+ scope: constant.character.escape.paragraph-separator.json5
+ - match: \\x[0-9a-fA-F]{2}
+ scope: constant.character.escape.unicode-symbol.basic-latin-or-latin-1-supplement.json5
+ - match: \\u[0-9a-fA-F]{4}\\u[0-9a-fA-F]{4}
+ scope: constant.character.escape.unicode-symbol.utf16-surrogate-pair.json5
+
+ invalid-string-escape-characters:
+ - meta_prepend: true
+ - match: ([^\\])(?:\x{2028}|\x{2029})
+ captures:
+ 1: invalid.illegal.expected-backslash-char.json5
+
+####[ Mapping ]#########################################################################################################
+
+ # TODO: add ECMAScript identifier
+
+ top-level-mapping-key:
+ - meta_append: true
+ - match: "'"
+ scope: punctuation.definition.string.begin.json5
+ push: top-level-mapping-key-single-quoted
+
+ top-level-mapping-key-single-quoted:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.key.json5 meta.toc-list.json5 meta.string.json5 string.quoted.single.json5
+ - meta_include_prototype: false
+ - include: inside-single-quoted-string
+
+ mapping-key:
+ - meta_append: true
+ - match: "'"
+ scope: punctuation.definition.string.begin.json5
+ push: mapping-key-single-quoted
+
+ mapping-key-single-quoted:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.key.json5 meta.string.json5 string.quoted.single.json5
+ - meta_include_prototype: false
+ - include: inside-single-quoted-string
diff --git a/JSON/JSONC.sublime-syntax b/JSON/JSONC.sublime-syntax
new file mode 100644
index 00000000000..4e11a17adf2
--- /dev/null
+++ b/JSON/JSONC.sublime-syntax
@@ -0,0 +1,162 @@
+%YAML 1.2
+---
+# https://yaml.org/spec/1.2/spec.html
+# https://www.sublimetext.com/docs/syntax.html#ver-dev
+# https://www.sublimetext.com/docs/syntax.html#testing:ver-dev
+# https://www.sublimetext.com/docs/scope_naming.html
+name: JSONC (JSON with Comments)
+scope: source.json.jsonc
+version: 2
+
+# https://www.sublimetext.com/docs/syntax.html#inheritance
+extends: Packages/JSON/JSON.sublime-syntax
+
+file_extensions:
+ # To not confuse beginners too much with comments being marked as invalid and
+ # not knowing where to change from `JSON` to `JSONC (JSON with Comments)`, it
+ # was decided by Jon to apply the `JSONC (JSON with Comments)` syntax by
+ # default to `*.json` files instead.
+ # See: https://github.com/sublimehq/Packages/issues/285
+
+ - json
+ # https://www.json.org/json-en.html
+ # https://datatracker.ietf.org/doc/html/rfc7159
+ # https://www.ecma-international.org/publications-and-standards/standards/ecma-404/
+
+ - jsonc
+
+ - sublime-build
+ # https://www.sublimetext.com/docs/build_systems.html
+
+ - sublime-color-scheme
+ # https://www.sublimetext.com/docs/color_schemes.html
+
+ - sublime-commands
+
+ - sublime-completions
+ # https://www.sublimetext.com/docs/completions.html
+
+ - sublime-keymap
+ # https://www.sublimetext.com/docs/key_bindings.html
+
+ - sublime-macro
+
+ - sublime-menu
+ # https://www.sublimetext.com/docs/menus.html
+
+ - sublime-mousemap
+
+ - sublime-project
+ # https://www.sublimetext.com/docs/projects.html
+
+ - sublime-settings
+ # https://www.sublimetext.com/docs/settings.html
+
+ - sublime-theme
+ # https://www.sublimetext.com/docs/themes.html
+
+ - sublime-workspace
+ # https://www.sublimetext.com/docs/projects.html
+
+ - .ember-cli
+
+ - .eslintrc
+ # ESLint Configuration
+ # https://eslint.org/docs/user-guide/configuring/
+
+ - .eslintrc.json
+ # ESLint Configuration
+ # https://eslint.org/docs/user-guide/configuring/
+
+ - .hintrc
+ # Webhint Configuration
+ # https://webhint.io/docs/user-guide/configuring-webhint/summary/
+
+ - .htmlhintrc
+ # HTMLHint Configuration
+ # https://htmlhint.com/docs/user-guide/configuration
+
+ - .jshintrc
+ # JSHint
+ # https://www.jshint.com/docs/#options
+
+ - .jslintrc
+ # JSLint's implementation of JSHint
+ # https://www.jslint.com/lint.html
+
+ - .stylintrc
+ # stylint Configuration
+ # https://github.com/SimenB/stylint
+
+ - .swcrc
+ # swc Configuration
+ # https://swc.rs/docs/configuring-swc
+
+ - eslintrc.json
+ # ESLint Configuration
+ # https://eslint.org/docs/user-guide/configuring/
+
+ - languagebabel
+
+ - tsconfig.json
+ # TypeScript Configuration
+ # https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
+
+first_line_match: |-
+ (?xi:
+ ^ \s* // .*? -\*- .*? \bjsonc\b .*? -\*- # editorconfig
+ )
+
+
+contexts:
+
+ prototype:
+ - include: comments
+
+ eol-pop:
+ - match: '$\n?'
+ pop: 1
+
+####[ Comments ]########################################################################################################
+
+ # completely override original context
+ comments:
+ - include: comment-line
+ - include: comment-doc-block
+ - include: comment-block
+
+ # completely override original context
+ comment-line:
+ - match: '//'
+ scope: punctuation.definition.comment.jsonc
+ push:
+ - meta_scope: comment.line.double-slash.jsonc
+ - meta_include_prototype: false
+ - include: eol-pop
+
+ # completely override original context
+ comment-doc-block:
+ - match: '/\*\*(?!/)'
+ scope: punctuation.definition.comment.begin.jsonc
+ push:
+ - meta_scope: comment.block.documentation.jsonc
+ - meta_include_prototype: false
+ - include: comment-block-end
+ - match: '^\s*(\*)(?!/)'
+ captures:
+ 1: punctuation.definition.comment.jsonc
+
+ # completely override original context
+ comment-block:
+ - match: '/\*'
+ scope: punctuation.definition.comment.begin.jsonc
+ push:
+ - meta_scope: comment.block.jsonc
+ - meta_include_prototype: false
+ - include: comment-block-end
+
+ # completely override original context
+ comment-block-end:
+ - match: '\*/'
+ scope: punctuation.definition.comment.end.jsonc
+ pop: 1
diff --git a/JSON/Line Terminator.tmPreferences b/JSON/Line Terminator.tmPreferences
new file mode 100644
index 00000000000..9482e9a53f1
--- /dev/null
+++ b/JSON/Line Terminator.tmPreferences
@@ -0,0 +1,17 @@
+
+
+
+ scope
+ source.json
+ settings
+
+ shellVariables
+
+
+ nameTM_LINE_TERMINATOR
+ value,
+
+
+
+
+
diff --git a/JSON/Symbol List - JSON.tmPreferences b/JSON/Symbol List - JSON.tmPreferences
new file mode 100644
index 00000000000..141613fb0e6
--- /dev/null
+++ b/JSON/Symbol List - JSON.tmPreferences
@@ -0,0 +1,11 @@
+
+
+
+ scopemeta.toc-list.json
+ settings
+
+ showInSymbolList1
+ showInIndexedSymbolList1
+
+
+
diff --git a/JSON/Symbol List - JSON5.tmPreferences b/JSON/Symbol List - JSON5.tmPreferences
new file mode 100644
index 00000000000..facdefaadf9
--- /dev/null
+++ b/JSON/Symbol List - JSON5.tmPreferences
@@ -0,0 +1,11 @@
+
+
+
+ scopemeta.toc-list.json5 | meta.toc-list.json
+ settings
+
+ showInSymbolList1
+ showInIndexedSymbolList1
+
+
+
diff --git a/JSON/Symbol List - JSONC.tmPreferences b/JSON/Symbol List - JSONC.tmPreferences
new file mode 100644
index 00000000000..701bd1bb40e
--- /dev/null
+++ b/JSON/Symbol List - JSONC.tmPreferences
@@ -0,0 +1,11 @@
+
+
+
+ scopemeta.toc-list.jsonc
+ settings
+
+ showInSymbolList1
+ showInIndexedSymbolList1
+
+
+
diff --git a/JSON/syntax_test_json.json b/JSON/syntax_test_json.json
deleted file mode 100644
index 77718007718..00000000000
--- a/JSON/syntax_test_json.json
+++ /dev/null
@@ -1,123 +0,0 @@
-// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
-
-{
-// <- meta.mapping.json punctuation.section.mapping.begin.json
- "bool": false,
-//^^^^^^ meta.mapping.key.json
-//^^^^^^^^^^^^^^ - meta.mapping meta.mapping
-// ^^^^^ constant.language.boolean.json
-
- "null": null,
-//^^^^^^ meta.mapping.key.json
-//^^^^^^^^^^^^^ - meta.mapping meta.mapping
-// ^^^^ constant.language.null.json
-
- "dict": { "key": "value" }
-// ^^^^^^^^^^^^^^^^^^ meta.mapping.value.json meta.mapping - meta.mapping meta.mapping meta.mapping
-// ^ punctuation.section.mapping.begin.json
-// ^ punctuation.section.mapping.end.json
-// ^^ meta.mapping.value.json meta.mapping.json
-// ^^^^^ meta.mapping.key.json string.quoted.double.json
-// ^^ meta.mapping.value.json meta.mapping.json
-// ^^^^^^^ meta.mapping.value.json meta.mapping.value.json string.quoted.double.json
-// ^^ meta.mapping.value.json meta.mapping.json
-
-, ,
-// <- punctuation.separator.mapping.pair.json
-//^ invalid.illegal.expected-mapping-key.json
-
- "sep": {},
-// ^ punctuation.separator.mapping.key-value.json
-
- "array": [ /**/ ],
-// ^^^^^^^^ meta.mapping.value.json meta.sequence.json
-// ^ punctuation.section.sequence.begin.json
-// ^^^^ comment.block.json
-// ^ punctuation.section.sequence.end.json
-
- "dict": {"foo": },
-// ^ invalid.illegal.expected-mapping-value.json
-// ^ punctuation.section.mapping.end.json
- "dict": {"foo":
- },
-//^ invalid.illegal.expected-mapping-value.json
-// ^ punctuation.section.mapping.end.json
-
- "dict": {"foo"/*comment*/:/*comment*/"bar"/*comment*/},
-// ^^^^^^^^^^^ comment.block.json
-// ^^^^^^^^^^^ comment.block.json
-// ^^^^^^^^^^^ comment.block.json
-
- "dict": {
- "foo": "bar"
- // comment
-// ^ - invalid
-// ^^^^^^^^^^ comment.line.double-slash.js
- ,
-// ^ punctuation.separator.mapping.pair.json
- "foo": "bar"
- /* comment */
-// ^ - invalid
-// ^^^^^^^^^^^^^ comment.block.json
- },
-//^ punctuation.section.mapping.end.json
-// ^ punctuation.separator.mapping.pair.json
-
- "string": "string",
-// ^ punctuation.definition.string.begin.json
-// ^^^^^^^^ meta.mapping.value.json string.quoted.double.json
-// ^ punctuation.definition.string.end.json
-
- "num": 20.09,
-// ^^^^^ meta.number.float.decimal.json constant.numeric.value.json
-// ^ punctuation.separator.decimal.json
-
- "neg": -9,
-// ^^ meta.number.integer.decimal.json
-// ^ keyword.operator.arithmetic.json
-// ^ constant.numeric.value.json
-
- "E": 20e10,
-// ^^^^^ meta.number.float.decimal.json constant.numeric.value.json
-//^^^ meta.mapping.key.json string.quoted.double.json
-// ^ punctuation.separator.mapping.key-value.json - meta.mapping.key
-
- "escape": "\n",
-// ^^ constant.character.escape.json
-// ^^^^ meta.mapping.value.json string.quoted.double.json - meta.mapping.key
-
- "illegal": "\.",
-// ^^ invalid.illegal.unrecognized-string-escape.json
-
- "unterminated string
-//^^^^^^^^^^^^^^^^^^^^ string.quoted.double.json
-// ^ string.quoted.double.json invalid.illegal.unclosed-string.json
-
-// <- - string
-
-/**/: "test",
-// ^ meta.mapping.json comment.block.json
-// ^ punctuation.separator.mapping.key-value.json - comment
-// ^^^^^^ meta.mapping.value.json string.quoted.double.json
-
- "array2":
- [
- "foobar",
-// ^^^^^^^^ meta.mapping.value meta.sequence.json string.quoted.double.json - meta.mapping.key
- ]
-
- [],
-//^ invalid.illegal.expected-mapping-separator.json
-// ^^^ invalid.illegal.expected-mapping-key.json
-
- "typing json": {}
- ,,,, "another key": false,
-
- "ke//y": "value"
-//^^^^^^^ meta.mapping.key.json string.quoted.double.json - comment
-
-/**
- *
-// ^ meta.mapping.json comment.block.documentation.json punctuation.definition.comment.json
-*/
-}
diff --git a/JSON/tests/indentation/syntax_test_indentation_json.mapping.json b/JSON/tests/indentation/syntax_test_indentation_json.mapping.json
new file mode 100644
index 00000000000..cb36ba9613b
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_json.mapping.json
@@ -0,0 +1,36 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+{
+ "a":
+ [
+ "a",
+ "b"
+ ],
+ "b":
+ [
+ {
+ "a": "a",
+ "b": "b"
+ },
+ {
+ "a": "a",
+ "b": "b"
+ }
+ ],
+ "c":
+ {
+ "a":
+ {
+ "a": "a",
+ "b": "b"
+ },
+ "b":
+ [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+}
diff --git a/JSON/tests/indentation/syntax_test_indentation_json.sequence.json b/JSON/tests/indentation/syntax_test_indentation_json.sequence.json
new file mode 100644
index 00000000000..e84350cae63
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_json.sequence.json
@@ -0,0 +1,89 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a"
+ },
+ {
+ "b": "b"
+ },
+ {
+ "c": "c"
+ }
+ ],
+ [
+ [0],
+ [0],
+ [0]
+ ]
+ ]
+ ]
+ ]
+]
diff --git a/JSON/tests/indentation/syntax_test_indentation_json5.mapping.json5 b/JSON/tests/indentation/syntax_test_indentation_json5.mapping.json5
new file mode 100644
index 00000000000..bd8da806f7c
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_json5.mapping.json5
@@ -0,0 +1,36 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "a":
+ [
+ "a",
+ "b"
+ ],
+ "b":
+ [
+ {
+ "a": "a",
+ "b": "b"
+ },
+ {
+ "a": "a",
+ "b": "b"
+ }
+ ],
+ "c":
+ {
+ "a":
+ {
+ "a": "a",
+ "b": "b"
+ },
+ "b":
+ [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+}
diff --git a/JSON/tests/indentation/syntax_test_indentation_json5.sequence.json5 b/JSON/tests/indentation/syntax_test_indentation_json5.sequence.json5
new file mode 100644
index 00000000000..5a40f5bb38a
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_json5.sequence.json5
@@ -0,0 +1,89 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a"
+ },
+ {
+ "b": "b"
+ },
+ {
+ "c": "c"
+ }
+ ],
+ [
+ [0],
+ [0],
+ [0]
+ ]
+ ]
+ ]
+ ]
+]
diff --git a/JSON/tests/indentation/syntax_test_indentation_jsonc.mapping.jsonc b/JSON/tests/indentation/syntax_test_indentation_jsonc.mapping.jsonc
new file mode 100644
index 00000000000..77dbaad820f
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_jsonc.mapping.jsonc
@@ -0,0 +1,36 @@
+// SYNTAX TEST reindent "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "a":
+ [
+ "a",
+ "b"
+ ],
+ "b":
+ [
+ {
+ "a": "a",
+ "b": "b"
+ },
+ {
+ "a": "a",
+ "b": "b"
+ }
+ ],
+ "c":
+ {
+ "a":
+ {
+ "a": "a",
+ "b": "b"
+ },
+ "b":
+ [
+ "a",
+ "b",
+ "c"
+ ]
+ }
+}
diff --git a/JSON/tests/indentation/syntax_test_indentation_jsonc.sequence.jsonc b/JSON/tests/indentation/syntax_test_indentation_jsonc.sequence.jsonc
new file mode 100644
index 00000000000..0499df39f34
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation_jsonc.sequence.jsonc
@@ -0,0 +1,89 @@
+// SYNTAX TEST reindent "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ {
+ "a": "a"
+ },
+ {
+ "b": "b"
+ },
+ {
+ "c": "c"
+ }
+ ],
+ [
+ [0],
+ [0],
+ [0]
+ ]
+ ]
+ ]
+ ]
+]
diff --git a/JSON/tests/symbols/syntax_test_json.symbols.json b/JSON/tests/symbols/syntax_test_json.symbols.json
new file mode 100644
index 00000000000..a507e8ce1a0
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_json.symbols.json
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json
+
+{
+ "key": "value",
+// @@@@@ definition
+// ^^^^^ meta.toc-list.json
+
+ "key-two": { "key-two-one": "value", "key-two-two": "value" }
+// ^^^^^^^^^ meta.toc-list.json
+// ^^^^^^^^^^^^^ - meta.toc-list.json
+// ^^^^^^^^^^^^^ - meta.toc-list.json
+// @@@@@@@@@ definition
+}
diff --git a/JSON/tests/symbols/syntax_test_json5.symbols.json5 b/JSON/tests/symbols/syntax_test_json5.symbols.json5
new file mode 100644
index 00000000000..e30ce4c07cb
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_json5.symbols.json5
@@ -0,0 +1,25 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "key-one": "value",
+// ^^^^^^^^^ meta.toc-list.json
+// @@@@@@@@@ definition
+
+ 'key-two': 'value',
+// ^^^^^^^^^ meta.toc-list.json5
+// @@@@@@@@@ definition
+
+ "key-three": { "key-three-one": "value", "key-three-two": "value" },
+// ^^^^^^^^^^^ meta.toc-list.json
+// ^^^^^^^^^^^^^^^ - meta.toc-list.json
+// ^^^^^^^^^^^^^^^ - meta.toc-list.json
+// @@@@@@@@@@@ definition
+
+ 'key-four': { 'key-four-one': 'value', 'key-four-two': 'value' }
+// ^^^^^^^^^^ meta.toc-list.json5
+// ^^^^^^^^^^^^^^ - meta.toc-list.json5
+// ^^^^^^^^^^^^^^ - meta.toc-list.json5
+// @@@@@@@@@@ definition
+}
diff --git a/JSON/tests/symbols/syntax_test_jsonc.symbols.jsonc b/JSON/tests/symbols/syntax_test_jsonc.symbols.jsonc
new file mode 100644
index 00000000000..f31bd24841c
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_jsonc.symbols.jsonc
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "key": "value",
+// @@@@@ definition
+// ^^^^^ meta.toc-list.json
+
+ "key-two": { "key-two-one": "value", "key-two-two": "value" }
+// ^^^^^^^^^ meta.toc-list.json
+// ^^^^^^^^^^^^^ - meta.toc-list.json
+// ^^^^^^^^^^^^^ - meta.toc-list.json
+// @@@@@@@@@ definition
+}
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_any_value.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_any_value.json
new file mode 100644
index 00000000000..b658c72cdf0
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_any_value.json
@@ -0,0 +1,18 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json
+
+[
+ ,
+// ^ meta.sequence.list
+// ^ meta.sequence.list invalid.illegal.expected-any-value
+// ^ meta.sequence.list
+
+ 1,
+// ^ meta.sequence.item.first
+
+ [, 1, 2]
+// ^ meta.sequence.item meta.sequence.list punctuation.definition.sequence.begin.json
+// ^ meta.sequence.item meta.sequence.list invalid.illegal.expected-any-value
+// ^ meta.sequence.item meta.sequence.item.first
+]
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.illegal.leading_or_trailing_comma_in_mapping.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.leading_or_trailing_comma_in_mapping.json
new file mode 100644
index 00000000000..f25b0ec864a
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.leading_or_trailing_comma_in_mapping.json
@@ -0,0 +1,13 @@
+// SYNTAX TEST "Package/JSON/JSON.sublime-syntax"
+
+// <- source.json
+
+{
+ ,
+// ^ meta.mapping invalid.illegal.leading-comma-in-mapping
+ "a": 1,
+ "b": { , "a": 1, "b": 2, },
+// ^ meta.mapping meta.mapping invalid.illegal.leading-comma-in-mapping
+// ^ meta.mapping meta.mapping invalid.illegal.trailing-comma-in-mapping
+// ^ meta.mapping invalid.illegal.trailing-comma-in-mapping
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.comment.json5 b/JSON/tests/syntax/syntax_test_json5.comment.json5
new file mode 100644
index 00000000000..50a752e9b7b
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.comment.json5
@@ -0,0 +1,42 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ // comment 'not a string'
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+
+ /** comment 'not a string' */
+// ^^^ comment.block.documentation punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block.documentation punctuation.definition.comment.end
+
+ /** comment
+ 'not a string' */
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block.documentation punctuation.definition.comment.end
+
+ /* comment 'not a string' */
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block punctuation.definition.comment.end
+
+ /* comment
+ 'not a string' */
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block punctuation.definition.comment.end
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected-non-digit-char.json5 b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected-non-digit-char.json5
new file mode 100644
index 00000000000..d392a8560e0
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected-non-digit-char.json5
@@ -0,0 +1,11 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ 'escape-character-null': '\00'
+// ^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.null
+// ^ invalid.illegal.expected-non-digit-char
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected_backslash_char.json5 b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected_backslash_char.json5
new file mode 100644
index 00000000000..c93264a946b
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.expected_backslash_char.json5
@@ -0,0 +1,17 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ 'expected-backslash-char-line-separator': 'x
',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^ invalid.illegal.expected-backslash-char
+// ^ - constant.character.escape.line-separator
+
+ 'expected-backslash-char-paragraph-separator': 'x
'
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^ invalid.illegal.expected-backslash-char
+// ^ - constant.character.escape.paragraph-separator
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.invalid.illegal.unrecognized-string-escape.json5 b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.unrecognized-string-escape.json5
new file mode 100644
index 00000000000..f5ee3cf70a5
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.unrecognized-string-escape.json5
@@ -0,0 +1,23 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ 'unrecognized-string-escape-unicode-symbol-too-short': '\x0',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^^ - constant.character.escape
+
+ 'unrecognized-string-escape-unicode-symbol-upper-case-too-short': '\X0',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^^ - constant.character.escape
+
+ 'unrecognized-string-escape-unicode-symbol-upper-case': '\X00'
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^^^ - constant.character.escape
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.meta.mapping.json5 b/JSON/tests/syntax/syntax_test_json5.meta.mapping.json5
new file mode 100644
index 00000000000..2365182099e
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.mapping.json5
@@ -0,0 +1,133 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+// <- meta.mapping punctuation.definition.mapping.begin
+
+ 'meta-mapping-value-constant': null,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-number': 0,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value
+// ^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-string': "value",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^^^ meta.mapping.value
+// ^^^^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-string': 'value',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^^^ meta.mapping.value
+// ^^^^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-sequence-empty': [],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.sequence.list.empty
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ 'meta-mapping-value-sequence-empty-with-space': [ ],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.sequence.list.empty
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ 'meta-mapping-value-sequence': [1, 2, 3],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^^^^^ meta.mapping.value
+// ^^^^^^^^^ - meta.mapping meta.mapping.value
+// ^ meta.mapping.value meta.sequence.list punctuation.definition.sequence.begin
+// ^ meta.mapping.value meta.sequence.list punctuation.definition.sequence.end
+
+ 'meta-mapping-value-mapping-empty': {},
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.mapping.empty
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ 'meta-mapping-value-mapping-empty-with-space': { },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping.empty
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ 'meta-mapping-value-mapping': { "a": 1, "b": 2 },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.begin
+// ^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.pair
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.end
+// ^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-mapping': { 'a': 1, 'b': 2 }
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value
+// ^ - meta.mapping meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.begin
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.pair
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.end
+// ^ - meta.mapping meta.mapping.value
+}
+// <- meta.mapping punctuation.definition.mapping.end
diff --git a/JSON/tests/syntax/syntax_test_json5.meta.sequence.json5 b/JSON/tests/syntax/syntax_test_json5.meta.sequence.json5
new file mode 100644
index 00000000000..1a00e39f058
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.sequence.json5
@@ -0,0 +1,59 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ true,
+// ^^^^ meta.sequence.item.first constant.language.boolean
+
+ false,
+// ^^^^^ meta.sequence.item constant.language.boolean
+// ^^^^^ - meta.sequence.item.first
+
+ null,
+// ^^^^ meta.sequence.item constant.language.null
+
+ 0,
+// ^ meta.sequence.item meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.sequence.item meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ meta.sequence.item string.quoted.double
+
+ 'value',
+// ^^^^^^^ meta.sequence.item string.quoted.single
+
+ [],
+// ^^ meta.sequence.item meta.sequence.list.empty
+
+ [ ],
+// ^^^ meta.sequence.item meta.sequence.list.empty
+
+ [1, 2, 3],
+// ^ meta.sequence.item meta.sequence.list
+// ^ meta.sequence.item meta.sequence.item.first
+// ^ meta.sequence.item meta.sequence.list
+// ^ meta.sequence.item meta.sequence.item - meta.sequence.item meta.sequence.item.first
+// ^ meta.sequence.item meta.sequence.list
+// ^ meta.sequence.item meta.sequence.item
+// ^ meta.sequence.item meta.sequence.list
+// ^ meta.sequence.list
+
+ {},
+// ^^ meta.sequence.item meta.mapping.empty
+
+ { },
+// ^^^ meta.sequence.item meta.mapping.empty
+
+ { "a": 1, "b": 2, "c": 3 },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.sequence.item meta.mapping
+
+ { 'a': 1, 'b': 2, 'c': 3 }
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.sequence.item meta.mapping
+]
+// <- meta.sequence.list punctuation.definition.sequence.end
diff --git a/JSON/tests/syntax/syntax_test_json5.number.float.decimal.explicitly_positive.json5 b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.explicitly_positive.json5
new file mode 100644
index 00000000000..c13c501f9ae
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.explicitly_positive.json5
@@ -0,0 +1,117 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "float-explicitly-positive-zero": +0.0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-zero-with-zero-exponent": +0.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-zero-exponent": +0.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-zero-exponent": +0e0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-zero-exponent": +0e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-zero-with-exponent": +0.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-exponent": +0.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-exponent": +0e9,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-exponent": +0e-9,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive": +9.0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-with-zero-exponent": +9.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-zero-exponent": +9.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-no-fraction-with-zero-exponent": +9e0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-zero-exponent": +9e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-with-exponent": +9.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-exponent": +9.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-no-fraction-with-exponent": +9e9,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-exponent": +9e-9
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.number.float.decimal.ieee_754.json5 b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.ieee_754.json5
new file mode 100644
index 00000000000..e64e75a4695
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.ieee_754.json5
@@ -0,0 +1,27 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "constant-language-nan": NaN,
+// ^^^ meta.number.float.decimal constant.language.nan
+ "constant-language-nan-pos": +NaN,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.language.nan
+ "constant-language-nan-neg": -NaN,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.language.nan
+
+ "constant-language-infinity": Infinity,
+// ^^^^^^^^ meta.number.float.decimal constant.language.infinity
+ "constant-language-infinity-pos": +Infinity,
+// ^^^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^^^ constant.language.infinity
+ "constant-language-infinity-neg": -Infinity
+// ^^^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^^^ constant.language.infinity
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.number.float.decimal.leading_period.json5 b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.leading_period.json5
new file mode 100644
index 00000000000..51ba5967ca8
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.leading_period.json5
@@ -0,0 +1,27 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "float-leading-period-followed-by-zero": .0,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "float-leading-period-followed-by-nonzero": .9,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-leading-period-followed-by-zero": -.0,
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-leading-period-followed-by-nonzero": -.9
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^^^ - invalid.illegal.meta-number-float-decimal
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.number.float.decimal.trailing_period.json5 b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.trailing_period.json5
new file mode 100644
index 00000000000..7859359e4cb
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.trailing_period.json5
@@ -0,0 +1,27 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "float-trailing-period-lead-by-zero": 0.,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "float-trailing-period-lead-by-nonzero": 9.,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-trailing-period-lead-by-zero": -0.,
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-trailing-period-lead-by-nonzero": -9.
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^^^ - invalid.illegal.meta-number-float-decimal
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.number.integer.hexadecimal.json5 b/JSON/tests/syntax/syntax_test_json5.number.integer.hexadecimal.json5
new file mode 100644
index 00000000000..64209c1d96c
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.integer.hexadecimal.json5
@@ -0,0 +1,64 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ "lower-case-hexadecimal-zero-integer": 0x0,
+// ^^^ meta.number.integer.hexadecimal
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "lower-case-explicitly-positive-hexadecimal-zero-integer": +0x0,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "lower-case-negative-hexadecimal-zero-integer": -0x0,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "lower-case-hexadecimal-integer": 0x1,
+// ^^^ meta.number.integer.hexadecimal
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "lower-case-explicitly-positive-hexadecimal-integer": +0x1,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "lower-case-negative-hexadecimal-integer": -0x1,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+
+
+ "upper-case-hexadecimal-zero-integer": 0X0,
+// ^^^ meta.number.integer.hexadecimal
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "upper-case-explicitly-positive-hexadecimal-zero-integer": +0X0,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "upper-case-negative-hexadecimal-zero-integer": -0X0,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "upper-case-hexadecimal-integer": 0X1,
+// ^^^ meta.number.integer.hexadecimal
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "upper-case-explicitly-positive-hexadecimal-integer": +0X1,
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+ "upper-case-negative-hexadecimal-integer": -0X1
+// ^^^^ meta.number.integer.hexadecimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.base
+// ^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_json5.string.json5 b/JSON/tests/syntax/syntax_test_json5.string.json5
new file mode 100644
index 00000000000..6c0727b9bb6
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.string.json5
@@ -0,0 +1,46 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ 'key': 'value',
+// ^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.single
+
+ 'escape-character-single-quote': '\'',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.single-quote
+
+ 'escape-character-vertical-tab': '\v',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.vertical-tab
+
+ 'escape-character-null': '\0',
+// ^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.null
+
+ 'escape-character-unicode-symbol-basic': '\x00',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^^^ constant.character.escape.unicode-symbol.basic-latin-or-latin-1-supplement
+
+ 'escape-character-unicode-symbol-utf16-surrogate-pair': '\u0000\u0000',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^^^^^^^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^^^^^^^^^^^ constant.character.escape.unicode-symbol.utf16-surrogate-pair
+// ^^^^^^ - constant.character.escape.unicode-symbol.basic-multilingual-plane
+// ^^^^^^^ - constant.character.escape.unicode-symbol.basic-multilingual-plane
+
+ 'escape-character-line-separator': '\
',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.line-separator
+
+ 'escape-character-paragraph-separator': '\
'
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.string string.quoted.single
+// ^^ constant.character.escape.paragraph-separator
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.comment.jsonc b/JSON/tests/syntax/syntax_test_jsonc.comment.jsonc
new file mode 100644
index 00000000000..bc2965a064d
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.comment.jsonc
@@ -0,0 +1,425 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ // comment // comment
+// ^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^^^^^^ - comment.line comment.line
+
+ // comment /** comment */
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^^^^^^^^^^ - comment.block.documentation
+// ^^^ - punctuation.definition.comment.begin
+// ^^ - punctuation.definition.comment.end
+
+ // comment /* comment */
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^^^^^^^^^ - comment.block
+// ^^ - punctuation.definition.comment.begin
+// ^^ - punctuation.definition.comment.end
+
+ // comment "not a string"
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.double
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+
+
+
+
+
+ /** comment // comment */
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation
+// ^^^ comment.block.documentation punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^ - comment.line
+// ^^ comment.block.documentation punctuation.definition.comment.end
+
+ /** comment /** comment */
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation
+// ^^^ comment.block.documentation punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^ - comment.block.documentation comment.block.documentation
+// ^^ comment.block.documentation punctuation.definition.comment.end
+// ^^ - comment.block.documentation comment.block.documentation punctuation.definition.comment.end
+
+ /** comment /* comment */
+// ^^^ comment.block.documentation punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation
+// ^^^^^^^^^^^^^ - comment.block.documentation comment.block
+// ^^ comment.block.documentation punctuation.definition.comment.end
+// ^^ - comment.block.documentation comment.block punctuation.definition.comment.end
+
+ /** comment "not a string" */
+// ^^^ comment.block.documentation punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.double
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block.documentation punctuation.definition.comment.end
+
+
+
+
+
+ /** comment
+ // comment */
+// ^^^^^^^^^^^^^ - comment.line
+// ^^ punctuation.definition.comment.end
+
+ /** comment
+ /** comment */
+// ^^^^^^^^^^^^^^ - comment.block.documentation comment.block.documentation
+// ^^ comment.block.documentation punctuation.definition.comment.end
+// ^^ - comment.block.documentation comment.block.documentation punctuation.definition.comment.end
+
+ /** comment
+ /* comment */
+// ^^^^^^^^^^^^^ - comment.block.documentation comment.block
+// ^^ comment.block.documentation punctuation.definition.comment.end
+// ^^ - comment.block.documentation comment.block punctuation.definition.comment.end
+
+ /** comment
+ "not a string" */
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.double
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block.documentation punctuation.definition.comment.end
+
+
+
+
+
+ /**
+ * comment
+// ^ comment.block.documentation punctuation.definition.comment
+ * comment
+ */
+
+
+
+
+
+ /* comment // comment */
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^ - comment.line
+// ^^ comment.block punctuation.definition.comment.end
+
+ /* comment /** comment */
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^^ - comment.block.documentation
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block.documentation punctuation.definition.comment.end
+
+ /* comment /* comment */
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^ - comment.block comment.block
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block comment.block punctuation.definition.comment.end
+
+ /* comment "not a string" */
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.double
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block punctuation.definition.comment.end
+
+
+
+
+
+ /* comment
+ // comment */
+// ^^^^^^^^^^^^^ - comment.line
+// ^^ comment.block punctuation.definition.comment.end
+
+ /* comment
+ /** comment */
+// ^^^^^^^^^^^^^^ - comment.block.documentation
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block.documentation punctuation.definition.comment.end
+
+ /* comment
+ /* comment */
+// ^^^^^^^^^^^^^ - comment.block comment.block
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block comment.block punctuation.definition.comment.end
+
+ /* comment
+ "not a string" */
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.double
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block punctuation.definition.comment.end
+
+
+
+
+
+ /*
+ * comment
+// ^ comment.block
+// ^ - punctuation.definition.comment
+ * comment
+ */
+
+
+
+
+
+ "empty-sequence-with-line-comment": [
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ ],
+
+ "empty-sequence-with-doc-block-comment-with-no-content": [ /***/ ],
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-sequence-with-doc-block-comment": [ /** */ ],
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-sequence-with-block-comment-with-no-content": [ /**/ ],
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-sequence-with-block-comment": [ /* */ ],
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+
+
+
+
+ "full-sequence-with-line-comment": [
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ 1,
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ 2
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ ,
+ 3
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ ],
+
+ "full-sequence-with-doc-block-comment-with-no-content": [ /***/ 1, /***/ 2 /***/ , 3 /***/ ],
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-sequence-with-doc-block-comment": [ /** */ 1, /** */ 2 /** */ , 3 /** */ ],
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-sequence-with-block-comment-with-no-content": [ /**/ 1, /**/ 2 /**/ , 3 /**/ ],
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-sequence-with-block-comment": [ /* */ 1, /* */ 2 /* */ , 3 /* */ ],
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+
+
+
+
+ "empty-mapping-with-line-comment": {
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ },
+
+ "empty-mapping-with-doc-block-comment-with-no-content": { /***/ },
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-mapping-with-doc-block-comment": { /** */ },
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-mapping-with-block-comment-with-no-content": { /**/ },
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-mapping-with-block-comment": { /* */ },
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+
+
+
+
+ "full-mapping-with-line-comment": {
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ "a": 1,
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ "b"
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ :
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ 2
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ ,
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ "c": 3
+ // line comment
+// ^^^^^^^^^^^^^^^ comment.line
+// ^^ punctuation.definition.comment
+ },
+
+ "full-mapping-with-doc-block-comment-with-no-content": { /***/ "a": 1, /***/ "b" /***/ : /***/ 2 /***/ , "c": 3 /***/ },
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-mapping-with-doc-block-comment": { /** */ "a": 1, /** */ "b" /** */ : /** */ 2 /** */ , "c": 3 /** */ },
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^^ comment.block.documentation
+// ^^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-mapping-with-block-comment-with-no-content": { /**/ "a": 1, /**/ "b" /**/ : /**/ 2 /**/ , "c": 3 /**/ },
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-mapping-with-block-comment": { /* */ "a": 1, /* */ "b" /* */ : 2 /* */ , "c": 3 /* */ }
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.constant.jsonc b/JSON/tests/syntax/syntax_test_jsonc.constant.jsonc
new file mode 100644
index 00000000000..b78b2a67b3f
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.constant.jsonc
@@ -0,0 +1,14 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "bool-false": false,
+// ^^^^^ constant.language.boolean
+
+ "bool-true": true,
+// ^^^^ constant.language.boolean
+
+ "null": null
+// ^^^^ constant.language.null
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.expected_lower_case_constant.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.expected_lower_case_constant.jsonc
new file mode 100644
index 00000000000..5ddab3c67ac
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.expected_lower_case_constant.jsonc
@@ -0,0 +1,24 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+[
+ null,
+// ^^^^ constant.language.null
+ Null,
+// ^^^^ invalid.illegal.expected-lower-case-null
+ NULL,
+// ^^^^ invalid.illegal.expected-lower-case-null
+ false,
+// ^^^^^ constant.language.boolean
+ False,
+// ^^^^^ invalid.illegal.expected-lower-case-boolean
+ FALSE,
+// ^^^^^ invalid.illegal.expected-lower-case-boolean
+ true,
+// ^^^^ constant.language.boolean
+ True,
+// ^^^^ invalid.illegal.expected-lower-case-boolean
+ TRUE
+// ^^^^ invalid.illegal.expected-lower-case-boolean
+]
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.jsonc
new file mode 100644
index 00000000000..9517b4f6e4a
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.jsonc
@@ -0,0 +1,26 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "c": "c"
+ , ,
+// ^ meta.mapping punctuation.separator.mapping.pair
+// ^ meta.mapping invalid.illegal.expected-mapping-key
+
+ "d": { "d": },
+// ^ meta.mapping.value meta.mapping invalid.illegal.expected-mapping-value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.end
+
+ "e": { "e":
+ },
+// ^ invalid.illegal.expected-mapping-value
+// ^ punctuation.definition.mapping.end
+
+ [],
+// ^^^ invalid.illegal.expected-mapping-key
+
+ "f": "f"
+ "g": "g"
+// ^ invalid.illegal.expected-mapping-separator
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.number_sign.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.number_sign.jsonc
new file mode 100644
index 00000000000..467a3fd4845
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.number_sign.jsonc
@@ -0,0 +1,147 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "float-explicitly-positive-zero": +0.0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ "float-explicitly-positive-zero-with-zero-exponent": +0.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-zero-exponent": +0.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-zero-exponent": +0e0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-zero-exponent": +0e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-zero-with-exponent": +0.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-exponent": +0.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-exponent": +0e9,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-exponent": +0e-9,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive": +9.0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-with-zero-exponent": +9.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-zero-exponent": +9.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-no-fraction-with-zero-exponent": +9e0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-zero-exponent": +9e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-with-exponent": +9.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-exponent": +9.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-no-fraction-with-exponent": +9e9,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-exponent": +9e-9
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.number-sign
+// ^^^^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_integer_decimal.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_integer_decimal.jsonc
new file mode 100644
index 00000000000..401d1c8e2f7
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_integer_decimal.jsonc
@@ -0,0 +1,16 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+
+ "explicitly-positive-zero": +0,
+// ^^ meta.mapping.value meta.number.integer.decimal
+// ^ invalid.illegal.number-sign
+// ^ constant.numeric.value
+
+ "explicitly-positive-integer": +9
+// ^^ meta.mapping.value meta.number.integer.decimal
+// ^ invalid.illegal.number-sign
+// ^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_string_escape.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_string_escape.jsonc
new file mode 100644
index 00000000000..8d2d68d1718
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unrecognized_string_escape.jsonc
@@ -0,0 +1,50 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "unrecognized-string-escape": "\.",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-upper-case-b": "\B",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-upper-case-f": "\F",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-upper-case-n": "\N",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-upper-case-r": "\R",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-upper-case-t": "\T",
+// ^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^ invalid.illegal.unrecognized-string-escape
+// ^^ - constant.character.escape
+
+ "unrecognized-string-escape-unicode-symbol-too-short": "\u123",
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^^^^ - constant.character.escape
+// ^^ invalid.illegal.unrecognized-string-escape
+
+ "unrecognized-string-escape-unicode-symbol-upper-case-and-too-short": "\U123",
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^^^^ - constant.character.escape
+// ^^ invalid.illegal.unrecognized-string-escape
+
+ "unrecognized-string-escape-unicode-symbol-upper-case": "\U1234"
+// ^^^^^^^^ meta.mapping.value meta.string string.quoted.double
+// ^^^^^^ - constant.character.escape
+// ^^ invalid.illegal.unrecognized-string-escape
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.jsonc b/JSON/tests/syntax/syntax_test_jsonc.jsonc
new file mode 100644
index 00000000000..23a5ab5cafb
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.jsonc
@@ -0,0 +1,20 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "unterminated string
+//^^^^^^^^^^^^^^^^^^^^ string.quoted.double
+// ^ string.quoted.double invalid.illegal.unclosed-string
+
+// <- - string
+
+/**/: "test"
+// ^ meta.mapping comment.block
+// ^ punctuation.separator.mapping.key-value - comment
+// ^^^^^^ meta.mapping.value string.quoted.double
+
+
+ "typing json": {}
+ ,,,, "another key": false
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc b/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc
new file mode 100644
index 00000000000..9bed072024d
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc
@@ -0,0 +1,108 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+// <- meta.mapping punctuation.definition.mapping.begin
+
+ "meta-mapping-value-constant": null,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ punctuation.separator.mapping.pair
+
+ "meta-mapping-value-number": 0,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ punctuation.separator.mapping.pair
+
+ "meta-mapping-value-string": "value",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ punctuation.separator.mapping.pair
+
+ "meta-mapping-value-sequence-empty": [],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.sequence.list.empty
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ "meta-mapping-value-sequence-empty-with-space": [ ],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.sequence.list.empty
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ "meta-mapping-value-sequence": [1, 2
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ meta.mapping.value meta.sequence.list punctuation.definition.sequence.begin
+// ^ meta.mapping.value meta.sequence.list punctuation.separator.sequence
+ ,
+// ^ - invalid
+ 3
+ ],
+// ^ meta.mapping.value meta.sequence.list punctuation.definition.sequence.end
+// ^ punctuation.separator.mapping.pair
+
+ "meta-mapping-value-mapping-empty": {},
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.mapping.empty
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ "meta-mapping-value-mapping-empty-with-space": { },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping.empty
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ "meta-mapping-value-mapping": { "a": 1
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.toc-list
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^^^^^^^^^^^^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.begin
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+ ,
+// ^ - invalid
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.pair
+ "b": 2
+// ^^^ meta.mapping.value meta.mapping.key
+// ^^^ - meta.toc-list
+// ^ meta.mapping.value meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping.value meta.mapping.value
+ }
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.end
+}
+// <- meta.mapping punctuation.definition.mapping.end
diff --git a/JSON/tests/syntax/syntax_test_jsonc.meta.sequence.jsonc b/JSON/tests/syntax/syntax_test_jsonc.meta.sequence.jsonc
new file mode 100644
index 00000000000..c82971a8826
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.sequence.jsonc
@@ -0,0 +1,62 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ true,
+// ^^^^ meta.sequence.item.first constant.language.boolean
+
+ false,
+// ^^^^^ meta.sequence.item constant.language.boolean
+
+ null,
+// ^^^^ meta.sequence.item constant.language.null
+
+ 0,
+// ^ meta.sequence.item meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.sequence.item meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ meta.sequence.item string.quoted.double
+
+ [],
+// ^^ meta.sequence.item meta.sequence.list.empty
+
+ [ ],
+// ^^^ meta.sequence.item meta.sequence.list.empty
+
+ [1, 2
+// ^ meta.sequence.item meta.sequence.list punctuation.definition.sequence.begin
+// ^ meta.sequence.item meta.sequence.item.first
+// ^ meta.sequence.item meta.sequence.list
+// ^ meta.sequence.item meta.sequence.item
+ ,
+// ^ - invalid
+// ^ meta.sequence.item meta.sequence.list punctuation.separator.sequence
+ "three"
+// ^^^^^^^ meta.sequence.item meta.sequence.item string.quoted.double - meta.mapping.key
+ ],
+// ^ meta.sequence.item meta.sequence.list punctuation.definition.sequence.end
+// ^ meta.sequence.list punctuation.separator.sequence
+
+ {},
+// ^^ meta.sequence.item meta.mapping.empty
+
+ { },
+// ^^^ meta.sequence.item meta.mapping.empty
+
+ { "a": 1, "b": 2
+// ^^^^^^^^^^^^^^^^ meta.sequence.item meta.mapping
+// ^ meta.sequence.item meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.sequence.item meta.mapping punctuation.separator.mapping.pair
+ ,
+// ^ - invalid
+ "c": 3
+ }
+]
+// <- meta.sequence.list punctuation.definition.sequence.end
diff --git a/JSON/tests/syntax/syntax_test_jsonc.number.jsonc b/JSON/tests/syntax/syntax_test_jsonc.number.jsonc
new file mode 100644
index 00000000000..71a96cd0ff8
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.number.jsonc
@@ -0,0 +1,251 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "zero": 0,
+// ^ meta.number.integer.decimal
+// ^ constant.numeric.value
+
+ "negative-zero": -0,
+// ^^ meta.number.integer.decimal
+// ^ constant.numeric.sign
+// ^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "integer": 9,
+// ^ meta.number.integer.decimal
+// ^ constant.numeric.value
+
+ "negative-integer": -9,
+// ^^ meta.number.integer.decimal
+// ^ constant.numeric.sign
+// ^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-zero": 0.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-zero": -0.0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-zero-with-zero-exponent": 0.0e0,
+// ^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-zero-with-negative-zero-exponent": 0.0e-0,
+// ^^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-zero-with-zero-exponent": -0.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-zero-with-negative-zero-exponent": -0.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-zero-no-fraction-with-zero-exponent": 0e0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-zero-no-fraction-with-zero-exponent": -0e0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-zero-no-fraction-with-negative-zero-exponent": 0e-0,
+// ^^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-zero-no-fraction-with-negative-zero-exponent": -0e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-zero-with-exponent": 0.0e9,
+// ^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-zero-with-negative-exponent": 0.0e-9,
+// ^^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-zero-with-exponent": -0.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-zero-with-negative-exponent": -0.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-zero-no-fraction-with-exponent": 0e9,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-zero-no-fraction-with-exponent": -0e9,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-zero-no-fraction-with-negative-exponent": 0e-9,
+// ^^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-zero-no-fraction-with-negative-exponent": -0e-9,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float": 9.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative": -9.0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-with-zero-exponent": 9.0e0,
+// ^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-with-negative-zero-exponent": 9.0e-0,
+// ^^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-with-zero-exponent": -9.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-with-negative-zero-exponent": -9.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-no-fraction-with-zero-exponent": 9e0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-no-fraction-with-zero-exponent": -9e0,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-no-fraction-with-negative-zero-exponent": 9e-0,
+// ^^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-no-fraction-with-negative-zero-exponent": -9e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-with-exponent": 9.0e9,
+// ^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-with-negative-exponent": 9.0e-9,
+// ^^^^^^ meta.number.float.decimal constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-with-exponent": -9.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-negative-with-negative-exponent": -9.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-no-fraction-with-exponent": 9e9,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-no-fraction-with-exponent": -9e9,
+// ^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ constant.numeric.value
+
+ "float-no-fraction-with-negative-exponent": 9e-9,
+// ^^^^ meta.number.float.decimal constant.numeric.value
+
+ "float-negative-no-fraction-with-negative-exponent": -9e-9
+// ^^^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.string.jsonc b/JSON/tests/syntax/syntax_test_jsonc.string.jsonc
new file mode 100644
index 00000000000..af86a377624
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.string.jsonc
@@ -0,0 +1,80 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "a": "\"",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.double-quote
+
+ "b": "\\",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.back-slash
+
+ "c": "\/",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.forward-slash
+
+ "d": "\b",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.backspace
+
+ "e": "\f",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.form-feed
+
+ "f": "\n",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.newline
+
+ "g": "\r",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.carriage-return
+
+ "h": "\t",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^ constant.character.escape.horizontal-tab
+
+ "i": "\u1234",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^^^^^ constant.character.escape.unicode-symbol.basic-multilingual-plane
+
+ "j": "\u12345",
+// ^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.value
+// ^^^^^^^^^ meta.mapping.value meta.string string.quoted.double - meta.mapping.key
+// ^^^^^^ constant.character.escape.unicode-symbol.basic-multilingual-plane
+// ^ - constant.character.escape
+
+ "ke//y": "value",
+// ^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+
+ "ke// y": "value",
+// ^^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+
+ "ke/***/y": "value",
+// ^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+
+ "ke/** */y": "value",
+// ^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+
+ "ke/**/y": "value",
+// ^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+
+ "ke/* */y": "value"
+// ^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - comment
+// ^^^^^^^ meta.mapping.value meta.string string.quoted.double
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.while_typing.jsonc b/JSON/tests/syntax/syntax_test_jsonc.while_typing.jsonc
new file mode 100644
index 00000000000..2127e683d07
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.while_typing.jsonc
@@ -0,0 +1,9 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "unterminated string
+ /**/: "test"
+// ^^^^ meta.mapping comment.block
+}
diff --git a/Markdown/Markdown.sublime-syntax b/Markdown/Markdown.sublime-syntax
index 6989819597e..c968aaddfbb 100644
--- a/Markdown/Markdown.sublime-syntax
+++ b/Markdown/Markdown.sublime-syntax
@@ -1186,6 +1186,8 @@ contexts:
- include: fenced-html
- include: fenced-java
- include: fenced-javascript
+ - include: fenced-json
+ - include: fenced-json5
- include: fenced-jsonc
- include: fenced-jspx
- include: fenced-jsx
@@ -1431,11 +1433,11 @@ contexts:
0: meta.code-fence.definition.end.javascript.markdown-gfm
1: punctuation.definition.raw.code-fence.end.markdown
- fenced-jsonc:
+ fenced-json:
- match: |-
(?x)
{{fenced_code_block_start}}
- ((?i:jsonc?))
+ ((?i:json))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.json.markdown-gfm
@@ -1448,6 +1450,40 @@ contexts:
0: meta.code-fence.definition.end.json.markdown-gfm
1: punctuation.definition.raw.code-fence.end.markdown
+ fenced-json5:
+ - match: |-
+ (?x)
+ {{fenced_code_block_start}}
+ ((?i:json5))
+ {{fenced_code_block_trailing_infostring_characters}}
+ captures:
+ 0: meta.code-fence.definition.begin.json5.markdown-gfm
+ 2: punctuation.definition.raw.code-fence.begin.markdown
+ 5: constant.other.language-name.markdown
+ embed: scope:source.json.json5
+ embed_scope: markup.raw.code-fence.json5.markdown-gfm
+ escape: '{{code_fence_escape}}'
+ escape_captures:
+ 0: meta.code-fence.definition.end.json5.markdown-gfm
+ 1: punctuation.definition.raw.code-fence.end.markdown
+
+ fenced-jsonc:
+ - match: |-
+ (?x)
+ {{fenced_code_block_start}}
+ ((?i:jsonc))
+ {{fenced_code_block_trailing_infostring_characters}}
+ captures:
+ 0: meta.code-fence.definition.begin.jsonc.markdown-gfm
+ 2: punctuation.definition.raw.code-fence.begin.markdown
+ 5: constant.other.language-name.markdown
+ embed: scope:source.json.jsonc
+ embed_scope: markup.raw.code-fence.jsonc.markdown-gfm
+ escape: '{{code_fence_escape}}'
+ escape_captures:
+ 0: meta.code-fence.definition.end.jsonc.markdown-gfm
+ 1: punctuation.definition.raw.code-fence.end.markdown
+
fenced-jspx:
- match: |-
(?x)
diff --git a/Markdown/syntax_test_markdown.md b/Markdown/syntax_test_markdown.md
index 310a52f0f0b..43d42b5bea8 100644
--- a/Markdown/syntax_test_markdown.md
+++ b/Markdown/syntax_test_markdown.md
@@ -1968,6 +1968,34 @@ for (var i = 0; i < 10; i++) {
```
| <- punctuation.definition.raw.code-fence.end
+```json
+| ^^^^ constant.other.language-name
+ { "key": "value", "sequence": ["one", "two"], "number": -0.9e1, "string": "\u1234 and // /** test */" }
+| ^^^^^ markup.raw.code-fence.json source.json meta.mapping.key string.quoted.double
+```
+
+```json5
+| ^^^^^ constant.other.language-name
+ { "key": 0x123, "mapping": {"one": Infinity, "two": NaN},
+| ^^^^^ markup.raw.code-fence.json5 source.json.json5 meta.mapping.key string.quoted.double
+| ^^^^^ meta.number.integer.hexadecimal.json5
+| ^^^^^^^^ constant.language.infinity.json5
+| ^^^ constant.language.nan.json5
+ "number": +0.9e1, 'single-quoted-string': '\v' }
+| ^^^^^^ meta.number.float.decimal.json5
+| ^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key string.quoted.single.json5
+| ^^^^ meta.mapping.value string.quoted.single.json5
+| ^^ constant.character.escape.vertical-tab.json5
+```
+
+```jsonc
+| ^^^^^ constant.other.language-name
+ { "key": "value", "sequence": ["one", "two"], // comment
+| ^^^^^ markup.raw.code-fence.jsonc source.json.jsonc meta.mapping.key string.quoted.double
+| ^^^^^^^^^^ comment.line.double-slash.jsonc
+ "number": -0.9e1, "string": "\u1234 and // /** test */" }
+```
+
```ts
| ^^ constant.other.language-name
declare type foo = 'bar'