TypeScript-TmLanguage/TypeScriptReact.YAML-tmLang...

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+
...