diff --git a/HTML/syntax_test_html.html b/HTML/syntax_test_html.html
index 9c1539aa100..2d2aedcd40e 100644
--- a/HTML/syntax_test_html.html
+++ b/HTML/syntax_test_html.html
@@ -127,23 +127,23 @@
diff --git a/JSON/.python-version b/JSON/.python-version
new file mode 100644
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 100644
index 00000000000..75aac0ef338
--- /dev/null
+++ b/JSON/Comments - JSON5.tmPreferences
@@ -0,0 +1,25 @@
+
+
+
+ scope
+ source.json.json5
+ settings
+
+ shellVariables
+
+
+ nameTM_COMMENT_START
+ value//
+
+
+ nameTM_COMMENT_START_2
+ value/*
+
+
+ nameTM_COMMENT_END_2
+ value*/
+
+
+
+
+
diff --git a/JSON/Comments - JSONC.tmPreferences b/JSON/Comments - JSONC.tmPreferences
new file mode 100644
index 00000000000..1ee8dd7e2af
--- /dev/null
+++ b/JSON/Comments - JSONC.tmPreferences
@@ -0,0 +1,25 @@
+
+
+
+ scope
+ source.json.jsonc
+ settings
+
+ shellVariables
+
+
+ nameTM_COMMENT_START
+ value//
+
+
+ nameTM_COMMENT_START_2
+ value/*
+
+
+ nameTM_COMMENT_END_2
+ value*/
+
+
+
+
+
diff --git a/JSON/Comments.tmPreferences b/JSON/Comments.tmPreferences
deleted file mode 100644
index d9695e9cf24..00000000000
--- a/JSON/Comments.tmPreferences
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- scope
- source.json
- settings
-
- shellVariables
-
-
- name
- TM_COMMENT_START
- value
- //
-
-
- name
- TM_COMMENT_START_2
- value
- /*
-
-
- name
- TM_COMMENT_END_2
- value
- */
-
-
-
-
-
diff --git a/JSON/Context.sublime-menu b/JSON/Context.sublime-menu
new file mode 100644
index 00000000000..c55090cced5
--- /dev/null
+++ b/JSON/Context.sublime-menu
@@ -0,0 +1,29 @@
+// Packages/JSON/Context.sublime-menu
+
+
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Context.sublime-menu
+
+
+[
+ // visible only with JSON syntax highlighting
+ {
+ "caption": "JSON: Minify",
+ "command": "json_minify"
+ },
+ {
+ "caption": "JSON: Prettify",
+ "command": "json_prettify"
+ },
+
+
+ // visible only with JSONC syntax highlighting
+ {
+ "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 100644
index 00000000000..c6a9be5e676
--- /dev/null
+++ b/JSON/Default.sublime-commands
@@ -0,0 +1,29 @@
+// Packages/JSON/Default.sublime-commands
+
+
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/Default.sublime-commands
+
+
+[
+ // visible only with JSON syntax highlighting
+ {
+ "caption": "JSON: Minify JSON",
+ "command": "json_minify"
+ },
+ {
+ "caption": "JSON: Prettify JSON",
+ "command": "json_prettify"
+ },
+
+
+ // visible only with JSONC syntax highlighting
+ {
+ "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..56ef9e4a4e7 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 }
- ]
- },
-
- // 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 }
- ]
- },
-
- // 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 }
- ]
- },
-
- // 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 }
- ]
- },
-
- // 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 }
- ]
- },
- { "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 }
- ]
- },
-]
\ No newline at end of file
+ // 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 }
+ ]
+ },
+
+ // 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 }
+ ]
+ },
+
+ // 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 }
+ ]
+ },
+
+ // 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 }
+ ]
+ },
+
+ // 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 }
+ ]
+ },
+ { "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 }
+ ]
+ },
+]
diff --git a/JSON/Fold.tmPreferences b/JSON/Fold.tmPreferences
deleted file mode 100644
index 09d2cbf5356..00000000000
--- a/JSON/Fold.tmPreferences
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- scope
- source.json
- settings
-
- indentationFoldingEnabled
-
- foldScopes
-
-
- begin
- punctuation.section.sequence.begin
- end
- punctuation.section.sequence.end
-
-
- begin
- punctuation.section.mapping.begin
- end
- punctuation.section.mapping.end
-
-
-
-
-
diff --git a/JSON/Folding Rules - JSON.tmPreferences b/JSON/Folding Rules - JSON.tmPreferences
new file mode 100644
index 00000000000..6fbb72cbbe6
--- /dev/null
+++ b/JSON/Folding Rules - JSON.tmPreferences
@@ -0,0 +1,27 @@
+
+
+
+ scope
+ source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+ settings
+
+ indentationFoldingEnabled
+
+ foldScopes
+
+
+ begin
+ punctuation.definition.mapping.begin
+ end
+ punctuation.definition.mapping.end
+
+
+ begin
+ punctuation.definition.sequence.begin
+ end
+ punctuation.definition.sequence.end
+
+
+
+
+
diff --git a/JSON/Folding Rules - JSON5.tmPreferences b/JSON/Folding Rules - JSON5.tmPreferences
new file mode 100644
index 00000000000..a77da66569c
--- /dev/null
+++ b/JSON/Folding Rules - JSON5.tmPreferences
@@ -0,0 +1,31 @@
+
+
+
+ scope
+ source.json.json5
+ settings
+
+ foldScopes
+
+
+ begin
+ punctuation.definition.comment.begin
+ end
+ punctuation.definition.comment.end
+
+
+ begin
+ punctuation.definition.mapping.begin
+ end
+ punctuation.definition.mapping.end
+
+
+ begin
+ punctuation.definition.sequence.begin
+ end
+ punctuation.definition.sequence.end
+
+
+
+
+
diff --git a/JSON/Folding Rules - JSONC.tmPreferences b/JSON/Folding Rules - JSONC.tmPreferences
new file mode 100644
index 00000000000..5c219270eeb
--- /dev/null
+++ b/JSON/Folding Rules - JSONC.tmPreferences
@@ -0,0 +1,31 @@
+
+
+
+ scope
+ source.json.jsonc
+ settings
+
+ foldScopes
+
+
+ begin
+ punctuation.definition.comment.begin
+ end
+ punctuation.definition.comment.end
+
+
+ begin
+ punctuation.definition.mapping.begin
+ end
+ punctuation.definition.mapping.end
+
+
+ begin
+ punctuation.definition.sequence.begin
+ end
+ punctuation.definition.sequence.end
+
+
+
+
+
diff --git a/JSON/Folding Rules - JSON_dotNET.tmPreferences b/JSON/Folding Rules - JSON_dotNET.tmPreferences
new file mode 100644
index 00000000000..6b1b4bd8892
--- /dev/null
+++ b/JSON/Folding Rules - JSON_dotNET.tmPreferences
@@ -0,0 +1,27 @@
+
+
+
+ scope
+ source.json.json-dotnet
+ settings
+
+ indentationFoldingEnabled
+
+ foldScopes
+
+
+ begin
+ punctuation.definition.mapping.begin
+ end
+ punctuation.definition.mapping.end
+
+
+ begin
+ punctuation.definition.sequence.begin
+ end
+ punctuation.definition.sequence.end
+
+
+
+
+
diff --git a/JSON/JSON.sublime-completions b/JSON/JSON.sublime-completions
new file mode 100644
index 00000000000..2bffbac3e4a
--- /dev/null
+++ b/JSON/JSON.sublime-completions
@@ -0,0 +1,27 @@
+{
+ "scope": "source.json",
+ "completions":
+ [
+ {
+ "trigger": "true",
+ "contents": "true",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "literal JSON constant"
+ },
+ {
+ "trigger": "false",
+ "contents": "false",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "literal JSON constant"
+ },
+ {
+ "trigger": "null",
+ "contents": "null",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "literal JSON constant"
+ }
+ ]
+}
diff --git a/JSON/JSON.sublime-settings b/JSON/JSON.sublime-settings
new file mode 100644
index 00000000000..40b58cd7ac7
--- /dev/null
+++ b/JSON/JSON.sublime-settings
@@ -0,0 +1,13 @@
+// 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
+
+
+{
+ "default_extension": "json",
+
+ // 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 9d1aa3aa281..239981a8d96 100644
--- a/JSON/JSON.sublime-syntax
+++ b/JSON/JSON.sublime-syntax
@@ -1,171 +1,534 @@
%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
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/
+
+hidden_file_extensions:
+ - .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
+
+ - .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
+ ^ \s* // .*? -\*- .*? \bjson\b .*? -\*- # editorconfig
)
+variables:
+ exponent: (?:[eE][-+]?\d+)
+ pos_integer_decimal: (?:0|[1-9]\d*)
+ html_entity: '&([a-zA-Z0-9]+|#\d+|#[Xx]\h+);'
+ email_domain: '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'
+ email_user: '[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+'
+
+########################################################################################################################
+
contexts:
prototype:
- include: comments
main:
- - include: value
+ - match: (?=\S)
+ push:
+ - invalid-remainder
+ - any-else-pop
- value:
- - include: constant
- - include: number
- - include: string
- - include: array
- - include: object
+####[ Helpers ]#########################################################################################################
- 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
+ any:
+ - include: structures
+ - include: values
+
+ any-else-pop:
+ - include: any
+ - include: else-pop
+
+ structures:
+ - include: objects
+ - include: arrays
+
+ values:
+ - include: constants
+ - include: numbers
+ - include: strings
+
+ invalid-remainder:
+ - match: '[,:]'
+ scope: invalid.illegal.unexpected-separator.json
+ - match: '[^,:\s]+'
+ scope: invalid.illegal.unexpected-code-after-first-structure-or-value.json
+
+####[ Prototypes ]######################################################################################################
+
+ else-pop:
+ - match: (?=\S)
+ pop: 1
+
+ eol-pop:
+ - match: '$\n?'
+ pop: 1
+
+####[ Comments ]########################################################################################################
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
+ - include: comment-line
+ - include: comment-block
+
+ comment-line:
+ - match: //
+ push: comment-line-content
+
+ comment-line-content:
+ - meta_include_prototype: false
+ - meta_scope: invalid.illegal.comment.json
+ - include: eol-pop
+
+ comment-block:
+ - match: /\*\*+/
+ scope: invalid.illegal.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
+ push: comment-block-content
+
+ comment-block-content:
+ - meta_include_prototype: false
+ - meta_scope: invalid.illegal.comment.json
+ - match: \*/
+ pop: 1
+
+####[ Constants ]#######################################################################################################
+
+ constants:
+ - include: valid-constants
+ - include: invalid-constants
- constant:
+ valid-constants:
+ - match: \b(?:null)\b
+ scope: constant.language.null.json
+ pop: 1
- match: \b(?:false|true)\b
scope: constant.language.boolean.json
- - match: \bnull\b
- scope: constant.language.null.json
+ pop: 1
- number:
- # handles integer and decimal numbers
- - match: (-?)((?:0|[1-9]\d*)(?:(?:(\.)\d+)(?:[eE][-+]?\d+)?|(?:[eE][-+]?\d+)))
+ invalid-constants:
+ # when erroneously containing upper case letters
+ - match: \b(?i:null)\b
+ scope: invalid.illegal.expected-lower-case-null.json
+ pop: 1
+ - match: \b(?i:false|true)\b
+ scope: invalid.illegal.expected-lower-case-boolean.json
+ pop: 1
+
+####[ Numbers ]#########################################################################################################
+
+ numbers:
+ - include: float
+ - include: integer
+
+ float:
+ - include: decimal-float
+
+ decimal-float:
+ - match: |-
+ (?x:
+ (?:(-)|(\+))?
+ (
+ {{pos_integer_decimal}}
+ (?:
+ (\.)\d+ {{exponent}}? # 1.1 1.1e1 1.1e-1 1.1e+1
+ | {{exponent}} # 1e1 1+e1 1-e1
+ )
+ )
+ )
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*)
+ 1: constant.numeric.sign.json
+ 2: invalid.illegal.numeric-sign.json
+ 3: constant.numeric.value.json
+ 4: punctuation.separator.decimal.json
+ pop: 1
+
+ integer:
+ - include: decimal-integer
+
+ decimal-integer:
+ - match: (?:(-)|(\+))?({{pos_integer_decimal}})
scope: meta.number.integer.decimal.json
captures:
- 1: keyword.operator.arithmetic.json
- 2: constant.numeric.value.json
+ 1: constant.numeric.sign.json
+ 2: invalid.illegal.numeric-sign.json
+ 3: constant.numeric.value.json
+ pop: 1
- 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.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.sequence.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:
+####[ Strings ]#########################################################################################################
+
+ strings:
+ - include: double-quoted-string
+
+ double-quoted-string:
- match: \"
scope: punctuation.definition.string.begin.json
- push: inside-string
+ set: double-quoted-string-content
- inside-string:
- - meta_scope: string.quoted.double.json
+ double-quoted-string-content:
- meta_include_prototype: false
+ - meta_scope: >-
+ meta.string.json
+ string.quoted.double.json
- match: \"
scope: punctuation.definition.string.end.json
pop: 1
- - include: string-escape
+ - include: double-quoted-string-escape-characters
+ - include: links
- match: \n
scope: invalid.illegal.unclosed-string.json
pop: 1
- string-escape:
+ links:
+ - include: autolink-email
+ - include: autolink-inet
+
+ autolink-email:
- 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
+ (?x:
+ (<)
+ (
+ (?:mailto(:))?
+ {{email_user}}
+ (@)
+ {{email_domain}}(?:\.{{email_domain}})*
)
+ (>)
)
- scope: constant.character.escape.json
+ scope: meta.link.email.json
+ captures:
+ 1: punctuation.definition.link.begin.json
+ 2: markup.underline.link.json
+ 3: punctuation.separator.path.json
+ 4: punctuation.separator.path.json
+ 5: punctuation.definition.link.end.json
+ - match: |-
+ (?x:
+ [\w.+-]+
+ (@)
+ [\w-]+(?:\.(?:(?![._-][\W])[\w_-])+)+(?![_-])
+ )
+ scope: >-
+ meta.link.email.json
+ markup.underline.link.json
+ captures:
+ 1: punctuation.separator.path.json
+
+ autolink-inet:
+ - match: <(?=[[:alpha:]][[:alnum:].+-]+:)
+ scope: punctuation.definition.link.begin.json
+ push:
+ - autolink-inet-angled-content
+ - link-url-scheme-separator
+ - match: (?:(?:https|http|ftp)(://)|www\.)[\w-]+
+ captures:
+ 1: punctuation.separator.path.json
+ push: autolink-inet-unquoted-content
+
+ autolink-inet-angled-content:
+ - meta_scope: meta.link.inet.json
+ - meta_content_scope: markup.underline.link.json
+ - match: \>
+ scope: punctuation.definition.link.end.json
+ pop: 1
+ - match: (?=\s)
+ pop: 1
+ - include: autolink-inet-common
+
+ autolink-inet-unquoted-content:
+ - meta_scope: >-
+ meta.link.inet.json
+ markup.underline.link.json
+ - match: (?=(?:\)|(?:{{html_entity}})*)[?!.,:*_~]*[\s<])
+ pop: 1
+ - include: autolink-inet-common
+
+ autolink-inet-group:
+ - match: \)
+ pop: 1
+ - match: (?=(?:{{html_entity}})*[?!.,:*_~]*[\s<])
+ pop: 1
+ - include: autolink-inet-common
+
+ autolink-inet-common:
+ - match: \(
+ push: autolink-inet-group
+ - match: '[/&?#]'
+ scope: punctuation.separator.path.json
+ - match: (%)\h{2}
+ scope: constant.character.escape.url.json
+ captures:
+ 1: punctuation.definition.escape.json
+
+ link-url-scheme-separator:
+ - match: ':/{,2}'
+ scope: punctuation.separator.path.json
+ pop: 1
+
+ double-quoted-string-escape-characters:
+ - match: (\\)\"
+ scope: constant.character.escape.double-quote.json # quotation mark
+ captures:
+ 1: punctuation.definition.escape.json
+ - include: string-escape-characters
+
+ string-escape-characters:
+ - include: valid-string-escape-characters
+ - include: invalid-string-escape-characters
+
+ valid-string-escape-characters:
+ - match: (\\)\\
+ scope: constant.character.escape.back-slash.json # reverse solidus
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)\/
+ scope: constant.character.escape.forward-slash.json # solidus
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)b
+ scope: constant.character.escape.backspace.json
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)f
+ scope: constant.character.escape.form-feed.json
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)n
+ scope: constant.character.escape.newline.json # linefeed
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)r
+ scope: constant.character.escape.carriage-return.json
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)t
+ scope: constant.character.escape.horizontal-tab.json
+ captures:
+ 1: punctuation.definition.escape.json
+ - match: (\\)u[0-9a-fA-F]{4}
+ scope: >-
+ constant.character.escape.unicode-symbol.basic-multilingual-plane.json
+ captures:
+ 1: punctuation.definition.escape.json
+
+ invalid-string-escape-characters:
- match: \\.
scope: invalid.illegal.unrecognized-string-escape.json
+
+####[ Sequences ]#######################################################################################################
+
+ arrays:
+ - match: \[
+ scope: punctuation.definition.sequence.begin.json
+ set:
+ - array-body
+ - array-item
+
+ array-body:
+ - meta_scope: meta.sequence.list.json
+ - match: \]
+ scope: punctuation.definition.sequence.end.json
+ pop: 1
+ - include: array-separators
+
+ array-separators:
+ - match: (?=,)
+ branch_point: array-separators
+ branch:
+ - valid-array-separator
+ - invalid-array-separator
+ - match: (?=\S)
+ push: array-item
+
+ valid-array-separator:
+ - match: ','
+ scope: punctuation.separator.sequence.json
+ set: array-expect-value
+
+ array-expect-value:
+ - match: (?=\])
+ fail: array-separators
+ - include: array-item
+
+ array-item:
+ - include: any
+ - include: invalid-array-separator
+
+ invalid-array-separator:
+ - match: ','
+ scope: invalid.illegal.unexpected-separator.json
+ - include: else-pop
+
+####[ Mappings ]########################################################################################################
+
+ # FIXME: leading separators
+ # FIXME: trailing commas
+
+ objects:
+ - match: \{
+ scope: punctuation.definition.mapping.begin.json
+ set: object-body
+
+ object-body:
+ - 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
+
+ mapping-key:
+ - match: \"
+ scope: punctuation.definition.string.begin.json
+ push: mapping-key-double-quoted
+
+ 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: double-quoted-string-content
+
+ mapping-separator:
+ - match: ':'
+ scope: punctuation.separator.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
+ - any-else-pop
+
+ mapping-value:
+ - clear_scopes: 1
+ - meta_scope: meta.mapping.value.json
+ - match: ','
+ scope: punctuation.separator.sequence.json
+ pop: 1
+ - match: \s*(?=\})
+ pop: 1
+ - match: \s(?!/[/*])(?=[^\s,])|[^\s,]
+ scope: invalid.illegal.expected-mapping-separator.json
+ pop: 1
diff --git a/JSON/JSON5.sublime-completions b/JSON/JSON5.sublime-completions
new file mode 100644
index 00000000000..6cfbd1d9c3d
--- /dev/null
+++ b/JSON/JSON5.sublime-completions
@@ -0,0 +1,48 @@
+{
+ "scope": "source.json.json5",
+ "completions":
+ [
+ {
+ "trigger": "Infinity",
+ "contents": "Infinity",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 positive infinity
literal constant \"Infinity\""
+ },
+ {
+ "trigger": "Infinity",
+ "contents": "+Infinity",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 positive infinity
literal constant \"Infinity\" with an optional plus as prefix"
+ },
+ {
+ "trigger": "Infinity",
+ "contents": "-Infinity",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 negative infinity
literal constant \"-Infinity\""
+ },
+ {
+ "trigger": "NaN",
+ "contents": "NaN",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 NaN
literal constant \"NaN\""
+ },
+ {
+ "trigger": "NaN",
+ "contents": "+NaN",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 NaN
literal constant \"NaN\" with an optional plus as prefix"
+ },
+ {
+ "trigger": "NaN",
+ "contents": "-NaN",
+ "annotation": "constant.language",
+ "kind": ["snippet", "s", "Snippet"],
+ "details": "JSON5 number
IEEE 754 NaN
literal constant \"NaN\" with an optional minus as prefix"
+ }
+ ]
+}
diff --git a/JSON/JSON5.sublime-settings b/JSON/JSON5.sublime-settings
new file mode 100644
index 00000000000..047cb2547ad
--- /dev/null
+++ b/JSON/JSON5.sublime-settings
@@ -0,0 +1,10 @@
+// Packages/JSON/JSON5.sublime-settings
+// Settings - Syntax Specific (Default)
+//
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/JSON5.sublime-settings
+
+
+{
+ "default_extension": "json5"
+}
diff --git a/JSON/JSON5.sublime-syntax b/JSON/JSON5.sublime-syntax
new file mode 100644
index 00000000000..ffe7c7a8c1f
--- /dev/null
+++ b/JSON/JSON5.sublime-syntax
@@ -0,0 +1,255 @@
+%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/
+
+hidden_file_extensions:
+ - .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:
+
+ # Boost documentation:
+ # https://www.boost.org/doc/libs/1_64_0/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html
+ # 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 ]#########################################################################################################
+
+ decimal-float:
+ - match: |-
+ (?x:
+ ([-+]?)
+ (
+ {{pos_integer_decimal}}
+ (?:
+ (\.)\d* {{exponent}}? # 1. 1.e1 1.e-1 1.e+1 1.1 1.1e1 1.1e-1 1.1e+1
+ | {{exponent}} # 1e1 1+e1 1-e1
+ )
+ | (\.)\d+ {{exponent}}? # .1 .1e1 .1e+1 .1e-1
+ )
+ )
+ 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
+ pop: 1
+ - match: ([-+]?)(Infinity)
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.language.infinity.json5
+ pop: 1
+ - match: ([-+]?)(NaN)
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.language.nan.json5
+ pop: 1
+
+ # when erroneously containing wrongly cased letters
+ - match: ([-+]?)(?i:(infinity))
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: invalid.illegal.expected-language-constant.json5
+ pop: 1
+ - match: ([-+]?)(?i:(nan))
+ scope: meta.number.float.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: invalid.illegal.expected-language-constant.json5
+ pop: 1
+
+ integer:
+ - meta_prepend: true
+ - include: hexadecimal-integer
+
+ decimal-integer:
+ - match: ([-+]?)({{pos_integer_decimal}})
+ scope: meta.number.integer.decimal.json5
+ captures:
+ 1: constant.numeric.sign.json5
+ 2: constant.numeric.value.json5
+ pop: 1
+
+ hexadecimal-integer:
+ - 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
+ pop: 1
+
+####[ Strings ]#########################################################################################################
+
+ strings:
+ - meta_append: true
+ - include: single-quoted-string
+
+ single-quoted-string:
+ - match: \'
+ scope: punctuation.definition.string.begin.json5
+ set: single-quoted-string-content
+
+ single-quoted-string-content:
+ - 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:
+ - match: \\\'
+ scope: constant.character.escape.single-quote.json5
+ - include: string-escape-characters
+
+ valid-string-escape-characters:
+ - meta_prepend: true
+ - 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
+ - match: ([^\\])(?:\x{2028}|\x{2029})
+ captures:
+ 1: invalid.illegal.expected-backslash-char.json5
+
+####[ Mappings ]########################################################################################################
+
+ mapping-key:
+ - meta_append: true
+ - match: \'
+ scope: punctuation.definition.string.begin.json5
+ push: mapping-key-single-quoted
+
+ # looking ahead at `identifier_start` would've been faster with possibly
+ # invalid matches, but we want to make sure we only match valid ecma
+ # `identifier_name`s as keys
+ - match: (?={{identifier_name}})
+ push: mapping-key-ecma
+
+ mapping-key-ecma:
+ - clear_scopes: 1
+ - meta_include_prototype: false
+ - meta_scope: >-
+ meta.mapping.key.json5
+ meta.string.json5
+ string.unquoted.plain.json5
+ - match: '{{identifier_break}}'
+ 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: single-quoted-string-content
diff --git a/JSON/JSONC.sublime-settings b/JSON/JSONC.sublime-settings
new file mode 100644
index 00000000000..9bd53bcb1f2
--- /dev/null
+++ b/JSON/JSONC.sublime-settings
@@ -0,0 +1,10 @@
+// Packages/JSON/JSONC.sublime-settings
+// Settings - Syntax Specific (Default)
+//
+// This file is being maintained at:
+// https://github.com/sublimehq/Packages/blob/master/JSON/JSONC.sublime-settings
+
+
+{
+ "default_extension": "jsonc"
+}
diff --git a/JSON/JSONC.sublime-syntax b/JSON/JSONC.sublime-syntax
new file mode 100644
index 00000000000..280dccc816a
--- /dev/null
+++ b/JSON/JSONC.sublime-syntax
@@ -0,0 +1,136 @@
+%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
+
+hidden_file_extensions:
+ - .ember-cli
+
+ - .esformatter
+ # esformatter: ECMAScript code formatter
+ # https://github.com/millermedeiros/esformatter
+
+ - .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
+
+ - .jsfmtrc
+ # jsfmt: For formatting, searching and re-writing JavaScript
+ # https://github.com/rdio/jsfmt#formatting
+
+ - .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 ]########################################################################################################
+
+ comment-line:
+ - match: //
+ scope: punctuation.definition.comment.jsonc
+ push: comment-line-content
+
+ comment-line-content:
+ - meta_include_prototype: false
+ - meta_scope: comment.line.double-slash.jsonc
+ - include: eol-pop
+
+ comment-block:
+ # empty block comments
+ - match: (/\*)\**(\*/)
+ scope: comment.block.empty.jsonc
+ captures:
+ 1: punctuation.definition.comment.begin.jsonc
+ 2: punctuation.definition.comment.end.jsonc
+ # normal block comments
+ - match: /\*
+ scope: punctuation.definition.comment.begin.jsonc
+ push: comment-block-content
+
+ comment-block-content:
+ - meta_include_prototype: false
+ - meta_scope: comment.block.jsonc
+ - include: comment-block-end
+
+ comment-block-end:
+ - match: \*/
+ scope: punctuation.definition.comment.end.jsonc
+ pop: 1
+
+####[ Sequences ]#######################################################################################################
+
+ array-separators:
+ - match: ','
+ scope: punctuation.separator.sequence.jsonc
+ push: array-item
diff --git a/JSON/JSON_dotNET.sublime-syntax b/JSON/JSON_dotNET.sublime-syntax
new file mode 100644
index 00000000000..cd20d59dbae
--- /dev/null
+++ b/JSON/JSON_dotNET.sublime-syntax
@@ -0,0 +1,106 @@
+%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_dotNET.sublime-syntax
+#
+# Date formatting:
+# https://www.iso.org/standard/70907.html (Basic rules)
+# https://www.iso.org/standard/70908.html (Extensions)
+# https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
+
+name: 'JSON .NET'
+scope: source.json.json-dotnet
+version: 2
+
+# https://www.sublimetext.com/docs/syntax.html#inheritance
+extends: Packages/JSON/JSON.sublime-syntax
+
+first_line_match: |-
+ (?xi:
+ ^ \s* // .*? -\*- .*? \bjson\.net\b .*? -\*- # editorconfig
+ )
+
+########################################################################################################################
+
+contexts:
+
+####[ Strings ]#########################################################################################################
+
+ strings:
+ - meta_prepend: true
+ - include: datetime-string
+
+ datetime-string:
+
+ # for date strings of json.Net v4.5+ with an ISO Date
+ # like "2000-01-01T00:00:00Z"
+ - match: |-
+ (?x:
+ (\")
+ (
+ \d{4} [-] \d{2} [-] \d{2}
+ [Tt]
+ \d{2} [:] \d{2} [:] \d{2}
+ (?:
+ Z | [-+] \d{1,2} (?: [:]\d{1,2})?
+ )?
+ )
+ (\")
+ )
+ scope: >-
+ meta.string.json-dotnet
+ string.quoted.double.datetime.json-dotnet
+ captures:
+ 1: punctuation.definition.string.begin.json-dotnet
+ 2: constant.other.timestamp.json-dotnet
+ 3: punctuation.definition.string.end.json-dotnet
+
+ # for date strings (of the old discontinued format) erroneously containing
+ # double escapes like "\/Date(1234)\/"
+ - match: |-
+ (?x:
+ (\")
+ (
+ (\\)
+ \/Date\(
+ \d+
+ \)
+ (\\)
+ \/
+ )
+ (\")
+ )
+ scope: >-
+ meta.string.json-dotnet
+ string.quoted.double.datetime.json-dotnet
+ captures:
+ 1: punctuation.definition.string.begin.json-dotnet
+ 2: constant.other.timestamp.json-dotnet
+ 3: invalid.illegal.double-escape.json-dotnet
+ 4: invalid.illegal.double-escape.json-dotnet
+ 5: punctuation.definition.string.end.json-dotnet
+
+ # the old discontinued format like "/Date(1234)/"
+ - match: |-
+ (?x:
+ (\")
+ (
+ \/Date\(
+ \d+
+ \)\/
+ )
+ (\")
+ )
+ scope: >-
+ meta.string.json-dotnet
+ string.quoted.double.datetime.json-dotnet
+ captures:
+ 1: punctuation.definition.string.begin.json-dotnet
+ 2: constant.other.timestamp.json-dotnet
+ 3: punctuation.definition.string.end.json-dotnet
diff --git a/JSON/Main.sublime-menu b/JSON/Main.sublime-menu
new file mode 100644
index 00000000000..fe6d5172c22
--- /dev/null
+++ b/JSON/Main.sublime-menu
@@ -0,0 +1,130 @@
+// 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",
+ "children":
+ [
+ {
+ "caption": "Minify",
+ "command": "json_minify"
+ },
+ {
+ "caption": "Prettify",
+ "command": "json_prettify"
+ },
+ { "caption": "-" },
+ {
+ "caption": "Automatically prettify before saving",
+ "command": "json_toggle_auto_prettify"
+ },
+ {
+ "caption": "Settings - Syntax Specific",
+ "command": "edit_settings",
+ "args":
+ {
+ "base_file": "${packages}/JSON/JSON.sublime-settings",
+ "default": "{\n\t$0\n}\n"
+ }
+ },
+ { "caption": "-" },
+ {
+ "caption": "Documentation: Specs",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://www.json.org/json-en.html"
+ }
+ },
+ {
+ "caption": "Documentation: RFC 7159",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://datatracker.ietf.org/doc/html/rfc7159"
+ }
+ },
+ {
+ "caption": "Documentation: ECMA 404",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://www.ecma-international.org/publications-and-standards/standards/ecma-404/"
+ }
+ }
+ ]
+ },
+ {
+ "caption": "JSONC (JSON with Comments)",
+ "children":
+ [
+ {
+ "caption": "Minify",
+ "command": "jsonc_minify"
+ },
+ {
+ "caption": "Prettify",
+ "command": "jsonc_prettify"
+ }
+ ]
+ },
+ {
+ "caption": "JSON5",
+ "children":
+ [
+ {
+ "caption": "Documentation: Specs",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://spec.json5.org/#summary-of-features"
+ }
+ }
+ ]
+ },
+ { "caption": "-" },
+ {
+ "caption": "Support",
+ "children":
+ [
+ {
+ "caption": "Changelog (Packages/JSON)",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://github.com/sublimehq/Packages/commits/master/JSON"
+ }
+ },
+ {
+ "caption": "Report a (JSON package) issue",
+ "command": "open_url",
+ "args":
+ {
+ "url": "https://github.com/sublimehq/Packages/issues"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/JSON/Symbol List.tmPreferences b/JSON/Symbol List.tmPreferences
new file mode 100644
index 00000000000..22c59c8cf92
--- /dev/null
+++ b/JSON/Symbol List.tmPreferences
@@ -0,0 +1,14 @@
+
+
+
+ scope
+ source.json meta.mapping.key - (meta.mapping.value meta.mapping.key | meta.sequence.list meta.mapping.key)
+ settings
+
+ showInSymbolList
+ 1
+ showInIndexedSymbolList
+ 1
+
+
+
diff --git a/JSON/main.py b/JSON/main.py
new file mode 100644
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 100644
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 100644
index 00000000000..87edd9af8e5
--- /dev/null
+++ b/JSON/src/json_prettify.py
@@ -0,0 +1,217 @@
+#!/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
+
+from __future__ import annotations
+import collections
+import decimal
+import json
+from typing import (
+ 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.json-dotnet | source.json.json5 | 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'JSON: {msg_header}:\n\n{msg_body}\n\n')
+
+
+def json2py(view: sublime.View) -> sublime.Value:
+ 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,
+ object_pairs_hook=collections.OrderedDict,
+ parse_float=decimal.Decimal
+ )
+ 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: sublime.Window = window
+
+ try:
+ if settings is None:
+ return
+ self._is_checked = settings.get(key=self._key, default=False)
+ 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
+
+
+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: sublime.Value = 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: sublime.Value = 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 100644
index 00000000000..40a4a3c5b3d
--- /dev/null
+++ b/JSON/src/jsonc_prettify.py
@@ -0,0 +1,140 @@
+#!/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
+
+from __future__ import annotations
+import json
+
+
+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) -> sublime.Value:
+ 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: sublime.Value = 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: sublime.Value = 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 ae0760eb3fb..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.sequence.json
-//^ invalid.illegal.expected-mapping-key.json
-
- "sep": {},
-// ^ punctuation.separator.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.sequence.json
- "foo": "bar"
- /* comment */
-// ^ - invalid
-// ^^^^^^^^^^^^^ comment.block.json
- },
-//^ punctuation.section.mapping.end.json
-// ^ punctuation.separator.sequence.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.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.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..3ee53e97659
--- /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.json-dotnet | source.json.json5 | source.json.jsonc)
+
+{
+ "a":
+ [
+ "a",
+ "b"
+ ],
+ "b":
+ [
+ {
+ "a": "a",
+ "b": "b"
+ },
+ {
+ "a": "a",
+ "b": "b"
+ }
+ ],
+ "c":
+ {
+ "a":
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ "b":
+ {
+ "a": "a",
+ "b": "b"
+ }
+ }
+}
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..195241b5aa4
--- /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",
+ "b",
+ "c"
+ ],
+ "b":
+ {
+ "a": "a",
+ "b": "b"
+ }
+ }
+}
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..ac262c92ceb
--- /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",
+ "b",
+ "c"
+ ],
+ "b":
+ {
+ "a": "a",
+ "b": "b"
+ }
+ }
+}
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..2f771ce94eb
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.json
@@ -0,0 +1,130 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {
+ "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..6ab4a36f9c9
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.json5
@@ -0,0 +1,154 @@
+// SYNTAX TEST reindent "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null,
+ Infinity,
+ +Infinity,
+ -Infinity,
+ NaN,
+ +NaN,
+ -NaN
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null,
+ Infinity,
+ +Infinity,
+ -Infinity,
+ NaN,
+ +NaN,
+ -NaN
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null,
+ Infinity,
+ +Infinity,
+ -Infinity,
+ NaN,
+ +NaN,
+ -NaN
+ ],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null,
+ Infinity,
+ +Infinity,
+ -Infinity,
+ NaN,
+ +NaN,
+ -NaN
+ ],
+ [
+ {
+ "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..54caa62f1fc
--- /dev/null
+++ b/JSON/tests/indentation/syntax_test_indentation.sequence.jsonc
@@ -0,0 +1,130 @@
+// SYNTAX TEST reindent "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+[
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ },
+ {
+ "a": "a",
+ "b": "b",
+ "c": "c"
+ }
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {"a": "a"},
+ {"b": "b"},
+ {"c": "c"}
+ ],
+ [
+ [
+ "a",
+ "b",
+ "c"
+ ],
+ [
+ 1,
+ 2,
+ 3
+ ],
+ [
+ 0.0,
+ 2.1,
+ -3.0
+ ],
+ [
+ true,
+ false,
+ null
+ ],
+ [
+ {
+ "a": "a"
+ },
+ {
+ "b": "b"
+ },
+ {
+ "c": "c"
+ }
+ ],
+ [
+ [0],
+ [0],
+ [0]
+ ]
+ ]
+ ]
+ ]
+]
diff --git a/JSON/tests/symbols/syntax_test_symbols.json5 b/JSON/tests/symbols/syntax_test_symbols.json5
new file mode 100644
index 00000000000..9e55303403b
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.json5
@@ -0,0 +1,67 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+ _keyOne: "value",
+// @@@@@@@ definition
+// ^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ $keyTwo: "value",
+// @@@@@@@ definition
+// ^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ \u1234keyThree: "value",
+// @@@@@@@@@@@@@@ definition
+// ^^^^^^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ "key-four": "value",
+// @@@@@@@@@@ definition
+// ^^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ 'key-five': 'value',
+// @@@@@@@@@@ definition
+// ^^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ "key-six":
+// @@@@@@@@@ definition
+// ^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+ {
+ _keySixOne: "value",
+// @@@@@@@@@@ none
+// ^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ $keySixTwo: "value",
+// @@@@@@@@@@ none
+// ^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ \u1234keySixThree: "value",
+// @@@@@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ "key-six-four": "value",
+// @@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ 'key-six-five': "value"
+// @@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ },
+
+ 'key-seven':
+// @@@@@@@@@@@ definition
+// ^^^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+ {
+ _keySevenOne: 'value',
+// @@@@@@@@@@@@ none
+// ^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ $keySevenTwo: 'value',
+// @@@@@@@@@@@@ none
+// ^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ \u1234keySevenThree: 'value',
+// @@@@@@@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ "key-seven-four": 'value',
+// @@@@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ 'key-seven-five': 'value'
+// @@@@@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+ }
+}
diff --git a/JSON/tests/symbols/syntax_test_symbols.jsonc b/JSON/tests/symbols/syntax_test_symbols.jsonc
new file mode 100644
index 00000000000..0408436f09f
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.jsonc
@@ -0,0 +1,17 @@
+// SYNTAX TEST "Packages/JSON/JSONC.sublime-syntax"
+
+// <- source.json.jsonc
+
+{
+ "key": "value",
+// @@@@@ definition
+// ^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ "key-two": { "key-two-one": "value", "key-two-two": "value" }
+// @@@@@@@@@ definition
+// ^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+}
diff --git a/JSON/tests/symbols/syntax_test_symbols.meta.mapping.json b/JSON/tests/symbols/syntax_test_symbols.meta.mapping.json
new file mode 100644
index 00000000000..713ca6b8828
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.meta.mapping.json
@@ -0,0 +1,17 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+{
+ "key": "value",
+// @@@@@ definition
+// ^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+
+ "key-two": { "key-two-one": "value", "key-two-two": "value" }
+// @@@@@@@@@ definition
+// ^^^^^^^^^ meta.mapping.key - meta.mapping.value meta.mapping.key
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.mapping.value meta.mapping.key
+}
diff --git a/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json b/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json
new file mode 100644
index 00000000000..70a5d414503
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json
@@ -0,0 +1,14 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+[
+ {
+ "key-one": "value",
+// @@@@@@@@@ none
+// ^^^^^^^^^ meta.sequence.list meta.mapping.key
+ "key-two": "value"
+// @@@@@@@@@ none
+// ^^^^^^^^^ meta.sequence.list meta.mapping.key
+ }
+]
diff --git a/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json5 b/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json5
new file mode 100644
index 00000000000..47053e6dac6
--- /dev/null
+++ b/JSON/tests/symbols/syntax_test_symbols.meta.sequence.json5
@@ -0,0 +1,22 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+[
+ {
+ "key-one-one": "value",
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.sequence.list meta.mapping.key
+ "key-one-two": "value"
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.sequence.list meta.mapping.key
+ },
+ {
+ 'key-two-one': 'value',
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.sequence.list meta.mapping.key
+ 'key-two-two': 'value'
+// @@@@@@@@@@@@@ none
+// ^^^^^^^^^^^^^ meta.sequence.list meta.mapping.key
+ }
+]
diff --git a/JSON/tests/syntax/syntax_test_json-dotnet.datetime_string.json-dotnet b/JSON/tests/syntax/syntax_test_json-dotnet.datetime_string.json-dotnet
new file mode 100644
index 00000000000..c88cf43dcec
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json-dotnet.datetime_string.json-dotnet
@@ -0,0 +1,25 @@
+// SYNTAX TEST "Packages/JSON/JSON_dotNET.sublime-syntax"
+
+// <- source.json.json-dotnet
+
+{
+ "key-one": "2000-01-01T00:00:00Z",
+// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.json-dotnet string.quoted.double.datetime.json-dotnet
+// ^ punctuation.definition.string.begin.json-dotnet
+// ^^^^^^^^^^^^^^^^^^^^ constant.other.timestamp.json-dotnet
+// ^ punctuation.definition.string.end.json-dotnet
+
+ "key-two": "/Date(1234)/",
+// ^^^^^^^^^^^^^^ meta.string.json-dotnet string.quoted.double.datetime.json-dotnet
+// ^ punctuation.definition.string.begin.json-dotnet
+// ^^^^^^^^^^^^ constant.other.timestamp.json-dotnet
+// ^ punctuation.definition.string.end.json-dotnet
+
+ "key-three": "\/Date(1234)\/"
+// ^^^^^^^^^^^^^^ meta.string.json-dotnet string.quoted.double.datetime.json-dotnet
+// ^ punctuation.definition.string.begin.json-dotnet
+// ^^^^^^^^^^^^^^ constant.other.timestamp.json-dotnet
+// ^ invalid.illegal.double-escape.json-dotnet
+// ^ invalid.illegal.double-escape.json-dotnet
+// ^ punctuation.definition.string.end.json-dotnet
+}
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..b25e8fc92b2
--- /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.json-dotnet | source.json.json5 | source.json.jsonc)
+
+// comment
+// <- invalid.illegal.comment - invalid.illegal.comment invalid.illegal.comment
+ // <- invalid.illegal.comment - invalid.illegal.comment invalid.illegal.comment
+//^^^^^^^^ invalid.illegal.comment - invalid.illegal.comment invalid.illegal.comment
+
+"testing use of meta_content_scope vs meta_scope"
diff --git a/JSON/tests/syntax/syntax_test_json.constant.json b/JSON/tests/syntax/syntax_test_json.constant.json
new file mode 100644
index 00000000000..0dfdfe6f9ce
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.constant.json
@@ -0,0 +1,15 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+[
+ false,
+// ^^^^^ constant.language.boolean
+
+ true,
+// ^^^^ constant.language.boolean
+
+ null
+// ^^^^ constant.language.null
+// ^^^^ - constant.language.empty
+]
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_lower_case_constant.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_lower_case_constant.json
new file mode 100644
index 00000000000..5b911e8fa8b
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.expected_lower_case_constant.json
@@ -0,0 +1,18 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | 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_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..f58d467e120
--- /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 - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+{
+ ,
+// ^ 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.numeric_sign.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.numeric_sign.json
new file mode 100644
index 00000000000..c4d4747c7e9
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.illegal.numeric_sign.json
@@ -0,0 +1,172 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | 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_json.invalid.illegal.unexpected_separator.json b/JSON/tests/syntax/syntax_test_json.invalid.illegal.unexpected_separator.json
new file mode 100644
index 00000000000..baebc78cd24
--- /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.json-dotnet | source.json.json5 | 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..372befae0b8
--- /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.json-dotnet | source.json.json5 | 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_json.invalid.toplevel-arrays.json b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-arrays.json
new file mode 100644
index 00000000000..81924c8c988
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-arrays.json
@@ -0,0 +1,10 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+[ ][ ]
+// <- meta.sequence.list.json punctuation.definition.sequence.begin.json
+ // <- meta.sequence.list.json
+//^ meta.sequence.list.json punctuation.definition.sequence.end.json
+// ^ invalid.illegal.unexpected-code-after-first-structure-or-value.json
+// ^ invalid.illegal.unexpected-code-after-first-structure-or-value.json
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.toplevel-objects.json b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-objects.json
new file mode 100644
index 00000000000..a3a83f5eb51
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-objects.json
@@ -0,0 +1,10 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+{ }{ }
+// <- meta.mapping.json punctuation.definition.mapping.begin.json
+ // <- meta.mapping.json
+//^ meta.mapping.json punctuation.definition.mapping.end.json
+// ^ invalid.illegal.unexpected-code-after-first-structure-or-value.json
+// ^ invalid.illegal.unexpected-code-after-first-structure-or-value.json
diff --git a/JSON/tests/syntax/syntax_test_json.invalid.toplevel-strings.json b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-strings.json
new file mode 100644
index 00000000000..68d238018fc
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.invalid.toplevel-strings.json
@@ -0,0 +1,10 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+"string""string"
+// <- meta.string.json string.quoted.double.json punctuation.definition.string.begin.json
+ // <- meta.string.json string.quoted.double.json
+//^^^^^^ meta.string.json string.quoted.double.json
+// ^ meta.string.json string.quoted.double.json punctuation.definition.string.end.json
+// ^^^^^^^^ invalid.illegal.unexpected-code-after-first-structure-or-value.json
diff --git a/JSON/tests/syntax/syntax_test_json.meta.link.email.json b/JSON/tests/syntax/syntax_test_json.meta.link.email.json
new file mode 100644
index 00000000000..0549eaa73d8
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.meta.link.email.json
@@ -0,0 +1,26 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+
+{
+ "email-one": "Firstname Lastname test@test.com",
+// ^^^^^^^^^^^^^ meta.link.email markup.underline.link
+ "email-two": "Firstname Lastname test+test@test.com",
+// ^^^^^^^^^^^^^^^^^^ meta.link.email markup.underline.link
+ "email-three": "Firstname Lastname ",
+// ^^^^^^^^^^^^^^^ meta.link.email
+// ^^^^^^^^^^^^^ markup.underline.link
+ "email-four": "Firstname Lastname ",
+// ^^^^^^^^^^^^^^^^^^^^ meta.link.email
+// ^^^^^^^^^^^^^^^^^^ markup.underline.link
+ "email-five": "Firstname Lastname ",
+// ^^^^^^^^^^^^^^^^^^^^^^ meta.link.email
+// ^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+ "email-six": "Firstname Lastname ",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.email
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+ "email-seven": "Firstname Lastname "
+// ^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.email
+// ^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+}
diff --git a/JSON/tests/syntax/syntax_test_json.meta.link.inet.json b/JSON/tests/syntax/syntax_test_json.meta.link.inet.json
new file mode 100644
index 00000000000..e350ae9d155
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.meta.link.inet.json
@@ -0,0 +1,43 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+
+{
+ "link-https": "",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+ "link-http": "",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+ "link-www": "www.sublimetext.com",
+// ^^^^^^^^^^^^^^^^^^^ meta.link.inet markup.underline.link
+ "link-ftp": "",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+ "link-irc": "",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+// ^ punctuation.separator.path
+ "link-abcd": "",
+// ^^^^^^^^^ meta.link.inet
+// ^^^^^^^ markup.underline.link
+ "link-made-up": "",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+ "link-http-empty": "",
+// ^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^ markup.underline.link
+// ^^^ punctuation.separator.path
+// ^ punctuation.separator.path
+ "link-localhost": ""
+// ^^^^^^^^^^^^^^^^^^^^ meta.link.inet
+// ^^^^^^^^^^^^^^^^^^ markup.underline.link
+// ^ punctuation.separator.path
+// ^ punctuation.separator.path
+}
diff --git a/JSON/tests/syntax/syntax_test_json.meta.sequence.json b/JSON/tests/syntax/syntax_test_json.meta.sequence.json
new file mode 100644
index 00000000000..924582990fb
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.meta.sequence.json
@@ -0,0 +1,55 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ true,
+// ^^^^ constant.language.boolean
+
+ false,
+// ^^^^^ constant.language.boolean
+
+ null,
+// ^^^^ constant.language.null
+// ^^^^ - constant.language.empty
+
+ 0,
+// ^ meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ string.quoted.double
+
+ [],
+// ^^ meta.sequence.list meta.sequence.list
+
+ [ ],
+// ^^^ meta.sequence.list meta.sequence.list
+
+ [1, 2, 3],
+// ^^^^^^^^^ meta.sequence.list 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
+
+ { },
+// ^^^ 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_json.number.json b/JSON/tests/syntax/syntax_test_json.number.json
new file mode 100644
index 00000000000..90d64dc6233
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.number.json
@@ -0,0 +1,251 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | 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_json.string.json b/JSON/tests/syntax/syntax_test_json.string.json
new file mode 100644
index 00000000000..080f3b5ade9
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json.string.json
@@ -0,0 +1,74 @@
+// SYNTAX TEST "Packages/JSON/JSON.sublime-syntax"
+
+// <- source.json - (source.json.json-dotnet | source.json.json5 | source.json.jsonc)
+
+[
+ "\"",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.double-quote
+// ^ punctuation.definition.escape
+
+ "\\",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.back-slash
+// ^ punctuation.definition.escape
+
+ "\/",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.forward-slash
+// ^ punctuation.definition.escape
+
+ "\b",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.backspace
+// ^ punctuation.definition.escape
+
+ "\f",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.form-feed
+// ^ punctuation.definition.escape
+
+ "\n",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.newline
+// ^ punctuation.definition.escape
+
+ "\r",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.carriage-return
+// ^ punctuation.definition.escape
+
+ "\t",
+// ^^^^ meta.string string.quoted.double
+// ^^ constant.character.escape.horizontal-tab
+// ^ punctuation.definition.escape
+
+ "\u1234",
+// ^^^^^^^^ meta.string string.quoted.double
+// ^^^^^^ constant.character.escape.unicode-symbol.basic-multilingual-plane
+// ^ punctuation.definition.escape
+
+ "\u12345",
+// ^^^^^^^^^ meta.string string.quoted.double
+// ^^^^^^ constant.character.escape.unicode-symbol.basic-multilingual-plane
+// ^ punctuation.definition.escape
+// ^ - constant.character.escape
+
+ "ke//y",
+// ^^^^^^^ meta.string string.quoted.double - comment
+
+ "ke// y",
+// ^^^^^^^^ meta.string string.quoted.double - comment
+
+ "ke/***/y",
+// ^^^^^^^^^^ meta.string string.quoted.double - comment
+
+ "ke/** */y",
+// ^^^^^^^^^^^ meta.string string.quoted.double - comment
+
+ "ke/**/y",
+// ^^^^^^^^^ meta.string string.quoted.double - comment
+
+ "ke/* */y"
+// ^^^^^^^^^^ meta.string string.quoted.double - comment
+]
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..91074b6bffa
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.comment.json5
@@ -0,0 +1,28 @@
+// 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
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^ - meta.string string.quoted.single
+// ^ - punctuation.definition.string.begin
+// ^ - punctuation.definition.string.end
+// ^^ comment.block punctuation.definition.comment.end
+
+ /* comment
+ 'not a string' */
+// ^^^^^^^^^^^^^^^^^ comment.block
+// ^^^^^^^^^^^^^^ - 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..4fd567182c8
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.invalid.illegal.json5
@@ -0,0 +1,77 @@
+// 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
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+ 'expected-language-constant-Infinity': -infinity,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^^^^^^ meta.mapping.value meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^^^^^^ invalid.illegal.expected-language-constant
+
+ 'expected-language-constant-NaN': -nan
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.single
+// ^^^^ meta.mapping.value meta.number.float.decimal
+// ^ constant.numeric.sign
+// ^^^ invalid.illegal.expected-language-constant
+}
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..16c1d8233a5
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.mapping.json5
@@ -0,0 +1,140 @@
+// 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.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+// ^ meta.mapping punctuation.separator.sequence
+
+ $identifierTwo: null,
+// ^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^^^^^^ meta.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ \u1234abc: null,
+// ^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^^^^^^^^^ meta.string string.unquoted.plain
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-constant': null,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^ meta.mapping.value
+// ^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-number': 0,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value
+// ^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-string': "value",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^^^^ meta.mapping.value
+// ^^^^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-string': 'value',
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^^^^ meta.mapping.value
+// ^^^^^^^ - meta.mapping meta.mapping.value
+
+ 'meta-mapping-value-sequence-empty': [],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.sequence.list
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ 'meta-mapping-value-sequence-empty-with-space': [ ],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.sequence.list
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ 'meta-mapping-value-sequence': [1, 2, 3],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.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.mapping punctuation.separator.key-value
+// ^^ meta.mapping.value meta.mapping
+// ^^ - meta.mapping meta.mapping.value
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ 'meta-mapping-value-mapping-empty-with-space': { },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^ meta.mapping.value meta.mapping
+// ^^^ - meta.mapping meta.mapping.value
+// ^ 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.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.begin
+// ^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping.key
+// ^ meta.mapping.value meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.separator.sequence
+// ^^^ meta.mapping.value meta.mapping.key
+// ^ meta.mapping.value meta.mapping punctuation.separator.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.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.begin
+// ^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping.key
+// ^ meta.mapping.value meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping.value
+// ^ meta.mapping.value meta.mapping punctuation.separator.sequence
+// ^^^ meta.mapping.value meta.mapping.key
+// ^ meta.mapping.value meta.mapping punctuation.separator.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.number.constant.language.json5 b/JSON/tests/syntax/syntax_test_json5.meta.number.constant.language.json5
new file mode 100644
index 00000000000..ab2f027e22f
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.number.constant.language.json5
@@ -0,0 +1,31 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+////[ 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
+}
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..6ddd2fdc6eb
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.meta.sequence.json5
@@ -0,0 +1,26 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+
+[
+// <- meta.sequence.list punctuation.definition.sequence.begin
+
+ 'value',
+// ^^^^^^^ string.quoted.single
+
+ ['a', 'b', 'c'],
+// ^^^^^^^^^^^^^^^ meta.sequence.list meta.sequence.list
+// ^ punctuation.definition.sequence.begin
+// ^^^ string.quoted.single
+// ^ punctuation.separator.sequence
+// ^^^ string.quoted.single
+// ^ punctuation.separator.sequence
+// ^^^ string.quoted.single
+// ^ punctuation.definition.sequence.end
+// ^ punctuation.separator.sequence
+
+ { '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..93112ed6c44
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.float.decimal.json5
@@ -0,0 +1,208 @@
+// 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
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////[ 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..ac09ff937cc
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_json5.number.integer.hexadecimal.json5
@@ -0,0 +1,70 @@
+// SYNTAX TEST "Packages/JSON/JSON5.sublime-syntax"
+
+// <- source.json.json5
+
+{
+////[ lower case hexadecimal ]//////////////////////////////////////////////////////////////////////////////////////////
+
+
+ "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 ]//////////////////////////////////////////////////////////////////////////////////////////
+
+
+ "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..099413438b2
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.comment.jsonc
@@ -0,0 +1,341 @@
+// 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
+// ^^ - punctuation.definition.comment.begin
+// ^^ - punctuation.definition.comment.end
+
+ // comment /**/
+// ^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^ - comment.block.empty
+// ^^^^ - comment.block
+// ^^ - punctuation.definition.comment.begin
+// ^^ - punctuation.definition.comment.end
+
+ // comment /***/
+// ^^^^^^^^^^^^^^^^^ comment.line.double-slash
+// ^^ comment.line.double-slash punctuation.definition.comment
+// ^^^^^ - comment.block.empty
+// ^^^^^ - 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.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ /***/
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ /* */
+// ^^^^^ comment.block
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+
+
+
+
+ /* 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 comment.block
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block comment.block punctuation.definition.comment.end
+
+ /* comment /**/
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^ comment.block
+// ^^^^ - comment.block comment.block.empty
+// ^^^^ - comment.block comment.block
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block comment.block.empty punctuation.definition.comment.end
+// ^^ - comment.block comment.block punctuation.definition.comment.end
+
+ /* comment /***/
+// ^^ comment.block punctuation.definition.comment.begin
+// ^^^^^^^^^^^^^^^ comment.block
+// ^^^^^ - comment.block comment.block.empty
+// ^^^^^ - comment.block comment.block
+// ^^ comment.block punctuation.definition.comment.end
+// ^^ - comment.block comment.block.empty 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 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-empty-block-comment-a": [ /**/ ],
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-sequence-with-empty-block-comment-b": [ /***/ ],
+// ^^^^^ comment.block.empty
+// ^^ 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-empty-block-comment-a": [ /**/ 1, /**/ 2 /**/ , 3 /**/ ],
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-sequence-with-empty-block-comment-b": [ /***/ 1, /***/ 2 /***/ , 3 /***/ ],
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ 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-empty-block-comment-a": { /**/ },
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "empty-mapping-with-empty-block-comment-b": { /***/ },
+// ^^^^^ 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-empty-block-comment-a": { /**/ "a": 1, /**/ "b" /**/ : /**/ 2 /**/ , "c": 3 /**/ },
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+
+ "full-mapping-with-empty-block-comment-b": { /***/ "a": 1, /***/ "b" /***/ : /***/ 2 /***/ , "c": 3 /***/ },
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ punctuation.definition.comment.begin
+// ^^ punctuation.definition.comment.end
+// ^^^^^ comment.block.empty
+// ^^ 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.invalid.illegal.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.jsonc
new file mode 100644
index 00000000000..0ee4b98e1af
--- /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.sequence
+// ^ 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.unclosed_string.jsonc b/JSON/tests/syntax/syntax_test_jsonc.invalid.illegal.unclosed_string.jsonc
new file mode 100644
index 00000000000..92306cc46d9
--- /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.string string.quoted.double
+// ^ invalid.illegal.unclosed-string
+
+ /**/: "test"
+// ^ - string.quoted.double
+// ^^^^ meta.mapping comment.block
+// ^ meta.mapping punctuation.separator.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..ec7b2b7299f
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.mapping.jsonc
@@ -0,0 +1,105 @@
+// 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.mapping punctuation.separator.key-value
+// ^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ meta.mapping punctuation.separator.sequence
+
+ "meta-mapping-value-number": 0,
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ meta.mapping punctuation.separator.sequence
+
+ "meta-mapping-value-string": "value",
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^^^^^ meta.mapping.value - meta.mapping.json meta.mapping.value
+// ^ meta.mapping punctuation.separator.sequence
+
+ "meta-mapping-value-sequence-empty": [],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.sequence.list
+// ^ punctuation.definition.sequence.begin
+// ^ punctuation.definition.sequence.end
+
+ "meta-mapping-value-sequence-empty-with-space": [ ],
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.sequence.list
+// ^ 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.mapping punctuation.separator.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
+// ^ meta.mapping punctuation.separator.sequence
+
+ "meta-mapping-value-mapping-empty": {},
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^ meta.mapping.value
+// ^^ - meta.mapping meta.mapping.value
+// ^^ meta.mapping.value meta.mapping
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+
+ "meta-mapping-value-mapping-empty-with-space": { },
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - meta.mapping meta.mapping.key
+// ^ meta.mapping punctuation.separator.key-value
+// ^^^ meta.mapping.value
+// ^^^ - meta.mapping meta.mapping.value
+// ^^^ meta.mapping.value meta.mapping
+// ^ punctuation.definition.mapping.begin
+// ^ punctuation.definition.mapping.end
+// ^ meta.mapping punctuation.separator.sequence
+
+ "meta-mapping-value-mapping": { "a": 1
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.mapping.key meta.string string.quoted.double - meta.mapping.json meta.mapping.key
+// ^ meta.mapping punctuation.separator.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.mapping.value meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping.value
+ ,
+// ^ - invalid
+// ^ meta.mapping.value meta.mapping punctuation.separator.sequence
+ "b": 2
+// ^^^ meta.mapping.value meta.mapping.key
+// ^ meta.mapping.value meta.mapping punctuation.separator.key-value
+// ^ meta.mapping.value meta.mapping.value
+
+ ,
+// ^ meta.mapping.value punctuation.separator.sequence
+ }
+// ^ meta.mapping.value meta.mapping punctuation.definition.mapping.end
+
+ ,
+// ^ meta.mapping punctuation.separator.sequence
+}
+// <- 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..c7ad238d7c1
--- /dev/null
+++ b/JSON/tests/syntax/syntax_test_jsonc.meta.sequence.jsonc
@@ -0,0 +1,71 @@
+// 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
+// ^^^^ - constant.language.empty
+
+ 0,
+// ^ meta.number.integer.decimal constant.numeric.value
+
+ 0.0,
+// ^^^ meta.number.float.decimal constant.numeric.value
+
+ "value",
+// ^^^^^^^ string.quoted.double
+
+ [],
+// ^^ meta.sequence.list
+
+ [ ],
+// ^^^ meta.sequence.list
+
+ [1, 2
+// ^ meta.sequence.list punctuation.definition.sequence.begin
+// ^ meta.sequence.list meta.sequence.list punctuation.separator.sequence
+ ,
+// ^ - 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.sequence.list meta.mapping
+
+ { },
+// ^^^ meta.sequence.list meta.mapping
+
+ { "a": 1, "b": 2
+// ^^^^^^^^^^^^^^^^ meta.sequence.list meta.mapping
+// ^ meta.mapping punctuation.separator.key-value
+// ^ meta.mapping punctuation.separator.sequence
+ ,
+// ^ - invalid
+// ^ meta.mapping punctuation.separator.sequence
+ "c": 3
+
+ ,
+// ^ meta.mapping punctuation.separator.sequence
+ }
+
+ ,
+// ^ meta.sequence.list punctuation.separator.sequence
+// ^ - invalid.illegal.unexpected-separator
+]
+// <- meta.sequence.list punctuation.definition.sequence.end
diff --git a/Markdown/Markdown.sublime-syntax b/Markdown/Markdown.sublime-syntax
index 64ee99ad7b7..fd47d68c828 100644
--- a/Markdown/Markdown.sublime-syntax
+++ b/Markdown/Markdown.sublime-syntax
@@ -910,7 +910,9 @@ contexts:
- include: fenced-html
- include: fenced-java
- include: fenced-javascript
+ - include: fenced-json5
- include: fenced-jsonc
+ - include: fenced-json
- include: fenced-jspx
- include: fenced-jsx
- include: fenced-lisp
@@ -1258,11 +1260,49 @@ contexts:
0: meta.code-fence.definition.end.javascript.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: '{{fenced_code_block_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?))
+ ((?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: '{{fenced_code_block_escape}}'
+ escape_captures:
+ 0: meta.code-fence.definition.end.jsonc.markdown-gfm
+ 1: punctuation.definition.raw.code-fence.end.markdown
+
+ fenced-json:
+ - match: |-
+ (?x)
+ {{fenced_code_block_start}}
+ ((?i:json))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.json.markdown-gfm
diff --git a/Markdown/tests/syntax_test_markdown.md b/Markdown/tests/syntax_test_markdown.md
index d7e6ec89173..d9f6b9b9b52 100644
--- a/Markdown/tests/syntax_test_markdown.md
+++ b/Markdown/tests/syntax_test_markdown.md
@@ -1862,6 +1862,27 @@ for (var i = 0; i < 10; i++) {
| <- meta.code-fence.definition.end.jsx.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
|^^ meta.code-fence.definition.end.jsx.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+```json5
+
+| <- markup.raw.code-fence.json5.markdown-gfm
+```
+| <- meta.code-fence.definition.end.json5.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+|^^ meta.code-fence.definition.end.json5.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+
+```jsonc
+
+| <- markup.raw.code-fence.jsonc.markdown-gfm
+```
+| <- meta.code-fence.definition.end.jsonc.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+|^^ meta.code-fence.definition.end.jsonc.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+
+```json
+
+| <- markup.raw.code-fence.json.markdown-gfm
+```
+| <- meta.code-fence.definition.end.json.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+|^^ meta.code-fence.definition.end.json.markdown-gfm punctuation.definition.raw.code-fence.end.markdown
+
```lisp
| <- markup.raw.code-fence.lisp.markdown-gfm source.lisp
diff --git a/Perl/Perl.sublime-syntax b/Perl/Perl.sublime-syntax
index 954cdeba3a4..c0fb678dab2 100644
--- a/Perl/Perl.sublime-syntax
+++ b/Perl/Perl.sublime-syntax
@@ -251,6 +251,18 @@ contexts:
embed: scope:source.js
embed_scope: source.js.embedded.perl
escape: (?=^{{pod}})
+ # embedded json5
+ - match: \bjson5\b
+ scope: constant.other.language-name.json5.perl
+ embed: scope:source.json.json5
+ embed_scope: source.json5.embedded.perl
+ 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
+ escape: (?=^{{pod}})
# embedded json
- match: \bjson\b
scope: constant.other.language-name.json.perl
@@ -930,6 +942,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:
@@ -1013,6 +1041,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.pl b/Perl/syntax_test_perl.pl
index ba96ed7b8b3..44ea4a7e016 100644
--- a/Perl/syntax_test_perl.pl
+++ b/Perl/syntax_test_perl.pl
@@ -112,18 +112,38 @@ =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 json5
+# <- 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.json5.perl
+
+# <- meta.comment.perl meta.interpolation.perl source.json5.embedded.perl source.json.json5
+=end
+# <- meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+#^^^ meta.comment.perl meta.interpolation.perl entity.name.tag.pod.perl
+
+=begin jsonc
+# <- 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.jsonc.perl
+
+# <- meta.comment.perl meta.interpolation.perl source.jsonc.embedded.perl source.json.jsonc
+=end
+# <- 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
+
+# <- 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