2021-04-29 13:18:31 +01:00

410 lines
14 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!--
This file is part of GtkSourceView
Author: Jeffery To <jeffery.to@gmail.com>
Copyright (C) 2019-2020 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="jsx" name="JSX" version="2.0" _section="Script">
<metadata>
<property name="mimetypes">application/jsx;application/x-jsx;text/x-jsx;text/jsx</property>
<property name="globs">*.jsx</property>
<property name="line-comment-start">//</property>
<property name="block-comment-start">/*</property>
<property name="block-comment-end">*/</property>
</metadata>
<styles>
<style id="element" name="Element"/>
<style id="spread-attribute" name="Spread attribute"/>
<style id="attribute-expression" name="Attribute expression"/>
<style id="child-expression" name="Child expression"/>
</styles>
<!-- from js:identifier-char -->
<keyword-char-class>(?!\x{2E2F})[\p{L}\p{Nl}\x{1885}-\x{1886}\x{2118}\x{212E}\x{309B}-\x{309C}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{00B7}\x{0387}\x{1369}-\x{1371}\x{19DA}$\x{200C}\x{200D}]</keyword-char-class>
<definitions>
<!-- Based on the JSX spec: https://github.com/facebook/jsx -->
<!-- using a style from another lang file before referencing a
context from the file causes "style not defined" errors
https://gitlab.gnome.org/GNOME/gtksourceview/issues/67
-->
<context id="style-not-defined-error-workaround">
<include>
<context ref="xml:xml"/>
</include>
</context> <!-- /style-not-defined-error-workaround -->
<!-- # General -->
<!-- reference js here to avoid "unknown id" error when referencing
a regex from js before referencing a context from js
https://gitlab.gnome.org/GNOME/gtksourceview/issues/67
-->
<context id="main-lang">
<include>
<context ref="js:js"/>
</include>
</context> <!-- /main-lang -->
<define-regex id="_start-tag-start">&lt;(?!/)</define-regex>
<!-- # Names -->
<define-regex id="_identifier-char" extended="true">
\%{js:identifier-char} | -
</define-regex> <!-- /_identifier-char -->
<define-regex id="_identifier-part" extended="true">
\%{_identifier-char} | \%{js:unicode-escape}
</define-regex> <!-- /_identifier-part -->
<!-- <JSXIdentifier> -->
<define-regex id="_identifier" extended="true">
\%{js:identifier-start} \%{_identifier-part}*
</define-regex> <!-- /_identifier -->
<define-regex id="_identifier-container-start" extended="true">
(?&lt;! \%{_identifier-char} ) (?= \%{js:identifier-start} )
</define-regex> <!-- /_identifier-container-start -->
<context id="_choice-identifier" end-parent="true">
<start>\%{_identifier-container-start}</start>
<end>\%{_identifier}</end>
</context> <!-- /_choice-identifier -->
<!-- <JSXNamespacedName> -->
<define-regex id="_namespaced-name" extended="true">
\%{_identifier} : \%{_identifier}
</define-regex> <!-- /_namespaced-name -->
<context id="_choice-namespaced-name" end-parent="true">
<start extended="true">
(?&lt;! \%{_identifier-char} ) (?= \%{_namespaced-name} )
</start>
<end>\%{_namespaced-name}</end>
</context> <!-- /_choice-namespaced-name -->
<!-- <JSXMemberExpression> -->
<define-regex id="_member-expression" extended="true">
\%{_identifier} (?: \. \%{_identifier} )+
</define-regex> <!-- /_member-expression -->
<context id="_choice-member-expression" end-parent="true">
<start extended="true">
(?&lt;! \%{_identifier-char} ) (?= \%{_member-expression} )
</start>
<end>\%{_member-expression}</end>
</context> <!-- /_choice-member-expression -->
<!-- # Element name -->
<!-- <JSXElementName> -->
<context id="_element-name" style-ref="xml:element-name" once-only="true">
<start>\%{_identifier-container-start}</start>
<end>\%{js:before-next-token}</end>
<include>
<context ref="js:comments"/>
<context id="_element-name-content">
<include>
<context ref="_choice-namespaced-name"/>
<context ref="_choice-member-expression"/>
<context ref="_choice-identifier"/>
</include>
</context> <!-- /_element-name-content -->
</include>
</context> <!-- /_element-name -->
<context id="_ordered-element-name" once-only="true">
<start>\%{js:before-next-token}</start>
<end>\%{js:before-next-token}</end>
<include>
<context ref="_element-name"/>
</include>
</context> <!-- /_ordered-element-name -->
<!-- # Attributes -->
<!-- ## Spread attributes -->
<!-- <JSXSpreadAttribute> -->
<context id="_spread-attributes" style-ref="spread-attribute">
<start>{</start>
<end>}</end>
<include>
<context ref="js:comments"/>
<context id="_spread-attribute-content">
<include>
<context ref="js:ordered-spread-syntax"/>
<context ref="js-expr:expression-without-comma"/>
</include>
</context> <!-- /_spread-attribute-content -->
</include>
</context> <!-- /_spread-attributes -->
<!-- ## Attribute name -->
<!-- <JSXAttributeName> -->
<context id="_attribute-names" style-ref="xml:attribute-name">
<start>\%{_identifier-container-start}</start>
<end>\%{js:before-next-token}</end>
<include>
<context ref="js:comments"/>
<context id="_attribute-name-content">
<include>
<context ref="_choice-namespaced-name"/>
<context ref="_choice-identifier"/>
</include>
</context> <!-- /_attribute-name-content -->
</include>
</context> <!-- /_attribute-names -->
<!-- ## Attribute value -->
<!-- <JSXAttributeValue> (part of) -->
<context id="_choice-attribute-value-string" style-ref="xml:attribute-value" end-parent="true" class="string" class-disabled="no-spell-check">
<start>["']</start>
<end>\%{0@start}</end>
<include>
<!-- no comments here -->
<context id="_attribute-value-string-content">
<include>
<!-- javascript escapes do not appear to be parsed here
but xml entities / character references appear to be
parsed -->
<context ref="xml:entity"/>
<context ref="xml:character-reference"/>
</include>
</context> <!-- /_attribute-value-string-content -->
</include>
</context> <!-- /_choice-attribute-value-string -->
<!-- <JSXAttributeValue> (part of) -->
<context id="_choice-attribute-value-expression" style-ref="attribute-expression" end-parent="true">
<start>{</start>
<end>}</end>
<include>
<context ref="js:comments"/>
<context id="_attribute-value-expression-content">
<include>
<!-- no spread syntax here -->
<context ref="js-expr:expression-without-comma"/>
</include>
</context> <!-- /_attribute-value-expression-content -->
</include>
</context> <!-- /_choice-attribute-value-expression -->
<!-- ## Attribute initializer -->
<!-- <JSXAttributeInitializer> -->
<context id="_attribute-initializers">
<start>=</start>
<end>\%{js:before-next-token}</end>
<include>
<context sub-pattern="0" where="start" style-ref="xml:attribute-name"/>
<context ref="js:comments"/>
<context id="_attribute-initializer-content">
<include>
<context ref="_choice-attribute-value-string"/>
<context ref="_choice-attribute-value-expression"/>
<context ref="choice-element"/>
</include>
</context> <!-- /_attribute-initializer-content -->
</include>
</context> <!-- /_attribute-initializers -->
<!-- # Element / fragment -->
<context id="_start-tag-tail-non-empty-element-content">
<include>
<!-- ## Start tag tail -->
<context id="_start-tag-tail" style-ref="xml:tag" once-only="true" class="no-spell-check">
<match>&gt;</match>
<include>
<context sub-pattern="0" style-ref="xml:element-name"/>
</include>
</context> <!-- /_start-tag-tail -->
<!-- ## End tag -->
<context id="_end-tag-end-parent" style-ref="xml:tag" end-parent="true" class="no-spell-check">
<start>&lt;/</start>
<end>&gt;</end>
<include>
<context sub-pattern="0" where="start" style-ref="xml:element-name"/>
<context sub-pattern="0" where="end" style-ref="xml:element-name"/>
<context ref="js:comments"/>
<context id="_end-tag-content">
<include>
<context ref="_ordered-element-name"/>
</include>
</context> <!-- /_end-tag-content -->
</include>
</context> <!-- /_end-tag-end-parent -->
<!-- ## Nested elements -->
<!-- <JSXElement> / <JSXFragment> -->
<context id="_elements" style-ref="element" class-disabled="no-spell-check">
<start>(?=\%{_start-tag-start})</start>
<include>
<!-- no comments here - comments parsed as regular text -->
<context ref="_element-content"/>
</include>
</context> <!-- /_elements -->
<!-- ## Child expressions -->
<!-- <JSXChild> / <JSXChildExpression> -->
<context id="_child-expressions" style-ref="child-expression" class="no-spell-check">
<start>{</start>
<end>}</end>
<include>
<context ref="js:comments"/>
<context id="_child-expression-content">
<include>
<context ref="js:ordered-spread-syntax"/>
<context ref="js-expr:expression-without-comma"/>
</include>
</context> <!-- /_child-expression-content -->
</include>
</context> <!-- /_child-expressions -->
<!-- ## XML syntax -->
<!-- javascript escapes do not appear to be parsed here
but xml character entity / numeric character references
appear to be parsed -->
<context ref="xml:entity"/>
<context ref="xml:character-reference"/>
<!-- ## Invalid characters -->
<!-- the spec does not allow these characters: { < > }
but we will only highlight > and } as errors -->
<context id="_invalid-characters" style-ref="xml:error">
<match>[&gt;}]</match>
</context> <!-- /_invalid-characters -->
</include>
</context> <!-- /_start-tag-tail-non-empty-element-content -->
<context id="_element-content">
<include>
<!-- ## Start tag -->
<!-- <JSXOpeningElement> / <JSXSelfClosingElement> -->
<context id="_start-tag-head" style-ref="xml:tag" once-only="true" class="no-spell-check">
<start>\%{_start-tag-start}</start>
<end>(?=/?&gt;)</end>
<include>
<context sub-pattern="0" where="start" style-ref="xml:element-name"/>
<context ref="js:comments"/>
<context id="_start-tag-head-content">
<include>
<context ref="_ordered-element-name"/>
<context ref="_spread-attributes"/>
<context ref="_attribute-names"/>
<context ref="_attribute-initializers"/>
</include>
</context> <!-- /_start-tag-head-content -->
</include>
</context> <!-- /_start-tag-head -->
<context id="_choice-start-tag-tail-empty-element" style-ref="xml:tag" end-parent="true" class="no-spell-check">
<start>(?=/&gt;)</start>
<end>/&gt;</end>
<include>
<context sub-pattern="0" where="end" style-ref="xml:element-name"/>
</include>
</context> <!-- /_choice-start-tag-tail-empty-element -->
<context id="_choice-start-tag-tail-non-empty-element" end-parent="true">
<start>(?=&gt;)</start>
<include>
<!-- no comments here - comments parsed as regular text -->
<context ref="_start-tag-tail-non-empty-element-content"/>
</include>
</context> <!-- /_choice-start-tag-tail-non-empty-element -->
</include>
</context> <!-- /_element-content -->
<!-- <JSXElement> / <JSXFragment> -->
<context id="choice-element" style-ref="element" end-parent="true" class-disabled="no-spell-check">
<start>(?=\%{_start-tag-start})</start>
<include>
<!-- no comments here - comments parsed as regular text -->
<context ref="_element-content"/>
</include>
</context> <!-- /choice-element -->
<!-- # Primary expression -->
<context id="_jsx-primary-expression-content">
<include>
<context ref="choice-element"/>
<context ref="js-expr:_primary-expression-content" original="true"/>
</include>
</context> <!-- /_jsx-primary-expression-content -->
<replace id="js-expr:_primary-expression-content" ref="_jsx-primary-expression-content"/>
<!-- # Main context -->
<context id="jsx" class="no-spell-check">
<include>
<context ref="main-lang"/>
</include>
</context> <!-- /jsx -->
</definitions>
</language>