[gtksourceview: 1/6] javascript.lang: Rewrite using context / language parsing
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview: 1/6] javascript.lang: Rewrite using context / language parsing
- Date: Fri, 1 Nov 2019 03:36:05 +0000 (UTC)
commit 343aa3a91f64261d679bf338ffefb370d1af5177
Author: Jeffery To <jeffery to gmail com>
Date: Thu Oct 10 23:00:05 2019 +0800
javascript.lang: Rewrite using context / language parsing
data/language-specs/html.lang | 14 +-
data/language-specs/javascript-expressions.lang | 746 ++++++++++
.../javascript-functions-classes.lang | 484 +++++++
data/language-specs/javascript-literals.lang | 601 ++++++++
data/language-specs/javascript-modules.lang | 435 ++++++
data/language-specs/javascript-statements.lang | 923 ++++++++++++
data/language-specs/javascript-values.lang | 697 +++++++++
data/language-specs/javascript.lang | 1472 +++++++++-----------
data/language-specs/json.lang | 4 +-
data/styles/classic.xml | 3 +-
data/styles/kate.xml | 3 +-
data/styles/tango.xml | 3 +-
po/POTFILES.skip | 6 +
tests/syntax-highlighting/file.html | 6 +
tests/syntax-highlighting/file.js | 848 ++++++++++-
15 files changed, 5385 insertions(+), 860 deletions(-)
---
diff --git a/data/language-specs/html.lang b/data/language-specs/html.lang
index 30145c2a..5fa31275 100644
--- a/data/language-specs/html.lang
+++ b/data/language-specs/html.lang
@@ -330,13 +330,25 @@
<include>
<context sub-pattern="0" where="start" style-ref="tag"/>
<context sub-pattern="0" where="end" style-ref="tag"/>
- <context ref="embedded-lang-hook"/>
<context ref="js:js"/>
</include>
</context>
</include>
</context>
+ <context id="js-embedded-lang-hooks">
+ <include>
+ <context end-parent="true">
+ <start>(?=</script(?:>|\s|$))</start>
+ <end>\%{def:always-match}</end>
+ </context>
+ <context ref="embedded-lang-hook"/>
+ <context ref="js:embedded-lang-hooks" original="true"/>
+ </include>
+ </context>
+
+ <replace id="js:embedded-lang-hooks" ref="js-embedded-lang-hooks"/>
+
<context id="tag" class="no-spell-check">
<start></?[a-z0-9_-]+</start>
<end>/?></end>
diff --git a/data/language-specs/javascript-expressions.lang b/data/language-specs/javascript-expressions.lang
new file mode 100644
index 00000000..5285196d
--- /dev/null
+++ b/data/language-specs/javascript-expressions.lang
@@ -0,0 +1,746 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-expr" name="JavaScript Expressions" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+ <!--
+ Expression / context structure:
+
+ left-hand side (lhs) expression: new Array ()
+ === ===== ==
+ / | \
+ pre-primary primary post-primary
+ expression expression expression
+
+ expression: - obj.count + 1
+ = ========= ===
+ / | \
+ pre-lhs lhs post-lhs
+ expression expression expression
+ -->
+
+
+ <!-- # Pre-primary expression -->
+
+ <context id="_pre-primary-expression">
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+
+ <!-- ES2017, cannot be followed by line terminator -->
+ <context id="_async-pre-primary-expression-keyword" style-ref="js:keyword">
+ <match extended="true">
+ \%[ async \%]
+ (?= # preceeds arrow function
+ \%{js:optional-whitespace-or-comments}
+ (?:
+ \%{js:identifier}
+ \%{js:optional-whitespace-or-comments}
+ => |
+ \( # can this be better?
+ )
+ )
+ (?! # does not preceed "function" (leave to function
expression)
+ \%{js:optional-whitespace-or-comments}
+ \%[ function \%]
+ )
+ </match>
+ </context> <!-- /_async-pre-primary-expression-keyword -->
+
+ <context id="_new-pre-primary-expression-keyword" style-ref="js:keyword">
+ <match extended="true">
+ \%[ new \%] (?! \%{js:new-target-object-keyword-suffix} )
+ </match>
+ </context> <!-- /_new-pre-primary-expression-keyword -->
+
+ </include>
+ </context> <!-- /_pre-primary-expression -->
+
+ <context id="_ordered-pre-primary-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_pre-primary-expression"/>
+ </include>
+ </context> <!-- /_ordered-pre-primary-expression -->
+
+
+ <!-- # Grouping / arrow function parameters
+
+ (2 + 3) * 4
+ (x, y) => x + y
+ (x, ...rest) => { return rest; }
+ -->
+
+ <!-- doing it this way, instead of using expression-with-comma,
+ will make later augmentation easier -->
+
+ <context id="_grouping-item-content">
+ <include>
+ <context ref="js:ordered-rest-syntax"/>
+ <context ref="expression-without-comma"/>
+ </include>
+ </context> <!-- /_grouping-item-content -->
+
+ <!-- <CoverParenthesizedExpressionAndArrowParameterList> -->
+ <context id="_choice-grouping" style-ref="js:grouping" end-parent="true">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:grouping-operator"/>
+ <context sub-pattern="0" where="end" style-ref="js:grouping-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_grouping-content">
+ <include>
+
+ <context id="_grouping-first-item" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_grouping-item-content"/>
+ </include>
+ </context> <!-- /_grouping-first-item -->
+
+ <context id="_grouping-items">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_grouping-item-content"/>
+ </include>
+ </context> <!-- /_grouping-items -->
+
+ </include>
+ </context> <!-- /_grouping-content -->
+
+ </include>
+ </context> <!-- /_choice-grouping -->
+
+
+ <!-- # Primary expression
+
+ this
+ Array
+ 'string'
+ 100
+ ( ... )
+ [ 1, 2, 3 ]
+ function () { ... }
+ /regex/
+ `template`
+ -->
+
+ <!-- <PrimaryExpression> -->
+ <context id="_primary-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_primary-expression-content">
+ <include>
+ <context ref="js-lit:choice-array-literal"/>
+ <context ref="js-lit:choice-object-literal"/>
+ <context ref="js-lit:choice-regular-expression-literal"/>
+ <context ref="js-lit:choice-template-literal"/>
+ <context ref="js-fn:choice-function-expression"/>
+ <context ref="js-fn:choice-class-expression"/>
+ <context ref="_choice-grouping"/>
+ <context ref="js-lit:choice-number"/>
+ <context ref="js-lit:choice-string"/>
+
+ <context id="_choice-primary-expression-identifier" end-parent="true">
+ <start>(?=\%{js:identifier-start})</start>
+ <end>\%{def:always-match}</end>
+ <include>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not extend the context by matching comments or
+ embedded-lang-hooks, which may lead to multiple identifiers -->
+
+ <context id="_primary-expression-identifier-content">
+ <include>
+ <!-- technically these would be choices, but it would be very
+ difficult to turn large keyword contexts into container
+ contexts with end-parent="true" -->
+ <context ref="js-lit:null-value"/>
+ <context ref="js-lit:boolean"/>
+ <context ref="js-val:global-values"/>
+ <context ref="js:identifier"/>
+ </include>
+ </context> <!-- /_primary-expression-identifier-content -->
+
+ </include>
+ </context> <!-- /_choice-primary-expression-identifier -->
+
+ </include>
+ </context> <!-- /_primary-expression-content -->
+
+ </include>
+ </context> <!-- /_primary-expression -->
+
+ <context id="_ordered-primary-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_primary-expression"/>
+ </include>
+ </context> <!-- /_ordered-primary-expression -->
+
+
+ <!-- # Function call
+ (in an expression, function arguments list after primary
+ value)
+
+ fn()
+ fn(a, b, ...list)
+ -->
+
+ <context id="_function-arguments-content">
+ <include>
+ <context ref="js:ordered-spread-syntax"/>
+ <context ref="expression-without-comma"/>
+ </include>
+ </context> <!-- /_function-arguments-content -->
+
+ <!-- <Arguments> -->
+ <context id="_function-arguments-lists">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_function-arguments-list-content">
+ <include>
+
+ <context id="_function-first-argument" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_function-arguments-content"/>
+ </include>
+ </context> <!-- /_function-first-argument -->
+
+ <context id="_function-arguments">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_function-arguments-content"/>
+ </include>
+ </context> <!-- /_function-arguments -->
+
+ </include>
+ </context> <!-- /_function-arguments-list-content -->
+
+ </include>
+ </context> <!-- /_function-arguments-lists -->
+
+
+ <!-- # Post-primary expression
+
+ obj.property
+ obj['property']
+ fn()
+ tag`template`
+ -->
+
+ <context id="_post-primary-expression">
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+
+ <!-- <MemberExpression> (part of) -->
+ <context id="_dot-property-accessors">
+ <start>\.(?!\.)</start> <!-- avoid matching rest/spread syntax -->
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_dot-property-accessor-content">
+ <include>
+ <context ref="js-val:properties-methods"/>
+ <context ref="js:identifier"/>
+ </include>
+ </context> <!-- /_dot-property-accessor-content -->
+
+ </include>
+ </context> <!-- /_dot-property-accessors -->
+
+ <!-- <MemberExpression> (part of) -->
+ <context id="_bracket-property-accessors">
+ <start>\[</start>
+ <end>]</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_bracket-property-accessor-content">
+ <include>
+ <context ref="expression-with-comma"/>
+ </include>
+ </context> <!-- /_bracket-property-accessor-content -->
+
+ </include>
+ </context> <!-- /_bracket-property-accessors -->
+
+ <context ref="_function-arguments-lists"/>
+ <context ref="js-lit:template-literals"/>
+ </include>
+ </context> <!-- /_post-primary-expression -->
+
+ <context id="_ordered-post-primary-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_post-primary-expression"/>
+ </include>
+ </context> <!-- /_ordered-post-primary-expression -->
+
+
+ <!-- # Increment / decrement operators -->
+
+ <!-- shared between pre- and post-lhs expressions -->
+ <context id="_increment-decrement-operators" style-ref="js:increment-decrement-operator">
+ <match>(\+\+|--)</match>
+ </context> <!-- /_increment-decrement-operators -->
+
+
+ <!-- # Pre-LHS expression -->
+
+ <context id="_pre-lhs-expression">
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="_increment-decrement-operators"/>
+
+ <context id="_keyword-unary-operators" style-ref="js:keyword">
+ <keyword>await</keyword> <!-- ES2017 -->
+ <keyword>delete</keyword>
+ <keyword>typeof</keyword>
+ <keyword>void</keyword>
+ <keyword>yield</keyword>
+ </context> <!-- /_keyword-unary-operators -->
+
+ <context ref="js:generator-modifier"/> <!-- for yield* -->
+
+ <context id="_unary-operators" style-ref="js:unary-operator">
+ <match extended="true">
+ (
+ \+ | # unary plus
+ - | # unary negation
+ ~ | # bitwise not
+ ! # logical not
+ )
+ </match>
+ </context> <!-- /_unary-operators -->
+
+ </include>
+ </context> <!-- /_pre-lhs-expression -->
+
+ <context id="_ordered-pre-lhs-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_pre-lhs-expression"/>
+ </include>
+ </context> <!-- /_ordered-pre-lhs-expression -->
+
+
+ <!-- # Left-hand side expression
+
+ this
+ new Array
+ 'string'.length
+ fn.apply()
+ list[1]
+ tag`template`
+ -->
+
+ <define-regex id="_expression-start" extended="true">
+ (?= [^\s:;\])}] ) (?! /[/*] )
+ </define-regex> <!-- /_expression-start -->
+
+ <!-- <LeftHandSideExpression> -->
+ <context id="lhs-expression" style-ref="js:expression" once-only="true">
+ <start>\%{_expression-start}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_lhs-expression-content">
+ <include>
+ <context ref="_ordered-pre-primary-expression"/>
+ <context ref="_ordered-primary-expression"/>
+ <context ref="_ordered-post-primary-expression"/>
+ </include>
+ </context> <!-- /_lhs-expression-content -->
+
+ </include>
+ </context> <!-- /lhs-expression -->
+
+
+ <!-- # Ternary operator -->
+
+ <context id="_choice-ternary-operator-missing-true-expression" end-parent="true">
+ <start>(?=:)</start>
+ <end>\%{def:always-match}</end>
+ </context> <!-- /_choice-ternary-operator-missing-true-expression -->
+
+ <!-- ## Without comma -->
+
+ <context id="_ternary-operator-without-comma-false-clause" once-only="true">
+ <start>:</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:ternary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-without-comma-false-clause-content">
+ <include>
+ <context ref="expression-without-comma"/>
+ </include>
+ </context> <!-- /_ternary-operator-without-comma-false-clause-content -->
+
+ </include>
+ </context> <!-- /_ternary-operator-without-comma-false-clause -->
+
+ <context id="_choice-ternary-operator-without-comma-true-expression" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-without-comma-true-expression-content">
+ <include>
+ <context ref="expression-without-comma"/>
+ <context ref="_ternary-operator-without-comma-false-clause"/>
+ </include>
+ </context> <!-- /_ternary-operator-without-comma-true-expression-content -->
+
+ </include>
+ </context> <!-- /_choice-ternary-operator-without-comma-true-expression -->
+
+ <context id="_ternary-operators-without-comma">
+ <start>\?</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:ternary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-without-comma-content">
+ <include>
+ <context ref="_choice-ternary-operator-missing-true-expression"/>
+ <context ref="_choice-ternary-operator-without-comma-true-expression"/>
+ </include>
+ </context> <!-- /_ternary-operator-without-comma-content -->
+
+ </include>
+ </context> <!-- /_ternary-operators-without-comma -->
+
+ <!-- ## With comma -->
+
+ <context id="_ternary-operator-with-comma-false-clause" once-only="true">
+ <start>:</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:ternary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-with-comma-false-clause-content">
+ <include>
+ <context ref="expression-with-comma"/>
+ </include>
+ </context> <!-- /_ternary-operator-with-comma-false-clause-content -->
+
+ </include>
+ </context> <!-- /_ternary-operator-with-comma-false-clause -->
+
+ <context id="_choice-ternary-operator-with-comma-true-expression" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-with-comma-true-expression-content">
+ <include>
+ <context ref="expression-with-comma"/>
+ <context ref="_ternary-operator-with-comma-false-clause"/>
+ </include>
+ </context> <!-- /_ternary-operator-with-comma-true-expression-content -->
+
+ </include>
+ </context> <!-- /_choice-ternary-operator-with-comma-true-expression -->
+
+ <context id="_ternary-operators-with-comma">
+ <start>\?</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:ternary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_ternary-operator-with-comma-content">
+ <include>
+ <context ref="_choice-ternary-operator-missing-true-expression"/>
+ <context ref="_choice-ternary-operator-with-comma-true-expression"/>
+ </include>
+ </context> <!-- /_ternary-operator-with-comma-content -->
+
+ </include>
+ </context> <!-- /_ternary-operators-with-comma -->
+
+
+ <!-- # Binary operators -->
+
+ <define-regex id="_keyword-binary-operator" extended="true">
+ (?: \%[ (?: instanceof | in ) \%] )
+ </define-regex> <!-- /_keyword-binary-operator -->
+
+ <!-- excluding comma operator -->
+ <define-regex id="_binary-operator" extended="true">
+ (?:
+ \*\* =? | # expotentiation (assignment) (ES2016)
+ [+/*%-] =? | # arithmetic (assignment)
+ [!=]==? | # equality
+ && | \|\| | # logical
+ [&|^] =? | # bitwise logical (assignment)
+ (?: << | >>>? ) =? | # bitwise shift (assignment)
+ [<>]=? | # relational
+ = # assignment
+ )
+ </define-regex> <!-- /_binary-operator -->
+
+ <!-- ## Without comma -->
+
+ <context id="_keyword-binary-operators-without-comma">
+ <start>\%{_keyword-binary-operator}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_keyword-binary-operator-without-comma-content">
+ <include>
+ <context ref="expression-without-comma"/>
+ </include>
+ </context> <!-- /_keyword-binary-operator-without-comma-content -->
+
+ </include>
+ </context> <!-- /_keyword-binary-operators-without-comma -->
+
+ <context id="_binary-operators-without-comma">
+ <start>\%{_binary-operator}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:binary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_binary-operator-without-comma-content">
+ <include>
+ <context ref="expression-without-comma"/>
+ </include>
+ </context> <!-- /_binary-operator-without-comma-content -->
+
+ </include>
+ </context> <!-- /_binary-operators-without-comma -->
+
+ <!-- ## With comma -->
+
+ <context id="_keyword-binary-operators-with-comma">
+ <start>\%{_keyword-binary-operator}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_keyword-binary-operator-with-comma-content">
+ <include>
+ <context ref="expression-with-comma"/>
+ </include>
+ </context> <!-- /_keyword-binary-operator-with-comma-content -->
+
+ </include>
+ </context> <!-- /_keyword-binary-operators-with-comma -->
+
+ <context id="_binary-operators-with-comma">
+ <start>(\%{_binary-operator}|,)</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:binary-operator"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_binary-operator-with-comma-content">
+ <include>
+ <context ref="expression-with-comma"/>
+ </include>
+ </context> <!-- /_binary-operator-with-comma-content -->
+ </include>
+ </context> <!-- /_binary-operators-with-comma -->
+
+
+ <!-- # Post-LHS expression -->
+
+ <!-- ## Without comma -->
+
+ <context id="_post-lhs-expression-without-comma">
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="_increment-decrement-operators"/>
+ <context ref="js-fn:arrow-functions"/>
+ <context ref="_ternary-operators-without-comma"/>
+ <context ref="_keyword-binary-operators-without-comma"/>
+ <context ref="_binary-operators-without-comma"/>
+ </include>
+ </context> <!-- /_post-lhs-expression-without-comma -->
+
+ <context id="_ordered-post-lhs-expression-without-comma" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_post-lhs-expression-without-comma"/>
+ </include>
+ </context> <!-- /_ordered-post-lhs-expression-without-comma -->
+
+ <!-- ## With comma -->
+
+ <context id="_post-lhs-expression-with-comma">
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="_increment-decrement-operators"/>
+ <context ref="js-fn:arrow-functions"/>
+ <context ref="_ternary-operators-with-comma"/>
+ <context ref="_keyword-binary-operators-with-comma"/>
+ <context ref="_binary-operators-with-comma"/>
+ </include>
+ </context> <!-- /_post-lhs-expression-with-comma -->
+
+ <context id="_ordered-post-lhs-expression-with-comma" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_post-lhs-expression-with-comma"/>
+ </include>
+ </context> <!-- /_ordered-post-lhs-expression-with-comma -->
+
+
+ <!-- # Expression
+
+ 2 + 3 - 1
+ true ? doThis() : doThat()
+ -->
+
+ <!-- ## Without comma -->
+
+ <context id="_expression-without-comma-content">
+ <include>
+ <context ref="_ordered-pre-lhs-expression"/>
+ <context ref="_lhs-expression-content"/>
+ <context ref="_ordered-post-lhs-expression-without-comma"/>
+ </include>
+ </context> <!-- /_expression-without-comma-content -->
+
+ <!-- <AssignmentExpression> -->
+ <context id="expression-without-comma" style-ref="js:expression" once-only="true">
+ <start>\%{_expression-start}(?!,)</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_expression-without-comma-content"/>
+ </include>
+ </context> <!-- /expression-without-comma -->
+
+ <!-- <AssignmentExpression> -->
+ <context id="choice-expression-without-comma" style-ref="js:expression" end-parent="true">
+ <start>\%{_expression-start}(?!,)</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_expression-without-comma-content"/>
+ </include>
+ </context> <!-- /choice-expression-without-comma -->
+
+ <!-- ## With comma -->
+
+ <context id="_expression-with-comma-content">
+ <include>
+ <context ref="_ordered-pre-lhs-expression"/>
+ <context ref="_lhs-expression-content"/>
+ <context ref="_ordered-post-lhs-expression-with-comma"/>
+ </include>
+ </context> <!-- /_expression-with-comma-content -->
+
+ <!-- <Expression> -->
+ <context id="expression-with-comma" style-ref="js:expression" once-only="true">
+ <start>\%{_expression-start}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_expression-with-comma-content"/>
+ </include>
+ </context> <!-- /expression-with-comma -->
+
+ <!-- <Expression> -->
+ <context id="choice-expression-with-comma" style-ref="js:expression" end-parent="true">
+ <start>\%{_expression-start}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_expression-with-comma-content"/>
+ </include>
+ </context> <!-- /choice-expression-with-comma -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript-functions-classes.lang
b/data/language-specs/javascript-functions-classes.lang
new file mode 100644
index 00000000..ad400bab
--- /dev/null
+++ b/data/language-specs/javascript-functions-classes.lang
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-fn" name="JavaScript Functions and Classes" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+
+ <!-- # Function expression
+
+ function () { return; }
+ function fn([x, y], z = 3, ...rest) { return x + y + z; }
+ -->
+
+ <!-- ## Function expression keyword -->
+
+ <context id="_function-expression-async-keyword" style-ref="js:keyword">
+ <keyword>async</keyword>
+ </context> <!-- /_function-expression-async-keyword -->
+
+ <context id="_ordered-function-expression-async-keyword" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_function-expression-async-keyword"/>
+ </include>
+ </context> <!-- /_ordered-function-expression-async-keyword -->
+
+ <context id="_function-expression-function-keyword" style-ref="js:keyword">
+ <keyword>function</keyword>
+ </context> <!-- /_function-expression-function-keyword -->
+
+ <context id="_ordered-function-expression-function-keyword" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_function-expression-function-keyword"/>
+ </include>
+ </context> <!-- /_ordered-function-expression-function-keyword -->
+
+ <!-- ## Function parameters list -->
+
+ <context id="_function-parameters-content">
+ <include>
+ <context ref="js:ordered-rest-syntax"/>
+ <context ref="js:ordered-assignment-target"/>
+ <context ref="js:ordered-default-value-assignment"/>
+ </include>
+ </context> <!-- /_function-parameters-content -->
+
+ <context id="_function-parameters-list" once-only="true">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_function-parameters-list-content">
+ <include>
+
+ <context id="_function-first-parameter" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_function-parameters-content"/>
+ </include>
+ </context> <!-- /_function-first-parameter -->
+
+ <context id="_function-parameters">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_function-parameters-content"/>
+ </include>
+ </context> <!-- /_function-parameters -->
+
+ </include>
+ </context> <!-- /_function-parameters-list-content -->
+
+ </include>
+ </context> <!-- /_function-parameters-list -->
+
+ <context id="_ordered-function-parameters-list" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_function-parameters-list"/>
+ </include>
+ </context> <!-- /_ordered-function-parameters-list -->
+
+ <!-- ## Function body -->
+
+ <!-- <FunctionBody> -->
+ <context id="_choice-function-body" end-parent="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_function-body-content">
+ <include>
+ <context ref="js-st:directives"/>
+ <context ref="js-st:statements"/>
+ </include>
+ </context> <!-- /_function-body-content -->
+
+ </include>
+ </context> <!-- /_choice-function-body -->
+
+ <context id="_last-function-body" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_choice-function-body"/>
+ </include>
+ </context> <!-- /_last-function-body -->
+
+ <!-- ## Function expression -->
+
+ <!-- <FunctionExpression> / <FunctionDeclaration> -->
+ <context id="choice-function-expression" style-ref="js:function-expression" end-parent="true">
+ <start>(?=\%{js:function-expression-keyword})</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_function-expression-content">
+ <include>
+ <context ref="_ordered-function-expression-async-keyword"/>
+ <context ref="_ordered-function-expression-function-keyword"/>
+ <context ref="js:ordered-generator-modifier"/>
+ <context ref="js:ordered-identifier"/>
+ <context ref="_ordered-function-parameters-list"/>
+ <context ref="_last-function-body"/>
+ </include>
+ </context> <!-- /_function-expression-content -->
+
+ </include>
+ </context> <!-- /choice-function-expression -->
+
+
+ <!-- # Arrow function
+
+ x => -x;
+ (x, y) => x + y
+ ({ a: x, b: y = 2}) => { return x + y; }
+ -->
+
+ <context id="_arrow-function-body" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_arrow-function-body-content">
+ <include>
+ <context ref="_choice-function-body"/>
+ <context ref="js-expr:choice-expression-without-comma"/>
+ </include>
+ </context> <!-- /_arrow-function-body-content -->
+
+ </include>
+ </context> <!-- /_arrow-function-body -->
+
+ <!-- <ArrowFunction> -->
+ <!-- parenthesized arrow function parameters matched by grouping
+ context -->
+ <context id="arrow-functions" style-ref="js:function-expression">
+ <start>=></start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_arrow-function-content">
+ <include>
+ <context ref="_arrow-function-body"/>
+ </include>
+ </context> <!-- /_arrow-function-content -->
+
+ </include>
+ </context> <!-- /arrow-functions -->
+
+
+ <!-- # Method definition
+
+ {
+ method() { ... },
+ get prop() { return this._prop; },
+ set prop(v) { this._prop = v; }
+ }
+ -->
+
+ <context id="_method-definition-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_method-definition-modifier-content">
+ <include>
+
+ <context id="_choice-method-definition-modifier-keyword" style-ref="js:keyword"
end-parent="true">
+ <keyword>get</keyword>
+ <keyword>set</keyword>
+ </context> <!-- /_choice-method-definition-modifier-keyword -->
+
+ <!-- ES2017, cannot be followed by line terminator -->
+ <context id="_choice-async-method-definition-modifier-keyword" style-ref="js:keyword"
end-parent="true">
+ <match extended="true">
+ \%[ async \%]
+ (?=
+ \%{js:optional-whitespace-or-comments}
+ (?:
+ \%{js:identifier-start} |
+ \%{js:generator-modifier}
+ )
+ )
+ </match>
+ </context> <!-- /_choice-async-method-definition-modifier-keyword -->
+
+ </include>
+ </context> <!-- /_method-definition-modifier-content -->
+
+ </include>
+ </context> <!-- /_method-definition-modifier -->
+
+ <context id="_ordered-method-definition-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_method-definition-modifier"/>
+ </include>
+ </context> <!-- /_ordered-method-definition-modifier -->
+
+ <!-- <MethodDefinition> -->
+ <context id="_method-definition" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_method-definition-content">
+ <include>
+ <context ref="_ordered-method-definition-modifier"/>
+ <context ref="js:ordered-generator-modifier"/>
+ <context ref="js-lit:ordered-property-name"/>
+ <context ref="_ordered-function-parameters-list" style-ref="js:function-expression"/>
+ <context ref="_last-function-body" style-ref="js:function-expression"/>
+ </include>
+ </context> <!-- /_method-definition-content -->
+
+ </include>
+ </context> <!-- /_method-definition -->
+
+ <context id="ordered-method-definition" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_method-definition"/>
+ </include>
+ </context> <!-- /ordered-method-definition -->
+
+
+ <!-- # Class expression
+
+ class Foo extends Bar {
+ constructor() { ... }
+ methodA() { ... }
+ static methodB() { ... }
+ }
+ -->
+
+ <!-- ## Class optional name -->
+
+ <context id="_class-optional-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-optional-name-content">
+ <include>
+
+ <context id="_choice-class-optional-name-ignore-extends" end-parent="true">
+ <start>(?=\%[extends\%])</start>
+ <end>\%{def:always-match}</end>
+ </context> <!-- /_choice-class-optional-name-ignore-extends -->
+
+ <context ref="js:choice-identifier"/>
+ </include>
+ </context> <!-- /_class-optional-name-content -->
+
+ </include>
+ </context> <!-- /_class-optional-name -->
+
+ <context id="_ordered-class-optional-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_class-optional-name"/>
+ </include>
+ </context> <!-- /_ordered-class-optional-name -->
+
+ <!-- ## Class extends clause -->
+
+ <context id="_class-extends-clause" once-only="true">
+ <start>\%[extends\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-extends-clause-content">
+ <include>
+ <context ref="js-expr:lhs-expression"/>
+ </include>
+ </context> <!-- /_class-extends-clause-content -->
+
+ </include>
+ </context> <!-- /_class-extends-clause -->
+
+ <context id="_ordered-class-extends-clause" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_class-extends-clause"/>
+ </include>
+ </context> <!-- /_ordered-class-extends-clause -->
+
+ <!-- ## Class body -->
+
+ <context id="_class-body-member-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-body-member-modifier-content">
+ <include>
+
+ <context id="_choice-class-body-member-modifier-keyword" style-ref="js:keyword"
end-parent="true">
+ <keyword>static</keyword>
+ </context> <!-- /_choice-class-body-member-modifier-keyword -->
+
+ </include>
+ </context> <!-- /_class-body-member-modifier-content -->
+
+ </include>
+ </context> <!-- /_class-body-member-modifier -->
+
+ <context id="_ordered-class-body-member-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_class-body-member-modifier"/>
+ </include>
+ </context> <!-- /_ordered-class-body-member-modifier -->
+
+ <context id="_class-body-members">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-body-member-content">
+ <include>
+ <context ref="_ordered-class-body-member-modifier"/>
+ <context ref="ordered-method-definition"/>
+ </include>
+ </context> <!-- /_class-body-member-content -->
+
+ </include>
+ </context> <!-- /_class-body-members -->
+
+ <context id="_class-body" once-only="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-body-content">
+ <include>
+ <context ref="_class-body-members"/>
+ </include>
+ </context> <!-- /_class-body-content -->
+
+ </include>
+ </context> <!-- /_class-body -->
+
+ <context id="_last-class-body" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_class-body"/>
+ </include>
+ </context> <!-- /_last-class-body -->
+
+ <!-- ## Class expression -->
+
+ <!-- <ClassExpression> / <ClassDeclaration> -->
+ <context id="choice-class-expression" style-ref="js:class-expression" end-parent="true">
+ <start>\%{js:class-expression-keyword}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-expression-content">
+ <include>
+ <context ref="_ordered-class-optional-name"/>
+ <context ref="_ordered-class-extends-clause"/>
+ <context ref="_last-class-body"/>
+ </include>
+ </context> <!-- /_class-expression-content -->
+
+ </include>
+ </context> <!-- /choice-class-expression -->
+
+ <!-- <ClassExpression> / <ClassDeclaration> -->
+ <context id="choice-class-expression-required-name" style-ref="js:class-expression" end-parent="true">
+ <start>\%{js:class-expression-keyword}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-expression-required-name-content">
+ <include>
+ <context ref="js:ordered-identifier"/>
+ <context ref="_ordered-class-extends-clause"/>
+ <context ref="_last-class-body"/>
+ </include>
+ </context> <!-- /_class-expression-required-name-content -->
+
+ </include>
+ </context> <!-- /choice-class-expression-required-name -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript-literals.lang b/data/language-specs/javascript-literals.lang
new file mode 100644
index 00000000..cdc4bd52
--- /dev/null
+++ b/data/language-specs/javascript-literals.lang
@@ -0,0 +1,601 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-lit" name="JavaScript Literals" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+
+ <!-- # Keyword values -->
+
+ <!-- <NullLiteral> -->
+ <context id="null-value" style-ref="js:null-value">
+ <keyword>null</keyword>
+ </context> <!-- /null-value -->
+
+ <!-- <BooleanLiteral> -->
+ <context id="boolean" style-ref="js:boolean">
+ <keyword>false</keyword>
+ <keyword>true</keyword>
+ </context> <!-- /boolean -->
+
+
+ <!-- # Number -->
+
+ <!-- <NumericLiteral> -->
+ <context id="choice-number">
+ <include>
+
+ <define-regex id="_decimal" extended="true">
+ (?>
+ (?: [1-9][0-9]* | 0 ) (?: \. [0-9]* )? |
+ \. [0-9]+
+ )
+ (?> [eE] [+-]? [0-9]+ )?
+ </define-regex> <!-- /_decimal -->
+
+ <!-- <DecimalLiteral> -->
+ <context id="_choice-decimal" style-ref="js:decimal" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_decimal}
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_decimal}</end>
+ </context> <!-- /_choice-decimal -->
+
+ <define-regex id="_decimal-integer" extended="true">
+ (?>
+ (?: [1-9][0-9]* | 0 )
+ )
+ </define-regex> <!-- /_decimal-integer -->
+
+ <!-- ES2020 -->
+ <!-- <DecimalBigIntegerLiteral> -->
+ <context id="_choice-decimal-big-integer" style-ref="js:decimal" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_decimal-integer} n
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_decimal-integer}n</end>
+ </context> <!-- /_choice-decimal-big-integer -->
+
+ <define-regex id="_binary-integer" extended="true">
+ (?> 0 [bB] [01]+ )
+ </define-regex> <!-- /_binary-integer -->
+
+ <!-- <BinaryIntegerLiteral> -->
+ <context id="_choice-binary-integer" style-ref="js:binary-integer" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_binary-integer} n?
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_binary-integer}n?</end>
+ </context> <!-- /_choice-binary-integer -->
+
+ <define-regex id="_octal-integer" extended="true">
+ (?> 0 [oO] [0-7]+ )
+ </define-regex> <!-- /_octal-integer -->
+
+ <!-- <OctalIntegerLiteral> -->
+ <context id="_choice-octal-integer" style-ref="js:octal-integer" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_octal-integer} n?
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_octal-integer}n?</end>
+ </context> <!-- /_choice-octal-integer -->
+
+ <!-- <HexIntegerLiteral> -->
+ <define-regex id="_hex-integer" extended="true">
+ (?> 0 [xX] [0-9a-fA-F]+ )
+ </define-regex> <!-- /_hex-integer -->
+
+ <context id="_choice-hex-integer" style-ref="js:hex-integer" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_hex-integer} n?
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_hex-integer}n?</end>
+ </context> <!-- /_choice-hex-integer -->
+
+ <define-regex id="_legacy-octal-integer" extended="true">
+ (?> 0 [0-7]+ )
+ </define-regex> <!-- /_legacy-octal-integer -->
+
+ <!-- Annex B: <LegacyOctalIntegerLiteral> -->
+ <context id="_choice-legacy-octal-integer" style-ref="js:error" end-parent="true">
+ <start extended="true">
+ (?<! \%{js:identifier-char} | \. )
+ (?=
+ \%{_legacy-octal-integer}
+ (?! \%{js:identifier-part} | \. )
+ )
+ </start>
+ <end>\%{_legacy-octal-integer}</end>
+ </context> <!-- /_choice-legacy-octal-integer -->
+
+ </include>
+ </context> <!-- /choice-number -->
+
+
+ <!-- # Escape sequences -->
+
+ <context id="_escapes">
+ <include>
+
+ <!-- Annex B: <LegacyOctalEscapeSequence> (preceeded by
+ backslash) -->
+ <context id="_legacy-octal-escape-sequences" style-ref="js:escape">
+ <match extended="true">
+ \\
+ (
+ 0 [0-7]{1,2} | # 0-padded number, not \0 (null character)
+ [1-3] [0-7]{0,2} | # max \377
+ [4-7] [0-7]{0,1}
+ )
+ </match>
+ </context> <!-- /_legacy-octal-escape-sequences -->
+
+ <!-- <EscapeSequence> (preceeded by backslash) -->
+ <context id="_escape-sequences" style-ref="js:escape">
+ <match extended="true">
+ (
+ \%{js:unicode-escape} |
+ \\
+ (
+ x[0-9a-fA-F]{2} | # hexadecimal escape
+ [^1-9xu] # single character escape
+ )
+ )
+ </match>
+ </context> <!-- /_escape-sequences -->
+
+ </include>
+ </context> <!-- /_escapes -->
+
+
+ <!-- # String -->
+
+ <context id="_string-content">
+ <include>
+ <context ref="_escapes"/>
+ <context ref="def:line-continue"/>
+ </include>
+ </context> <!-- /_string-content -->
+
+ <!-- <StringLiteral> -->
+ <context id="choice-string" style-ref="js:string" end-at-line-end="true" end-parent="true"
class="string" class-disabled="no-spell-check">
+ <start>["']</start>
+ <end>\%{0@start}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+ <context ref="_string-content"/>
+ </include>
+ </context> <!-- /choice-string -->
+
+ <!-- <StringLiteral> -->
+ <context id="choice-string-path" style-ref="js:included-file" end-at-line-end="true" end-parent="true"
class="path">
+ <start>["']</start>
+ <end>\%{0@start}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+ <context ref="_string-content"/>
+ </include>
+ </context> <!-- /choice-string-path -->
+
+
+ <!-- # Array literal
+
+ [ 1, 2, 3, ...anotherArray ]
+ -->
+
+ <context id="_array-literal-element-content">
+ <include>
+ <context ref="js:ordered-spread-syntax"/>
+ <context ref="js-expr:expression-without-comma"/>
+ </include>
+ </context> <!-- /_array-literal-element-content -->
+
+ <!-- <ArrayLiteral> -->
+ <context id="choice-array-literal" style-ref="js:array-literal" end-parent="true">
+ <start>\[</start>
+ <end>]</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_array-literal-content">
+ <include>
+
+ <context id="_array-literal-first-element" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_array-literal-element-content"/>
+ </include>
+ </context> <!-- /_array-literal-first-element -->
+
+ <context id="_array-literal-elements">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_array-literal-element-content"/>
+ </include>
+ </context> <!-- /_array-literal-elements -->
+
+ </include>
+ </context> <!-- /_array-literal-content -->
+
+ </include>
+ </context> <!-- /choice-array-literal -->
+
+
+ <!-- # Property name -->
+
+ <!-- <PropertyName> -->
+ <context id="_property-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_property-name-content">
+ <include>
+
+ <!-- <ComputedPropertyName> -->
+ <context id="_choice-computed-property-name" end-parent="true">
+ <start>\[</start>
+ <end>]</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_computed-property-name-content">
+ <include>
+ <context ref="js-expr:expression-without-comma"/>
+ </include>
+ </context> <!-- /_computed-property-name-content -->
+
+ </include>
+ </context> <!-- /_choice-computed-property-name -->
+
+ <context ref="choice-number"/>
+ <context ref="choice-string"/>
+
+ <define-regex id="_special-property-names" extended="true">
+ (?: \%[ constructor \%] )
+ </define-regex> <!-- /_special-property-names -->
+
+ <context id="_choice-special-property-name" style-ref="js:built-in-method" end-parent="true">
+ <start>(?=\%{_special-property-names})</start>
+ <end>\%{_special-property-names}</end>
+ </context> <!-- /_choice-special-property-name -->
+
+ <context ref="js:choice-identifier-name"/>
+ </include>
+ </context> <!-- /_property-name-content -->
+
+ </include>
+ </context> <!-- /_property-name -->
+
+ <context id="ordered-property-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_property-name"/>
+ </include>
+ </context> <!-- /ordered-property-name -->
+
+
+ <!-- # Object literal
+
+ {
+ propertyA: 'a',
+ propertyB: getB(),
+ [ computedName() ]: 2 + 3,
+ method() { ... },
+ get prop() { return this._prop; },
+ set prop(v) { this._prop = v; },
+ ...objectToCopy
+ }
+ -->
+
+ <context id="_object-literal-property-content">
+ <include>
+
+ <context id="_object-literal-property-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_object-literal-property-name-content">
+ <include>
+ <context ref="js:ordered-spread-syntax"/> <!-- ES2018 -->
+ <context ref="js-fn:ordered-method-definition"/> <!-- includes property-name -->
+ </include>
+ </context> <!-- /_object-literal-property-name-content -->
+
+ </include>
+ </context> <!-- /_object-literal-property-name -->
+
+ <context id="_object-literal-property-value" once-only="true">
+ <start>:</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_object-literal-property-value-content">
+ <include>
+ <context ref="js-expr:expression-without-comma"/>
+ </include>
+ </context> <!-- /_object-literal-property-value-content -->
+
+ </include>
+ </context> <!-- /_object-literal-property-value -->
+
+ </include>
+ </context> <!-- /_object-literal-property-content -->
+
+ <!-- <ObjectLiteral> -->
+ <context id="choice-object-literal" style-ref="js:object-literal" end-parent="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_object-literal-content">
+ <include>
+
+ <context id="_object-literal-first-property" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_object-literal-property-content"/>
+ </include>
+ </context> <!-- /_object-literal-first-property -->
+
+ <context id="_object-literal-properties">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_object-literal-property-content"/>
+ </include>
+ </context> <!-- /_object-literal-properties -->
+
+ </include>
+ </context> <!-- /_object-literal-content -->
+
+ </include>
+ </context> <!-- /choice-object-literal -->
+
+
+ <!-- # Regular expression literal
+
+ /(foo|bar)+/u
+ -->
+
+ <!-- only valid in regular expressions -->
+ <context id="_control-escapes" style-ref="js:escape">
+ <match>\\c[a-zA-Z]</match>
+ </context> <!-- /_control-escapes -->
+
+ <!-- ES2018 -->
+ <context id="_unicode-property-escapes" style-ref="js:escape">
+ <match extended="true">
+ \\ [pP] \{ ( [a-zA-Z_]+ = )? [a-zA-Z0-9_]+ \}
+ </match>
+ </context> <!-- /_unicode-property-escapes -->
+
+ <!-- ES2018 -->
+ <context id="_named-capture-groups">
+ <match extended="true">
+ \(\? < ( \%{js:identifier} ) >
+ </match>
+ <include>
+ <context sub-pattern="1" style-ref="js:regex-group"/>
+ </include>
+ </context> <!-- /_named-capture-groups -->
+
+ <!-- ES2018 -->
+ <context id="_named-capture-group-backreferences" style-ref="js:escape">
+ <match extended="true">
+ \\k < ( \%{js:identifier} ) >
+ </match>
+ <include>
+ <context sub-pattern="1" style-ref="js:regex-group"/>
+ </include>
+ </context> <!-- /_named-capture-group-backreferences -->
+
+ <context id="_regular-expression-character-classes" style-ref="js:regex-class" style-inside="true">
+ <start>\[</start>
+ <end>]</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+
+ <context id="_regular-expression-character-class-content">
+ <include>
+ <context ref="_control-escapes"/>
+ <context ref="_unicode-property-escapes"/>
+ <context ref="_escapes"/>
+ </include>
+ </context> <!-- /_regular-expression-character-class-content -->
+
+ </include>
+ </context> <!-- /_regular-expression-character-classes -->
+
+ <!-- <RegularExpressionLiteral> -->
+ <!-- technically, line terminators are not allowed inside -->
+ <context id="choice-regular-expression-literal" style-ref="js:regex" end-parent="true">
+ <start>/</start>
+ <end>/([gimsuy]*)</end> <!-- s (dotAll): ES2018 -->
+ <include>
+ <context sub-pattern="1" where="end" style-ref="js:regex-flag"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+
+ <context id="_regular-expression-literal-content">
+ <include>
+ <context ref="_control-escapes"/>
+ <context ref="_unicode-property-escapes"/>
+ <context ref="_named-capture-group-backreferences"/>
+ <context ref="_escapes"/>
+ <context ref="_named-capture-groups"/>
+ <context ref="_regular-expression-character-classes"/>
+ </include>
+ </context> <!-- /_regular-expression-literal-content -->
+
+ </include>
+ </context> <!-- /choice-regular-expression-literal -->
+
+
+ <!-- # Template literal (template string)
+
+ `this is a ${adjective} template`
+
+ the contexts are structured this way so that the
+ template-literal and template-placeholder styles (and any
+ styles inside the placeholder) do not overlap
+ -->
+
+ <context id="_template-content">
+ <include>
+ <context ref="_escapes"/>
+ <context ref="def:line-continue"/>
+ </include>
+ </context> <!-- /_template-content -->
+
+ <context id="_template-literal-content">
+ <include>
+
+ <context id="_template-head" style-ref="js:template-literal" once-only="true">
+ <start>(?<=`)</start>
+ <end>(?=`|\$\{)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+ <context ref="_template-content"/>
+ </include>
+ </context> <!-- /_template-head -->
+
+ <context id="_template-substitution-tails" style-ref="js:template-literal">
+ <start>(?<=})</start>
+ <end>(?=`|\$\{)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <!-- no comments here -->
+ <context ref="_template-content"/>
+ </include>
+ </context> <!-- /_template-substitution-tails -->
+
+ <context id="_template-placeholders">
+ <start>\$\{</start>
+ <end>}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:template-placeholder"/>
+ <context sub-pattern="0" where="end" style-ref="js:template-placeholder"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_template-placeholder-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_template-placeholder-content -->
+
+ </include>
+ </context> <!-- /_template-placeholders -->
+
+ </include>
+ </context> <!-- /_template-literal-content -->
+
+ <!-- <Template> / <TemplateLiteral> -->
+ <context id="template-literals">
+ <start>`</start>
+ <end>`</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:template-literal"/>
+ <context sub-pattern="0" where="end" style-ref="js:template-literal"/>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not match comments or embedded-lang-hooks here, because
+ template-head must match immediately -->
+ <context ref="_template-literal-content"/>
+ </include>
+ </context> <!-- /template-literals -->
+
+ <!-- <Template> / <TemplateLiteral> -->
+ <context id="choice-template-literal" end-parent="true">
+ <start>`</start>
+ <end>`</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:template-literal"/>
+ <context sub-pattern="0" where="end" style-ref="js:template-literal"/>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not match comments or embedded-lang-hooks here, because
+ template-head must match immediately -->
+ <context ref="_template-literal-content"/>
+ </include>
+ </context> <!-- /choice-template-literal -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript-modules.lang b/data/language-specs/javascript-modules.lang
new file mode 100644
index 00000000..57119030
--- /dev/null
+++ b/data/language-specs/javascript-modules.lang
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-mod" name="JavaScript Modules" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+
+ <!-- # Shared between export and import declarations -->
+
+ <!-- ## (Import) From module
+
+ from 'module'
+ -->
+
+ <context id="_from-module" once-only="true">
+ <start>\%[from\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_from-module-content">
+ <include>
+ <context ref="js-lit:choice-string-path"/>
+ </include>
+ </context> <!-- /_from-module-content -->
+
+ </include>
+ </context> <!-- /_from-module -->
+
+ <context id="_ordered-from-module" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_from-module"/>
+ </include>
+ </context> <!-- /_ordered-from-module -->
+
+ <!-- ## Export / import name group
+
+ { x, y as b }
+ { x as default }
+ { default }
+ { default as y }
+ -->
+
+ <context id="_name-group-identifier" once-only="true">
+ <start>(?=\%{js:identifier-start})</start>
+ <end>\%{def:always-match}</end>
+ <include>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not extend the context by matching comments or
+ embedded-lang-hooks, which may lead to multiple identifiers -->
+
+ <context id="_name-group-identifier-content">
+ <include>
+
+ <context id="_name-group-keywords" style-ref="js:keyword">
+ <keyword>default</keyword>
+ </context> <!-- /_name-group-keywords -->
+
+ <context ref="js:identifier"/>
+ </include>
+ </context> <!-- /_name-group-identifier-content -->
+
+ </include>
+ </context> <!-- /_name-group-identifier -->
+
+ <context id="_name-group-as-identifier" once-only="true">
+ <start>\%[as\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_name-group-as-identifier-content">
+ <include>
+ <context ref="_name-group-identifier"/>
+ </include>
+ </context> <!-- /_name-group-as-identifier-content -->
+
+ </include>
+ </context> <!-- /_name-group-as-identifier -->
+
+ <context id="_name-group-name-content">
+ <include>
+ <context ref="_name-group-identifier"/>
+ <context ref="_name-group-as-identifier"/>
+ </include>
+ </context> <!-- /_name-group-name-content -->
+
+ <!-- <ExportClause> / <NamedImports> -->
+ <context id="_name-group" once-only="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_name-group-content">
+ <include>
+
+ <context id="_name-group-first-name" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_name-group-name-content"/>
+ </include>
+ </context> <!-- /_name-group-first-name -->
+
+ <context id="_name-group-names">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_name-group-name-content"/>
+ </include>
+ </context> <!-- /_name-group-names -->
+
+ </include>
+ </context> <!-- /_name-group-content -->
+
+ </include>
+ </context> <!-- /_name-group -->
+
+ <context id="_ordered-name-group" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_name-group"/>
+ </include>
+ </context> <!-- /_ordered-name-group -->
+
+
+ <!-- # Export declaration -->
+
+ <!-- ## Export named
+
+ export { x, y as b };
+ export { x as default };
+ export { default } from 'module';
+ -->
+
+ <context id="_choice-export-named" end-parent="true">
+ <start>(?=\{)</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_choice-export-named-content">
+ <include>
+ <context ref="_ordered-name-group"/>
+ <context ref="_ordered-from-module"/>
+ </include>
+ </context> <!-- /_choice-export-named-content -->
+
+ </include>
+ </context> <!-- /_choice-export-named -->
+
+ <!-- ## Export default
+
+ export default function () { ... }
+ export default class { ... }
+ export default expr;
+ -->
+
+ <context id="_choice-export-default" end-parent="true">
+ <start>\%[default\%]</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_export-default-content">
+ <include>
+ <context ref="js-fn:choice-class-expression"/>
+ <context ref="js-fn:choice-function-expression"/>
+ <context ref="js-expr:choice-expression-without-comma"/>
+ </include>
+ </context> <!-- /_export-default-content -->
+
+ </include>
+ </context> <!-- /_choice-export-default -->
+
+ <!-- ## Export all
+
+ export * from 'module';
+ -->
+
+ <context id="_choice-export-all" end-parent="true">
+ <start>\*</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_export-all-content">
+ <include>
+ <context ref="_ordered-from-module"/>
+ </include>
+ </context> <!-- /_export-all-content -->
+
+ </include>
+ </context> <!-- /_choice-export-all -->
+
+ <!-- ## Export declaration
+
+ export { foo, bar as barry };
+ export const a = 1;
+ export default function () { ... }
+ export * from 'module';
+ -->
+
+ <!-- <ExportDeclaration> -->
+ <context id="export-declarations" style-ref="js:export-import-declaration">
+ <start>\%[export\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_export-declaration-content">
+ <include>
+ <context ref="_choice-export-named"/>
+ <context ref="_choice-export-default"/>
+ <context ref="_choice-export-all"/>
+ <context ref="js-fn:choice-class-expression-required-name"/>
+ <context ref="js-fn:choice-function-expression"/>
+ <context ref="js-st:choice-variable-declaration"/>
+ </include>
+ </context> <!-- /_export-declaration-content -->
+
+ </include>
+ </context> <!-- /export-declarations -->
+
+
+ <!-- # Import declaration -->
+
+ <!-- ## Import named
+
+ import { default as y } from 'module';
+ -->
+
+ <context id="_choice-import-named" end-parent="true">
+ <start>(?=\{)</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_choice-import-named-content">
+ <include>
+ <context ref="_ordered-name-group"/>
+ <context ref="_ordered-from-module"/>
+ </include>
+ </context> <!-- /_choice-import-named-content -->
+
+ </include>
+ </context> <!-- /_choice-import-named -->
+
+ <!-- ## Import as namespace
+
+ import * as nm from 'module';
+ -->
+
+ <context id="_as-namespace" once-only="true">
+ <start>\%[as\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_as-namespace-content">
+ <include>
+ <context ref="js:identifier"/>
+ </include>
+ </context> <!-- /_as-namespace-content -->
+
+ </include>
+ </context> <!-- /_as-namespace -->
+
+ <context id="_ordered-as-namespace" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_as-namespace"/>
+ </include>
+ </context> <!-- /_ordered-as-namespace -->
+
+ <context id="_choice-import-as-namespace" end-parent="true">
+ <start>\*</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_import-as-namespace-content">
+ <include>
+ <context ref="_ordered-as-namespace"/>
+ <context ref="_ordered-from-module"/>
+ </include>
+ </context> <!-- /_import-as-namespace-content -->
+
+ </include>
+ </context> <!-- /_choice-import-as-namespace -->
+
+ <!-- ## Import default
+
+ import def from 'module';
+ import def, { a, b } from 'module';
+ import def, * as nm from 'module';
+ -->
+
+ <context id="_choice-import-default-additional" end-parent="true">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_import-default-additional-content">
+ <include>
+ <context ref="_choice-import-named"/>
+ <context ref="_choice-import-as-namespace"/>
+ </include>
+ </context> <!-- /_import-default-additional-content -->
+
+ </include>
+ </context> <!-- /_choice-import-default-additional -->
+
+ <context id="_choice-import-default-only" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_import-default-only-content">
+ <include>
+ <context ref="_ordered-from-module"/>
+ </include>
+ </context> <!-- /_import-default-only-content -->
+
+ </include>
+ </context> <!-- /_choice-import-default-only -->
+
+ <context id="_choice-import-default" end-parent="true">
+ <start>(?=\%{js:identifier-start})</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_import-default-content">
+ <include>
+ <context ref="js:ordered-identifier"/>
+ <context ref="_choice-import-default-additional"/>
+ <context ref="_choice-import-default-only"/>
+ </include>
+ </context> <!-- /_import-default-content -->
+
+ </include>
+ </context> <!-- /_choice-import-default -->
+
+ <!-- ## Import declaration
+
+ import { foo as food, bar } from 'module';
+ import defaultFn, * as Mod from 'module';
+ import 'module';
+ -->
+
+ <!-- <ImportDeclaration> -->
+ <context id="import-declarations" style-ref="js:export-import-declaration">
+ <start extended="true">
+ \%[ import \%] (?! \%{js:import-function-keyword-suffix} )
+ </start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_import-declaration-content">
+ <include>
+ <context ref="_choice-import-named"/>
+ <context ref="_choice-import-as-namespace"/>
+ <context ref="_choice-import-default"/>
+ <context ref="js-lit:choice-string-path"/>
+ </include>
+ </context> <!-- /_import-declaration-content -->
+
+ </include>
+ </context> <!-- /import-declarations -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript-statements.lang b/data/language-specs/javascript-statements.lang
new file mode 100644
index 00000000..25f0bbe5
--- /dev/null
+++ b/data/language-specs/javascript-statements.lang
@@ -0,0 +1,923 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-st" name="JavaScript Statements" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+
+ <!-- # Use strict directive -->
+
+ <!-- apparently, back references are not supported -->
+ <context id="_use-strict-directives" style-ref="js:directive">
+ <start extended="true">
+ (?:
+ " use [ ] strict " |
+ ' use [ ] strict '
+ )
+ </start>
+ <end>\%{js:statement-end}</end>
+ </context> <!-- /_use-strict-directives -->
+
+
+ <!-- # Directives -->
+
+ <!-- directives are valid at the start of scripts, modules, and
+ function bodies (but not block statements)
+ -->
+ <context id="directives">
+ <include>
+ <context ref="_use-strict-directives"/>
+ </include>
+ </context> <!-- /directives -->
+
+
+ <!-- # Test condition for if / switch / while / etc. -->
+
+ <context id="_condition" once-only="true">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments" />
+
+ <context id="_condition-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_condition-content -->
+
+ </include>
+ </context> <!-- /_condition -->
+
+ <context id="_ordered-condition" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_condition"/>
+ </include>
+ </context> <!-- /_ordered-condition -->
+
+
+ <!-- # Block statement
+
+ {
+ ...
+ }
+ -->
+
+ <!-- <BlockStatement> -->
+ <context id="_block-statements" style-ref="js:block-statement">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_block-statement-content">
+ <include>
+ <context ref="statements"/>
+ </include>
+ </context> <!-- /_block-statement-content -->
+
+ </include>
+ </context> <!-- /_block-statements -->
+
+
+ <!-- # Break statement
+
+ break;
+ break outerLoop;
+ -->
+
+ <!-- <BreakStatement> -->
+ <context id="_break-statements" style-ref="js:break-statement">
+ <start>\%[break\%]</start>
+ <end>\%{js:statement-end-or-end-of-line}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments-no-extend-parent"/>
+
+ <context id="_break-statement-content">
+ <include>
+ <context ref="js:ordered-identifier"/>
+ </include>
+ </context> <!-- /_break-statement-content -->
+
+ </include>
+ </context> <!-- /_break-statements -->
+
+
+ <!-- # Class declaration
+
+ class Foo extends Bar { ... }
+ -->
+
+ <!-- <ClassExpression> / <ClassDeclaration> -->
+ <context id="_class-declarations">
+ <start>(?=\%{js:class-expression-keyword})</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_class-declaration-content">
+ <include>
+ <context ref="js-fn:choice-class-expression-required-name"/>
+ </include>
+ </context> <!-- /_class-declaration-content -->
+
+ </include>
+ </context> <!-- /_class-declarations -->
+
+
+ <!-- # Continue statement
+
+ continue;
+ continue outerLoop;
+ -->
+
+ <!-- <ContinueStatement> -->
+ <context id="_continue-statements" style-ref="js:continue-statement">
+ <start>\%[continue\%]</start>
+ <end>\%{js:statement-end-or-end-of-line}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments-no-extend-parent"/>
+
+ <context id="_continue-statement-content">
+ <include>
+ <context ref="js:ordered-identifier"/>
+ </include>
+ </context> <!-- /_continue-statement-content -->
+
+ </include>
+ </context> <!-- /_continue-statements -->
+
+
+ <!-- # Debugger statement
+
+ debugger;
+ -->
+
+ <!-- <DebuggerStatement> -->
+ <context id="_debugger-statements" style-ref="js:debugger-statement">
+ <start>\%[debugger\%]</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_debugger-statement-content"/>
+
+ </include>
+ </context> <!-- /_debugger-statements -->
+
+
+ <!-- # Expression statement
+
+ a = 1;
+ main();
+ i++;
+ -->
+
+ <!-- <ExpressionStatement> -->
+ <context id="_expression-statements" style-ref="js:expression-statement">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_expression-statement-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_expression-statement-content -->
+
+ </include>
+ </context> <!-- /_expression-statements -->
+
+
+ <!-- # For statement
+
+ for (var i = 0; i < length; i++) loop();
+ for (prop in obj) { ... }
+ for (value of iterator) { ... }
+ -->
+
+ <context id="_for-statement-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-modifier-content">
+ <include>
+
+ <context id="_choice-for-statement-modifier-keyword" style-ref="js:keyword" end-parent="true">
+ <keyword>await</keyword> <!-- ES2018 -->
+ </context> <!-- /_choice-for-statement-modifier-keyword -->
+
+ </include>
+ </context> <!-- /_for-statement-modifier-content -->
+
+ </include>
+ </context> <!-- /_for-statement-modifier -->
+
+ <context id="_ordered-for-statement-modifier" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_for-statement-modifier"/>
+ </include>
+ </context> <!-- /_ordered-for-statement-modifier -->
+
+ <context id="_for-statement-test">
+ <include>
+
+ <context id="_for-statement-test-initial-expression" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-test-initial-expression-content">
+ <include>
+ <context ref="_choice-variable-declaration-without-semicolon"/>
+ <context ref="js-expr:choice-expression-with-comma"/>
+ </include>
+ </context> <!-- /_for-statement-test-initial-expression-content -->
+
+ </include>
+ </context> <!-- /_for-statement-test-initial-expression -->
+
+ <context id="_for-statement-test-condition" once-only="true">
+ <start>;</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-test-condition-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_for-statement-test-condition-content -->
+
+ </include>
+ </context> <!-- /_for-statement-test-condition -->
+
+ <context id="_for-statement-test-increment-expression" once-only="true">
+ <start>;</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-test-increment-expression-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_for-statement-test-increment-expression-content -->
+
+ </include>
+ </context> <!-- /_for-statement-test-increment-expression -->
+
+ </include>
+ </context> <!-- /_for-statement-test -->
+
+ <context id="_for-statement-in" once-only="true">
+ <start>\%[in\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-in-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_for-statement-in-content -->
+
+ </include>
+ </context> <!-- /_for-statement-in -->
+
+ <context id="_for-statement-of" once-only="true">
+ <start>\%[of\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-of-content">
+ <include>
+ <context ref="js-expr:expression-without-comma"/>
+ </include>
+ </context> <!-- /_for-statement-of-content -->
+
+ </include>
+ </context> <!-- /_for-statement-of -->
+
+ <context id="_for-statement-condition" once-only="true">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-condition-content">
+ <include>
+ <context ref="_for-statement-test"/>
+ <context ref="_for-statement-in"/>
+ <context ref="_for-statement-of"/>
+ </include>
+ </context> <!-- /_for-statement-condition-content -->
+
+ </include>
+ </context> <!-- /_for-statement-condition -->
+
+ <context id="_ordered-for-statement-condition" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_for-statement-condition"/>
+ </include>
+ </context> <!-- /_ordered-for-statement-condition -->
+
+ <!-- <IterationStatement> (part of) -->
+ <context id="_for-statements" style-ref="js:for-statement">
+ <start>\%[for\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_for-statement-content">
+ <include>
+ <context ref="_ordered-for-statement-modifier"/>
+ <context ref="_ordered-for-statement-condition"/>
+ </include>
+ </context> <!-- /_for-statement-content -->
+
+ </include>
+ </context> <!-- /_for-statements -->
+
+
+ <!-- # Function declaration
+
+ function fn() { ... }
+ -->
+
+ <!-- <FunctionExpression> / <FunctionDeclaration> -->
+ <context id="_function-declarations">
+ <start>(?=\%{js:function-expression-keyword})</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_function-declaration-content">
+ <include>
+ <context ref="js-fn:choice-function-expression"/>
+ </include>
+ </context> <!-- /_function-declaration-content -->
+
+ </include>
+ </context> <!-- /_function-declarations -->
+
+
+ <!-- # If...else statement
+
+ if (done) return;
+ if (i > 0) { ... } else if (i < 0) { ... } else { ... }
+ -->
+
+ <!-- <IfStatement> (part of) -->
+ <context id="_if-statements" style-ref="js:if-statement">
+ <start>\%[if\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_if-statement-content">
+ <include>
+ <context ref="_ordered-condition"/>
+ </include>
+ </context> <!-- /_if-statement-content -->
+
+ </include>
+ </context> <!-- /_if-statements -->
+
+ <!-- <IfStatement> (part of) -->
+ <context id="_else-statements" style-ref="js:else-statement">
+ <start>\%[else\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_else-statement-content"/>
+
+ </include>
+ </context> <!-- /_else-statements -->
+
+
+ <!-- # Label statement
+
+ loop: for (...) {...}
+ -->
+
+ <!-- <LabelledStatement> -->
+ <!-- technically, only statements (and function declarations in
+ non-strict mode) are allowed to follow a label identifier, but
+ let's just end the label statement after the colon
+ -->
+ <context id="_label-statements" style-ref="js:label-statement">
+ <start extended="true">
+ (?=
+ \%{js:identifier}
+ \%{js:optional-whitespace-or-comments}
+ :
+ )
+ </start>
+ <end>:</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_label-statement-content">
+ <include>
+ <!-- technically, yield and await are valid label identifiers
+ in non-strict mode and non-module code, respectively
+ but let's not allow it (and have them highlighted as
+ reserved words)
+ -->
+ <context ref="js:ordered-identifier"/>
+ </include>
+ </context> <!-- /_label-statement-content -->
+
+ </include>
+ </context> <!-- /_label-statements -->
+
+
+ <!-- # Return statement
+
+ return;
+ return value;
+ -->
+
+ <!-- <ReturnStatement> -->
+ <context id="_return-statements" style-ref="js:return-statement">
+ <start>\%[return\%]</start>
+ <end>\%{js:statement-end-or-end-of-line}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments-no-extend-parent"/>
+
+ <context id="_return-statement-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_return-statement-content -->
+
+ </include>
+ </context> <!-- /_return-statements -->
+
+
+ <!-- # Switch statement
+
+ switch (a) {
+ case 1: ... ; break;
+ case 2: ... ; break;
+ default: ...
+ }
+ -->
+
+ <context id="_case-clauses">
+ <start>\%[case\%]</start>
+ <end>:</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_case-clause-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_case-clause-content -->
+
+ </include>
+ </context> <!-- /_case-clauses -->
+
+ <context id="_default-clauses">
+ <start>\%[default\%]</start>
+ <end>:</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_default-clause-content"/>
+
+ </include>
+ </context> <!-- /_default-clauses -->
+
+ <context id="_switch-body" once-only="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_switch-body-content">
+ <include>
+ <context ref="_case-clauses"/>
+ <context ref="_default-clauses"/>
+ <context ref="statements"/>
+ </include>
+ </context> <!-- /_switch-body-content -->
+
+ </include>
+ </context> <!-- /_switch-body -->
+
+ <context id="_last-switch-body" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_switch-body"/>
+ </include>
+ </context> <!-- /_last-switch-body -->
+
+ <!-- <SwitchStatement> -->
+ <context id="_switch-statements" style-ref="js:switch-statement">
+ <start>\%[switch\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_switch-statement-content">
+ <include>
+ <context ref="_ordered-condition"/>
+ <context ref="_last-switch-body"/>
+ </include>
+ </context> <!-- /_switch-statement-content -->
+
+ </include>
+ </context> <!-- /_switch-statements -->
+
+
+ <!-- # Throw statement
+
+ throw new Error();
+ -->
+
+ <!-- <ThrowStatement> -->
+ <context id="_throw-statements" style-ref="js:throw-statement">
+ <start>\%[throw\%]</start>
+ <end>\%{js:statement-end-or-end-of-line}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments-no-extend-parent"/>
+
+ <context id="_throw-statement-content">
+ <include>
+ <context ref="js-expr:expression-with-comma"/>
+ </include>
+ </context> <!-- /_throw-statement-content -->
+
+ </include>
+ </context> <!-- /_throw-statements -->
+
+
+ <!-- # Try...catch statement
+
+ try { ... } catch (e) { ... } finally { ... }
+ -->
+
+ <context id="_try-body" once-only="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_try-body-content">
+ <include>
+ <context ref="statements"/>
+ </include>
+ </context> <!-- /_try-body-content -->
+
+ </include>
+ </context> <!-- /_try-body -->
+
+ <context id="_last-try-body" end-parent="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_try-body"/>
+ </include>
+ </context> <!-- /_last-try-body -->
+
+ <!-- <TryStatement> -->
+ <context id="_try-statements" style-ref="js:try-catch-statement">
+ <start>\%[try\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_try-statement-content">
+ <include>
+ <context ref="_last-try-body"/>
+ </include>
+ </context> <!-- /_try-statement-content -->
+
+ </include>
+ </context> <!-- /_try-statements -->
+
+ <context id="_catch-statement-exception" once-only="true">
+ <start>\(</start>
+ <end>\)</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_catch-statement-exception-content">
+ <include>
+ <context ref="js:identifier"/>
+ </include>
+ </context> <!-- /_catch-statement-exception-content -->
+
+ </include>
+ </context> <!-- /_catch-statement-exception -->
+
+ <context id="_ordered-catch-statement-exception" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="_catch-statement-exception"/>
+ </include>
+ </context> <!-- /_ordered-catch-statement-exception -->
+
+ <!-- <Catch> -->
+ <context id="_catch-statements" style-ref="js:try-catch-statement">
+ <start>\%[catch\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_catch-statement-content">
+ <include>
+ <context ref="_ordered-catch-statement-exception"/>
+ <context ref="_last-try-body"/>
+ </include>
+ </context> <!-- /_catch-statement-content -->
+
+ </include>
+ </context> <!-- /_catch-statements -->
+
+ <!-- <Finally> -->
+ <context id="_finally-statements" style-ref="js:try-catch-statement">
+ <start>\%[finally\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_finally-statement-content">
+ <include>
+ <context ref="_last-try-body"/>
+ </include>
+ </context> <!-- /_finally-statement-content -->
+
+ </include>
+ </context> <!-- /_finally-statements -->
+
+
+ <!-- # Variable declaration
+
+ var a, b = 2;
+ let [a, b] = [1, 2];
+ const { a, y: b = 4, c = 5 } = { a: 1, y: 2 };
+ -->
+
+ <define-regex id="_variable-declaration-keyword" extended="true">
+ (?: \%[ (?: const | let | var ) \%] )
+ </define-regex> <!-- /_variable-declaration-keyword -->
+
+ <context id="_variable-declaration-item-content">
+ <include>
+ <context ref="js:ordered-assignment-target"/>
+ <context ref="js:ordered-default-value-assignment"/>
+ </include>
+ </context> <!-- /_variable-declaration-item-content -->
+
+ <context id="_variable-declaration-content">
+ <include>
+
+ <context id="_variable-declaration-first-item" once-only="true">
+ <start>\%{js:before-next-token}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_variable-declaration-item-content"/>
+ </include>
+ </context> <!-- /_variable-declaration-first-item -->
+
+ <context id="_variable-declaration-items">
+ <start>,</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_variable-declaration-item-content"/>
+ </include>
+ </context> <!-- /_variable-declaration-items -->
+
+ </include>
+ </context> <!-- /_variable-declaration-content -->
+
+ <!-- <VariableStatement> / <LexicalDeclaration> -->
+ <context id="_variable-declarations" style-ref="js:variable-declaration">
+ <start>\%{_variable-declaration-keyword}</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_variable-declaration-content"/>
+ </include>
+ </context> <!-- /_variable-declarations -->
+
+ <!-- <VariableStatement> / <LexicalDeclaration> -->
+ <context id="choice-variable-declaration" style-ref="js:variable-declaration" end-parent="true">
+ <start>\%{_variable-declaration-keyword}</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_variable-declaration-content"/>
+ </include>
+ </context> <!-- /choice-variable-declaration -->
+
+ <!-- <VariableStatement> / <LexicalDeclaration> -->
+ <context id="_choice-variable-declaration-without-semicolon" style-ref="js:variable-declaration"
end-parent="true">
+ <start>\%{_variable-declaration-keyword}</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+ <context ref="_variable-declaration-content"/>
+ </include>
+ </context> <!-- /_choice-variable-declaration-without-semicolon -->
+
+
+ <!-- # While / do...while statement
+
+ while (true) loop();
+ do { ... } while (a > 0);
+ -->
+
+ <!-- <IterationStatement> (part of) -->
+ <context id="_while-statements" style-ref="js:while-statement">
+ <start>\%[while\%]</start>
+ <end>\%{js:statement-end}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_while-statement-content">
+ <include>
+ <context ref="_ordered-condition"/>
+ </include>
+ </context> <!-- /_while-statement-content -->
+
+ </include>
+ </context> <!-- /_while-statements -->
+
+ <!-- <IterationStatement> (part of) -->
+ <context id="_do-statements" style-ref="js:while-statement">
+ <start>\%[do\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_do-statement-content"/>
+
+ </include>
+ </context> <!-- /_do-statements -->
+
+
+ <!-- # With statement
+
+ with (o) doIt();
+ with (obj) { ... }
+ -->
+
+ <!-- <WithStatement> -->
+ <context id="_with-statements" style-ref="js:with-statement">
+ <start>\%[with\%]</start>
+ <end>\%{js:before-next-token}</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context ref="js:embedded-lang-hooks"/>
+ <context ref="js:comments"/>
+
+ <context id="_with-statement-content">
+ <include>
+ <context ref="_ordered-condition"/>
+ </include>
+ </context> <!-- /_with-statement-content -->
+
+ </include>
+ </context> <!-- /_with-statements -->
+
+
+ <!-- # Statements -->
+
+ <!-- <StatementList> -->
+ <!-- statements and declarations that are valid in "scripts" (as
+ opposed to modules) and in block statements -->
+ <context id="statements">
+ <include>
+ <context ref="_block-statements"/>
+ <context ref="_break-statements"/>
+ <context ref="_class-declarations"/>
+ <context ref="_continue-statements"/>
+ <context ref="_debugger-statements"/>
+ <context ref="_for-statements"/>
+ <context ref="_function-declarations"/>
+ <context ref="_if-statements"/>
+ <context ref="_else-statements"/>
+ <context ref="_label-statements"/>
+ <context ref="_return-statements"/>
+ <context ref="_switch-statements"/>
+ <context ref="_throw-statements"/>
+ <context ref="_try-statements"/>
+ <context ref="_catch-statements"/>
+ <context ref="_finally-statements"/>
+ <context ref="_variable-declarations"/>
+ <context ref="_while-statements"/>
+ <context ref="_do-statements"/>
+ <context ref="_with-statements"/>
+ <context ref="_expression-statements"/> <!-- catch-all -->
+ </include>
+ </context> <!-- /statements -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript-values.lang b/data/language-specs/javascript-values.lang
new file mode 100644
index 00000000..c1e41d5a
--- /dev/null
+++ b/data/language-specs/javascript-values.lang
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Scott Martin <scott coffeeblack org>
+ Copyright (C) 2004 Scott Martin <scott coffeeblack org>
+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
+ Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
+ Copyright (C) 2005-2007 Emanuele Aina
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="js-val" name="JavaScript Built-in Values" version="2.0" _section="Script" hidden="true">
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+ <definitions>
+
+ <!--
+ See javascript.lang for general notes, naming conventions, etc.
+ -->
+
+
+ <!-- # Global values -->
+
+ <context id="global-values">
+ <include>
+
+ <!--
+ There was a long discussion on ##javascript on freenode between
+ 'katspaugh', 'joo' and 'prog_' on whether 'undefined' should be
+ highlighted on not, specialy as a constant. The conclusion was "It can't
+ be highlighted as a constant literal value, because it can be an
+ identifier (of a variable value) but leave it be as it is. Let tradition
+ and convention obscure the details."
+ -->
+
+ <!-- 18.1 Value Properties of the Global Object -->
+ <context id="_values" style-ref="js:built-in-value">
+ <keyword>Infinity</keyword>
+ <keyword>NaN</keyword>
+ <keyword>undefined</keyword>
+ </context> <!-- /_values -->
+
+ <!-- 18.2 Function Properties of the Global Object -->
+ <context id="_functions" style-ref="js:built-in-function">
+ <keyword>decodeURIComponent</keyword>
+ <keyword>decodeURI</keyword>
+ <keyword>encodeURIComponent</keyword>
+ <keyword>encodeURI</keyword>
+ <keyword>eval</keyword>
+ <keyword>isFinite</keyword>
+ <keyword>isNaN</keyword>
+ <keyword>parseFloat</keyword>
+ <keyword>parseInt</keyword>
+ </context> <!-- /_functions -->
+
+ <context id="_constructors" style-ref="js:built-in-constructor">
+ <keyword>ArrayBuffer</keyword>
+ <keyword>Array</keyword>
+ <keyword>BigInt</keyword> <!-- ES2020 -->
+ <keyword>Boolean</keyword>
+ <keyword>Date</keyword>
+ <keyword>Error</keyword>
+ <keyword>EvalError</keyword>
+ <keyword>Float32Array</keyword>
+ <keyword>Float64Array</keyword>
+ <keyword>Function</keyword>
+ <keyword>Int16Array</keyword>
+ <keyword>Int32Array</keyword>
+ <keyword>Int8Array</keyword>
+ <keyword>Map</keyword>
+ <keyword>Number</keyword>
+ <keyword>Object</keyword>
+ <keyword>Promise</keyword>
+ <keyword>Proxy</keyword>
+ <keyword>RangeError</keyword>
+ <keyword>ReferenceError</keyword>
+ <keyword>Reflect</keyword>
+ <keyword>RegExp</keyword>
+ <keyword>Set</keyword>
+ <keyword>String</keyword>
+ <keyword>Symbol</keyword>
+ <keyword>SyntaxError</keyword>
+ <keyword>TypeError</keyword>
+ <keyword>Uint16Array</keyword>
+ <keyword>Uint32Array</keyword>
+ <keyword>Uint8Array</keyword>
+ <keyword>Uint8ClampedArray</keyword>
+ <keyword>URIError</keyword>
+ <keyword>WeakMap</keyword>
+ <keyword>WeakSet</keyword>
+ </context> <!-- /_constructors -->
+
+ <context id="_objects" style-ref="js:built-in-object">
+ <keyword>Intl</keyword>
+ <keyword>JSON</keyword>
+ <keyword>Math</keyword>
+ <keyword>WebAssembly</keyword>
+ </context> <!-- /_objects -->
+
+ <context id="_object-keywords" style-ref="js:keyword">
+ <keyword>arguments</keyword>
+ <keyword>globalThis</keyword> <!-- ES2020 -->
+ <keyword>super</keyword>
+ <keyword>this</keyword>
+ </context> <!-- /_object-keywords -->
+
+ <context id="_import-function-keyword">
+ <start extended="true">
+ \%[ import \%] (?= \%{js:import-function-keyword-suffix} )
+ </start>
+ <end>(?=\()</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <!-- no embedded-lang-hooks here -->
+ <context ref="js:comments"/>
+ </include>
+ </context> <!-- /_import-function-keyword -->
+
+ <context id="_new-target-object-keyword">
+ <start extended="true">
+ \%[ new \%] (?= \%{js:new-target-object-keyword-suffix} )
+ </start>
+ <end>\%[target\%]</end>
+ <include>
+ <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+ <context sub-pattern="0" where="end" style-ref="js:keyword"/>
+ <!-- no embedded-lang-hooks here -->
+ <context ref="js:comments"/>
+
+ <context id="_new-target-object-keyword-content">
+ <include>
+ <context ref="js:ordered-keyword-dot"/>
+ </include>
+ </context> <!-- /_new-target-object-keyword-content -->
+
+ </include>
+ </context> <!-- /_new-target-object-keyword -->
+
+ </include>
+ </context> <!-- /global-values -->
+
+
+ <!-- # Properties / methods -->
+
+ <context id="properties-methods">
+ <include>
+
+ <context id="_intl-constructors" style-ref="js:built-in-constructor">
+ <keyword>Collator</keyword>
+ <keyword>DateTimeFormat</keyword>
+ <keyword>NumberFormat</keyword>
+ <keyword>PluralRules</keyword>
+ </context> <!-- /_intl-constructors -->
+
+ <context id="_webassembly-constructors" style-ref="js:built-in-constructor">
+ <keyword>CompileError</keyword>
+ <keyword>Global</keyword>
+ <keyword>Instance</keyword>
+ <keyword>LinkError</keyword>
+ <keyword>Memory</keyword>
+ <keyword>Module</keyword>
+ <keyword>RuntimeError</keyword>
+ <keyword>Table</keyword>
+ </context> <!-- /_webassembly-constructors -->
+
+ <context id="_array-properties" style-ref="js:built-in-property">
+ <keyword>length</keyword>
+ </context> <!-- /_array-properties -->
+
+ <context id="_array-methods" style-ref="js:built-in-method">
+ <keyword>concat</keyword>
+ <keyword>copyWithin</keyword>
+ <keyword>entries</keyword>
+ <keyword>every</keyword>
+ <keyword>fill</keyword>
+ <keyword>filter</keyword>
+ <keyword>findIndex</keyword>
+ <keyword>find</keyword>
+ <keyword>flatMap</keyword> <!-- ES2019 -->
+ <keyword>flat</keyword> <!-- ES2019 -->
+ <keyword>forEach</keyword>
+ <keyword>from</keyword>
+ <keyword>includes</keyword> <!-- ES2016 -->
+ <keyword>indexOf</keyword>
+ <keyword>isArray</keyword>
+ <keyword>join</keyword>
+ <keyword>keys</keyword>
+ <keyword>lastIndexOf</keyword>
+ <keyword>map</keyword>
+ <keyword>of</keyword>
+ <keyword>pop</keyword>
+ <keyword>push</keyword>
+ <keyword>reduceRight</keyword>
+ <keyword>reduce</keyword>
+ <keyword>reverse</keyword>
+ <keyword>shift</keyword>
+ <keyword>slice</keyword>
+ <keyword>some</keyword>
+ <keyword>sort</keyword>
+ <keyword>unshift</keyword>
+ <keyword>values</keyword>
+ </context> <!-- /_array-methods -->
+
+ <context id="_arraybuffer-properties" style-ref="js:built-in-property">
+ <keyword>byteLength</keyword>
+ </context> <!-- /_arraybuffer-properties -->
+
+ <context id="_arraybuffer-methods" style-ref="js:built-in-method">
+ <keyword>isView</keyword>
+ <keyword>slice</keyword>
+ </context> <!-- /_arraybuffer-methods -->
+
+ <!-- ES2020 -->
+ <context id="_bigint-methods" style-ref="js:built-in-method">
+ <keyword>asIntN</keyword>
+ <keyword>asUintN</keyword>
+ </context> <!-- /_bigint-methods -->
+
+ <context id="_dataview-properties" style-ref="js:built-in-property">
+ <keyword>buffer</keyword>
+ <keyword>byteLength</keyword>
+ <keyword>byteOffset</keyword>
+ </context> <!-- /_dataview-properties -->
+
+ <context id="_dataview-methods" style-ref="js:built-in-method">
+ <keyword>getFloat32</keyword>
+ <keyword>getFloat64</keyword>
+ <keyword>getInt16</keyword>
+ <keyword>getInt32</keyword>
+ <keyword>getInt8</keyword>
+ <keyword>getUint16</keyword>
+ <keyword>getUint32</keyword>
+ <keyword>getUint8</keyword>
+ <keyword>setFloat32</keyword>
+ <keyword>setFloat64</keyword>
+ <keyword>setInt16</keyword>
+ <keyword>setInt32</keyword>
+ <keyword>setInt8</keyword>
+ <keyword>setUint16</keyword>
+ <keyword>setUint32</keyword>
+ <keyword>setUint8</keyword>
+ </context> <!-- /_dataview-methods -->
+
+ <context id="_date-methods" style-ref="js:built-in-method">
+ <keyword>getDate</keyword>
+ <keyword>getDay</keyword>
+ <keyword>getFullYear</keyword>
+ <keyword>getHours</keyword>
+ <keyword>getMilliseconds</keyword>
+ <keyword>getMinutes</keyword>
+ <keyword>getMonth</keyword>
+ <keyword>getSeconds</keyword>
+ <keyword>getTime</keyword>
+ <keyword>getTimezoneOffset</keyword>
+ <keyword>getUTCDate</keyword>
+ <keyword>getUTCDay</keyword>
+ <keyword>getUTCFullYear</keyword>
+ <keyword>getUTCHours</keyword>
+ <keyword>getUTCMilliseconds</keyword>
+ <keyword>getUTCMinutes</keyword>
+ <keyword>getUTCMonth</keyword>
+ <keyword>getUTCSeconds</keyword>
+ <keyword>now</keyword>
+ <keyword>parse</keyword>
+ <keyword>setDate</keyword>
+ <keyword>setFullYear</keyword>
+ <keyword>setHours</keyword>
+ <keyword>setMilliseconds</keyword>
+ <keyword>setMinutes</keyword>
+ <keyword>setMonth</keyword>
+ <keyword>setSeconds</keyword>
+ <keyword>setTime</keyword>
+ <keyword>setUTCDate</keyword>
+ <keyword>setUTCFullYear</keyword>
+ <keyword>setUTCHours</keyword>
+ <keyword>setUTCMilliseconds</keyword>
+ <keyword>setUTCMinutes</keyword>
+ <keyword>setUTCMonth</keyword>
+ <keyword>setUTCSeconds</keyword>
+ <keyword>toDateString</keyword>
+ <keyword>toISOString</keyword>
+ <keyword>toJSON</keyword>
+ <keyword>toLocaleDateString</keyword>
+ <keyword>toLocaleTimeString</keyword>
+ <keyword>toTimeString</keyword>
+ <keyword>toUTCString</keyword>
+ <keyword>UTC</keyword>
+ </context> <!-- /_date-methods -->
+
+ <context id="_error-properties" style-ref="js:built-in-property">
+ <keyword>message</keyword>
+ <keyword>name</keyword>
+ </context> <!-- /_error-properties -->
+
+ <context id="_function-properties" style-ref="js:built-in-property">
+ <keyword>length</keyword>
+ <keyword>name</keyword>
+ </context> <!-- /_function-properties -->
+
+ <context id="_function-methods" style-ref="js:built-in-method">
+ <keyword>apply</keyword>
+ <keyword>bind</keyword>
+ <keyword>call</keyword>
+ </context> <!-- /_function-methods -->
+
+ <context id="_generator-methods" style-ref="js:built-in-method">
+ <keyword>next</keyword>
+ <keyword>return</keyword>
+ <keyword>throw</keyword>
+ </context> <!-- /_generator-methods -->
+
+ <context id="_intl-methods" style-ref="js:built-in-method">
+ <keyword>formatToParts</keyword> <!-- common to intl format object instances -->
+ <keyword>format</keyword> <!-- common to intl format object instances -->
+ <keyword>getCanonicalLocales</keyword>
+ <keyword>resolvedOptions</keyword> <!-- common to intl object instances -->
+ <keyword>supportedLocalesOf</keyword> <!-- common to intl objects -->
+ </context> <!-- /_intl-methods -->
+
+ <context id="_intl-collator-methods" style-ref="js:built-in-method">
+ <keyword>compare</keyword>
+ </context> <!-- /_intl-collator-methods -->
+
+ <context id="_intl-pluralrules-methods" style-ref="js:built-in-method">
+ <keyword>select</keyword>
+ </context> <!-- /_intl-pluralrules-methods -->
+
+ <context id="_json-methods" style-ref="js:built-in-method">
+ <keyword>parse</keyword>
+ <keyword>stringify</keyword>
+ </context> <!-- /_json-methods -->
+
+ <context id="_map-properties" style-ref="js:built-in-property">
+ <keyword>size</keyword>
+ </context> <!-- /_map-properties -->
+
+ <context id="_map-methods" style-ref="js:built-in-method">
+ <keyword>clear</keyword>
+ <keyword>delete</keyword>
+ <keyword>entries</keyword>
+ <keyword>forEach</keyword>
+ <keyword>get</keyword>
+ <keyword>has</keyword>
+ <keyword>keys</keyword>
+ <keyword>set</keyword>
+ <keyword>values</keyword>
+ </context> <!-- /_map-methods -->
+
+ <context id="_math-properties" style-ref="js:built-in-property">
+ <keyword>E</keyword>
+ <keyword>LN10</keyword>
+ <keyword>LN2</keyword>
+ <keyword>LOG10E</keyword>
+ <keyword>LOG2E</keyword>
+ <keyword>PI</keyword>
+ <keyword>SQRT1_2</keyword>
+ <keyword>SQRT2</keyword>
+ </context> <!-- /_math-properties -->
+
+ <context id="_math-methods" style-ref="js:built-in-method">
+ <keyword>abs</keyword>
+ <keyword>acosh</keyword>
+ <keyword>acos</keyword>
+ <keyword>asinh</keyword>
+ <keyword>asin</keyword>
+ <keyword>atan2</keyword>
+ <keyword>atanh</keyword>
+ <keyword>atan</keyword>
+ <keyword>cbrt</keyword>
+ <keyword>ceil</keyword>
+ <keyword>clz32</keyword>
+ <keyword>cosh</keyword>
+ <keyword>cos</keyword>
+ <keyword>expm1</keyword>
+ <keyword>exp</keyword>
+ <keyword>floor</keyword>
+ <keyword>fround</keyword>
+ <keyword>hypot</keyword>
+ <keyword>imul</keyword>
+ <keyword>log10</keyword>
+ <keyword>log1p</keyword>
+ <keyword>log2</keyword>
+ <keyword>log</keyword>
+ <keyword>max</keyword>
+ <keyword>min</keyword>
+ <keyword>pow</keyword>
+ <keyword>random</keyword>
+ <keyword>round</keyword>
+ <keyword>sign</keyword>
+ <keyword>sinh</keyword>
+ <keyword>sin</keyword>
+ <keyword>sqrt</keyword>
+ <keyword>tanh</keyword>
+ <keyword>tan</keyword>
+ <keyword>trunc</keyword>
+ </context> <!-- /_math-methods -->
+
+ <context id="_number-properties" style-ref="js:built-in-property">
+ <keyword>EPSILON</keyword>
+ <keyword>MAX_SAFE_INTEGER</keyword>
+ <keyword>MAX_VALUE</keyword>
+ <keyword>MIN_SAFE_INTEGER</keyword>
+ <keyword>MIN_VALUE</keyword>
+ <keyword>NaN</keyword>
+ <keyword>NEGATIVE_INFINITY</keyword>
+ <keyword>POSITIVE_INFINITY</keyword>
+ </context> <!-- /_number-properties -->
+
+ <context id="_number-methods" style-ref="js:built-in-method">
+ <keyword>isFinite</keyword>
+ <keyword>isInteger</keyword>
+ <keyword>isNaN</keyword>
+ <keyword>isSafeInteger</keyword>
+ <keyword>parseFloat</keyword>
+ <keyword>parseInt</keyword>
+ <keyword>toExponential</keyword>
+ <keyword>toFixed</keyword>
+ <keyword>toPrecision</keyword>
+ </context> <!-- /_number-methods -->
+
+ <context id="_object-properties" style-ref="js:built-in-property">
+ <keyword>constructor</keyword>
+ <keyword>prototype</keyword>
+ </context> <!-- /_object-properties -->
+
+ <context id="_object-methods" style-ref="js:built-in-method">
+ <keyword>assign</keyword>
+ <keyword>create</keyword>
+ <keyword>defineProperties</keyword>
+ <keyword>defineProperty</keyword>
+ <keyword>entries</keyword> <!-- ES2017 -->
+ <keyword>freeze</keyword>
+ <keyword>fromEntries</keyword> <!-- ES2019 -->
+ <keyword>getOwnPropertyDescriptors</keyword> <!-- ES2017 -->
+ <keyword>getOwnPropertyDescriptor</keyword>
+ <keyword>getOwnPropertyNames</keyword>
+ <keyword>getOwnPropertySymbols</keyword>
+ <keyword>getPrototypeOf</keyword>
+ <keyword>hasOwnProperty</keyword>
+ <keyword>isExtensible</keyword>
+ <keyword>isFrozen</keyword>
+ <keyword>isPrototypeOf</keyword>
+ <keyword>isSealed</keyword>
+ <keyword>is</keyword>
+ <keyword>keys</keyword>
+ <keyword>preventExtensions</keyword>
+ <keyword>propertyIsEnumerable</keyword>
+ <keyword>seal</keyword>
+ <keyword>setPrototypeOf</keyword>
+ <keyword>toLocaleString</keyword>
+ <keyword>toString</keyword>
+ <keyword>valueOf</keyword>
+ <keyword>values</keyword> <!-- ES2017 -->
+ </context> <!-- /_object-methods -->
+
+ <context id="_promise-methods" style-ref="js:built-in-method">
+ <keyword>allSettled</keyword> <!-- ES2020 -->
+ <keyword>all</keyword>
+ <keyword>catch</keyword>
+ <keyword>finally</keyword> <!-- ES2018 -->
+ <keyword>race</keyword>
+ <keyword>reject</keyword>
+ <keyword>resolve</keyword>
+ <keyword>then</keyword>
+ </context> <!-- /_promise-methods -->
+
+ <context id="_proxy-methods" style-ref="js:built-in-method">
+ <keyword>revocable</keyword>
+ </context> <!-- /_proxy-methods -->
+
+ <context id="_reflect-methods" style-ref="js:built-in-method">
+ <keyword>apply</keyword>
+ <keyword>construct</keyword>
+ <keyword>defineProperty</keyword>
+ <keyword>deleteProperty</keyword>
+ <keyword>getOwnPropertyDescriptor</keyword>
+ <keyword>getPrototypeOf</keyword>
+ <keyword>get</keyword>
+ <keyword>has</keyword>
+ <keyword>isExtensible</keyword>
+ <keyword>ownKeys</keyword>
+ <keyword>preventExtensions</keyword>
+ <keyword>setPrototypeOf</keyword>
+ <keyword>set</keyword>
+ </context> <!-- /_reflect-methods -->
+
+ <context id="_regexp-properties" style-ref="js:built-in-property">
+ <keyword>flags</keyword>
+ <keyword>global</keyword>
+ <keyword>ignoreCase</keyword>
+ <keyword>lastIndex</keyword>
+ <keyword>multiline</keyword>
+ <keyword>source</keyword>
+ <keyword>sticky</keyword>
+ <keyword>unicode</keyword>
+ </context> <!-- /_regexp-properties -->
+
+ <context id="_regexp-methods" style-ref="js:built-in-method">
+ <keyword>exec</keyword>
+ <keyword>test</keyword>
+ </context> <!-- /_regexp-methods -->
+
+ <context id="_set-properties" style-ref="js:built-in-property">
+ <keyword>size</keyword>
+ </context> <!-- /_set-properties -->
+
+ <context id="_set-methods" style-ref="js:built-in-method">
+ <keyword>add</keyword>
+ <keyword>clear</keyword>
+ <keyword>delete</keyword>
+ <keyword>entries</keyword>
+ <keyword>forEach</keyword>
+ <keyword>has</keyword>
+ <keyword>keys</keyword>
+ <keyword>values</keyword>
+ </context> <!-- /_set-methods -->
+
+ <context id="_string-properties" style-ref="js:built-in-property">
+ <keyword>length</keyword>
+ </context> <!-- /_string-properties -->
+
+ <context id="_string-methods" style-ref="js:built-in-method">
+ <keyword>charAt</keyword>
+ <keyword>charCodeAt</keyword>
+ <keyword>codePointAt</keyword>
+ <keyword>concat</keyword>
+ <keyword>endsWith</keyword>
+ <keyword>fromCharCode</keyword>
+ <keyword>fromCodePoint</keyword>
+ <keyword>includes</keyword>
+ <keyword>indexOf</keyword>
+ <keyword>lastIndexOf</keyword>
+ <keyword>localeCompare</keyword>
+ <keyword>matchAll</keyword> <!-- ES2020 -->
+ <keyword>match</keyword>
+ <keyword>normalize</keyword>
+ <keyword>padEnd</keyword> <!-- ES2017 -->
+ <keyword>padStart</keyword> <!-- ES2017 -->
+ <keyword>raw</keyword>
+ <keyword>repeat</keyword>
+ <keyword>replace</keyword>
+ <keyword>search</keyword>
+ <keyword>slice</keyword>
+ <keyword>split</keyword>
+ <keyword>startsWith</keyword>
+ <keyword>substring</keyword>
+ <keyword>toLocaleLowerCase</keyword>
+ <keyword>toLocaleUpperCase</keyword>
+ <keyword>toLowerCase</keyword>
+ <keyword>toUpperCase</keyword>
+ <keyword>trimEnd</keyword> <!-- ES2019 -->
+ <keyword>trimStart</keyword> <!-- ES2019 -->
+ <keyword>trim</keyword>
+ </context> <!-- /_string-methods -->
+
+ <context id="_symbol-properties" style-ref="js:built-in-property">
+ <keyword>asyncIterator</keyword> <!-- ES2018 -->
+ <keyword>description</keyword> <!-- ES2019 -->
+ <keyword>hasInstance</keyword>
+ <keyword>isConcatSpreadable</keyword>
+ <keyword>iterator</keyword>
+ <keyword>matchAll</keyword>
+ <keyword>match</keyword>
+ <keyword>replace</keyword>
+ <keyword>search</keyword>
+ <keyword>species</keyword>
+ <keyword>split</keyword>
+ <keyword>toPrimitive</keyword>
+ <keyword>toStringTag</keyword>
+ <keyword>unscopables</keyword>
+ </context> <!-- /_symbol-properties -->
+
+ <context id="_symbol-methods" style-ref="js:built-in-method">
+ <keyword>for</keyword>
+ <keyword>keyFor</keyword>
+ </context> <!-- /_symbol-methods -->
+
+ <!-- TypedArray is one of these objects:
+ * Float32Array
+ * Float64Array
+ * Int16Array
+ * Int32Array
+ * Int8Array
+ * Uint16Array
+ * Uint32Array
+ * Uint8Array
+ * Uint8ClampedArray
+ -->
+ <context id="_typedarray-properties" style-ref="js:built-in-property">
+ <keyword>buffer</keyword>
+ <keyword>byteLength</keyword>
+ <keyword>byteOffset</keyword>
+ <keyword>BYTES_PER_ELEMENT</keyword>
+ <keyword>length</keyword>
+ <keyword>name</keyword>
+ </context> <!-- /_typedarray-properties -->
+
+ <context id="_typedarray-methods" style-ref="js:built-in-method">
+ <keyword>copyWithin</keyword>
+ <keyword>entries</keyword>
+ <keyword>every</keyword>
+ <keyword>fill</keyword>
+ <keyword>filter</keyword>
+ <keyword>findIndex</keyword>
+ <keyword>find</keyword>
+ <keyword>forEach</keyword>
+ <keyword>from</keyword>
+ <keyword>indexOf</keyword>
+ <keyword>join</keyword>
+ <keyword>keys</keyword>
+ <keyword>lastIndexOf</keyword>
+ <keyword>map</keyword>
+ <keyword>of</keyword>
+ <keyword>reduceRight</keyword>
+ <keyword>reduce</keyword>
+ <keyword>reverse</keyword>
+ <keyword>set</keyword>
+ <keyword>slice</keyword>
+ <keyword>some</keyword>
+ <keyword>sort</keyword>
+ <keyword>subarray</keyword>
+ <keyword>values</keyword>
+ </context> <!-- /_typedarray-methods -->
+
+ <context id="_weakmap-methods" style-ref="js:built-in-method">
+ <keyword>delete</keyword>
+ <keyword>get</keyword>
+ <keyword>has</keyword>
+ <keyword>set</keyword>
+ </context> <!-- /_weakmap-methods -->
+
+ <context id="_weakset-methods" style-ref="js:built-in-method">
+ <keyword>add</keyword>
+ <keyword>delete</keyword>
+ <keyword>has</keyword>
+ </context> <!-- /_weakset-methods -->
+
+ <context id="_webassembly-methods" style-ref="js:built-in-method">
+ <keyword>compileStreaming</keyword>
+ <keyword>compile</keyword>
+ <keyword>instantiateStreaming</keyword>
+ <keyword>instantiate</keyword>
+ <keyword>validate</keyword>
+ </context> <!-- /_webassembly-methods -->
+
+ <context id="_webassembly-instance-properties" style-ref="js:built-in-property">
+ <keyword>exports</keyword>
+ </context> <!-- /_webassembly-instance-properties -->
+
+ <context id="_webassembly-global-properties" style-ref="js:built-in-property">
+ <keyword>value</keyword>
+ </context> <!-- /_webassembly-global-properties -->
+
+ <context id="_webassembly-module-methods" style-ref="js:built-in-method">
+ <keyword>customSections</keyword>
+ <keyword>exports</keyword>
+ <keyword>imports</keyword>
+ </context> <!-- /_webassembly-module-methods -->
+
+ <context id="_webassembly-memory-properties" style-ref="js:built-in-property">
+ <keyword>buffer</keyword>
+ </context> <!-- /_webassembly-memory-properties -->
+
+ <context id="_webassembly-memory-methods" style-ref="js:built-in-method">
+ <keyword>grow</keyword>
+ </context> <!-- /_webassembly-memory-methods -->
+
+ <context id="_webassembly-table-properties" style-ref="js:built-in-property">
+ <keyword>length</keyword>
+ </context> <!-- /_webassembly-table-properties -->
+
+ <context id="_webassembly-table-methods" style-ref="js:built-in-method">
+ <keyword>get</keyword>
+ <keyword>grow</keyword>
+ <keyword>set</keyword>
+ </context> <!-- /_webassembly-table-methods -->
+
+ </include>
+ </context> <!-- /properties-methods -->
+
+ </definitions>
+</language>
diff --git a/data/language-specs/javascript.lang b/data/language-specs/javascript.lang
index d9627cbf..ca904861 100644
--- a/data/language-specs/javascript.lang
+++ b/data/language-specs/javascript.lang
@@ -8,7 +8,7 @@
Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
Copyright (C) 2005-2007 Emanuele Aina
- Copyright (C) 2018 Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
GtkSourceView is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -34,838 +34,704 @@
</metadata>
<styles>
- <style id="escape" name="Escaped Character" map-to="def:special-char"/>
- <style id="decimal" name="Decimal Number" map-to="def:decimal"/>
- <style id="base-n-number" name="Base-N Number" map-to="def:base-n-integer"/>
- <style id="big-integer" name="Big Integer" map-to="def:number"/>
- <style id="null-value" name="Null Value" map-to="def:special-constant"/>
- <style id="undefined-value" name="Undefined Value" map-to="def:special-constant"/>
- <style id="boolean" name="Boolean Value" map-to="def:boolean"/>
- <style id="keyword" name="Keyword" map-to="def:keyword"/>
- <style id="type" name="Data Type" map-to="def:type"/>
- <style id="function" name="Function" map-to="def:builtin"/>
- <style id="properties" name="Properties" map-to="def:statement"/>
- <style id="constructors" name="Constructors" map-to="def:type"/>
- <style id="future-words" name="Future Reserved Keywords" map-to="def:error"/>
- <style id="string" name="String" map-to="def:string"/>
- <style id="regex" name="Regular Expression" map-to="def:string"/>
+
+ <!-- General -->
+ <style id="error" name="Error" map-to="def:error"/>
+ <style id="keyword" name="Keyword" map-to="def:keyword"/>
+ <style id="reserved-word" name="Reserved word" map-to="def:reserved"/>
+ <style id="directive" name="Directive" map-to="def:preprocessor"/>
+
+ <!-- Literals -->
+ <style id="null-value" name="Null value" map-to="def:special-constant"/>
+ <style id="boolean" name="Boolean value" map-to="def:boolean"/>
+ <style id="decimal" name="Decimal number" map-to="def:decimal"/>
+ <style id="base-n-integer" name="Base-n integer" map-to="def:base-n-integer"/>
+ <style id="binary-integer" name="Binary integer" map-to="js:base-n-integer"/>
+ <style id="octal-integer" name="Octal integer" map-to="js:base-n-integer"/>
+ <style id="hex-integer" name="Hexadecimal integer" map-to="js:base-n-integer"/>
+ <style id="escape" name="Escaped character" map-to="def:special-char"/>
+ <style id="string" name="String" map-to="def:string"/>
+ <style id="included-file" name="Included file" map-to="js:string"/>
+ <style id="regex" name="Regular expression" map-to="def:string"/>
+ <style id="regex-class" name="RE character class" map-to="def:special-char"/>
+ <style id="regex-group" name="RE group name" map-to="def:identifier"/>
+ <style id="regex-flag" name="RE flag" map-to="def:special-constant"/>
+ <style id="template-literal" name="Template literal" map-to="js:string"/>
+ <style id="template-placeholder" name="Template placeholder" map-to="def:preprocessor"/>
+
+ <!-- Built-in values -->
+ <style id="built-in-value" name="Built-in value" map-to="def:special-constant"/>
+ <style id="built-in-function" name="Built-in function" map-to="def:builtin"/>
+ <style id="built-in-constructor" name="Built-in constructor" map-to="def:type"/>
+ <style id="built-in-object" name="Built-in object" map-to="def:builtin"/>
+ <style id="built-in-property" name="Built-in property" map-to="def:statement"/>
+ <style id="built-in-method" name="Built-in method" map-to="js:built-in-function"/>
+
+ <!-- The following are for debugging use -->
+
+ <!-- General -->
+ <style id="identifier" name="Identifier"/>
+ <style id="rest-syntax" name="Rest syntax"/>
+ <style id="spread-syntax" name="Spread syntax"/>
+ <style id="array-destructuring" name="Array destructuring"/>
+ <style id="object-destructuring" name="Object destructuring"/>
+
+ <!-- Literals -->
+ <style id="array-literal" name="Array literal"/>
+ <style id="object-literal" name="Object literal"/>
+
+ <!-- Functions and classes -->
+ <style id="function-expression" name="Function expression"/>
+ <style id="class-expression" name="Class expression"/>
+
+ <!-- Expressions -->
+ <style id="grouping" name="Grouping"/>
+ <style id="grouping-operator" name="Grouping operator"/>
+ <style id="increment-decrement-operator" name="Increment decrement operator"/>
+ <style id="unary-operator" name="Unary operator"/>
+ <style id="binary-operator" name="Binary operator"/>
+ <style id="comma-operator" name="Comma operator"/>
+ <style id="ternary-operator" name="Ternary operator"/>
+ <style id="expression" name="Expression"/>
+
+ <!-- Statements -->
+ <style id="block-statement" name="Block statement"/>
+ <style id="break-statement" name="Break statement"/>
+ <style id="continue-statement" name="Continue statement"/>
+ <style id="debugger-statement" name="Debugger statement"/>
+ <style id="expression-statement" name="Expression statement"/>
+ <style id="for-statement" name="For statement"/>
+ <style id="if-statement" name="If statement"/>
+ <style id="else-statement" name="Else statement"/>
+ <style id="label-statement" name="Label statement"/>
+ <style id="return-statement" name="Return statement"/>
+ <style id="switch-statement" name="Switch statement"/>
+ <style id="throw-statement" name="Throw statement"/>
+ <style id="try-catch-statement" name="Try catch statement"/>
+ <style id="variable-declaration" name="Variable declaration"/>
+ <style id="while-statement" name="While statement"/>
+ <style id="with-statement" name="With statement"/>
+
+ <!-- Modules -->
+ <style id="export-import-declaration" name="Export import declaration"/>
+
</styles>
+ <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
<definitions>
- <define-regex id="is-member">(?<=[^.]\.)</define-regex>
+ <!--
+ "Tags" (e.g. <Script>) or section numbers (e.g. 13.2 Block)
+ inside comments refer to relevant productions or sections from
+ the ECMAScript Language Specification, respectively.
+
+ Current draft: https://tc39.es/ecma262/
+
+ Supported level: ES2019
+
+ Supported ES2020 proposals:
+ * String.prototype.matchAll
+ * import()
+ * BigInt
+ * Promise.allSettled
+ * globalThis
+
+ Features from Annex B of the spec are not highlighted to
+ discourage their use, except:
+ * Legacy octal number literals: Highlighted as errors to
+ reduce accidental usage
+ * Legacy octal escape sequences: Highlighted as normal escapes
+ as they are inside strings; the string and error styles may
+ conflict with each other
+
+ Not supported yet:
+ * SharedArrayBuffer and Atomics (ES2017): Browser support is
+ minimal / disabled to mitigate speculative side-channel
+ attacks (Meltdown / Spectre)
+ * RegExp lookbehind assertions (ES2018): Lookahead assertions
+ are not highlighted either
+
+
+ Also supported:
+ * ECMAScript Internationalization API
+ Current draft: https://tc39.es/ecma402/
+ Supported level: 2018
+ * WebAssembly JavaScript Interface
+ Editor's draft: https://webassembly.github.io/spec/js-api/
+ Supported level: Candidate Recommendation, 18 July 2019
+ * WebAssembly Web API
+ Editor's draft: https://webassembly.github.io/spec/web-api/
+ Supported level: Candidate Recommendation, 18 July 2019
+
+
+ Naming convention for contexts:
+ * Prefixes:
+ * "_" (underscore): "Private" to one or more "public"
+ contexts (can still be overriden by child languages)
+ * "ordered-": Wrapper for another context so that it can only
+ match in a referenced position (has once-only="true")
+ * "last-": An "ordered-" wrapper with end-parent="true",
+ which will end the parent under all circumstances
+ * "choice-": One option in a group where only one can be
+ selected (has end-parent="true")
+ * Suffixes:
+ * Plural: Can match multiple times
+ * Singular: Has once-only="true"
+ * "-end-parent": Has end-parent="true"
+ * "-no-extend-parent": Has extend-parent="false"
+ * "-content": Holds children of container contexts
+
+ End-parent contexts are container contexts to avoid the
+ end-parent bug:
+ https://gitlab.gnome.org/GNOME/gtksourceview/issues/14
+ -->
+
+
+ <!-- # General -->
+
+ <!-- <UnicodeEscapeSequence> -->
+ <define-regex id="unicode-escape" extended="true">
+ (?: \\u (?: [0-9a-fA-F]{4} | \{ [0-9a-fA-F]{1,} \} ) )
+ </define-regex> <!-- /unicode-escape -->
+
+ <!-- <IdentifierStart> -->
+ <!-- should include all Unicode ID_Start code points -->
+ <define-regex id="identifier-start" extended="true">
+ (?: [a-zA-Z_$] | \%{unicode-escape} )
+ </define-regex> <!-- /identifier-start -->
- <!--regex-->
- <define-regex id="regex-opts">[gim]*</define-regex>
+ <!-- for lookbehinds -->
+ <define-regex id="identifier-char">[a-zA-Z0-9_$]</define-regex>
+
+ <!-- <IdentifierPart> -->
+ <!-- should include all Unicode ID_Continue code points,
+ ZWNJ / ZWJ -->
+ <define-regex id="identifier-part" extended="true">
+ (?: \%{identifier-char} | \%{unicode-escape} )
+ </define-regex> <!-- /identifier-part -->
+
+ <!-- <IdentifierName> -->
+ <define-regex id="identifier" extended="true">
+ (?: \%{identifier-start} \%{identifier-part}* )
+ </define-regex> <!-- /identifier-->
+
+ <define-regex id="before-next-token">(?=\S)</define-regex>
+
+ <define-regex id="statement-end" extended="true">
+ (?: ; | \%{before-next-token} )
+ </define-regex> <!-- /statement-end -->
+
+ <define-regex id="statement-end-or-end-of-line" extended="true">
+ (?: \%{statement-end} | $ )
+ </define-regex> <!-- /statement-end-or-end-of-line -->
+
+ <!-- wherever this is used, the highlighting will be more brittle,
+ because comments can span multiple lines -->
+ <define-regex id="optional-whitespace-or-comments" extended="true">
+ (?> (?: \s+ | /\*.*?\*/ )* )
+ </define-regex> <!-- /optional-whitespace-or-comments -->
+
+ <define-regex id="generator-modifier">\*</define-regex>
+
+ <!-- "unknown id" errors can occur when using a regex defined in one
+ component file in another component file
+ so we move the definitions of these regexes here
+ -->
- <!--contexts NOT used in the main context-->
- <context id="escape" style-ref="escape">
- <match extended="true">
- \\
+ <define-regex id="import-function-keyword-suffix" extended="true">
+ (?:
+ \%{optional-whitespace-or-comments}
+ \(
+ )
+ </define-regex> <!-- /import-function-keyword-suffix -->
+
+ <define-regex id="new-target-object-keyword-suffix" extended="true">
+ (?:
+ \%{optional-whitespace-or-comments}
+ \.
+ \%{optional-whitespace-or-comments}
+ target \%]
+ )
+ </define-regex> <!-- /new-target-object-keyword-suffix -->
+
+ <!-- async function (ES2017)
+ no line terminator allowed between "async" and "function" -->
+ <define-regex id="function-expression-keyword" extended="true">
+ (?:
(?:
- (?: [1-7][0-7]{0,2} | [0-7]{2,3} ) | # octal escape (\0 is the null character, not octal)
- x[0-9a-fA-F]{2} | # hexadecimal escape
- u[0-9a-fA-F]{4} | # unicode escape
- u\{[0-9a-fA-F]{1,}\} | # unicode code point escape
- . # single character escape
- )
- </match>
- </context>
-
- <!-- only valid in regular expressions -->
- <context id="control-escape" style-ref="escape">
- <match>\\c[a-zA-Z]</match>
- </context>
-
- <context id="regex-bracketed" style-ref="escape" style-inside="true">
+ \%[ async \%]
+ \%{optional-whitespace-or-comments}
+ )?
+ \%[ function \%]
+ )
+ </define-regex> <!-- /function-expression-keyword -->
+
+ <define-regex id="class-expression-keyword" extended="true">
+ (?: \%[ class \%] )
+ </define-regex> <!-- /class-expression-keyword -->
+
+ <!-- ## Embedded lang hooks
+ a placeholder context where an embedding language (e.g. html)
+ can <replace>
+ -->
+
+ <context id="embedded-lang-hooks"/>
+
+ <!-- ## Comments -->
+
+ <context id="_in-comment" class-disabled="no-spell-check">
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="def:in-comment" original="true"/>
+ </include>
+ </context> <!-- /_in-comment -->
+
+ <replace id="def:in-comment" ref="_in-comment"/>
+
+ <!-- includes def:in-comment instead of def:in-line-comment,
+ because line continuations are not allowed inside single-line
+ comments -->
+ <context id="_c-like-comment" style-ref="def:comment" end-at-line-end="true"
class-disabled="no-spell-check" class="comment">
+ <start>//</start>
+ <include>
+ <context ref="def:in-comment"/>
+ </include>
+ </context> <!-- /_c-like-comment -->
+
+ <context id="_c-like-comment-no-extend-parent" style-ref="def:comment" end-at-line-end="true"
class-disabled="no-spell-check" class="comment" extend-parent="false">
+ <start>//</start>
+ <include>
+ <context ref="def:in-comment"/>
+ </include>
+ </context> <!-- /_c-like-comment-no-extend-parent -->
+
+ <context id="_c-like-comment-multiline-no-extend-parent" style-ref="def:comment"
class-disabled="no-spell-check" class="comment" extend-parent="false">
+ <start>/\*</start>
+ <end>\*/</end>
+ <include>
+ <context ref="def:in-comment"/>
+ </include>
+ </context> <!-- /_c-like-comment-multiline-no-extend-parent -->
+
+ <context id="comments">
+ <include>
+ <context ref="_c-like-comment"/>
+ <context ref="def:c-like-comment-multiline"/>
+ <context ref="def:c-like-close-comment-outside-comment"/>
+ </include>
+ </context> <!-- /comments -->
+
+ <!-- for statements that cannot contain line terminators -->
+ <context id="comments-no-extend-parent">
+ <include>
+ <context ref="_c-like-comment-no-extend-parent"/>
+ <context ref="_c-like-comment-multiline-no-extend-parent"/>
+ <context ref="def:c-like-close-comment-outside-comment"/>
+ </include>
+ </context> <!-- /comments-no-extend-parent -->
+
+ <!-- ## Identifiers -->
+
+ <!-- <ReservedWord> -->
+ <context id="_reserved-words">
+ <include>
+
+ <!-- <Keyword> -->
+ <context id="_keywords" style-ref="reserved-word">
+ <keyword>await</keyword> <!-- ES2017 -->
+ <keyword>break</keyword>
+ <keyword>case</keyword>
+ <keyword>catch</keyword>
+ <keyword>class</keyword>
+ <keyword>const</keyword>
+ <keyword>continue</keyword>
+ <keyword>debugger</keyword>
+ <keyword>default</keyword>
+ <keyword>delete</keyword>
+ <keyword>do</keyword>
+ <keyword>else</keyword>
+ <keyword>export</keyword>
+ <keyword>extends</keyword>
+ <keyword>finally</keyword>
+ <keyword>for</keyword>
+ <keyword>function</keyword>
+ <keyword>if</keyword>
+ <keyword>import</keyword>
+ <keyword>instanceof</keyword>
+ <keyword>in</keyword>
+ <keyword>new</keyword>
+ <keyword>return</keyword>
+ <keyword>super</keyword>
+ <keyword>switch</keyword>
+ <keyword>this</keyword>
+ <keyword>throw</keyword>
+ <keyword>try</keyword>
+ <keyword>typeof</keyword>
+ <keyword>var</keyword>
+ <keyword>void</keyword>
+ <keyword>while</keyword>
+ <keyword>with</keyword>
+ <keyword>yield</keyword> <!-- allowed as a variable name in non-strict mode -->
+ </context> <!-- /_keywords -->
+
+ <!-- "treated as reserved words through static semantic
+ restrictions"
+ https://tc39.github.io/ecma262/#sec-keywords -->
+ <context id="_strict-mode-keywords" style-ref="reserved-word">
+ <keyword>let</keyword>
+ <keyword>static</keyword>
+ </context> <!-- /_strict-mode-keywords -->
+
+ <!-- <FutureReservedWord> -->
+ <context id="_future-reserved-words" style-ref="reserved-word">
+ <keyword>enum</keyword>
+ </context> <!-- /_future-reserved-words -->
+
+ <!-- usage in strict mode "restricted using static semantic
+ restrictions"
+ https://tc39.github.io/ecma262/#sec-future-reserved-words -->
+ <context id="_strict-mode-future-reserved-words" style-ref="reserved-word">
+ <keyword>implements</keyword>
+ <keyword>interface</keyword>
+ <keyword>package</keyword>
+ <keyword>private</keyword>
+ <keyword>protected</keyword>
+ <keyword>public</keyword>
+ </context> <!-- /_strict-mode-future-reserved-words -->
+
+ <context ref="js-lit:null-value" style-ref="reserved-word"/>
+ <context ref="js-lit:boolean" style-ref="reserved-word"/>
+ </include>
+ </context> <!-- /_reserved-words -->
+
+ <context id="_identifier-names" style-ref="identifier">
+ <match>\%{identifier}</match>
+ </context> <!-- /_identifier-names -->
+
+ <context id="choice-identifier-name" end-parent="true">
+ <start>(?=\%{identifier-start})</start>
+ <end>\%{def:always-match}</end>
+ <include>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not extend the context by matching comments or
+ embedded-lang-hooks, which may lead to multiple identifiers -->
+
+ <context id="_identifier-name-content">
+ <include>
+ <context ref="_identifier-names"/>
+ </include>
+ </context> <!-- /_identifier-name-content -->
+
+ </include>
+ </context> <!-- /choice-identifier-name -->
+
+ <context id="_identifier-content">
+ <include>
+ <context ref="_reserved-words"/>
+ <context ref="_identifier-names"/>
+ </include>
+ </context> <!-- /_identifier-content -->
+
+ <context id="identifier" once-only="true">
+ <start>(?=\%{identifier-start})</start>
+ <end>\%{def:always-match}</end>
+ <include>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not extend the context by matching comments or
+ embedded-lang-hooks, which may lead to multiple identifiers -->
+ <context ref="_identifier-content"/>
+ </include>
+ </context> <!-- /identifier -->
+
+ <context id="choice-identifier" end-parent="true">
+ <start>(?=\%{identifier-start})</start>
+ <end>\%{def:always-match}</end>
+ <include>
+ <!-- no embedded-lang-hooks here -->
+ <!-- no comments here -->
+ <!-- do not extend the context by matching comments or
+ embedded-lang-hooks, which may lead to multiple identifiers -->
+ <context ref="_identifier-content"/>
+ </include>
+ </context> <!-- /choice-identifier -->
+
+ <context id="ordered-identifier" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="identifier"/>
+ </include>
+ </context> <!-- /ordered-identifier -->
+
+ <!-- ## Default value assignment -->
+
+ <!-- <Initializer> -->
+ <context id="_default-value-assignment" once-only="true">
+ <start>=</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+
+ <context id="_default-value-assignment-content">
+ <include>
+ <context ref="js-expr:expression-without-comma"/>
+ </include>
+ </context> <!-- /_default-value-assignment-content -->
+
+ </include>
+ </context> <!-- /_default-value-assignment -->
+
+ <context id="ordered-default-value-assignment" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="_default-value-assignment"/>
+ </include>
+ </context> <!-- /ordered-default-value-assignment -->
+
+ <!-- ## Misc syntax -->
+
+ <context id="_keyword-dot" style-ref="keyword" once-only="true">
+ <match>\.</match>
+ </context> <!-- /_keyword-dot -->
+
+ <context id="ordered-keyword-dot" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="_keyword-dot"/>
+ </include>
+ </context> <!-- /ordered-keyword-dot -->
+
+ <context id="_rest-syntax" style-ref="rest-syntax" once-only="true">
+ <match>\.\.\.</match>
+ </context> <!-- /_rest-syntax -->
+
+ <context id="ordered-rest-syntax" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="_rest-syntax"/>
+ </include>
+ </context> <!-- /ordered-rest-syntax -->
+
+ <context id="_spread-syntax" style-ref="spread-syntax" once-only="true">
+ <match>\.\.\.</match>
+ </context> <!-- /_spread-syntax -->
+
+ <context id="ordered-spread-syntax" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="_spread-syntax"/>
+ </include>
+ </context> <!-- /ordered-spread-syntax -->
+
+ <context id="generator-modifier" once-only="true">
+ <match>\%{generator-modifier}</match>
+ </context> <!-- /generator-modifier -->
+
+ <context id="ordered-generator-modifier" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="generator-modifier"/>
+ </include>
+ </context> <!-- /ordered-generator-modifier -->
+
+
+ <!-- # Assignment target -->
+
+ <!-- ## Array destructuring
+
+ [ a, b, ...rest ] = [ 1, 2, 3, 4 ]
+ [ a = 1, b = 2, c = 3 ] = [ 11, 12 ]
+ -->
+
+ <context id="_array-destructuring-element-content">
+ <include>
+ <context ref="ordered-rest-syntax"/>
+ <context ref="ordered-assignment-target"/>
+ <context ref="ordered-default-value-assignment"/>
+ </include>
+ </context> <!-- /_array-destructuring-element-content -->
+
+ <!-- <ArrayBindingPattern> -->
+ <context id="_choice-array-destructuring" style-ref="array-destructuring" end-parent="true">
<start>\[</start>
<end>]</end>
<include>
- <context ref="control-escape"/>
- <context ref="escape"/>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+
+ <context id="_array-destructuring-content">
+ <include>
+
+ <context id="_array-destructuring-first-element" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+ <context ref="_array-destructuring-element-content"/>
+ </include>
+ </context> <!-- /_array-destructuring-first-element -->
+
+ <context id="_array-destructuring-elements">
+ <start>,</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+ <context ref="_array-destructuring-element-content"/>
+ </include>
+ </context> <!-- /_array-destructuring-elements -->
+
+ </include>
+ </context> <!-- /_array-destructuring-content -->
+
</include>
- </context>
+ </context> <!-- /_choice-array-destructuring -->
- <!--contexts used in the main context-->
- <context id="string" style-ref="string" end-at-line-end="true" class="string"
class-disabled="no-spell-check">
- <start>"</start>
- <end>"</end>
+ <!-- ## Object destructuring
+
+ { a, y: b, ...rest } = { a: 1, y: 2, i: 3, y: 4 }
+ { a = 1, y: b = 2, c = 3 } = { a: 11, y: 12 }
+ -->
+
+ <context id="_object-destructuring-assignment-target" once-only="true">
+ <start>:</start>
+ <end>\%{before-next-token}</end>
<include>
- <context ref="escape"/>
- <context ref="def:line-continue"/>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+
+ <context id="_object-destructuring-assignment-target-content">
+ <include>
+ <context ref="ordered-assignment-target"/>
+ </include>
+ </context> <!-- /_object-destructuring-assignment-target-content -->
+
</include>
- </context>
+ </context> <!-- /_object-destructuring-assignment-target -->
- <context id="single-quoted-string" style-ref="string" end-at-line-end="true" class="string"
class-disabled="no-spell-check">
- <start>'</start>
- <end>'</end>
+ <context id="_ordered-object-destructuring-assignment-target" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
<include>
- <context ref="escape"/>
- <context ref="def:line-continue"/>
+ <context ref="_object-destructuring-assignment-target"/>
</include>
- </context>
-
- <context id="regex-simple" style-ref="regex">
- <start extended="true">
- ((?<=([(]|\s))|^)
- \/
- (?=
- ([^/\\]*(\\.))*
- [^/]*
- \/
- \%{regex-opts}
- \s*
- ([),;.\/\]:}]|$)
- )</start>
- <end>\/\%{regex-opts}</end>
+ </context> <!-- /_ordered-object-destructuring-assignment-target -->
+
+ <context id="_object-destructuring-property-content">
<include>
- <context ref="control-escape"/>
- <context ref="escape"/>
- <context ref="regex-bracketed"/>
+ <context ref="ordered-rest-syntax"/> <!-- ES2018 -->
+ <context ref="js-lit:ordered-property-name"/>
+ <context ref="_ordered-object-destructuring-assignment-target"/>
+ <context ref="ordered-default-value-assignment"/>
</include>
- </context>
-
- <context id="decimal" style-ref="decimal">
- <match extended="true">
- (?<! [\w\.] )
- (?>
- ( [1-9][0-9]* | 0 ) ( \. [0-9]* )? |
- \. [0-9]+
- )
- (?> [eE] [+-]? [0-9]+ )?
- (?! [\w\.] )
- </match>
- </context>
-
- <context id="binary-integer" style-ref="base-n-number">
- <match extended="true">
- (?<![\w\.]) (?>0 [bB] [01]+) (?![\w\.])
- </match>
- </context>
-
- <context id="octal-integer" style-ref="base-n-number">
- <match extended="true">
- (?<![\w\.]) (?>0 [oO] [0-7]+) (?![\w\.])
- </match>
- </context>
-
- <context id="hex-integer" style-ref="base-n-number">
- <match extended="true">
- (?<![\w\.]) (?>0 [xX] [0-9a-fA-F]+) (?![\w\.])
- </match>
- </context>
-
- <context id="big-integer" style-ref="big-integer">
- <match extended="true">
- (?<![\w\.]) (?>( [1-9][0-9]* | 0 ) n) (?![\w\.])
- </match>
- </context>
-
- <!-- deprecated -->
- <context id="legacy-octal-integer" style-ref="base-n-number">
- <match extended="true">
- (?<![\w\.]) (?>0 [0-7]+) (?![\w\.])
- </match>
- </context>
+ </context> <!-- /_object-destructuring-property-content -->
- <!--
- There was a long discussion on ##javascript on freenode between
- 'katspaugh', 'joo' and 'prog_' on whether 'undefined' should be
- highlighted on not, specialy as a constant. The conclusion was "It can't
- be highlighted as a constant literal value, because it can be an
- identifier (of a variable value) but leave it be as it is. Let tradition
- and convention obscure the details."
- -->
- <context id="undefined-value" style-ref="undefined-value">
- <keyword>undefined</keyword>
- </context>
-
- <context id="null-value" style-ref="null-value">
- <keyword>null</keyword>
- </context>
-
- <context id="boolean" style-ref="boolean">
- <keyword>false</keyword>
- <keyword>true</keyword>
- </context>
-
- <context id="keywords" style-ref="keyword">
- <keyword>arguments</keyword>
- <keyword>async</keyword>
- <keyword>as</keyword>
- <keyword>await</keyword>
- <keyword>break</keyword>
- <keyword>case</keyword>
- <keyword>catch</keyword>
- <keyword>class</keyword>
- <keyword>const</keyword>
- <keyword>constructor</keyword>
- <keyword>continue</keyword>
- <keyword>debugger</keyword>
- <keyword>default</keyword>
- <keyword>delete</keyword>
- <keyword>do</keyword>
- <keyword>else</keyword>
- <keyword>export</keyword>
- <keyword>extends</keyword>
- <keyword>finally</keyword>
- <keyword>for</keyword>
- <keyword>from</keyword>
- <keyword>function</keyword>
- <keyword>get</keyword>
- <keyword>if</keyword>
- <keyword>import</keyword>
- <keyword>instanceof</keyword>
- <keyword>in</keyword>
- <keyword>let</keyword>
- <keyword>new</keyword>
- <keyword>of</keyword>
- <keyword>return</keyword>
- <keyword>set</keyword>
- <keyword>static</keyword>
- <keyword>super</keyword>
- <keyword>switch</keyword>
- <keyword>this</keyword>
- <keyword>throw</keyword>
- <keyword>try</keyword>
- <keyword>typeof</keyword>
- <keyword>var</keyword>
- <keyword>void</keyword>
- <keyword>while</keyword>
- <keyword>with</keyword>
- <keyword>yield</keyword>
- </context>
-
- <context id="types" style-ref="type">
- <keyword>Infinity</keyword>
- <keyword>NaN</keyword>
- </context>
-
- <context id="global-functions" style-ref="function">
- <keyword>decodeURIComponent</keyword>
- <keyword>decodeURI</keyword>
- <keyword>encodeURIComponent</keyword>
- <keyword>encodeURI</keyword>
- <keyword>escape</keyword> <!-- deprecated -->
- <keyword>eval</keyword>
- <keyword>isFinite</keyword>
- <keyword>isNaN</keyword>
- <keyword>parseFloat</keyword>
- <keyword>parseInt</keyword>
- <keyword>unescape</keyword> <!-- deprecated -->
- </context>
-
- <context id="array-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>length</keyword>
- </context>
-
- <context id="array-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>concat</keyword>
- <keyword>copyWithin</keyword>
- <keyword>entries</keyword>
- <keyword>every</keyword>
- <keyword>fill</keyword>
- <keyword>filter</keyword>
- <keyword>findIndex</keyword>
- <keyword>find</keyword>
- <keyword>forEach</keyword>
- <keyword>from</keyword>
- <keyword>indexOf</keyword>
- <keyword>isArray</keyword>
- <keyword>join</keyword>
- <keyword>keys</keyword>
- <keyword>lastIndexOf</keyword>
- <keyword>map</keyword>
- <keyword>of</keyword>
- <keyword>pop</keyword>
- <keyword>push</keyword>
- <keyword>reduceRight</keyword>
- <keyword>reduce</keyword>
- <keyword>reverse</keyword>
- <keyword>shift</keyword>
- <keyword>slice</keyword>
- <keyword>some</keyword>
- <keyword>sort</keyword>
- <keyword>unshift</keyword>
- <keyword>values</keyword>
- </context>
-
- <context id="arraybuffer-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>byteLength</keyword>
- </context>
-
- <context id="arraybuffer-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>isView</keyword>
- <keyword>slice</keyword>
- </context>
-
- <context id="dataview-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>buffer</keyword>
- <keyword>byteLength</keyword>
- <keyword>byteOffset</keyword>
- </context>
-
- <context id="dataview-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>getFloat32</keyword>
- <keyword>getFloat64</keyword>
- <keyword>getInt16</keyword>
- <keyword>getInt32</keyword>
- <keyword>getInt8</keyword>
- <keyword>getUint16</keyword>
- <keyword>getUint32</keyword>
- <keyword>getUint8</keyword>
- <keyword>setFloat32</keyword>
- <keyword>setFloat64</keyword>
- <keyword>setInt16</keyword>
- <keyword>setInt32</keyword>
- <keyword>setInt8</keyword>
- <keyword>setUint16</keyword>
- <keyword>setUint32</keyword>
- <keyword>setUint8</keyword>
- </context>
-
- <context id="date-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>getDate</keyword>
- <keyword>getDay</keyword>
- <keyword>getFullYear</keyword>
- <keyword>getHours</keyword>
- <keyword>getMilliseconds</keyword>
- <keyword>getMinutes</keyword>
- <keyword>getMonth</keyword>
- <keyword>getSeconds</keyword>
- <keyword>getTime</keyword>
- <keyword>getTimezoneOffset</keyword>
- <keyword>getUTCDate</keyword>
- <keyword>getUTCDay</keyword>
- <keyword>getUTCFullYear</keyword>
- <keyword>getUTCHours</keyword>
- <keyword>getUTCMilliseconds</keyword>
- <keyword>getUTCMinutes</keyword>
- <keyword>getUTCMonth</keyword>
- <keyword>getUTCSeconds</keyword>
- <keyword>getYear</keyword> <!-- deprecated -->
- <keyword>now</keyword>
- <keyword>parse</keyword>
- <keyword>setDate</keyword>
- <keyword>setFullYear</keyword>
- <keyword>setHours</keyword>
- <keyword>setMilliseconds</keyword>
- <keyword>setMinutes</keyword>
- <keyword>setMonth</keyword>
- <keyword>setSeconds</keyword>
- <keyword>setTime</keyword>
- <keyword>setUTCDate</keyword>
- <keyword>setUTCFullYear</keyword>
- <keyword>setUTCHours</keyword>
- <keyword>setUTCMilliseconds</keyword>
- <keyword>setUTCMinutes</keyword>
- <keyword>setUTCMonth</keyword>
- <keyword>setUTCSeconds</keyword>
- <keyword>setYear</keyword> <!-- deprecated -->
- <keyword>toDateString</keyword>
- <keyword>toGMTString</keyword> <!-- deprecated -->
- <keyword>toISOString</keyword>
- <keyword>toJSON</keyword>
- <keyword>toLocaleDateString</keyword>
- <keyword>toLocaleTimeString</keyword>
- <keyword>toTimeString</keyword>
- <keyword>toUTCString</keyword>
- <keyword>UTC</keyword>
- </context>
-
- <context id="error-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>message</keyword>
- <keyword>name</keyword>
- </context>
-
- <context id="function-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>length</keyword>
- <keyword>name</keyword>
- <keyword>target</keyword> <!-- for new.target -->
- </context>
-
- <context id="function-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>apply</keyword>
- <keyword>bind</keyword>
- <keyword>call</keyword>
- </context>
-
- <context id="generator-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>next</keyword>
- <keyword>return</keyword>
- <keyword>throw</keyword>
- </context>
-
- <context id="json-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>parse</keyword>
- <keyword>stringify</keyword>
- </context>
-
- <context id="map-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>size</keyword>
- </context>
-
- <context id="map-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>clear</keyword>
- <keyword>delete</keyword>
- <keyword>entries</keyword>
- <keyword>forEach</keyword>
- <keyword>get</keyword>
- <keyword>has</keyword>
- <keyword>keys</keyword>
- <keyword>set</keyword>
- <keyword>values</keyword>
- </context>
-
- <context id="math-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>E</keyword>
- <keyword>LN10</keyword>
- <keyword>LN2</keyword>
- <keyword>LOG10E</keyword>
- <keyword>LOG2E</keyword>
- <keyword>PI</keyword>
- <keyword>SQRT1_2</keyword>
- <keyword>SQRT2</keyword>
- </context>
-
- <context id="math-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>abs</keyword>
- <keyword>acosh</keyword>
- <keyword>acos</keyword>
- <keyword>asinh</keyword>
- <keyword>asin</keyword>
- <keyword>atan2</keyword>
- <keyword>atanh</keyword>
- <keyword>atan</keyword>
- <keyword>cbrt</keyword>
- <keyword>ceil</keyword>
- <keyword>clz32</keyword>
- <keyword>cosh</keyword>
- <keyword>cos</keyword>
- <keyword>expm1</keyword>
- <keyword>exp</keyword>
- <keyword>floor</keyword>
- <keyword>fround</keyword>
- <keyword>hypot</keyword>
- <keyword>imul</keyword>
- <keyword>log10</keyword>
- <keyword>log1p</keyword>
- <keyword>log2</keyword>
- <keyword>log</keyword>
- <keyword>max</keyword>
- <keyword>min</keyword>
- <keyword>pow</keyword>
- <keyword>random</keyword>
- <keyword>round</keyword>
- <keyword>sign</keyword>
- <keyword>sinh</keyword>
- <keyword>sin</keyword>
- <keyword>sqrt</keyword>
- <keyword>tanh</keyword>
- <keyword>tan</keyword>
- <keyword>trunc</keyword>
- </context>
-
- <context id="number-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>EPSILON</keyword>
- <keyword>MAX_SAFE_INTEGER</keyword>
- <keyword>MAX_VALUE</keyword>
- <keyword>MIN_SAFE_INTEGER</keyword>
- <keyword>MIN_VALUE</keyword>
- <keyword>NaN</keyword>
- <keyword>NEGATIVE_INFINITY</keyword>
- <keyword>POSITIVE_INFINITY</keyword>
- </context>
-
- <context id="number-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>isFinite</keyword>
- <keyword>isInteger</keyword>
- <keyword>isNaN</keyword>
- <keyword>isSafeInteger</keyword>
- <keyword>parseFloat</keyword>
- <keyword>parseInt</keyword>
- <keyword>toExponential</keyword>
- <keyword>toFixed</keyword>
- <keyword>toPrecision</keyword>
- </context>
-
- <context id="object-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>constructor</keyword>
- <keyword>prototype</keyword>
- </context>
-
- <context id="object-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>assign</keyword>
- <keyword>create</keyword>
- <keyword>defineProperties</keyword>
- <keyword>defineProperty</keyword>
- <keyword>freeze</keyword>
- <keyword>getOwnPropertyDescriptor</keyword>
- <keyword>getOwnPropertyNames</keyword>
- <keyword>getOwnPropertySymbols</keyword>
- <keyword>getPrototypeOf</keyword>
- <keyword>hasOwnProperty</keyword>
- <keyword>isExtensible</keyword>
- <keyword>isFrozen</keyword>
- <keyword>isPrototypeOf</keyword>
- <keyword>isSealed</keyword>
- <keyword>is</keyword>
- <keyword>keys</keyword>
- <keyword>preventExtensions</keyword>
- <keyword>propertyIsEnumerable</keyword>
- <keyword>seal</keyword>
- <keyword>setPrototypeOf</keyword>
- <keyword>toLocaleString</keyword>
- <keyword>toString</keyword>
- <keyword>valueOf</keyword>
- </context>
-
- <context id="promise-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>all</keyword>
- <keyword>catch</keyword>
- <keyword>race</keyword>
- <keyword>reject</keyword>
- <keyword>resolve</keyword>
- <keyword>then</keyword>
- </context>
-
- <context id="proxy-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>revocable</keyword>
- </context>
-
- <context id="reflect-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>apply</keyword>
- <keyword>construct</keyword>
- <keyword>defineProperty</keyword>
- <keyword>deleteProperty</keyword>
- <keyword>getOwnPropertyDescriptor</keyword>
- <keyword>getPrototypeOf</keyword>
- <keyword>get</keyword>
- <keyword>has</keyword>
- <keyword>isExtensible</keyword>
- <keyword>ownKeys</keyword>
- <keyword>preventExtensions</keyword>
- <keyword>setPrototypeOf</keyword>
- <keyword>set</keyword>
- </context>
-
- <context id="regexp-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>flags</keyword>
- <keyword>global</keyword>
- <keyword>ignoreCase</keyword>
- <keyword>lastIndex</keyword>
- <keyword>multiline</keyword>
- <keyword>source</keyword>
- <keyword>sticky</keyword>
- <keyword>unicode</keyword>
- </context>
-
- <context id="regexp-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>exec</keyword>
- <keyword>test</keyword>
- </context>
-
- <context id="set-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>size</keyword>
- </context>
-
- <context id="set-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>add</keyword>
- <keyword>clear</keyword>
- <keyword>delete</keyword>
- <keyword>entries</keyword>
- <keyword>forEach</keyword>
- <keyword>has</keyword>
- <keyword>keys</keyword>
- <keyword>values</keyword>
- </context>
-
- <context id="string-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>length</keyword>
- </context>
-
- <context id="string-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>charAt</keyword>
- <keyword>charCodeAt</keyword>
- <keyword>codePointAt</keyword>
- <keyword>concat</keyword>
- <keyword>endsWith</keyword>
- <keyword>fromCharCode</keyword>
- <keyword>fromCodePoint</keyword>
- <keyword>includes</keyword>
- <keyword>indexOf</keyword>
- <keyword>lastIndexOf</keyword>
- <keyword>localeCompare</keyword>
- <keyword>match</keyword>
- <keyword>normalize</keyword>
- <keyword>raw</keyword>
- <keyword>repeat</keyword>
- <keyword>replace</keyword>
- <keyword>search</keyword>
- <keyword>slice</keyword>
- <keyword>split</keyword>
- <keyword>startsWith</keyword>
- <keyword>substring</keyword>
- <keyword>substr</keyword> <!-- deprecated -->
- <keyword>toLocaleLowerCase</keyword>
- <keyword>toLocaleUpperCase</keyword>
- <keyword>toLowerCase</keyword>
- <keyword>toUpperCase</keyword>
- <keyword>trim</keyword>
- </context>
-
- <context id="symbol-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>hasInstance</keyword>
- <keyword>isConcatSpreadable</keyword>
- <keyword>iterator</keyword>
- <keyword>match</keyword>
- <keyword>replace</keyword>
- <keyword>search</keyword>
- <keyword>species</keyword>
- <keyword>split</keyword>
- <keyword>toPrimitive</keyword>
- <keyword>toStringTag</keyword>
- <keyword>unscopables</keyword>
- </context>
-
- <context id="symbol-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>for</keyword>
- <keyword>keyFor</keyword>
- </context>
-
- <!-- TypedArray is one of these objects:
- * Float32Array
- * Float64Array
- * Int16Array
- * Int32Array
- * Int8Array
- * Uint16Array
- * Uint32Array
- * Uint8Array
- * Uint8ClampedArray
+ <!-- <ObjectBindingPattern> -->
+ <context id="_choice-object-destructuring" style-ref="object-destructuring" end-parent="true">
+ <start>{</start>
+ <end>}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+
+ <context id="_object-destructuring-content">
+ <include>
+
+ <context id="_object-destructuring-first-property" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+ <context ref="_object-destructuring-property-content"/>
+ </include>
+ </context> <!-- /_object-destructuring-properties -->
+
+ <context id="_object-destructuring-properties">
+ <start>,</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+ <context ref="_object-destructuring-property-content"/>
+ </include>
+ </context> <!-- /_object-destructuring-properties -->
+
+ </include>
+ </context> <!-- /_object-destructuring-content -->
+
+ </include>
+ </context> <!-- /_choice-object-destructuring -->
+
+ <!-- ## Assignment target
+
+ Things that can appear on the left side of an equals sign
+ (identifier or array/object destructuring assignment), in all
+ places (function parameters, variable declaration) *except* in
+ assignment expressions (array/object literals will match for
+ array/object destructuring)
-->
- <context id="typedarray-properties" style-ref="properties">
- <prefix>\%{is-member}</prefix>
- <keyword>buffer</keyword>
- <keyword>byteLength</keyword>
- <keyword>byteOffset</keyword>
- <keyword>BYTES_PER_ELEMENT</keyword>
- <keyword>length</keyword>
- <keyword>name</keyword>
- </context>
-
- <context id="typedarray-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>copyWithin</keyword>
- <keyword>entries</keyword>
- <keyword>every</keyword>
- <keyword>fill</keyword>
- <keyword>filter</keyword>
- <keyword>findIndex</keyword>
- <keyword>find</keyword>
- <keyword>forEach</keyword>
- <keyword>from</keyword>
- <keyword>indexOf</keyword>
- <keyword>join</keyword>
- <keyword>keys</keyword>
- <keyword>lastIndexOf</keyword>
- <keyword>map</keyword>
- <keyword>of</keyword>
- <keyword>reduceRight</keyword>
- <keyword>reduce</keyword>
- <keyword>reverse</keyword>
- <keyword>set</keyword>
- <keyword>slice</keyword>
- <keyword>some</keyword>
- <keyword>sort</keyword>
- <keyword>subarray</keyword>
- <keyword>values</keyword>
- </context>
-
- <context id="weakmap-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>delete</keyword>
- <keyword>get</keyword>
- <keyword>has</keyword>
- <keyword>set</keyword>
- </context>
-
- <context id="weakset-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>add</keyword>
- <keyword>delete</keyword>
- <keyword>has</keyword>
- </context>
-
- <context id="bigint-methods" style-ref="function">
- <prefix>\%{is-member}</prefix>
- <keyword>asIntN</keyword>
- <keyword>asUintN</keyword>
- </context>
-
- <context id="constructors" style-ref="constructors">
- <keyword>ArrayBuffer</keyword>
- <keyword>Array</keyword>
- <keyword>BigInt</keyword>
- <keyword>Boolean</keyword>
- <keyword>Date</keyword>
- <keyword>Error</keyword>
- <keyword>EvalError</keyword>
- <keyword>Float32Array</keyword>
- <keyword>Float64Array</keyword>
- <keyword>Function</keyword>
- <keyword>Int16Array</keyword>
- <keyword>Int32Array</keyword>
- <keyword>Int8Array</keyword>
- <keyword>JSON</keyword>
- <keyword>Map</keyword>
- <keyword>Math</keyword>
- <keyword>Number</keyword>
- <keyword>Object</keyword>
- <keyword>Promise</keyword>
- <keyword>Proxy</keyword>
- <keyword>RangeError</keyword>
- <keyword>ReferenceError</keyword>
- <keyword>Reflect</keyword>
- <keyword>RegExp</keyword>
- <keyword>Set</keyword>
- <keyword>String</keyword>
- <keyword>Symbol</keyword>
- <keyword>SyntaxError</keyword>
- <keyword>TypeError</keyword>
- <keyword>Uint16Array</keyword>
- <keyword>Uint32Array</keyword>
- <keyword>Uint8Array</keyword>
- <keyword>Uint8ClampedArray</keyword>
- <keyword>URIError</keyword>
- <keyword>WeakMap</keyword>
- <keyword>WeakSet</keyword>
- </context>
-
- <context id="future-words" style-ref="future-words">
- <keyword>enum</keyword>
-
- <!-- in strict mode -->
- <keyword>implements</keyword>
- <keyword>interface</keyword>
- <keyword>package</keyword>
- <keyword>private</keyword>
- <keyword>protected</keyword>
- <keyword>public</keyword>
- </context>
-
- <context id="template-string" style-ref="string" class="string" class-disabled="no-spell-check">
- <start>`</start>
- <end>`</end>
+
+ <!-- <VariableDeclaration> / <LexicalBinding> -->
+ <context id="_assignment-target" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
<include>
- <context ref="escape"/>
- <context ref="def:line-continue"/>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
- <!-- FIXME: syntax highlight should go back to none here -->
- <context id="template-expression" style-ref="function">
- <start>\$\{</start>
- <end>\}</end>
+ <context id="_assignment-target-content">
<include>
- <context ref="js:*"/>
+ <context ref="_choice-array-destructuring"/>
+ <context ref="_choice-object-destructuring"/>
+ <context ref="choice-identifier"/>
</include>
- </context>
+ </context> <!-- /_assignment-target-content -->
+
</include>
- </context>
+ </context> <!-- /_assignment-target -->
+
+ <context id="ordered-assignment-target" once-only="true">
+ <start>\%{before-next-token}</start>
+ <end>\%{before-next-token}</end>
+ <include>
+ <context ref="_assignment-target"/>
+ </include>
+ </context> <!-- /ordered-assignment-target -->
+
+
+ <!-- Approximate code order for component files:
+ * javascript-literals.lang
+ * javascript-values.lang
+ * javascript-functions-classes.lang
+ * javascript-expressions.lang
+ * javascript-statements.lang
+ * javascript-modules.lang
+ -->
+
+
+ <!-- # Main context -->
- <!--main context-->
<context id="js" class="no-spell-check">
<include>
- <context ref="def:c-like-comment"/>
- <context ref="def:c-like-comment-multiline"/>
- <context ref="def:c-like-close-comment-outside-comment"/>
- <context ref="string" />
- <context ref="single-quoted-string" />
- <context ref="template-string"/>
- <context ref="decimal"/>
- <context ref="binary-integer"/>
- <context ref="octal-integer"/>
- <context ref="hex-integer"/>
- <context ref="big-integer"/>
- <context ref="legacy-octal-integer"/>
- <context ref="undefined-value"/>
- <context ref="null-value"/>
- <context ref="boolean"/>
- <context ref="types"/>
- <context ref="global-functions"/>
- <context ref="array-properties"/>
- <context ref="array-methods"/>
- <context ref="arraybuffer-properties"/>
- <context ref="arraybuffer-methods"/>
- <context ref="dataview-properties"/>
- <context ref="dataview-methods"/>
- <context ref="date-methods"/>
- <context ref="error-properties"/>
- <context ref="function-properties"/>
- <context ref="function-methods"/>
- <context ref="generator-methods"/>
- <context ref="json-methods"/>
- <context ref="map-properties"/>
- <context ref="map-methods"/>
- <context ref="math-properties"/>
- <context ref="math-methods"/>
- <context ref="number-properties"/>
- <context ref="number-methods"/>
- <context ref="object-properties"/>
- <context ref="object-methods"/>
- <context ref="promise-methods"/>
- <context ref="proxy-methods"/>
- <context ref="reflect-methods"/>
- <context ref="regexp-properties"/>
- <context ref="regexp-methods"/>
- <context ref="set-properties"/>
- <context ref="set-methods"/>
- <context ref="string-properties"/>
- <context ref="string-methods"/>
- <context ref="symbol-properties"/>
- <context ref="symbol-methods"/>
- <context ref="typedarray-properties"/>
- <context ref="typedarray-methods"/>
- <context ref="weakmap-methods"/>
- <context ref="weakset-methods"/>
- <context ref="bigint-methods"/>
- <context ref="constructors"/>
- <context ref="keywords"/>
- <context ref="future-words"/>
- <context ref="regex-simple"/>
+ <context ref="embedded-lang-hooks"/>
+ <context ref="comments"/>
+ <context ref="js-st:directives"/>
+ <context ref="js-mod:export-declarations"/>
+ <context ref="js-mod:import-declarations"/>
+ <context ref="js-st:statements"/>
</include>
- </context>
- <!--main context-->
+ </context> <!-- /js -->
</definitions>
</language>
diff --git a/data/language-specs/json.lang b/data/language-specs/json.lang
index aebb8f5c..6f9bc817 100644
--- a/data/language-specs/json.lang
+++ b/data/language-specs/json.lang
@@ -110,8 +110,8 @@
<context ref="string"/>
<context ref="decimal"/>
<context ref="float"/>
- <context ref="js:null-value" style-ref="null-value"/>
- <context ref="js:boolean" style-ref="boolean"/>
+ <context ref="js-lit:null-value" style-ref="null-value"/>
+ <context ref="js-lit:boolean" style-ref="boolean"/>
<context ref="catchall"/>
</include></context>
diff --git a/data/styles/classic.xml b/data/styles/classic.xml
index bc35f93e..d61fa964 100644
--- a/data/styles/classic.xml
+++ b/data/styles/classic.xml
@@ -106,8 +106,7 @@
<style name="xml:attribute-name" foreground="violet"/>
<style name="xml:namespace" foreground="green" bold="true"/>
- <style name="js:object" foreground="#2E8B57" bold="true"/>
- <style name="js:constructors" foreground="#008B8B"/>
+ <style name="js:built-in-constructor" use-style="def:identifier"/>
<style name="latex:display-math" foreground="#6A5ACD"/>
<style name="latex:command" foreground="#2E8B57" bold="true"/>
diff --git a/data/styles/kate.xml b/data/styles/kate.xml
index 369632a5..c0a91455 100644
--- a/data/styles/kate.xml
+++ b/data/styles/kate.xml
@@ -128,8 +128,7 @@
<style name="docbook:gui-elements" use-style="docbook-element"/>
<style name="docbook:structural-elements" use-style="docbook-element"/>
- <style name="js:object" foreground="dark-green"/>
- <style name="js:constructors" bold="true"/>
+ <style name="js:built-in-constructor" bold="true"/>
<style name="mooscript:special-vars" use-style="c:preprocessor"/>
diff --git a/data/styles/tango.xml b/data/styles/tango.xml
index f4a38866..3f9ff0d1 100644
--- a/data/styles/tango.xml
+++ b/data/styles/tango.xml
@@ -117,8 +117,7 @@
<style name="xml:tags" foreground="chameleon3"/>
<style name="xml:namespace" bold="true"/>
- <style name="js:object" foreground="chameleon3" bold="true"/>
- <style name="js:constructors" foreground="chameleon3"/>
+ <style name="js:built-in-constructor" foreground="chameleon3"/>
<style name="latex:display-math" foreground="plum3"/>
<style name="latex:command" foreground="chameleon3" bold="true"/>
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 9e0b7358..578f211e 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -68,7 +68,13 @@ data/language-specs/imagej.lang
data/language-specs/ini.lang
data/language-specs/jade.lang
data/language-specs/java.lang
+data/language-specs/javascript-expressions.lang
+data/language-specs/javascript-functions-classes.lang
data/language-specs/javascript.lang
+data/language-specs/javascript-literals.lang
+data/language-specs/javascript-modules.lang
+data/language-specs/javascript-statements.lang
+data/language-specs/javascript-values.lang
data/language-specs/j.lang
data/language-specs/json.lang
data/language-specs/julia.lang
diff --git a/tests/syntax-highlighting/file.html b/tests/syntax-highlighting/file.html
index 699360d1..9cfcedd5 100644
--- a/tests/syntax-highlighting/file.html
+++ b/tests/syntax-highlighting/file.html
@@ -9,6 +9,12 @@
pre.display {font-family: serif}
pre.format {font-family: serif}
</style>
+ <script type="text/javascript">
+ window.addEventListener('click', function (e) {
+ e.preventDefault();
+ alert('Hi there!');
+ }, false);
+ </script>
</head>
<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#800080" alink="#FF0000">
diff --git a/tests/syntax-highlighting/file.js b/tests/syntax-highlighting/file.js
index 42ba602d..2e023514 100644
--- a/tests/syntax-highlighting/file.js
+++ b/tests/syntax-highlighting/file.js
@@ -1,64 +1,816 @@
-// Regular expressions:
-/abc/
-x = /abc/;
+/*
+ * Expressions (in expression statements)
+ */
+
+/*
+ * Literals
+ */
+
+/* Keyword values */
+
+var NULL = null;
+var TRUE = true;
+var FALSE = false;
+
+
+/* Number */
+
+var decimal1 = 0;
+var decimal2 = 123.45;
+var decimal3 = .66667;
+var decimal4 = 10e20;
+var decimal5 = 0.2e+1;
+var decimal6 = .5E-20;
+var hex1 = 0xDEADBEEF;
+var hex2 = 0Xcafebabe;
+
+// ES2015 binary and octal numbers
+let binary1 = 0b1010;
+let binary2 = 0B00001111;
+let octal1 = 0o0123;
+let octal2 = 0O4567;
+
+// Legacy octal numbers
+var legacy_octal1 = 01;
+var legacy_octal2 = 007;
+
+// BigInt (ES2020)
+var decimal1 = 0n;
+var decimal2 = 123n;
+var hex1 = 0xDEADBEEFn;
+var hex2 = 0Xcafebaben;
+var binary1 = 0b1010n;
+var binary2 = 0B00001111n;
+var octal1 = 0o0123n;
+var octal2 = 0O4567n;
+
+
+/* String */
+
+// Escape sequences
+'\b\f\n\r\t\v\0\'\"\\'; // Single character escape
+"\1\01\001"; // Octal escape (Annex B)
+'\xA9'; // Hexadecimal escape
+"\u00a9"; // Unicode escape
+'\u{1D306}'; // Unicode code point escape
+
+
+/* Array literal */
+
+[];
+[1];
+[1.0, 'two', 0x03];
+
+// Trailing comma
+[
+ [1,2,3],
+ [4,5,6],
+];
+
+// Spread syntax
+[1, ...a, 2];
+
+
+/* Object literal */
+
+a = {};
+a = { prop: 'value' };
+a = { prop: 'value', extends: 1 };
+
+// Trailing comma
+a = {
+ prop: 'value',
+ extends: 1,
+};
+
+// Shorthand property names
+a = { b, c, d };
+
+// Getter / setter
+a = {
+ _hidden: null,
+ get property() { return _hidden; },
+ set property(value) { this._hidden = value; }
+};
+
+// Shorthand function notation
+a = {
+ method() {},
+ *generator() {},
+
+ // Async function (ES2017)
+ async method() {},
+ async /* comment */ method() {},
+ async() {},// method called "async"
+ async: false, // property called "async"
+ async prop: 'val', // incorrectly highlighted (syntax error)
+
+ // Async generator (ES2018)
+ async *generator() {}
+};
+
+// Computed property names
+a = {
+ ['prop']: 1,
+ ['method']() {}
+};
+
+// Spread properties (ES2018)
+a = { ...b };
+
+
+/* Regular expression literal */
+
+/abc/;
+x = /abc/gi;
function_with_regex_arg(/abc/);
-[ /abc/, /def/];
-{ regex: /abc/ };
+[ /abc/m, /def/u ];
+a = { regex: /abc/s }; // s (dotAll): ES2018
(1 === 0) ? /abc/ : /def/;
-/abc/ /* Comment */
-/abc/ // Comment
+/abc/; /* Comment */
+/abc/; // Comment
var matches = /abc/.exec('Alphabet ... that should contain abc, right?');
-// No regex here:
+// No regex here
a = [thing / thing, thing / thing];
x = a /b/ c / d;
-// Character groups with backslashes:
-/[ab\\]/ // a, b or backslash
-/[ab\]]/ // a, b or ]
-/\\[ab]/ // a or b preceded by backslash
-/\[ab]/ // Literally "[ab]"
-
-// Escape sequences:
-'\b\f\n\r\t\v\0\'\"\\' // Single character escape
-"\1\01\001" // Octal escape
-'\xA9' // Hexadecimal escape
-"\u00a9" // Unicode escape
-'\u{1D306}' // Unicode code point escape
-/\cJ/ // Control escape
-'\
-' // Newline escape
-
-// ES2015 binary and octal numbers:
-let binary1 = 0b1010;
-let binary2 = 0B00001111;
-let octal1 = 0o0123;
-let octal2 = 0O4567;
+// Character groups with backslashes
+/[ab\\]/; // a, b or backslash
+/[ab\]]/; // a, b or ]
+/\\[ab]/; // a or b preceded by backslash
+/\[ab]/; // Literally "[ab]"
-// Big integers:
-let bigInt = 543789527895762347856234897532n;
-let bigIntZero = 0n;
-let bigIntConst = BigInt('1234513123123');
-312312n+5234523n-12n*3123n/4n%3231n**-123123n;
+// Control escape
+/\cJ/;
-// Template strings
-// ----------------
-// Template strings are delimited by back-ticks (grave accent) and
-// can span multiple lines. They allow for expressions that inside
-// of a dollar-sign plus curly-bracket construct (${...}).
+// Unicode property escape (ES2018)
+/\p{General_Category=Letter}/u;
+/\p{Letter}/u;
-console.log(`The sum of 2 and 2 is ${2 + 2}`);
+// Named capture groups (ES2018)
+/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
+/(?<foobar>foo|bar)/u;
+/^(?<half>.*).\k<half>$/u; // backreference
-// Interpolation inside interpolation
-let interp = `Hello ${
- Math.random() > 0.5
- ? 'World!'
- : `${Math.random() > 0.5 ? 'Alice' : 'Bob'}!`
-}`;
+/* Template literal */
+
+console.log(`The sum of 2 and 2 is ${2 + 2}`);
let y = 8;
let my_string = `This is a multiline
string that also contains
a template ${y + (4.1 - 2.2)}`;
-let escaped = `\b\f\`\\\u00a8\u{12345}\
-`;
+
+
+/*
+ * Built-in values
+ */
+
+// global object values
+Infinity;
+NaN;
+undefined;
+
+// global object functions
+decodeURIComponent();
+decodeURI();
+encodeURIComponent();
+encodeURI();
+eval();
+isFinite();
+isNaN();
+parseFloat();
+parseInt();
+
+// constructors (subset)
+Array();
+BigInt(); // ES2020
+Boolean();
+Date();
+Error();
+Function();
+Map();
+Object();
+Promise();
+RegExp();
+Set();
+String();
+Symbol();
+
+// objects
+JSON.parse();
+Math.random();
+
+// object keywords
+arguments;
+globalThis; // ES2020
+new.target;
+new . /* comment */ target;
+super;
+this;
+new . /* comment
+*/ target; // not correctly highlighted
+new // comment
+.target; // not correctly highlighted
+
+// function keywords
+import(); // ES2020
+import /* comment */ (); // ES2020
+import /* comment
+*/ (); // not correctly highlighted (though it may appear correct)
+import // comment
+(); // not correctly highlighted (though it may appear correct)
+
+// properties (subset)
+array.length;
+Math.PI;
+Number.NaN;
+object.constructor;
+Class.prototype;
+Symbol.asyncIterator; // ES2018
+Symbol('desc').description; // ES2019
+
+// methods (subset)
+array.keys();
+date.toString();
+object.valueOf();
+re.test();
+array.includes(); // ES2016
+Object.values(); // ES2017
+Object.entries(); // ES2017
+string.padStart(); // ES2017
+string.padEnd(); // ES2017
+Object.getOwnPropertyDescriptors(); // ES2017
+promise.finally(); // ES2018
+Object.fromEntries(); // ES2019
+string.trimStart(); // ES2019
+string.trimEnd(); // ES2019
+array.flat(); // ES2019
+array.flatMap(); // ES2019
+string.matchAll(); // ES2020
+Promise.allSettled(); // ES2020
+BigInt.asUintN(); // ES2020
+
+
+/*
+ * Function expression, arrow function
+ */
+
+a = function () { return 1 };
+a = function fn() {
+ return;
+};
+a = function fn(x) {};
+a = function fn(x, y) {};
+
+// Arrow function
+x => -x;
+() => {};
+(x, y) => x + y;
+(x, y) => { return x + y; };
+(x, y) => /* comment */ { return x + y; } /* comment */ ;
+(x) => ({ a: x }); // return object
+
+// Default parameters
+a = function fn(x, y = 1) {};
+(x, y = 1) => x + y;
+
+// Parameter without default after default parameters
+a = function fn(x = 1, y) {};
+(x = 1, y) => x + y;
+
+// Array destructuring
+a = function fn([x]) {};
+a = function fn([x, y]) {};
+([x]) => x;
+([x, y]) => x + y;
+
+// Object destructuring
+a = function fn({ x }) {};
+a = function fn({ x, b: y }) {};
+({ x }) => x;
+({ x, b: y }) => x + y;
+
+// Destructuring and default value
+a = function f([x, y] = [1, 2], {c: z} = {c: 3}) {};
+([x, y] = [1, 2], {c: z} = {c: x + y}) => x + y + z;
+
+// Generator function
+a = function*fn() {};
+a = function * fn() {};
+
+// Rest parameters
+a = function fn(...rest) {};
+a = function fn(x, y, ...rest) {};
+(...rest) => rest;
+(x, y, ...rest) => rest;
+
+// Async function (ES2017)
+a = async function fn() {};
+a = async /* comment */ function fn() {};
+a = async /* comment
+*/ function fn() {}; // correctly highlighted, because async cannot be followed by a line terminator
+async x => x;
+async () => {};
+async /* comment */ () => {};
+async /* comment
+*/ () => {}; // correctly highlighted, because async cannot be followed by a line terminator
+async(); // incorrectly highlighted
+
+// Async generator (ES2018)
+a = async function * fn() {};
+
+// Trailing comma (ES2017)
+a = function fn(x, y,) {};
+(x, y,) => x + y;
+
+// Trailing comma after rest parameters (syntax error)
+a = function fn(x, y, ...rest,) {};
+(x, y, ...rest,) => rest;
+
+
+/*
+ * Class expression
+ */
+
+a = class Foo {
+ constructor() {
+ }
+ method(x, y) {
+ return x + y;
+ }
+ *generator() {}
+};
+a = class extends Bar {
+ constructor() {
+ this._value = null;
+ }
+ get property() {
+ return this._value;
+ }
+ set property(x) {
+ this._value = x;
+ }
+ static get bar() {
+ return 'bar';
+ }
+};
+
+
+/*
+ * Operators
+ * use groupings to test, as there can only be one expression (in the
+ * first grouping item)
+ */
+
+// Grouping
+( 1 + 2 );
+
+// Increment / decrement
+( ++a );
+( --a );
+( a++ );
+( a-- );
+
+// Keyword unary
+( await promise() ); // ES2017
+( delete obj.prop );
+( new Array() );
+( void 1 );
+( typeof 'str' );
+( yield 1 );
+( yield* fn() );
+
+// Arithmetic
+( 1 + 2 );
+( 1 - 2 );
+( 1 * 2 );
+( 1 / 2 );
+( 1 % 2 );
+( 1 ** 2 ); // ES2016
+( +1 );
+( -1 );
+
+// Keyword relational
+( prop in obj );
+( obj instanceof constructor );
+
+// Comparison
+( 1 == 2 );
+( 1 != 2 );
+( 1 === 2 );
+( 1 !== 2 );
+( 1 < 2 );
+( 1 > 2 );
+( 1 <= 2 );
+( 1 >= 2 );
+
+// Bitwise
+( 1 & 2 );
+( 1 | 2 );
+( 1 ^ 2 );
+( ~1 );
+( 1 << 2 );
+( 1 >> 2 );
+( 1 >>> 2 );
+
+// Logical
+( 1 && 2 );
+( 1 || 2 );
+( !1 );
+
+// Assignment
+( a = 1 );
+( a += 1 );
+( a -= 1 );
+( a *= 1 );
+( a /= 1 );
+( a %= 1 );
+( a **= 1 ); // ES2016
+( a <<= 1 );
+( a >>= 1 );
+( a >>>= 1 );
+( a &= 1 );
+( a |= 1 );
+( a ^= 1 );
+( [a, b] = [1, 2] ); // array destructuring
+( {a, b} = { a: 1, b: 2} ); // object destructuring
+
+// Comma
+1, 2 ;
+
+// Conditional / ternary
+( true ? 1 : 2 );
+( true ? : 2 ); // missing true value (syntax error)
+
+
+/*
+ * Property accessors
+ */
+
+// Dot notation
+arr.length;
+obj
+ . prototype
+ . constructor;
+
+// Bracket notation
+arr['length'];
+obj
+ ['prototype']
+ ['constructor'];
+
+// Mixed
+obj
+ ['prototype']
+ . constructor;
+obj
+ . prototype
+ ['constructor'];
+
+
+/*
+ * Function call
+ */
+
+fn();
+obj.fn(1);
+obj['fn'](1, 2);
+
+// Spread syntax
+fn(x, y, ...args);
+
+// Trailing comma (ES2017)
+fn(x, y,);
+
+
+/* Tagged template */
+
+myTag`That ${ person } is ${ age }`;
+
+
+/*
+ * Statements and declarations
+ */
+
+/* Use strict directive */
+
+"use strict";
+function () {
+ 'use strict';
+}
+
+// invalid directives
+" use strict";
+'use strict ';
+"use strict";
+'use strict';
+"hello 'use strict' world";
+fn("use strict");
+{ 'use strict'; }
+
+
+/* Block statement */
+
+{
+ hello();
+ world();
+}
+{ hello(); world() }
+
+
+/* Break statement */
+
+break;
+break label;
+break // end statement
+ label; // separate statement
+{ break }
+
+
+/*
+ * Class declaration
+ */
+
+class Foo {
+ constructor() {
+ }
+ method(x, y) {
+ return x + y;
+ }
+ *generator() {}
+}
+class Foo extends Bar {
+ constructor() {
+ this._value = null;
+ }
+ get property() {
+ return this._value;
+ }
+ set property(x) {
+ this._value = x;
+ }
+ static get bar() {
+ return 'bar';
+ }
+}
+
+
+/* Continue statement */
+
+continue;
+continue label;
+continue // end statement
+ label; // separate statement
+{ continue }
+
+
+/* Debugger statement */
+
+debugger;
+debugger
+ ;
+
+
+/* Export / import statement */
+
+export { a };
+export { a, b, };
+export { x as a };
+export { x as a, y as b, };
+export var a;
+export let a, b;
+export const a = 1;
+export var a = 1, b = 2;
+export function fn() {}
+export function* fn() {}
+export class Class {}
+
+export default 1;
+export default function () {}
+export default function *fn() {}
+export default class {}
+export { a as default, b };
+
+export * from 'module';
+export { a, b } from 'module';
+export { x as a, y as b, } from 'module';
+export { default } from 'module';
+
+import a from "module";
+import * as ns from "module";
+import { a } from "module";
+import { a, b } from "module";
+import { x as a } from "module";
+import { x as a, y as b } from "module";
+import { default as a } from "module";
+import a, { b } from "module";
+import a, * as nm from "module";
+import "module";
+
+
+/* For statement */
+
+for (i = 0; i < 10; i++) something();
+for (var i = 10; i >= 0; i--) {
+ something();
+}
+for (i = 0, j = 0; i < 10; i++, j++) something();
+for (let i = 10, j = 0; i >= 0; i--, j += 1) {
+ something();
+}
+for (prop in obj) {} // matches "in" binary operator instead
+for (const prop in obj) {}
+for (val of generator()) {}
+for (var val of array) {}
+for await (let x of asyncIterable) {} // ES2018
+for /* comment */ await /* comment */ (let x of asyncIterable) {} // ES2018
+
+
+/* Function declaration statement */
+
+function fn() {
+ return;
+}
+async function fn() {} // ES2017
+async /* comment */ function fn() {} // ES2017
+async /* comment
+*/ function fn() {} // correctly highlighted, because async cannot be followed by a line terminator
+
+
+/* If..else statement */
+
+if (a < 0) lessThan(); else if (a > 0) greaterThan(); else equal();
+if (a < 0)
+ lessThan();
+else if (a > 0)
+ greaterThan();
+else
+ equal();
+if (a < 0) {
+ lessThan();
+} else if (a > 0) {
+ greaterThan();
+} else {
+ equal();
+}
+
+
+/* Label statement */
+
+outer: for (var i = 0; i < 10; i++) {
+inner /* comment */ : for (var j = 0; j < 2; j++) {}
+}
+loop /* comment
+*/ : for (var i in obj) {} // incorrectly highlighted (though it may appear correct)
+
+
+/* Return statement */
+
+return;
+return 1;
+return // end statement
+ 1; // separate statement
+return (
+ 1
+);
+{ return a }
+
+
+/* Switch statement */
+
+switch (foo) {
+case 1:
+ doIt();
+ break;
+case '2':
+ doSomethingElse();
+ break;
+default:
+ oops();
+}
+
+
+/* Throw statement */
+
+throw e;
+throw new Error();
+throw // end statement (syntax error)
+ e; // separate statement
+throw (
+ new Error()
+);
+{ throw new Error() }
+
+
+/* Try...catch statement */
+
+try {
+ somethingDangerous();
+}
+catch (e) {
+ didntWork(e);
+}
+catch { // ES2019
+ return false;
+}
+finally {
+ cleanup();
+}
+
+
+/* Variable declaration */
+
+// Declaration only
+const a;
+let a, b, c;
+var a
+ ,
+ b
+ ,
+ c
+ ;
+
+// With assignment
+const a = 1;
+let a = 1, b = [2, 3], c = 4;
+var a
+ =
+ 1
+ ,
+ b
+ =
+ [
+ 2
+ ,
+ 3
+ ]
+ ,
+ c
+ =
+ 4
+ ;
+
+// Array destructuring
+var [a, b] = [1, 2];
+var [
+ a
+ ,
+ b
+ ]
+ =
+ [
+ 1
+ ,
+ 2
+ ]
+ ;
+var [a = 5, b = 7] = [1]; // default values
+var [a, , b] = f(); // ignoring some returned values
+var [a, ...b] = [1, 2, 3]; // rest syntax
+
+// Object destructuring
+var { a, b } = { a: 1, b: 2 };
+var {
+ a
+ ,
+ b
+ }
+ =
+ {
+ a
+ :
+ 1
+ ,
+ b
+ :
+ 2
+ }
+ ;
+var { a: foo, b: bar } = { a: 1, b: 2 }; // assigning to new variable names
+var { a = 5, b = 7 } = { a: 1 }; // default values
+var { a: foo = 5, b: bar = 7 } = { a: 1 }; // assigning to new variable names and default values
+var { ['a']: foo, ['b']: bar } = { a: 1, b: 2 }; // computed property names
+var { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 }; // rest properties (ES2018)
+
+
+/* While / do...while statement */
+
+while (true) something();
+while (1) {
+ something();
+}
+do something(); while (false);
+do {
+ something();
+} while (0);
+
+
+/* With statement */
+
+with (Math) {
+ a = PI * r * r;
+ x = r * cos(PI);
+ y = r * sin(PI / 2);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]