diff --git a/JSON/.python-version b/JSON/.python-version
new file mode 100755
index 00000000000..cc1923a40b1
--- /dev/null
+++ b/JSON/.python-version
@@ -0,0 +1 @@
+3.8
diff --git a/JSON/Comments - JSON5.tmPreferences b/JSON/Comments - JSON5.tmPreferences
new file mode 100755
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 100755
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/Context.sublime-menu b/JSON/Context.sublime-menu
new file mode 100755
index 00000000000..4329c528ff4
--- /dev/null
+++ b/JSON/Context.sublime-menu
@@ -0,0 +1,25 @@
+// Packages/JSON/Context.sublime-menu
+
+
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Context.sublime-menu
+
+
+[
+ {
+ "caption": "JSON: Minify",
+ "command": "json_minify"
+ },
+ {
+ "caption": "JSON: Prettify",
+ "command": "json_prettify"
+ },
+ {
+ "caption": "JSONC: Minify",
+ "command": "jsonc_minify"
+ },
+ {
+ "caption": "JSONC: Prettify",
+ "command": "jsonc_prettify"
+ }
+]
diff --git a/JSON/Default.sublime-commands b/JSON/Default.sublime-commands
new file mode 100755
index 00000000000..91ac0be852a
--- /dev/null
+++ b/JSON/Default.sublime-commands
@@ -0,0 +1,25 @@
+// Packages/JSON/Default.sublime-commands
+
+
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Default.sublime-commands
+
+
+[
+ {
+ "caption": "JSON: Minify JSON",
+ "command": "json_minify"
+ },
+ {
+ "caption": "JSON: Prettify JSON",
+ "command": "json_prettify"
+ },
+ {
+ "caption": "JSONC: Minify JSONC",
+ "command": "jsonc_minify"
+ },
+ {
+ "caption": "JSONC: Prettify JSONC",
+ "command": "jsonc_prettify"
+ }
+]
diff --git a/JSON/Default.sublime-keymap b/JSON/Default.sublime-keymap
index e11d9bce5c6..eab203888dd 100644
--- a/JSON/Default.sublime-keymap
+++ b/JSON/Default.sublime-keymap
@@ -1,63 +1,70 @@
+// Packages/JSON/Default.sublime-keymap
+
+
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Default.sublime-keymap
+
+
[
// Auto-pair quotations: "key": '|',
{ "keys": ["'"], "command": "insert_snippet", "args": {"contents": "'$0'"}, "context":
[
- { "key": "setting.auto_match_enabled" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['\\w]$", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
+ { "key": "setting.auto_match_enabled" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "preceding_text", "operator": "not_regex_contains", "operand": "['\\w]$", "match_all": true },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
]
},
// Auto-pair quotations: "key": "|",
{ "keys": ["\""], "command": "insert_snippet", "args": {"contents": "\"$0\""}, "context":
[
- { "key": "setting.auto_match_enabled" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "preceding_text", "operator": "not_regex_contains", "operand": "[\"\\w]$", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
+ { "key": "setting.auto_match_enabled" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "preceding_text", "operator": "not_regex_contains", "operand": "[\"\\w]$", "match_all": true },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
]
},
// Auto-pair braces: "key": {|},
{ "keys": ["{"], "command": "insert_snippet", "args": {"contents": "{$0}"}, "context":
[
- { "key": "setting.auto_match_enabled" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
+ { "key": "setting.auto_match_enabled" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
]
},
// Auto-pair square brackets: "key": [|],
{ "keys": ["["], "command": "insert_snippet", "args": {"contents": "[$0]"}, "context":
[
- { "key": "setting.auto_match_enabled" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
+ { "key": "setting.auto_match_enabled" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |]|,|:|\\}|$)", "match_all": true }
]
},
// Add indented line in square brackets
{ "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context":
[
- { "key": "setting.auto_indent" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "preceding_text", "operator": "regex_contains", "operand": "\\[$", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true }
+ { "key": "setting.auto_indent" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "\\[$", "match_all": true },
+ { "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true }
]
},
{ "keys": ["shift+enter"], "command": "insert_snippet", "args": {"contents": "\n\t$0\n"}, "context":
[
- { "key": "setting.auto_indent" },
- { "key": "selector", "operand": "source.json" },
- { "key": "selection_empty", "match_all": true },
- { "key": "preceding_text", "operator": "regex_contains", "operand": "\\[$", "match_all": true },
- { "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true }
+ { "key": "setting.auto_indent" },
+ { "key": "selector", "operand": "source.json" },
+ { "key": "selection_empty", "match_all": true },
+ { "key": "preceding_text", "operator": "regex_contains", "operand": "\\[$", "match_all": true },
+ { "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 100755
index 00000000000..0193a607530
--- /dev/null
+++ b/JSON/JSON (Basic).sublime-syntax
@@ -0,0 +1,388 @@
+%YAML 1.2
+---
+# YAML Documentation:
+# https://yaml.org/spec/1.2/spec.html
+# Sublime Text Documentation:
+# 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
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/JSON%20(Basic).sublime-syntax
+#
+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:
+ - match: '(?=\S)'
+ push: top-level-expect-object
+
+####[ Top level ]#######################################################################################################
+
+ # Try these below one-by-one.
+
+ top-level-expect-object:
+ - include: top-level-objects
+ - match: ''
+ push: top-level-expect-array
+
+ top-level-expect-array:
+ - include: arrays
+ - match: ''
+ push: top-level-expect-constant
+
+ top-level-expect-constant:
+ - include: constants
+ - match: ''
+ push: top-level-expect-number
+
+ top-level-expect-number:
+ - include: numbers
+ - match: ''
+ push: top-level-expect-string
+
+ top-level-expect-string:
+ - include: strings
+ - match: ''
+ push: top-level-expect-invalid-remainder
+
+ top-level-expect-invalid-remainder:
+ - match: ','
+ scope: invalid.illegal.unexpected-separator.json
+ - match: ':'
+ scope: invalid.illegal.unexpected-separator.json
+ - match: '\S*'
+ scope: invalid.illegal.unexpected-code-after-first-structure-or-value.json
+
+####[ Structural helpers ]##############################################################################################
+
+ any:
+ - include: structures
+ - include: values
+
+ structures:
+ - include: objects
+ - include: arrays
+
+ values:
+ - include: constants
+ - include: numbers
+ - include: strings
+
+####[ Helpers ]#########################################################################################################
+
+ eol-pop:
+ - match: '$\n?'
+ pop: 1
+
+####[ Comments ]########################################################################################################
+
+ comments:
+ - meta_include_prototype: false
+ - include: comment-line
+ - include: comment-doc-block
+ - include: comment-block
+
+ comment-line:
+ - meta_include_prototype: false
+ - match: '//'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_include_prototype: false
+ - meta_content_scope: invalid.illegal.comment.json
+ - include: eol-pop
+
+ comment-doc-block:
+ - meta_include_prototype: false
+ - match: '/\*\*(?!/)'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_include_prototype: false
+ - meta_content_scope: invalid.illegal.comment.json
+ - include: comment-block-end
+ - match: '^\s*(\*)(?!/)'
+ captures:
+ 1: invalid.illegal.comment.json
+
+ comment-block:
+ - meta_include_prototype: false
+ - match: '/\*'
+ scope: invalid.illegal.comment.json
+ push:
+ - meta_include_prototype: false
+ - meta_content_scope: invalid.illegal.comment.json
+ - include: comment-block-end
+
+ comment-block-end:
+ - meta_include_prototype: false
+ - 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 erroneously containing upper case letters
+ - 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.numeric-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.numeric-sign.json
+ 3: constant.numeric.value.json
+
+####[ Strings ]#########################################################################################################
+
+ strings:
+ - include: double-quoted-strings
+
+ double-quoted-strings:
+ - match: \"
+ scope: punctuation.definition.string.begin.json
+ push: inside-double-quoted-string
+
+ inside-double-quoted-string:
+ - meta_include_prototype: false
+ - meta_scope: meta.string.json string.quoted.double.json
+ - 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:
+ - meta_include_prototype: false
+ - match: \\\"
+ scope: constant.character.escape.double-quote.json
+ - include: string-escape-characters
+
+ string-escape-characters:
+ - meta_include_prototype: false
+ - include: valid-string-escape-characters
+ - include: invalid-string-escape-characters
+
+ valid-string-escape-characters:
+ - meta_include_prototype: false
+ - 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:
+ - meta_include_prototype: false
+ - match: \\.
+ scope: invalid.illegal.unrecognized-string-escape.json
+
+####[ Sequence ]########################################################################################################
+
+ arrays:
+ - include: empty-arrays
+ - match: \[
+ scope: punctuation.definition.sequence.begin.json
+ push:
+ - array-body
+ - array-illegal-separator
+
+ array-body:
+ - meta_scope: meta.sequence.list.json
+ - match: \]
+ scope: punctuation.definition.sequence.end.json
+ pop: 1
+ - include: array-separators
+ - include: any
+ - match: '[^\s\]]'
+ scope: invalid.illegal.expected-separator.json
+
+ array-separators:
+ - match: (?=,)
+ branch_point: array-separators
+ branch:
+ - array-separator
+ - array-illegal-separator
+
+ array-separator:
+ - match: ','
+ scope: punctuation.separator.sequence.json
+ set: array-expect-value
+
+ array-expect-value:
+ - match: (?=\])
+ fail: array-separators
+ - include: array-illegal-separator
+
+ array-illegal-separator:
+ - match: ','
+ scope: invalid.illegal.unexpected-separator.json
+ - match: (?=\S)
+ pop: 1
+
+ empty-arrays:
+ - match: (\[)\s*(\])
+ scope: meta.sequence.list.empty.json
+ captures:
+ 1: punctuation.definition.sequence.begin.json
+ 2: punctuation.definition.sequence.end.json
+
+####[ 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 to index them as symbols.
+
+ top-level-objects:
+ - 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_include_prototype: false
+ - meta_scope: meta.mapping.key.json meta.toc-list.json meta.string.json string.quoted.double.json
+ - include: inside-double-quoted-string
+
+ mapping-key-double-quoted:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - meta_scope: meta.mapping.key.json meta.string.json string.quoted.double.json
+ - 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-settings b/JSON/JSON.sublime-settings
new file mode 100755
index 00000000000..f2bcd73da13
--- /dev/null
+++ b/JSON/JSON.sublime-settings
@@ -0,0 +1,11 @@
+// Packages/JSON/JSON.sublime-settings
+// Settings - Syntax Specific (Default)
+//
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/JSON.sublime-settings
+
+
+{
+ // whether `on_pre_save_async` events auto-trigger the `json_prettify` command
+ "json.auto_prettify": false
+}
diff --git a/JSON/JSON.sublime-syntax b/JSON/JSON.sublime-syntax
index b7bd6a312df..903c25e8c4f 100644
--- a/JSON/JSON.sublime-syntax
+++ b/JSON/JSON.sublime-syntax
@@ -1,170 +1,130 @@
%YAML 1.2
---
+# YAML Documentation:
+# https://yaml.org/spec/1.2/spec.html
+# Sublime Text Documentation:
+# 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
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/JSON.sublime-syntax
+#
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
+ # 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/
+
+ - .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
+
+ - .markdownlintrc
+ # https://github.com/DavidAnson/markdownlint
+
+ - .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
first_line_match: |-
(?xi:
^ \s* // .*? -\*- .*? \bjson\b .*? -\*- # editorconfig
)
-
-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
diff --git a/JSON/JSON5.sublime-syntax b/JSON/JSON5.sublime-syntax
new file mode 100755
index 00000000000..a8b4001a8e7
--- /dev/null
+++ b/JSON/JSON5.sublime-syntax
@@ -0,0 +1,254 @@
+%YAML 1.2
+---
+# YAML Documentation:
+# https://yaml.org/spec/1.2/spec.html
+# Sublime Text Documentation:
+# 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
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/JSON5.sublime-syntax
+#
+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/#summary-of-features
+ # https://262.ecma-international.org/5.1/
+
+ - .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
+
+ - .parcelrc
+ # parcel Bundler Configuration
+ # https://github.com/parcel-bundler/parcel
+ # https://parceljs.org/features/plugins/#.parcelrc
+
+ - .postcssrc.json
+ # PostCSS Configuration
+ # https://postcss.org
+
+ - 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
+
+ - techdocs_metadata.json
+ # Spotify's @backstage/techdocs_common Configuration
+ # https://github.com/backstage/backstage/tree/master/packages/techdocs-common
+ # https://backstage.io/docs/features/techdocs/techdocs-overview
+
+first_line_match: |-
+ (?xi:
+ ^ \s* // .*? -\*- .*? \bjson5\b .*? -\*- # editorconfig
+ )
+
+
+variables:
+
+ # Unicode documentation:
+ # https://www.unicode.org/versions/latest/
+ # https://www.unicode.org/Public/UCD/latest/ucd/
+ # Oniguruma documentation:
+ # https://github.com/kkos/oniguruma/blob/master/doc/RE
+ # https://github.com/kkos/oniguruma/blob/master/doc/UNICODE_PROPERTIES
+
+ identifier_escape: (?:\\u(?:\h{4}|\{\h+\}))
+ identifier_start: (?:[_$\p{L}\p{Nl}]|{{identifier_escape}})
+ identifier_part: (?:[_$\p{L}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]|{{identifier_escape}})
+ identifier_break: (?!{{identifier_part}})
+
+ identifier_name: (?:{{identifier_start}}{{identifier_part}}*{{identifier_break}})
+
+
+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 ]#########################################################################################################
+
+ strings:
+ - meta_append: true
+ - include: single-quoted-strings
+
+ single-quoted-strings:
+ - match: \'
+ scope: punctuation.definition.string.begin.json5
+ push: inside-single-quoted-string
+
+ inside-single-quoted-string:
+ - meta_include_prototype: false
+ - meta_scope: meta.string.json5 string.quoted.single.json5
+ - 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:
+ - meta_include_prototype: false
+ - match: \\\'
+ scope: constant.character.escape.single-quote.json5
+ - include: string-escape-characters
+
+ valid-string-escape-characters:
+ - meta_prepend: true
+ - meta_include_prototype: false
+ - match: ((\\)\x{2028})(?:(.*)(?:$\n))
+ captures:
+ 1: constant.character.escape.line-separator.json5
+ 2: punctuation.separator.continuation.line.json5
+ 3: invalid.illegal.expected-eol-after-line-continuation.json5
+ - match: ((\\)\x{2029})(?:(.*)(?:$\n))
+ captures:
+ 1: constant.character.escape.paragraph-separator.json5
+ 2: punctuation.separator.continuation.line.json5
+ 3: invalid.illegal.expected-eol-after-line-continuation.json5
+ - match: '(\\)(?:$\n)'
+ captures:
+ 1: punctuation.separator.continuation.line.json5
+ - match: \\v
+ scope: constant.character.escape.vertical-tab.json5
+ - match: (\\0)([0-9])?
+ captures:
+ 1: constant.character.escape.null.json5
+ 2: invalid.illegal.unexpected-digit-character.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
+ - meta_include_prototype: false
+ - match: ([^\\])(?:\x{2028}|\x{2029})
+ captures:
+ 1: invalid.illegal.expected-backslash-char.json5
+
+####[ Mapping ]#########################################################################################################
+
+ # The top-level contexts here are to ensure that we can apply `meta.toc-list`
+ # to the top-level object keys to index them as symbols.
+
+ top-level-mapping-key:
+ - meta_append: true
+ - match: '(?={{identifier_name}})'
+ push: top-level-mapping-key-ecma
+ - match: "'"
+ scope: punctuation.definition.string.begin.json5
+ push: top-level-mapping-key-single-quoted
+
+ top-level-mapping-key-ecma:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - match: '{{identifier_name}}'
+ scope: meta.mapping.key.json5 meta.toc-list.json5 meta.string.json5 string.unquoted.plain.json5
+ pop: 1
+
+ top-level-mapping-key-single-quoted:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - meta_scope: meta.mapping.key.json5 meta.toc-list.json5 meta.string.json5 string.quoted.single.json5
+ - include: inside-single-quoted-string
+
+ mapping-key:
+ - meta_append: true
+ - match: "'"
+ scope: punctuation.definition.string.begin.json5
+ push: mapping-key-single-quoted
+ - match: '(?={{identifier_name}})'
+ push: mapping-key-ecma
+
+ mapping-key-ecma:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - match: '{{identifier_name}}'
+ scope: meta.mapping.key.json5 meta.string.json5 string.unquoted.plain.json5
+ pop: 1
+
+ mapping-key-single-quoted:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - meta_scope: meta.mapping.key.json5 meta.string.json5 string.quoted.single.json5
+ - include: inside-single-quoted-string
diff --git a/JSON/JSONC.sublime-syntax b/JSON/JSONC.sublime-syntax
new file mode 100755
index 00000000000..58b4556da04
--- /dev/null
+++ b/JSON/JSONC.sublime-syntax
@@ -0,0 +1,155 @@
+%YAML 1.2
+---
+# YAML Documentation:
+# https://yaml.org/spec/1.2/spec.html
+# Sublime Text Documentation:
+# 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
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/JSONC.sublime-syntax
+#
+name: JSONC
+scope: source.json.jsonc
+version: 2
+
+# https://www.sublimetext.com/docs/syntax.html#inheritance
+extends: Packages/JSON/JSON.sublime-syntax
+
+file_extensions:
+ - 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:
+
+####[ Comments ]########################################################################################################
+
+ # completely override original context
+ comment-line:
+ - meta_include_prototype: false
+ - match: '//'
+ scope: punctuation.definition.comment.jsonc
+ push:
+ - meta_include_prototype: false
+ - meta_scope: comment.line.double-slash.jsonc
+ - include: eol-pop
+
+ # completely override original context
+ comment-doc-block:
+ - meta_include_prototype: false
+ - match: '/\*\*(?!/)'
+ scope: punctuation.definition.comment.begin.jsonc
+ push:
+ - meta_include_prototype: false
+ - meta_scope: comment.block.documentation.jsonc
+ - include: comment-block-end
+ - match: '^\s*(\*)(?!/)'
+ captures:
+ 1: punctuation.definition.comment.jsonc
+
+ # completely override original context
+ comment-block:
+ - meta_include_prototype: false
+ - match: '/\*'
+ scope: punctuation.definition.comment.begin.jsonc
+ push:
+ - meta_include_prototype: false
+ - meta_scope: comment.block.jsonc
+ - include: comment-block-end
+
+ # completely override original context
+ comment-block-end:
+ - meta_include_prototype: false
+ - match: '\*/'
+ scope: punctuation.definition.comment.end.jsonc
+ pop: 1
+
+####[ Sequence ]########################################################################################################
+
+ # completely override original context
+ array-separators:
+ - match: ','
+ scope: punctuation.separator.sequence.jsonc
+ push: array-illegal-separator
diff --git a/JSON/Main.sublime-menu b/JSON/Main.sublime-menu
new file mode 100755
index 00000000000..2d376cf973a
--- /dev/null
+++ b/JSON/Main.sublime-menu
@@ -0,0 +1,124 @@
+// Packages/JSON/Main.sublime-menu
+//
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Main.sublime-menu
+
+
+[
+ {
+ "id": "preferences",
+ "children":
+ [
+ {
+ "id": "package-settings",
+ "children":
+ [
+ {
+ "caption": "JSON",
+ "children":
+ [
+ {
+ "caption": "JSON: Minify",
+ "command": "json_minify"
+ },
+ {
+ "caption": "JSON: Prettify",
+ "command": "json_prettify"
+ },
+ {
+ "command": "json_toggle_auto_prettify",
+ "caption": "JSON: Automatically prettify before saving",
+ "checkbox": false
+ },
+ {
+ "caption": "JSONC: Minify",
+ "command": "jsonc_minify"
+ },
+ {
+ "caption": "JSONC: Prettify",
+ "command": "jsonc_prettify"
+ },
+ { "caption": "-" },
+
+ // entries at this level above may be hidden depending
+ // upon the current view's syntax
+
+ {
+ "caption": "JSON: Settings - Syntax Specific",
+ "command": "edit_settings",
+ "args":
+ {
+ "base_file": "${packages}/JSON/JSON.sublime-settings",
+ "default": "{\n\t$0\n}\n"
+ }
+ },
+ { "caption": "-" },
+ {
+ "caption": "Documentation",
+ "children":
+ [
+ {
+ "caption": "JSON: Specs",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://www.json.org/json-en.html"
+ }
+ },
+ {
+ "caption": "JSON: RFC 7159",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://datatracker.ietf.org/doc/html/rfc7159"
+ }
+ },
+ {
+ "caption": "JSON: ECMA 404",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://www.ecma-international.org/publications-and-standards/standards/ecma-404/"
+ }
+ },
+ { "caption": "-" },
+ {
+ "caption": "JSON5: Specs",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://spec.json5.org/#summary-of-features"
+ }
+ }
+ ]
+ },
+ { "caption": "-" },
+ {
+ "caption": "Support",
+ "children":
+ [
+ {
+ "caption": "Changelog",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://github.com/sublimehq/Packages/commits/master/JSON"
+ }
+ },
+ {
+ "caption": "Report an issue",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://github.com/sublimehq/Packages/issues"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/JSON/Symbol List - JSON.tmPreferences b/JSON/Symbol List - JSON.tmPreferences
new file mode 100755
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 100755
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/main.py b/JSON/main.py
new file mode 100755
index 00000000000..8ddf5603bdb
--- /dev/null
+++ b/JSON/main.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/main.py
+
+
+import sublime
+
+from .src import *
+
+
+def plugin_loaded() -> None:
+ json_prettify.plugin_loaded()
+
+
+def plugin_unloaded() -> None:
+ json_prettify.plugin_unloaded()
diff --git a/JSON/src/__init__.py b/JSON/src/__init__.py
new file mode 100755
index 00000000000..181339e8b50
--- /dev/null
+++ b/JSON/src/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/src/__init__.py
+
+
+from .json_prettify import *
+from .jsonc_prettify import *
diff --git a/JSON/src/json_prettify.py b/JSON/src/json_prettify.py
new file mode 100755
index 00000000000..9e7e86e7e78
--- /dev/null
+++ b/JSON/src/json_prettify.py
@@ -0,0 +1,211 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/src/json_prettify.py
+
+
+import sublime
+import sublime_plugin
+
+import json
+from typing import (
+ Any,
+ Union
+)
+
+
+PKG_NAME: str = __package__.split('.')[0]
+settings: Union[sublime.Settings, None] = None
+base_settings: str = 'JSON.sublime-settings'
+base_scope: str = 'source.json - (source.json.jsonc | source.json.json5)'
+
+
+def status_msg(msg: str = '') -> None:
+ if msg == '': return
+ sublime.status_message(f'{PKG_NAME}: {msg}')
+
+
+def print_msg(msg_header: str = '', msg_body: str = '') -> None:
+ if msg_body == '': return
+ print(f'JSON: {msg_header}:\n\n{msg_body}\n\n')
+
+
+def json2py(view: sublime.View) -> Any:
+ old_contents: str = view.substr(
+ x=whole_view(view)
+ )
+ try:
+ return json.loads( # https://docs.python.org/3.8/library/json.html#json.loads
+ s=old_contents
+ )
+ except Exception as e:
+ print_msg(msg_header='Conversion failed due to error:', msg_body=f'{e}')
+ return None
+
+
+def whole_view(view: sublime.View) -> sublime.Region:
+ return sublime.Region(
+ a=0,
+ b=view.size()
+ )
+
+
+def is_json(view: sublime.View) -> bool:
+ return view.match_selector(
+ pt=0,
+ selector=base_scope
+ )
+
+
+def plugin_loaded(reload: bool = False) -> None:
+ try:
+ global settings
+ settings = sublime.load_settings(base_name=base_settings)
+ settings.clear_on_change(tag='reload')
+ settings.add_on_change(
+ tag='reload',
+ callback=lambda: plugin_loaded(reload=True)
+ )
+ except Exception as e:
+ print_msg(msg_header=f'Loading "{base_settings}" failed due to error', msg_body=f'{e}')
+
+ if reload:
+ status_msg('Reloaded settings on change.')
+
+
+def plugin_unloaded() -> None:
+ global settings
+ settings = None
+
+
+class JsonToggleAutoPrettify(sublime_plugin.WindowCommand):
+
+ _is_checked: bool = False
+ _key: str = 'json.auto_prettify'
+
+ def __init__(self, window: sublime.Window) -> None:
+ self.window = window
+
+ try:
+ if settings is None:
+ return
+ self._is_checked = settings.has(key=self._key)
+ except Exception:
+ pass
+
+ def run(self) -> None:
+ try:
+ global settings
+ if settings is None:
+ return
+ if self._is_checked:
+ settings.erase(key=self._key) # remove the override (true) of the default (false)
+ else:
+ settings.set(key=self._key, value=True)
+ sublime.save_settings(base_name=base_settings)
+ self._is_checked = not self._is_checked # toggle
+ except Exception:
+ pass
+
+ def is_checked(self) -> bool:
+ return self._is_checked
+
+ def is_visible(self) -> bool:
+ try:
+ view: Union[sublime.View, None] = self.window.active_view()
+ if view is None:
+ return False
+ return is_json(view)
+ except Exception as e:
+ print_msg('Error while trying to check if active view is JSON', msg_body=f'{e}')
+ return False
+
+
+class JsonAutoPrettifyListener(sublime_plugin.EventListener):
+
+ _key: str = 'json.auto_prettify'
+
+ def on_pre_save_async(self, view) -> None:
+ if not is_json(view):
+ return
+ if settings is None:
+ return
+ if not settings.get(key=self._key, default=False):
+ return
+ view.run_command(cmd='json_prettify')
+
+
+class JsonPrettify(sublime_plugin.TextCommand):
+
+ def run(self, edit_token: sublime.Edit) -> None:
+ """
+ Attempt to prettify the current view's JSON contents. Print errors to
+ the console when it fails.
+ """
+
+ try:
+ json_as_python: Any = json2py(self.view)
+ if json_as_python is None: return
+ self.view.replace(
+ edit_token,
+ r=whole_view(self.view),
+ text=json.dumps( # https://docs.python.org/3.8/library/json.html#json.dumps
+ obj=json_as_python,
+ allow_nan=False,
+ indent=4,
+ sort_keys=True
+ )
+ )
+ status_msg('Prettified.')
+ except Exception as e:
+ print_msg(msg_header='Conversion failed due to error', msg_body=f'{e}')
+ status_msg('Prettifying failed. See console for details.')
+ pass
+
+ def is_enabled(self) -> bool:
+ return is_json(self.view)
+
+ def is_visible(self) -> bool:
+ return is_json(self.view)
+
+ def description(self) -> str:
+ return 'Prettify JSON'
+
+
+class JsonMinify(sublime_plugin.TextCommand):
+
+ def run(self, edit_token: sublime.Edit) -> None:
+ """
+ Attempt to minify the current view's JSON contents. Print errors to
+ the console when it fails.
+ """
+
+ try:
+ json_as_python: Any = json2py(self.view)
+ if json_as_python is None: return
+ self.view.replace(
+ edit_token,
+ r=whole_view(self.view),
+ text=json.dumps( # https://docs.python.org/3.8/library/json.html#json.dumps
+ obj=json_as_python,
+ allow_nan=False,
+ indent=None,
+ separators=(',', ':'),
+ sort_keys=True
+ )
+ )
+ status_msg('Minified.')
+ except Exception as e:
+ print_msg(msg_header='Conversion failed due to error', msg_body=f'{e}')
+ status_msg('Minifying failed. See console for details.')
+ pass
+
+ def is_enabled(self) -> bool:
+ return is_json(self.view)
+
+ def is_visible(self) -> bool:
+ return is_json(self.view)
+
+ def description(self) -> str:
+ return 'Minify JSON'
diff --git a/JSON/src/jsonc_prettify.py b/JSON/src/jsonc_prettify.py
new file mode 100755
index 00000000000..88dd3aeafb9
--- /dev/null
+++ b/JSON/src/jsonc_prettify.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# This file is being maintained at:
+# https://github.com/sublimehq/Packages/blob/master/JSON/src/jsonc_prettify.py
+
+
+import sublime
+import sublime_plugin
+
+import json
+from typing import (
+ Any
+)
+
+
+PKG_NAME: str = __package__.split('.')[0]
+base_scope: str = 'source.json.jsonc'
+
+
+def status_msg(msg: str = '') -> None:
+ if msg == '': return
+ sublime.status_message(f'{PKG_NAME}: {msg}')
+
+
+def print_msg(msg_header: str = '', msg_body: str = '') -> None:
+ if msg_body == '': return
+ print(f'JSONC: {msg_header}:\n\n{msg_body}\n\n')
+
+
+def json2py(view: sublime.View) -> Any:
+ old_contents: str = view.substr(
+ x=whole_view(view)
+ )
+ return sublime.decode_value(
+ data=old_contents
+ )
+
+
+def whole_view(view: sublime.View) -> sublime.Region:
+ return sublime.Region(
+ a=0,
+ b=view.size()
+ )
+
+
+def is_jsonc(view: sublime.View) -> bool:
+ return view.match_selector(
+ pt=0,
+ selector=base_scope
+ )
+
+
+class JsoncPrettify(sublime_plugin.TextCommand):
+
+ def run(self, edit_token: sublime.Edit, auto: bool = False) -> None:
+ """
+ Attempt to prettify the current view's JSONC contents. Print errors to
+ the console when it fails.
+ """
+
+ try:
+ if not auto and not sublime.ok_cancel_dialog(
+ msg='Prettifying JSONC will remove included comments and trailing commas.',
+ ok_title='Continue',
+ title='JSONC: Prettify' # only shown on Windows
+ ):
+ return
+ json_as_python = json2py(self.view)
+ self.view.replace(
+ edit_token,
+ r=whole_view(self.view),
+ text=json.dumps( # https://docs.python.org/3.8/library/json.html#json.dumps
+ obj=json_as_python,
+ allow_nan=False,
+ indent=4,
+ sort_keys=True
+ )
+ )
+ status_msg('Prettified.')
+ except Exception as e:
+ print_msg(msg_header='Conversion failed due to error', msg_body=f'{e}')
+ status_msg('Prettifying failed. See console for details.')
+ pass
+
+ def is_enabled(self) -> bool:
+ return is_jsonc(self.view)
+
+ def is_visible(self) -> bool:
+ return is_jsonc(self.view)
+
+ def description(self) -> str:
+ return 'Prettify JSONC'
+
+
+class JsoncMinify(sublime_plugin.TextCommand):
+
+ def run(self, edit_token: sublime.Edit, auto: bool = False) -> None:
+ """
+ Attempt to minify the current view's JSONC contents. Print errors to
+ the console when it fails.
+ """
+
+ try:
+ if not auto and not sublime.ok_cancel_dialog(
+ msg='Minifying JSONC will remove included comments and trailing commas.',
+ ok_title='Continue',
+ title='JSONC: Minify' # only shown on Windows
+ ):
+ return
+ json_as_python = json2py(self.view)
+ self.view.replace(
+ edit_token,
+ r=whole_view(self.view),
+ text=json.dumps( # https://docs.python.org/3.8/library/json.html#json.dumps
+ obj=json_as_python,
+ allow_nan=False,
+ indent=None,
+ separators=(',', ':'),
+ sort_keys=True
+ )
+ )
+ status_msg('Minified.')
+ except Exception as e:
+ print_msg(msg_header='Conversion failed due to error', msg_body=f'{e}')
+ status_msg('Minifying failed. See console for details.')
+ pass
+
+ def is_enabled(self) -> bool:
+ return is_jsonc(self.view)
+
+ def is_visible(self) -> bool:
+ return is_jsonc(self.view)
+
+ def description(self) -> str:
+ return 'Minify JSONC'
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.mapping.json b/JSON/tests/indentation/syntax_test_indentation.mapping.json
new file mode 100644
index 00000000000..cb36ba9613b
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.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.mapping.json5 b/JSON/tests/indentation/syntax_test_indentation.mapping.json5
new file mode 100644
index 00000000000..bd8da806f7c
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.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.mapping.jsonc b/JSON/tests/indentation/syntax_test_indentation.mapping.jsonc
new file mode 100644
index 00000000000..77dbaad820f
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.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.sequence.json b/JSON/tests/indentation/syntax_test_indentation.sequence.json
new file mode 100644
index 00000000000..6c7ba39e55a
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.json
@@ -0,0 +1,90 @@
+// 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.sequence.json5 b/JSON/tests/indentation/syntax_test_indentation.sequence.json5
new file mode 100644
index 00000000000..647e32e2a7d
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.json5
@@ -0,0 +1,90 @@
+// 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.sequence.jsonc b/JSON/tests/indentation/syntax_test_indentation.sequence.jsonc
new file mode 100644
index 00000000000..dfb2ce15980
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.jsonc
@@ -0,0 +1,90 @@
+// 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_symbols.json b/JSON/tests/symbols/syntax_test_symbols.json
new file mode 100644
index 00000000000..102c67dabb6
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.json
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+{
+ "key": "value",
+// ^^^^^ meta.toc-list.json
+// @@@@@ definition
+
+ "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_symbols.json5 b/JSON/tests/symbols/syntax_test_symbols.json5
new file mode 100644
index 00000000000..6946b6a96aa
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.json5
@@ -0,0 +1,37 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ _keyOne: "value",
+// ^^^^^^^ meta.toc-list.json5
+// @@@@@@@ definition
+
+ $keyTwo: "value",
+// ^^^^^^^ meta.toc-list.json5
+// @@@@@@@ definition
+
+ \u1234keyThree: "value",
+// ^^^^^^^^^^^^^^ meta.toc-list.json5
+// @@@@@@@@@@@@@@ definition
+
+ "key-four": "value",
+// ^^^^^^^^^^ meta.toc-list.json
+// @@@@@@@@@@ definition
+
+ 'key-five': 'value',
+// ^^^^^^^^^^ meta.toc-list.json5
+// @@@@@@@@@@ definition
+
+ "key-six": { "key-three-one": "value", "key-three-two": "value" },
+// ^^^^^^^^^ meta.toc-list.json
+// ^^^^^^^^^^^^^^^ - meta.toc-list.json
+// ^^^^^^^^^^^^^^^ - meta.toc-list.json
+// @@@@@@@@@ definition
+
+ 'key-seven': { '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_symbols.jsonc b/JSON/tests/symbols/syntax_test_symbols.jsonc
new file mode 100644
index 00000000000..1bbb9c71e97
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.jsonc
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "key": "value",
+// ^^^^^ meta.toc-list.json
+// @@@@@ definition
+
+ "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.comment.json b/JSON/tests/syntax/syntax_test_json.comment.json
new file mode 100644
index 00000000000..5465aeec8fc
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.comment.json
@@ -0,0 +1,10 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+// comment
+// <- invalid.illegal.comment - invalid.illegal.cooment invalid.illegal.comment
+ // <- invalid.illegal.comment - invalid.illegal.cooment invalid.illegal.comment
+//^^^^^^^^ invalid.illegal.comment - invalid.illegal.cooment invalid.illegal.comment
+
+"testing use of meta_content_scope vs meta_scope"
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..1b21ab889f0
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.leading_or_trailing_comma_in_mapping.json
@@ -0,0 +1,11 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json
+
+{
+ ,
+// ^ meta.mapping invalid.illegal.expected-mapping-key
+ "a": 1,
+ "b": { , "a": 1, "b": 2, },
+// ^ meta.mapping meta.mapping invalid.illegal.expected-mapping-key
+}
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_separator.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_separator.json
new file mode 100644
index 00000000000..aea2b898cd4
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_separator.json
@@ -0,0 +1,23 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+[
+ ,
+// ^^^ meta.sequence.list
+// ^ invalid.illegal.unexpected-separator
+
+ 1,,
+// ^^^^^ meta.sequence.list
+// ^ constant.numeric.value
+// ^ punctuation.separator.sequence
+// ^ invalid.illegal.unexpected-separator
+
+ [, 1,, 2,],
+// ^^^^^^^^^ meta.sequence.list meta.sequence.list
+// ^ invalid.illegal.unexpected-separator
+// ^ punctuation.separator.sequence
+// ^ invalid.illegal.unexpected-separator
+// ^ invalid.illegal.unexpected-separator
+// ^ invalid.illegal.unexpected-separator
+]
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_structure_or_value.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_structure_or_value.json
new file mode 100644
index 00000000000..d8637690c3b
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_structure_or_value.json
@@ -0,0 +1,10 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - source.json.jsonc
+
+ 5, 5
+// ^ invalid.illegal.unexpected-separator
+// ^ invalid.illegal.unexpected-code-after-first-structure-or-value
+
+ // comment
+// ^^^^^^^^^^ invalid.illegal.comment - invalid.illegal.unexpected-code-after-first-structure-or-value
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.json5 b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.json5
new file mode 100644
index 00000000000..57ff925bcba
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.json5
@@ -0,0 +1,57 @@
+// 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
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ '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.unexpected-digit-character
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ '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..d75c6004285
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.mapping.json5
@@ -0,0 +1,160 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+// <- meta.mapping punctuation.definition.mapping.begin
+
+ _identifierOne: null,
+// ^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^ meta.toc-list
+// ^^^^^^^^^^^^^^ meta.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ $identifierTwo: null,
+// ^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^ meta.toc-list
+// ^^^^^^^^^^^^^^ meta.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ \u1234abc: null,
+// ^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^ meta.toc-list
+// ^^^^^^^^^ meta.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ '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..95e9965c1e2
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.sequence.json5
@@ -0,0 +1,58 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ true,
+// ^^^^ constant.language.boolean
+
+ false,
+// ^^^^^ constant.language.boolean
+
+ null,
+// ^^^^ constant.language.null
+
+ 0,
+// ^ meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ string.quoted.double
+
+ 'value',
+// ^^^^^^^ string.quoted.single
+
+ [],
+// ^^ meta.sequence.list.empty
+
+ [ ],
+// ^^^ meta.sequence.list.empty
+
+ [1, 2, 3],
+// ^^^^^^^^^ meta.sequence.list
+// ^ punctuation.definition.sequence.begin
+// ^ constant.numeric.value
+// ^ punctuation.separator.sequence
+// ^ constant.numeric.value
+// ^ punctuation.separator.sequence
+// ^ constant.numeric.value
+// ^ punctuation.definition.sequence.end
+// ^ punctuation.separator.sequence
+ {},
+// ^^ meta.mapping.empty
+
+ { },
+// ^^^ meta.mapping.empty
+
+ { "a": 1, "b": 2, "c": 3 },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping
+
+ { 'a': 1, 'b': 2, 'c': 3 }
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping
+]
+// <- meta.sequence.list punctuation.definition.sequence.end
diff --git a/JSON/tests/syntax/syntax_test_json5.number.float.decimal.json5 b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.json5
new file mode 100644
index 00000000000..5fb934bd6ec
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.json5
@@ -0,0 +1,240 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////[ explicitly positive ]/////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "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
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////[ ieee 754 ]////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "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
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////[ leading period ]//////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-leading-period-followed-by-zero": .0,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "float-leading-period-followed-by-nonzero": .9,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-leading-period-followed-by-zero": -.0,
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-leading-period-followed-by-nonzero": -.9,
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^^ - invalid.illegal.meta-number-float-decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////[ trailing period ]/////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-trailing-period-lead-by-zero": 0.,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "float-trailing-period-lead-by-nonzero": 9.,
+// ^^ meta.number.float.decimal
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-trailing-period-lead-by-zero": -0.,
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^^ - invalid.illegal.meta-number-float-decimal
+
+ "negative-float-trailing-period-lead-by-nonzero": -9.
+// ^^^ meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+// ^^^ - 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..3a6942dfe43
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.string.json5
@@ -0,0 +1,65 @@
+// 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
+
+ 'line-continuation-single': 'line\
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single \
+// ^^^^^^ meta.mapping.value meta.string string.quoted.single \
+// ^ punctuation.separator.continuation.line \
+ continuation',
+// ^ meta.mapping.value meta.string string.quoted.single
+
+ "line-continuation-double": "line\
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double \
+// ^^^^^^ meta.mapping.value meta.string string.quoted.double \
+// ^ punctuation.separator.continuation.line \
+ continuation",
+// ^ meta.mapping.value meta.string string.quoted.double
+
+
+ '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 \
+ ',
+// ^ meta.mapping.value meta.string string.quoted.single
+
+ '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 \
+ '
+// ^ meta.mapping.value meta.string string.quoted.single
+}
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..e0300f61762
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.expected_lower_case_constant.jsonc
@@ -0,0 +1,18 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+[
+ Null,
+// ^^^^ invalid.illegal.expected-lower-case-null
+ NULL,
+// ^^^^ invalid.illegal.expected-lower-case-null
+ False,
+// ^^^^^ invalid.illegal.expected-lower-case-boolean
+ FALSE,
+// ^^^^^ invalid.illegal.expected-lower-case-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.numeric_sign.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.numeric_sign.jsonc
new file mode 100644
index 00000000000..c9cb8b64402
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.numeric_sign.jsonc
@@ -0,0 +1,172 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+
+ "explicitly-positive-zero": +0,
+// ^^ meta.mapping.value meta.number.integer.decimal
+// ^ invalid.illegal.numeric-sign
+// ^ constant.numeric.value
+
+ "explicitly-positive-integer": +9,
+// ^^ meta.mapping.value meta.number.integer.decimal
+// ^ invalid.illegal.numeric-sign
+// ^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-zero": +0.0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-zero-with-zero-exponent": +0.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-zero-exponent": +0.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-zero-exponent": +0e0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-zero-exponent": +0e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-zero-with-exponent": +0.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-with-negative-exponent": +0.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-zero-no-fraction-with-exponent": +0e9,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-zero-no-fraction-with-negative-exponent": +0e-9,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive": +9.0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-with-zero-exponent": +9.0e0,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-zero-exponent": +9.0e-0,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-no-fraction-with-zero-exponent": +9e0,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-zero-exponent": +9e-0,
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^ constant.numeric.value
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-with-exponent": +9.0e9,
+// ^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+ "float-explicitly-positive-with-negative-exponent": +9.0e-9,
+// ^^^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^^^ constant.numeric.value
+// ^ punctuation.separator.decimal
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ "float-explicitly-positive-no-fraction-with-exponent": +9e9,
+// ^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^ constant.numeric.value
+
+ "float-explicitly-positive-no-fraction-with-negative-exponent": +9e-9
+// ^^^^^ meta.number.float.decimal
+// ^ invalid.illegal.numeric-sign
+// ^^^^ constant.numeric.value
+}
diff --git a/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unclosed_string.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unclosed_string.jsonc
new file mode 100644
index 00000000000..1462439bb67
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unclosed_string.jsonc
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "unterminated string
+// ^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.toc-list meta.string string.quoted.double
+// ^ invalid.illegal.unclosed-string
+
+ /**/: "test"
+// ^ - string.quoted.double
+// ^^^^ meta.mapping comment.block
+// ^ punctuation.separator.mapping.key-value
+// ^^^^^^ meta.mapping.value meta.string string.quoted.double
+}
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.meta.mapping.jsonc b/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc
new file mode 100644
index 00000000000..81bec88d24f
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc
@@ -0,0 +1,109 @@
+// 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
+// ^ meta.mapping.value meta.sequence.list punctuation.separator.sequence
+ 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..cd677830f12
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.sequence.jsonc
@@ -0,0 +1,67 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ true,
+// ^^^^ constant.language.boolean
+
+ false,
+// ^^^^^ constant.language.boolean
+
+ null,
+// ^^^^ constant.language.null
+
+ 0,
+// ^ meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ string.quoted.double
+
+ [],
+// ^^ meta.sequence.list.empty
+
+ [ ],
+// ^^^ meta.sequence.list.empty
+
+ [1, 2
+// ^ meta.sequence.list punctuation.definition.sequence.begin
+// ^ meta.sequence.list
+ ,
+// ^ - invalid
+// ^ meta.sequence.list punctuation.separator.sequence
+ "three",
+// ^^^^^^^ string.quoted.double - meta.mapping.key
+// ^ punctuation.separator.sequence
+// ^ - invalid.illegal.unexpected-separator
+ ],
+// ^ meta.sequence.list punctuation.definition.sequence.end
+// ^ meta.sequence.list punctuation.separator.sequence
+
+ {},
+// ^^ meta.mapping.empty
+
+ { },
+// ^^^ meta.mapping.empty
+
+ { "a": 1, "b": 2
+// ^^^^^^^^^^^^^^^^ meta.mapping
+// ^ meta.mapping punctuation.separator.mapping.key-value
+// ^ meta.mapping punctuation.separator.mapping.pair
+ ,
+// ^ - invalid
+// ^ meta.mapping punctuation.separator.mapping.pair
+ "c": 3
+ }
+
+ ,
+// ^ punctuation.separator.sequence
+// ^ - invalid.illegal.unexpected-separator
+]
+// <- 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/Markdown/Markdown.sublime-syntax b/Markdown/Markdown.sublime-syntax
index c573f3cbe68..9610eba3494 100644
--- a/Markdown/Markdown.sublime-syntax
+++ b/Markdown/Markdown.sublime-syntax
@@ -1216,7 +1216,12 @@ contexts:
- include: fenced-html
- include: fenced-java
- include: fenced-javascript
+
+ # don't match json before json5 or jsonc
+ - include: fenced-json5
- include: fenced-jsonc
+ - include: fenced-json
+
- include: fenced-jspx
- include: fenced-jsx
- include: fenced-lisp
@@ -1461,23 +1466,57 @@ 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
2: punctuation.definition.raw.code-fence.begin.markdown
5: constant.other.language-name.markdown
embed: scope:source.json
- embed_scope: markup.raw.code-fence.json.markdown-gfm
+ embed_scope: markup.raw.code-fence.json.markdown-gfm source.json
escape: '{{code_fence_escape}}'
escape_captures:
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 source.json.json5
+ 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 source.json.jsonc
+ 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.fenced_code_json.md b/Markdown/syntax_test_markdown.fenced_code_json.md
new file mode 100644
index 00000000000..aaf77d99928
--- /dev/null
+++ b/Markdown/syntax_test_markdown.fenced_code_json.md
@@ -0,0 +1,30 @@
+// SYNTAX TEST "Packages/Markdown/Markdown.sublime-syntax"
+
+
+```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 */" }
+```
diff --git a/Perl/Perl.sublime-syntax b/Perl/Perl.sublime-syntax
index 6ad29675b84..782154d26c0 100644
--- a/Perl/Perl.sublime-syntax
+++ b/Perl/Perl.sublime-syntax
@@ -251,12 +251,27 @@ contexts:
embed: scope:source.js
embed_scope: source.js.embedded.perl
escape: (?=^{{pod}})
+
+ # don't match json before json5 and jsonc
+ # embedded json5
+ - match: \bjson5\b
+ scope: constant.other.language-name.json5.perl
+ embed: scope:source.json.json5
+ embed_scope: source.json5.embedded.perl source.json.json5
+ escape: (?=^{{pod}})
+ # embedded jsonc
+ - match: \bjsonc\b
+ scope: constant.other.language-name.jsonc.perl
+ embed: scope:source.json.jsonc
+ embed_scope: source.jsonc.embedded.perl source.json.jsonc
+ escape: (?=^{{pod}})
# embedded json
- match: \bjson\b
scope: constant.other.language-name.json.perl
embed: scope:source.json
- embed_scope: source.json.embedded.perl
+ embed_scope: source.json.embedded.perl source.json
escape: (?=^{{pod}})
+
# embedded sql
- match: \bsql\b
scope: constant.other.language-name.sql.perl
@@ -928,6 +943,22 @@ contexts:
3: entity.name.tag.heredoc.js.perl
4: punctuation.definition.tag.end.perl
set: [string-heredoc-javascript, string-heredoc-expr]
+ # embedded json5
+ - match: \s*((['"]?)(\s*JSON5)(\2))
+ captures:
+ 1: meta.tag.heredoc.perl
+ 2: punctuation.definition.tag.begin.perl
+ 3: entity.name.tag.heredoc.json5.perl
+ 4: punctuation.definition.tag.end.perl
+ set: [string-heredoc-json5, string-heredoc-expr]
+ # embedded jsonc
+ - match: \s*((['"]?)(\s*JSONC)(\2))
+ captures:
+ 1: meta.tag.heredoc.perl
+ 2: punctuation.definition.tag.begin.perl
+ 3: entity.name.tag.heredoc.jsonc.perl
+ 4: punctuation.definition.tag.end.perl
+ set: [string-heredoc-jsonc, string-heredoc-expr]
# embedded json
- match: \s*((['"]?)(\s*JSON)(\2))
captures:
@@ -1011,6 +1042,24 @@ contexts:
embed: scope:source.js
escape: (?=^ *JAVASCRIPT$)
+ string-heredoc-json5:
+ - meta_content_scope: source.json5.embedded.perl
+ - match: ^\3$
+ scope: meta.tag.heredoc.perl entity.name.tag.heredoc.json5.perl
+ pop: true
+ - match: ''
+ embed: scope:source.json.json5
+ escape: (?=^ *JSON5$)
+
+ string-heredoc-jsonc:
+ - meta_content_scope: source.jsonc.embedded.perl
+ - match: ^\3$
+ scope: meta.tag.heredoc.perl entity.name.tag.heredoc.jsonc.perl
+ pop: true
+ - match: ''
+ embed: scope:source.json.jsonc
+ escape: (?=^ *JSONC$)
+
string-heredoc-json:
- meta_content_scope: source.json.embedded.perl
- match: ^\3$
diff --git a/Perl/syntax_test_perl.embedded_json.pl b/Perl/syntax_test_perl.embedded_json.pl
new file mode 100644
index 00000000000..c7e60ff1648
--- /dev/null
+++ b/Perl/syntax_test_perl.embedded_json.pl
@@ -0,0 +1,25 @@
+// SYNTAX TEST "Packages/Perl/Perl.sublime-syntax"
+
+###[ POD TESTS ] #############################################################
+
+=pod
+
+=begin json
+// <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+ // <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+//^^^^ entity.name.tag.pod.perl
+//^^^^^^^^^ meta.comment.perl meta.interpolation.perl
+// ^ - constant - entity
+// ^^^^ constant.other.language-name.json.perl
+ {
+//^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
+ "key": "value"
+// ^^^^^^^^^^^^^^^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
+ }
+//^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
+=end
+// <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+ // <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+//^^ meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+
+=cut
diff --git a/Perl/syntax_test_perl.pl b/Perl/syntax_test_perl.pl
index e8c68e09549..66d499464b7 100644
--- a/Perl/syntax_test_perl.pl
+++ b/Perl/syntax_test_perl.pl
@@ -112,22 +112,6 @@ =head1 B<--param>
# <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
#^^^ meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
-=begin json
-# <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
-#^^^^^^^^^^ meta.comment.perl meta.interpolation.perl
-#^^^^^ entity.name.tag.pod.perl
-# ^ - constant - entity
-# ^^^^ constant.other.language-name.json.perl
- {
-# ^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
- "key": "value",
-# ^^^^^^^^^^^^^^^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
- }
-# ^ meta.comment.perl meta.interpolation.perl source.json.embedded.perl source.json
-=end
-# <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
-#^^^ meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
-
=begin sql
# <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
#^^^^^^^^^^ meta.comment.perl meta.interpolation.perl