%YAML 1.2
---
# Vue Single-File Component (.vue) 语法高亮。
#
# 自包含实现:不依赖 `extends: Packages/HTML/...`(syntect 不认 ST 包路径),
# 改用 embed: scope: 引用本项目已有的 HTML/JS/TS/TSX/CSS scope。
#
# 关键约束(syntect 5.3 实测):
# - embed 规则必须用纯净写法 `match + embed + escape`,不能附加 pop/embed_scope,
# 否则 embed 失效并静默回退纯文本。
# - escape 用 lookahead `(?=...)` 不消费闭合标签,交给外层 context 处理。
#
# 分段策略:SFC 的 /])'
###[ TEMPLATE ]#############################################################
template-tag-open:
- meta_scope: meta.tag.structure.template.begin.html
- include: tag-attributes
- match: '/>'
scope: punctuation.definition.tag.end.html
pop: 1
- match: '>'
scope: punctuation.definition.tag.end.html
push: template-content
template-content:
- meta_include_prototype: false
- meta_content_scope: meta.template.vue
# 闭合 :结束段
- match: '(?=])'
pop: 1
# Vue 插值 {{ ... }}:embed JS 表达式
- match: '\{\{'
scope: punctuation.section.interpolation.begin.html
embed: scope:source.js
escape: '\}\}'
escape_captures:
0: punctuation.section.interpolation.end.html
# 其余:按 HTML 处理(标签、文本、属性),同时识别 Vue 指令
- include: scope:text.html.basic
###[ SCRIPT ]###############################################################
# 分流在 main 完成:含 lang="ts|tsx|typescript" 的 ])'
###[ STYLE ]################################################################
style-tag-open:
- meta_scope: meta.tag.structure.style.begin.html
- include: tag-attributes
- match: '/>'
scope: punctuation.definition.tag.end.html
pop: 1
- match: '>'
scope: punctuation.definition.tag.end.html
embed: scope:source.css
escape: '(?=])'
###[ SHARED ]###############################################################
# 标签属性扫描:Vue 指令 + 普通属性 + 值。供 template/script/style 的 open context 复用。
tag-attributes:
# Vue 指令(v-if / @click / :prop / #slot)优先,标为属性名
- match: '{{vue_directive}}\s*(=)?'
scope: entity.other.attribute-name.html
# 普通属性名 = 值
- match: '\b[A-Za-z-][\w:-]*\s*(=)'
scope: entity.other.attribute-name.html
push: maybe-attr-value
# 布尔属性
- match: '\b[A-Za-z-][\w:-]*'
scope: entity.other.attribute-name.html
- include: whitespace
maybe-attr-value:
- include: whitespace
- match: '"'
scope: punctuation.definition.string.begin.html
set: double-quoted-attr-value
- match: "'"
scope: punctuation.definition.string.begin.html
set: single-quoted-attr-value
- match: '(?=\S)'
pop: 1
double-quoted-attr-value:
- meta_scope: string.quoted.double.html
- match: '"'
scope: punctuation.definition.string.end.html
pop: 1
- include: attr-value-escapes
single-quoted-attr-value:
- meta_scope: string.quoted.single.html
- match: "'"
scope: punctuation.definition.string.end.html
pop: 1
- include: attr-value-escapes
attr-value-escapes:
- match: '&[a-zA-Z]+;|\d+;|[0-9A-Fa-f]+;'
scope: constant.character.entity.html
whitespace:
- match: '\s+'