Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Merge pull request #172 from cuberoot/add-jsx
Browse files Browse the repository at this point in the history
Add support for JSX tags to the CoffeeScript grammar
  • Loading branch information
smashwilson authored Jan 25, 2019
2 parents c851642 + 6f9a231 commit a1ca025
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 0 deletions.
85 changes: 85 additions & 0 deletions grammars/coffeescript.cson
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
'coffee.erb'
'cson'
'_coffee'
'cjsx'
]
'firstLineMatch': '''(?x)
# Hashbang
Expand All @@ -27,6 +28,9 @@
)
'''
'patterns': [
{
'include': '#jsx'
}
{
'match': '(new)\\s+(?:(?:(class)\\s+(\\w+(?:\\.\\w*)*)?)|(\\w+(?:\\.\\w*)*))'
'name': 'meta.class.instance.constructor.coffee'
Expand Down Expand Up @@ -1148,3 +1152,84 @@
'include': '#embedded_comment'
}
]

'jsx':
'patterns': [
{
'include': '#jsx-tag'
}
{
'include': '#jsx-end-tag'
}
]

'jsx-expression':
'begin': '{'
'beginCaptures':
'0':
'name': 'meta.brace.curly.coffee'
'end': '}'
'endCaptures':
'0':
'name': 'meta.brace.curly.coffee'

'patterns': [
{
'include': '#double_quoted_string'
}
{
'include': '$self'
}
]

'jsx-attribute':
'patterns': [
{
'captures':
'1':
'name': 'entity.other.attribute-name.coffee'
'2':
'name': 'keyword.operator.assignment.coffee'
'match': '(?:^|\\s+)([-\\w.]+)\\s*(=)'
}
{
'include': '#double_quoted_string'
}
{
'include': '#single_quoted_string'
}
{
'include': '#jsx-expression'
}
]

'jsx-tag':
'patterns': [
{
'begin': '(<)([-\\w\\.]+)'
'beginCaptures':
'1':
'name': 'punctuation.definition.tag.coffee'
'2':
'name': 'entity.name.tag.coffee'
'end': '(/?>)'
'name': 'meta.tag.coffee'
'patterns': [
'include': '#jsx-attribute'
]
}
]

'jsx-end-tag':
'patterns': [
{
'begin': '(</)([-\\w\\.]+)'
'beginCaptures':
'1':
'name': 'punctuation.definition.tag.coffee'
'2':
'name': 'entity.name.tag.coffee'
'end': '(/?>)'
'name': 'meta.tag.coffee'
}
]
53 changes: 53 additions & 0 deletions spec/coffee-script-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,59 @@ describe "CoffeeScript grammar", ->
expect(tokens[8]).toEqual value: 'b', scopes: ['source.coffee', 'string.quoted.single.coffee', 'constant.character.escape.backslash.coffee']
expect(tokens[9]).toEqual value: "'", scopes: ['source.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee']

describe "jsx", ->
it "tokenises HTML tags", ->
{tokens} = grammar.tokenizeLine("<div></div>")
expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']
expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]
expect(tokens[2]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]
expect(tokens[3]).toEqual value: '</', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee' ]
expect(tokens[4]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]
expect(tokens[5]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]

{tokens} = grammar.tokenizeLine("<div/>")
expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']
expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]
expect(tokens[2]).toEqual value: '/>', scopes: ['source.coffee', 'meta.tag.coffee' ]

it "tokenises HTML tags with attributes", ->
{tokens} = grammar.tokenizeLine("<div class='myclass' id=\"myid\">")
expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']
expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]
expect(tokens[2]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]
expect(tokens[3]).toEqual value: 'class', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]
expect(tokens[4]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]
expect(tokens[5]).toEqual value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.begin.coffee' ]
expect(tokens[6]).toEqual value: 'myclass', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee' ]
expect(tokens[7]).toEqual value: '\'', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.single.coffee', 'punctuation.definition.string.end.coffee' ]
expect(tokens[8]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]
expect(tokens[9]).toEqual value: 'id', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]
expect(tokens[10]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]
expect(tokens[11]).toEqual value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.begin.coffee' ]
expect(tokens[12]).toEqual value: 'myid', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee' ]
expect(tokens[13]).toEqual value: '"', scopes: ['source.coffee', 'meta.tag.coffee', 'string.quoted.double.coffee', 'punctuation.definition.string.end.coffee' ]
expect(tokens[14]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee' ]

it "tokenises HTML tags with attributes that have expressions", ->
{tokens} = grammar.tokenizeLine("<div on-click={(e)->@handleClick(e)}>")
expect(tokens[0]).toEqual value: '<', scopes: ['source.coffee', 'meta.tag.coffee', 'punctuation.definition.tag.coffee']
expect(tokens[1]).toEqual value: 'div', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.name.tag.coffee' ]
expect(tokens[2]).toEqual value: ' ', scopes: ['source.coffee', 'meta.tag.coffee' ]
expect(tokens[3]).toEqual value: 'on-click', scopes: ['source.coffee', 'meta.tag.coffee', 'entity.other.attribute-name.coffee' ]
expect(tokens[4]).toEqual value: '=', scopes: ['source.coffee', 'meta.tag.coffee', 'keyword.operator.assignment.coffee' ]
expect(tokens[5]).toEqual value: '{', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee']
expect(tokens[6]).toEqual value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.begin.bracket.round.coffee' ]
expect(tokens[7]).toEqual value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'variable.parameter.function.coffee' ]
expect(tokens[8]).toEqual value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'meta.parameters.coffee', 'punctuation.definition.parameters.end.bracket.round.coffee' ]
expect(tokens[9]).toEqual value: '->', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function.inline.coffee', 'storage.type.function.coffee' ]
expect(tokens[10]).toEqual value: '@', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'variable.other.readwrite.instance.coffee' ]
expect(tokens[11]).toEqual value: 'handleClick', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'entity.name.function.coffee' ]
expect(tokens[12]).toEqual value: '(', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.begin.bracket.round.coffee' ]
expect(tokens[13]).toEqual value: 'e', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee' ]
expect(tokens[14]).toEqual value: ')', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.function-call.coffee', 'meta.arguments.coffee', 'punctuation.definition.arguments.end.bracket.round.coffee' ]
expect(tokens[15]).toEqual value: '}', scopes: ['source.coffee', 'meta.tag.coffee', 'meta.brace.curly.coffee']
expect(tokens[16]).toEqual value: '>', scopes: ['source.coffee', 'meta.tag.coffee']

describe "firstLineMatch", ->
it "recognises interpreter directives", ->
valid = """
Expand Down

0 comments on commit a1ca025

Please sign in to comment.