news 2026/9/6 15:56:54

Typst 官方 VS Code 语言支持扩展解析:tools/support 的语言注册、编辑行为配置与 TextMate 语法规则

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Typst 官方 VS Code 语言支持扩展解析:tools/support 的语言注册、编辑行为配置与 TextMate 语法规则

Typst 官方 VS Code 语言支持扩展解析:tools/support 的语言注册、编辑行为配置与 TextMate 语法规则

【免费下载链接】typstA markup-based typesetting system that is powerful and easy to learn.项目地址: https://gitcode.com/GitHub_Trending/ty/typst

本文为 Typst 仓库中 tools/support 目录下官方随附的 VS Code 语言支持扩展做逐文件解析。读完本篇,你将理解一个最小化语言扩展是如何通过package.json声明语言 ID 与语法、通过config.json控制注释切换与括号自动补全、通过typst.tmLanguage.json实现 markup 与 code 双上下文的 TextMate 高亮规则的,并掌握通过符号链接安装该扩展的具体方法及其维护状态。

扩展的定位与维护状态

根据 tools/support/README.md 的说明,该扩展为 Typst 提供最小化(minimal)的语言支持,内容仅包含两样东西:

  • 一份语法定义(TextMate grammar),用于语法高亮;
  • 一份语言配置(language configuration),用于注释切换、括号自动关闭等编辑器行为。

README 同时给出了三条明确的使用前提,这也是读者在评估是否采用前必须了解的事实:

  1. 该扩展最初是为 Typst 自身的开发目的而创建的("created for development purposes only"),主要服务于 Typst 仓库内部开发者编辑.typ文件;
  2. 它当前不被维护,且官方承认其语法规则存在 bug("It is not maintained and its grammar is buggy");
  3. 官方建议有日常编辑需求的用户改用第三方更积极维护的Tinymist 扩展,本仓库内的tools/support应视为"轻量兜底方案"而非正式编辑器产品。

从仓库结构看,tools/目录下与 VS Code 生态相关的还有 tools/test-helper 扩展——这是一个帮助管理 Typst 测试套件的辅助扩展,二者都属于仓库开发工具链的一部分,而非发行给终端用户的组件。

扩展清单:package.json 如何声明一个 Typst 语言

package.json 是整个扩展的入口清单,虽然只有 29 行,但完整覆盖了 VS Code 语言扩展所需的最小字段集。

基本元信息

字段说明
nametypst扩展标识名
displayNameTypst编辑器中显示的名称
descriptionTypst Language Support.扩展用途描述
version0.0.1版本号为初始占位值,侧面印证 README 中"未正式维护"的定位
engines.vscode^1.53.0要求 VS Code 1.53 及以上版本
categories["Programming Languages"]声明为编程语言类扩展

语言注册(contributes.languages)

清单在contributes.languages中注册了 Typst 语言:

"languages": [ { "id": "typst", "aliases": ["Typst", "typst"], "extensions": [".typ"], "configuration": "./config.json" } ]

这一节做了四件事:

  • id: "typst":确定语言标识符,后续语法、主题覆盖、语言特定设置都以此为锚点;
  • aliasesTypsttypst两种写法都可用于编辑器状态栏的语言切换器;
  • extensions: [".typ"]:把.typ文件后缀绑定到该语言。仓库中大量.typ源文件(如 tests/suite 下的测试用例、docs 下的文档源文件)即依赖此绑定获得高亮;
  • configuration: "./config.json":指向下一节要详细解析的语言行为配置文件。

语法注册(contributes.grammars)

"grammars": [ { "language": "typst", "scopeName": "source.typst", "path": "./typst.tmLanguage.json" } ]

它将typst语言与 TextMate 语法文件绑定,并声明了顶层作用域名source.typst。这一点与 typst.tmLanguage.json 末尾的"scopeName": "source.typst"字段相互呼应——两个文件中的 scopeName 必须一致,语法主题才能正确命中规则。

语言行为配置:config.json 全字段解析

config.json 是 VS Code 语言配置协议(Language Configuration)的标准文件,共 29 行,定义了 Typst 在编辑器中的交互行为。逐项说明如下。

注释定义(comments)

"comments": { "lineComment": "//", "blockComment": ["/*", "*/"] }
  • 行注释前缀为//,编辑器中Ctrl+/注释切换即基于此;
  • 块注释定界符为/* ... */,支持 VS Code 的块注释插入与切换。

括号配对(brackets)

"brackets": [ ["[", "]"], { 实际为 ["{", "}"], ["(", ")"] ]

声明了三组结构性括号,用于编辑器的括号跳转、选中扩展等功能。

自动闭合对(autoClosingPairs)

"autoClosingPairs": [ { "open": "[", "close": "]" }, { "open": "{", "close": "}" }, { "open": "(", "close": ")" }, { "open": "\"", "close": "\"", "notIn": ["string"] }, { "open": "$", "close": "$", "notIn": ["string"] } ]

三组括号之外,还有两个与 Typst 语义直接相关的配置:

  • 双引号自动闭合,且notIn: ["string"]限定只在字符串作用域之外触发,避免在字符串内部再次输入"时被错误补全;
  • 美元符号$自动闭合——这是针对 Typst 数学定界符的专门配置:在正文中敲入$时会自动补上闭合$,方便快速包裹行内数学。

自动闭合字符(autoCloseBefore)

"autoCloseBefore": "$ \n\t"

表示$、空格、换行符与制表符这些字符出现前会先触发未闭合括号的自动闭合。将$列入其中,同样是服务于"在数学表达式结束处自然收束定界符"的编辑体验。

环境包裹对(surroundingPairs)

"surroundingPairs": [ ["[", "]"], ["{", "}"], ["(", ")"], ["\"", "\""], ["*", "*"], ["_", "_"], ["`", "`"], ["$", "$"] ]

当光标位于一段选中文字之间时,输入该对的左侧字符会用整对符号包裹选区。除常规括号与引号外,特别纳入了*_`$四组——它们正好对应 Typst 标记语言中的粗体(*text*)、斜体(_text_)、原始文本/代码块(反引号)、数学定界符四种行内语法,使得"选中一段文字后直接敲_变斜体"这类操作可以一步完成。

高亮引擎:typst.tmLanguage.json 语法结构详解

typst.tmLanguage.json 是一份标准 TextMate 语法定义(共约 382 行),也是该扩展的核心资产。它的整体组织方式如下:

顶层 patterns → #markup(入口) repository: ├─ comments 注释规则(块注释 + 行注释) ├─ common 公共 include(目前仅注释) ├─ markup 正文(markup 上下文)规则集 ├─ code 代码(code 上下文)规则集 ├─ constants 常量与字面量规则集 └─ arguments 函数参数规则集

顶层只有一条{"include": "#markup"}(见 typst.tmLanguage.json#L3-L5),意味着所有规则都从 markup 上下文出发,进入#代码区后再切换到 code 上下文——这与 Typst "标记中嵌代码、代码中嵌标记"的双层语法结构完全对应。

双上下文设计:markup 与 code 的切换

markup 规则集末尾(#L206-L209)有一条兜底规则:

{ "name": "meta.block.content.typst", "begin": "#", "end": "\\s", "patterns": [{ "include": "#code" }] }

它把#之后的代码段交给#code规则集处理;而 code 上下文(#L217-L228)又反过来处理两种嵌套容器:

  • {...}代码块 → 递归进入#code
  • [...]内容块 → 递归切回#markup

这种双向递归使语法能够正确区分#let x = [正文]中的正文部分与代码部分,例如:

#let title = "Hello" #show heading.where(level: 1): set text(size: 14pt) = 第一章 这是 **粗体**、*斜体*、`raw` 文本与 $x^2$ 数学。 <figure-label>@figure-label #enum(items) { item => text[item] }

注释规则的一个细节

markup 上下文的行注释规则(#L17-L21)使用了负向后顾(?<!:)//

{ "name": "comment.line.double-slash.typst", "begin": "(?<!:)//" }

要求//前不能紧跟冒号,目的是避免把http://这类 URL 中的斜杠误判为行注释起始(markup 中另有独立的 URL 高亮规则,#L80-L82)。而 code 上下文中的//注释(#L231-L235)则没有这个限制,因为 Typst 代码区里//就是纯粹的注释。

markup 上下文覆盖的典型语法点

从 typst.tmLanguage.json 的 markup 规则集(#L30-L212)可以核对以下 Typst 正文语法均被覆盖:

语法作用域 / 匹配位置
转义字符(\*\#\_\u{...}等)constant.character.escape.content.typstL34-L36
手动换行\\punctuation.definition.linebreak.typstL38-L40
不换行空格~、软连字符-?punctuation.definition.nonbreaking-space.typstL41-L48
破折号--/---、省略号...punctuation.definition.en-dash.typstL49-L60
符号引用:sym:(如:star:constant.symbol.typstL62-L64
粗体*text*/ 斜体_text_markup.bold.typst/markup.italic.typst,且支持内部再递归#markupL66-L78
URL 高亮markup.underline.link.typstL80-L82
原始文本:反引号行内与 ```` `` 块级markup.raw.inline.typst/markup.raw.block.typstL84-L94
数学定界$...$string.other.math.typstL96-L100
标题= 一级标题markup.heading.typst+entity.name.section.typstL102-L108
无序/有序/描述列表punctuation.definition.list.*.typstL110-L123
标签<label>与引用@labelentity.other.label.typst/entity.other.reference.typstL125-L133
语句#let / #set / #show / #context / #import / #include / #export / #if各自keyword.*作用域,块体递归#codeL135-L186
控制流#for / #while / #break / #continue / #returnkeyword.control.*.typstL159-L186
函数名(#name(...)/#name[...]entity.name.function.typstL188-L192
函数调用参数区复用#arguments规则集L194-L199
变量插值#varentity.other.interpolated.typstL200-L204

code 上下文与常量体系

code 规则集(#L213-L314)处理裸代码(如{ ... }块内)中的词法单元:

  • 分隔符与运算符,:分隔符,=>..运算符,== != <= < >= >关系运算符,+= -= *= /= =赋值运算符,算术运算符+ * / -(其中减号用负向后顾排除标识符内部的-),以及and / or / not逻辑字面运算符;
  • 关键字let as in set show contextif elsefor while break continueimport include exportreturn全部有对应的keyword.*规则;
  • 函数识别:两条entity.name.function.typst规则分别匹配"标识符后跟[("的函数调用,以及show 选择器:函数模式下的被绑定函数名(#L286-L294);
  • 兜底变量:任何未被前述规则命中的标识符都归入variable.other.typst(#L303-L305)。

constants 规则集(#L315-L370)则把 Typst 的字面量做成了完整的常量家族:

常量类型匹配示例作用域
none/auto关键字常量constant.language.none.typst/constant.language.auto.typst
布尔值truefalseconstant.language.boolean.typst
长度10pt1.5em2in12mm0.5cmconstant.numeric.length.typst
角度90deg1.5radconstant.numeric.angle.typst
百分比50%constant.numeric.percentage.typst
弹性单位1frconstant.numeric.fr.typst
整数(含进制)420xFF0b1010o7constant.numeric.integer.typst
浮点数3.141e-3constant.numeric.float.typst
字符串(含转义)"a\nb"\u{..}等 |string.quoted.double.typst`

值得注意的是,fr、长度单位与角度单位在这里都有独立的高亮作用域——这与 Typst 语言本身把12pt50%1fr作为带类型数值一等公民的设计相呼应,也让基于作用域的自定义主题可以分别给不同量纲着色。

arguments 规则集(#L371-L379)负责函数参数列表的高亮:以:结尾的标识符被标记为variable.parameter.typst(具名参数/参数标签),其余部分继续按 code 规则处理。

安装方式:符号链接法

README 给出的唯一安装方式是符号链接

The simplest way to install this extension (and keep it up-to-date) is to add a symlink from~/.vscode/extensions/typst-supporttopath/to/typst/tools/support.

即把用户目录下的 VS Code 扩展挂载点~/.vscode/extensions/typst-support软链到本地仓库中的tools/support目录。这一方式有两个直接好处:

  • 始终与仓库代码同步:软链指向的是源码目录本身,对语法文件的任何改动在编辑器侧无需"重装"即可生效,适合 Typst 仓库内部开发时边改语法边验证;
  • 不产生副本:仓库中不存在打包/发布流程(从清单中也没有 marketplace 发布相关字段看,可以推断该扩展未走扩展市场分发),软链是最省事的挂载方式。

Windows 用户若需实现同样效果,可使用管理员权限的mklink /D创建目录符号链接。需要再次强调 README 的告诫:由于官方明确其"仅用于开发目的、不再维护、语法存在 bug",对高亮质量有更高要求的日常写作场景,建议转向第三方 Tinymist 扩展。

在仓库中的位置与验证方式

结合仓库现状可以这样理解该组件的边界:

  • 不参与编译管线:根 Cargo.toml 的 workspace members 为crates/*docstests等,tools/下的两个扩展均独立于 Rust 工作区,仅供编辑器侧使用;
  • 它是纯声明式资源:全部功能由三个 JSON 文件表达(清单、语言行为、语法规则),没有可执行代码,因此"运行"它的方式就是让 VS Code 加载这个目录;
  • 语法覆盖是否有效,可以用仓库中现成的.typ文件直接验证——例如打开 tests/suite/foundations 或 docs/content/tutorial 下的任一 Typst 源文件,观察标题、数学、#set语句与12pt类常量是否获得预期高亮;
  • 仓库对开发者的相关提示还散见于 tests/src/args.rs(建议用code --diff在 VS Code 中查看测试 diff)与 tests/README.md(介绍tools/test-helper扩展),说明tools/目录整体是 Typst 团队内部开发工作流的配套工具。

小结

tools/support用一个不到 400 行的 TextMate 语法、一个 29 行的语言配置和一个 29 行的扩展清单,搭出了 Typst 在 VS Code 中的最小可用语言体验:语言 ID 与.typ后缀绑定、注释/括号/数学定界符的编辑行为、以及 markup 与 code 双上下文递归的高亮体系。它当前的官方定位是"开发用、未维护"的兜底方案,日常重度使用建议参考官方推荐的第三方 Tinymist 扩展;但作为理解 Typst 语法在编辑器侧如何被表达的一份"活文档",这三个 JSON 文件值得任何想要自定义 Typst 主题或构建自己编辑器集成的开发者逐条阅读。

【免费下载链接】typstA markup-based typesetting system that is powerful and easy to learn.项目地址: https://gitcode.com/GitHub_Trending/ty/typst

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 15:56:04

DuckDB 在未来机器人领域的应用:让每台机器人都拥有“本地数据大脑”

DuckDB 在未来机器人领域的应用&#xff1a;让每台机器人都拥有“本地数据大脑” 当机器人从单一机械执行设备走向具身智能系统&#xff0c;真正限制其规模化落地的往往不只是机械臂、传感器或大模型&#xff0c;而是数据&#xff1a;如何把来自摄像头、激光雷达、力传感器、关…

作者头像 李华
网站建设 2026/9/6 15:52:22

DeepTutor 从 0 到 1:3 条命令拉起一个真正陪学的本地 AI 导师

DeepTutor 从 0 到 1&#xff1a;3 条命令拉起一个真正陪学的本地 AI 导师 【免费下载链接】DeepTutor DeepTutor: Lifelong Personalized Tutoring. https://deeptutor.info/. 项目地址: https://gitcode.com/GitHub_Trending/dee/DeepTutor DeepTutor 是一个开源的“智…

作者头像 李华
网站建设 2026/9/6 15:50:58

ComfyUI性能优化实战:按显存档位选参数,从OOM到多卡并行

ComfyUI性能优化实战&#xff1a;按显存档位选参数&#xff0c;从OOM到多卡并行 【免费下载链接】ComfyUI The most powerful and modular diffusion model GUI, api and backend with a graph/nodes interface. 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI …

作者头像 李华
网站建设 2026/9/6 15:45:11

Docker记录:误删宿主机挂载目录导致 PostgreSQL 数据丢失

Docker记录&#xff1a;误删宿主机挂载目录导致 PostgreSQL 数据丢失1. Docker启动PostgreSQL服务2. 我删了什么&#xff1f;3. Ooops&#xff01;问题来了4.问题核心&#xff1a;为什么删掉宿主机目录后&#xff0c;容器数据就访问不了&#xff1f;5.总结最近在使用 Docker 部…

作者头像 李华