Skip to content

Commit

Permalink
Initial support for JSX tags
Browse files Browse the repository at this point in the history
Resolves #148
Fixes #218
  • Loading branch information
deathaxe committed Aug 26, 2024
1 parent 52392b3 commit 4556045
Show file tree
Hide file tree
Showing 3 changed files with 252 additions and 0 deletions.
180 changes: 180 additions & 0 deletions CoffeeScript.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ contexts:
- include: classes
- include: keywords
- include: functions
- include: jsx-tags
- include: expressions

expressions:
Expand Down Expand Up @@ -573,6 +574,171 @@ contexts:
pop: 1
- include: script

###[ JSX TAGS ]################################################################

jsx-tags:
- match: (<)(?:({{component_names}})|({{tag_names}}))(?=\s|/?>)
captures:
1: punctuation.definition.tag.begin.coffee
2: entity.name.tag.component.coffee
3: entity.name.tag.coffee
push:
- jsx-meta
- jsx-tag-open-body

jsx-meta:
- meta_include_prototype: false
- meta_scope: meta.jsx.coffee
- include: immediately-pop

jsx-body:
- match: (</)(?:({{component_names}})|({{tag_names}}))(?=\s|/?>)
captures:
1: punctuation.definition.tag.begin.coffee
2: entity.name.tag.component.coffee
3: entity.name.tag.coffee
set: jsx-tag-close-body
- match: (<)(?:({{component_names}})|({{tag_names}}))(?=\s|/?>)
captures:
1: punctuation.definition.tag.begin.coffee
2: entity.name.tag.component.coffee
3: entity.name.tag.coffee
push: jsx-tag-open-body
- include: jsx-text-interpolations

jsx-tag-close-body:
- meta_include_prototype: false
- meta_scope: meta.tag.coffee
- match: /?>
scope: punctuation.definition.tag.end.coffee
pop: 1

jsx-tag-open-body:
- meta_include_prototype: false
- meta_scope: meta.tag.coffee
- match: />
scope: punctuation.definition.tag.end.coffee
pop: 1
- match: \>
scope: punctuation.definition.tag.end.coffee
set: jsx-body
- match: '{{attribute_name_start}}'
push:
- jsx-tag-attribute-meta
- jsx-tag-attribute-assignment
- jsx-tag-attribute-name

jsx-tag-attribute-name:
- meta_scope: entity.other.attribute-name.coffee
- include: jsx-string-interpolations
- match: '{{attribute_name_break}}'
pop: 1
- match: '["''`<]'
scope: invalid.illegal.attribute-name.coffee

jsx-tag-attribute-meta:
- meta_include_prototype: false
- meta_scope: meta.attribute-with-value.coffee
- include: immediately-pop

jsx-tag-attribute-assignment:
- meta_include_prototype: false
- match: =
scope: punctuation.separator.key-value.coffee
set: jsx-tag-attribute-value
- include: else-pop

jsx-tag-attribute-value:
- meta_include_prototype: false
- match: \"
scope: punctuation.definition.string.begin.coffee
set: jsx-tag-attribute-value-double-quoted-content
- match: \'
scope: punctuation.definition.string.begin.coffee
set: jsx-tag-attribute-value-single-quoted-content
- match: '{{unquoted_attribute_start}}'
set: jsx-tag-attribute-value-unquoted-content
- include: else-pop

jsx-tag-attribute-value-double-quoted-content:
# See the top of this file for why prototype is excluded
- meta_include_prototype: false
- meta_scope: meta.string.coffee string.quoted.double.coffee
- match: \"
scope: punctuation.definition.string.end.coffee
pop: 1
- include: jsx-string-interpolations

jsx-tag-attribute-value-single-quoted-content:
# See the top of this file for why prototype is excluded
- meta_include_prototype: false
- meta_scope: meta.string.coffee string.quoted.single.coffee
- match: \'
scope: punctuation.definition.string.end.coffee
pop: 1
- include: jsx-string-interpolations

jsx-tag-attribute-value-unquoted-content:
# See the top of this file for why prototype is excluded
- meta_include_prototype: false
- meta_content_scope: meta.string.coffee string.unquoted.coffee
- include: jsx-string-interpolations
- match: '{{unquoted_attribute_break}}'
pop: 1
- match: '["''`<]'
scope: invalid.illegal.attribute-value.coffee

jsx-string-interpolations:
- match: \{#
scope: punctuation.definition.comment.begin.coffee
push: jsx-string-comment-body
- match: \{
scope: punctuation.section.interpolation.begin.coffee
push: jsx-string-interpolation-body

jsx-string-comment-body:
# required to support "toggle_comment"
- clear_scopes: 1
- meta_scope: meta.interpolation.coffee comment.block.coffee
- include: jsx-text-comment-body

jsx-string-interpolation-body:
- clear_scopes: 1
- meta_scope: meta.interpolation.coffee
- meta_content_scope: source.coffee.embedded.jsx
- include: jsx-text-interpolation-body

jsx-text-interpolations:
- match: \{#
scope: punctuation.definition.comment.begin.coffee
push: jsx-text-comment-body
- match: \{
scope: punctuation.section.interpolation.begin.coffee
push: jsx-text-interpolation-body

jsx-text-comment-body:
# required to support "toggle_comment"
- meta_scope: meta.interpolation.coffee comment.block.coffee
- match: \}
scope: punctuation.definition.comment.end.coffee
pop: 1

jsx-text-interpolation-body:
- meta_scope: meta.interpolation.coffee
- meta_content_scope: source.coffee.embedded.jsx
- match: \}
scope: punctuation.section.interpolation.end.coffee
pop: 1
- match: \#
scope: punctuation.definition.comment.coffee
push: jsx-line-comment-body
- include: script

jsx-line-comment-body:
- meta_scope: comment.line.number-sign.coffee
- match: $\n?|(?=})
pop: 1

###[ VARIABLES ]###############################################################

instance-variables:
Expand All @@ -596,4 +762,18 @@ contexts:

variables:

ascii_space: '\t\n\f '

identifier: '[a-zA-Z\$_]\w*'

component_names: '[A-Z][[:alnum:]_.-]*'
tag_names: '[[:alpha:]][[:alnum:]_.-]*'

# https://html.spec.whatwg.org/multipage/syntax.coffee#attributes-2
attribute_name_break_char: '[{{ascii_space}}=/>]'
attribute_name_break: (?={{attribute_name_break_char}})
attribute_name_start: (?=[^{{attribute_name_break_char}}])

# https://html.spec.whatwg.org/multipage/syntax.coffee#syntax-attribute-value
unquoted_attribute_break: (?=[{{ascii_space}}]|/?>)
unquoted_attribute_start: (?=[^{{ascii_space}}=>])
26 changes: 26 additions & 0 deletions Comments JSX.tmPreferences
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>scope</key>
<string>source.coffee meta.jsx, source.coffee meta.jsx meta.interpolation comment.line</string>
<key>settings</key>
<dict>
<key>shellVariables</key>
<array>
<dict>
<key>name</key>
<string>TM_COMMENT_START</string>
<key>value</key>
<string>{# </string>
</dict>
<dict>
<key>name</key>
<string>TM_COMMENT_END</string>
<key>value</key>
<string> }</string>
</dict>
</array>
</dict>
</dict>
</plist>
46 changes: 46 additions & 0 deletions tests/syntax_test_scope.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,49 @@ class App.Router extends Snakeskin.Router
@variable
# ^^^^^^^^^ variable.other.readwrite.instance.coffee
# ^ punctuation.definition.variable.coffee

###[ JSX ]#####################################################################

<Component attrib="va{@lue}">
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.jsx.coffee meta.tag.coffee
# ^ punctuation.definition.tag.begin.coffee
# ^^^^^^^^^ entity.name.tag.component.coffee
# ^^^^^^^^^^^^^^^^^ meta.attribute-with-value.coffee
# ^^^^^^ entity.other.attribute-name.coffee
# ^ punctuation.separator.key-value.coffee
# ^^^ meta.string.coffee string.quoted.double.coffee
# ^^^^^^ meta.string.coffee meta.interpolation.coffee
# ^ punctuation.section.interpolation.begin.coffee
# ^^^^ source.coffee.embedded.jsx variable.other.readwrite.instance.coffee
# ^ punctuation.section.interpolation.end.coffee
# ^ meta.string.coffee string.quoted.double.coffee punctuation.definition.string.end.coffee
# ^ punctuation.definition.tag.end.coffee
<h1>Text {# comment}!</h1>
# ^^^^ meta.jsx.coffee meta.tag.coffee
# ^ punctuation.definition.tag.begin.coffee
# ^^ entity.name.tag.coffee
# ^ punctuation.definition.tag.end.coffee
# ^^^^^ meta.jsx.coffee - meta.interpolation
# ^^^^^^^^^^^ meta.jsx.coffee meta.interpolation.coffee comment.block.coffee
# ^^ punctuation.definition.comment.begin.coffee
# ^ punctuation.definition.comment.end.coffee
# ^ meta.jsx.coffee - meta.interpolation
# ^^^^^ meta.jsx.coffee meta.tag.coffee
# ^^ punctuation.definition.tag.begin.coffee
# ^^ entity.name.tag.coffee
# ^ punctuation.definition.tag.end.coffee
</Component>
# ^^^^^^^^^^^^ meta.jsx.coffee meta.tag.coffee
# ^^ punctuation.definition.tag.begin.coffee
# ^^^^^^^^^ entity.name.tag.component.coffee
# ^ punctuation.definition.tag.end.coffee
# ^ - meta.jsx - meta.tag

<EmailInput
{# THIS IS A GOOD COMMENT }
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.jsx.coffee meta.tag.coffee meta.attribute-with-value.coffee meta.interpolation.coffee comment.block.coffee
{...@props}
# ^^^^^^^^^^^ meta.jsx.coffee meta.tag.coffee meta.attribute-with-value.coffee meta.interpolation.coffee
/>
# ^^ meta.jsx.coffee meta.tag.coffee punctuation.definition.tag.end.coffee
# ^ - meta.jsx - meta.tag

0 comments on commit 4556045

Please sign in to comment.