204 строки
6.6 KiB
YAML
204 строки
6.6 KiB
YAML
# [PackageDev] target_format: plist, ext: tmLanguage
|
|
# Similar to TypeScript.YAML-tmLanguage except:
|
|
# - Remove type assertion (cast.expr.tsx)
|
|
# - Add JSX expression (HTML-like expression).
|
|
---
|
|
name: TypeScriptReact
|
|
scopeName: source.tsx
|
|
fileTypes: [tsx]
|
|
uuid: 805375ec-d614-41f5-8993-5843fe63ea82
|
|
|
|
variables:
|
|
possiblyMultilineArrow: ([\(]\s*([\{\[]\s*)?$) # during lookup treat ( followed by line end as arrow
|
|
jsxTagOrAtrributeIdentifier: '[_$a-zA-Z][-$\w.]'
|
|
jsxTagNamespace: (?:({{jsxTagOrAtrributeIdentifier}}*)(?<!\.|-)(:))?
|
|
jsxTagName: \s*{{jsxTagNamespace}}((?:[a-z][a-z0-9]*|({{jsxTagOrAtrributeIdentifier}}*))(?<!\.|-))
|
|
jsxOpeningTagWithoutAttributes: (<){{jsxTagName}}?\s*(>)
|
|
jsxClosingTag: (</){{jsxTagName}}?\s*(>)
|
|
jsxTagStart: (<){{jsxTagName}}(?=(({{typeArguments}}\s*)|(\s+))(?!\?)|\/?>)
|
|
jsxTagStartLookahead: (?={{jsxTagStart}})
|
|
jsxLookBehindInExpression: (?<!\+\+|--)(?<=[({\[,?=>:*]|&&|\|\||\?|{{lookBehindReturn}}|{{lookBehindDefault}}|^)\s*
|
|
|
|
repository:
|
|
# Additions:
|
|
# expression repository need to include jsx first followed by whaterver ts grammar says
|
|
expressionWithoutIdentifiers:
|
|
patterns:
|
|
- include: '#jsx'
|
|
|
|
# Overrides:
|
|
|
|
# We need to override this to make sure cast is not matched from typescript
|
|
# We can safely include jsx because thats the first rule matched anyways so it wont impact at all
|
|
cast:
|
|
patterns:
|
|
- include: '#jsx'
|
|
|
|
# jsx syntax is taken from https://github.com/babel/babel-sublime
|
|
jsx:
|
|
patterns:
|
|
- include: '#jsx-tag-without-attributes-in-expression'
|
|
- include: '#jsx-tag-in-expression'
|
|
|
|
#jsx tags
|
|
jsx-tag-without-attributes-in-expression:
|
|
begin: '{{jsxLookBehindInExpression}}(?={{jsxOpeningTagWithoutAttributes}})'
|
|
end: (?!{{jsxOpeningTagWithoutAttributes}})
|
|
patterns:
|
|
- include: '#jsx-tag-without-attributes'
|
|
|
|
jsx-tag-without-attributes:
|
|
name: meta.tag.without-attributes.tsx
|
|
begin: '{{jsxOpeningTagWithoutAttributes}}'
|
|
end: '{{jsxClosingTag}}'
|
|
beginCaptures:
|
|
'1': {name: punctuation.definition.tag.begin.tsx}
|
|
'2': {name: entity.name.tag.namespace.tsx}
|
|
'3': {name: punctuation.separator.namespace.tsx}
|
|
'4': {name: entity.name.tag.tsx}
|
|
'5': {name: support.class.component.tsx}
|
|
'6': {name: punctuation.definition.tag.end.tsx}
|
|
endCaptures:
|
|
'1': {name: punctuation.definition.tag.begin.tsx}
|
|
'2': {name: entity.name.tag.namespace.tsx}
|
|
'3': {name: punctuation.separator.namespace.tsx}
|
|
'4': {name: entity.name.tag.tsx}
|
|
'5': {name: support.class.component.tsx}
|
|
'6': {name: punctuation.definition.tag.end.tsx}
|
|
contentName: meta.jsx.children.tsx
|
|
patterns:
|
|
- include: '#jsx-children'
|
|
|
|
jsx-tag-in-expression:
|
|
# We need to differentiate between the relational '<' operator and the beginning of a tag using the surrounding context.
|
|
begin: |-
|
|
(?x)
|
|
{{jsxLookBehindInExpression}}
|
|
(?!<\s*[_$[:alpha:]][_$[:alnum:]]*((\s+extends\s+[^=>])|,)) # look ahead is not type parameter of arrow
|
|
{{jsxTagStartLookahead}}
|
|
end: (?!{{jsxTagStart}})
|
|
patterns:
|
|
- include: '#jsx-tag'
|
|
|
|
jsx-tag:
|
|
name: meta.tag.tsx
|
|
begin: '{{jsxTagStartLookahead}}'
|
|
end: (/>)|(?:{{jsxClosingTag}})
|
|
endCaptures:
|
|
'1': { name: punctuation.definition.tag.end.tsx }
|
|
'2': { name: punctuation.definition.tag.begin.tsx }
|
|
'3': { name: entity.name.tag.namespace.tsx }
|
|
'4': { name: punctuation.separator.namespace.tsx }
|
|
'5': { name: entity.name.tag.tsx }
|
|
'6': { name: support.class.component.tsx }
|
|
'7': { name: punctuation.definition.tag.end.tsx }
|
|
patterns:
|
|
- begin: '{{jsxTagStart}}'
|
|
beginCaptures:
|
|
'1': { name: punctuation.definition.tag.begin.tsx }
|
|
'2': { name: entity.name.tag.namespace.tsx }
|
|
'3': { name: punctuation.separator.namespace.tsx }
|
|
'4': { name: entity.name.tag.tsx }
|
|
'5': { name: support.class.component.tsx }
|
|
end: (?=[/]?>)
|
|
patterns:
|
|
- include: '#comment'
|
|
- include: '#type-arguments'
|
|
- include: '#jsx-tag-attributes'
|
|
- begin: (>)
|
|
beginCaptures:
|
|
'1': { name: punctuation.definition.tag.end.tsx }
|
|
end: (?=</)
|
|
contentName: meta.jsx.children.tsx
|
|
patterns:
|
|
- include: '#jsx-children'
|
|
|
|
#jsx children
|
|
jsx-children:
|
|
patterns:
|
|
- include: '#jsx-tag-without-attributes'
|
|
# Because this would be included from the jsx-children, this doesnt need to inspect surrounding context
|
|
- include: '#jsx-tag'
|
|
- include: '#jsx-evaluated-code'
|
|
- include: '#jsx-entities'
|
|
|
|
#entities and evaluated code
|
|
jsx-evaluated-code:
|
|
name: meta.embedded.expression.tsx
|
|
begin: \{
|
|
end: \}
|
|
beginCaptures:
|
|
'0': { name: punctuation.section.embedded.begin.tsx }
|
|
endCaptures:
|
|
'0': { name: punctuation.section.embedded.end.tsx }
|
|
patterns:
|
|
- include: '#expression'
|
|
|
|
jsx-entities:
|
|
patterns:
|
|
- name: constant.character.entity.tsx
|
|
match: (&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)
|
|
captures:
|
|
'1': {name: punctuation.definition.entity.tsx}
|
|
'3': {name: punctuation.definition.entity.tsx}
|
|
- name: invalid.illegal.bad-ampersand.tsx
|
|
match: '&'
|
|
|
|
#jsx attributes
|
|
jsx-tag-attributes:
|
|
name: meta.tag.attributes.tsx
|
|
begin: \s+
|
|
end: (?=[/]?>)
|
|
patterns:
|
|
- include: '#comment'
|
|
- include: '#jsx-tag-attribute-name'
|
|
- include: '#jsx-tag-attribute-assignment'
|
|
- include: '#jsx-string-double-quoted'
|
|
- include: '#jsx-string-single-quoted'
|
|
- include: '#jsx-evaluated-code'
|
|
- include: '#jsx-tag-attributes-illegal'
|
|
|
|
jsx-tag-attribute-name:
|
|
match: |-
|
|
(?x)
|
|
\s*
|
|
(?:({{jsxTagOrAtrributeIdentifier}}*)(:))?
|
|
([_$a-zA-Z][-$\w]*)
|
|
(?=\s|=|/?>|/\*|//)
|
|
captures:
|
|
'1': {name: entity.other.attribute-name.namespace.tsx}
|
|
'2': {name: punctuation.separator.namespace.tsx}
|
|
'3': {name: entity.other.attribute-name.tsx}
|
|
|
|
jsx-tag-attribute-assignment:
|
|
name: keyword.operator.assignment.tsx
|
|
match: =(?=\s*(?:'|"|{|/\*|//|\n))
|
|
|
|
jsx-string-double-quoted:
|
|
name: string.quoted.double.tsx
|
|
begin: '"'
|
|
end: '"'
|
|
beginCaptures:
|
|
'0': {name: punctuation.definition.string.begin.tsx}
|
|
endCaptures:
|
|
'0': {name: punctuation.definition.string.end.tsx}
|
|
patterns:
|
|
- include: '#jsx-entities'
|
|
|
|
jsx-string-single-quoted:
|
|
name: string.quoted.single.tsx
|
|
begin: "'"
|
|
end: "'"
|
|
beginCaptures:
|
|
'0': {name: punctuation.definition.string.begin.tsx}
|
|
endCaptures:
|
|
'0': {name: punctuation.definition.string.end.tsx}
|
|
patterns:
|
|
- include: '#jsx-entities'
|
|
|
|
jsx-tag-attributes-illegal:
|
|
name: invalid.illegal.attribute.tsx
|
|
match: \S+
|
|
|
|
...
|