为 Sway 构建 Prism 语法高亮:prism-sway 语言定义与构建流程解析
【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway
Sway 是 Fuel 生态中用于编写智能合约与脚本的领域专用语言。为了让开发者社区能够借助 PrismJS 在网页、文档与代码分享场景中高亮 Sway 代码,本仓库在 scripts/prism 目录下维护了一套独立的 Prism 语言定义与构建脚本。本文将基于 scripts/prism/README.md 的构建指引,逐层拆解prism-sway.js的 token 定义、components.json的组件清单、build.sh的完整构建流程,并给出可复现的更新、构建与本地调试操作步骤,帮助你在修改高亮规则后快速产出可发布的prism-sway.min.js。
一、文件组成与各自职责
scripts/prism 目录只包含四个文件,职责非常清晰:
| 文件 | 作用 |
|---|---|
| README.md | 构建与测试操作指引(本文依据的主文档) |
| prism-sway.js | Sway 语言的 Prism 语法定义(源文件,需人工维护) |
| prism-sway.min.js | 构建产物,供网页直接引用的压缩版本 |
| components.json | Prism 官方构建系统使用的组件清单,在其中注册了sway语言 |
| build.sh | 自动克隆 Prism、注入 Sway 定义并执行官方构建的脚本 |
工作流的核心是:修改prism-sway.js→ 运行./build.sh→ 得到更新后的prism-sway.min.js。这与 README 第一句 "Updateprism-sway.jsfile" 完全对应。
二、prism-sway.js:Sway 语言定义逐项拆解
prism-sway.js 是整条链路的灵魂。它以 IIFE 的形式向全局Prism对象注册Prism.languages.sway,通过一系列正则模式将 Sway 源码切分为可着色的 token。以下按定义顺序说明各 token 的技术细节。
1. 注释:支持 4 层嵌套的多行注释
Sway 允许多行注释嵌套,这是很多语言的高亮器容易处理错的地方。prism-sway.js在 第 3–8 行 用递归替换<self>占位符的方式构造了一个可嵌套 4 层的多行注释正则:
var multilineComment = /\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source; for (var i = 0; i < 2; i++) { // support 4 levels of nested comments multilineComment = multilineComment.replace(/<self>/g, function () { return multilineComment; }); }随后在 第 12–23 行 注册两类注释:嵌套多行注释/* ... */(greedy: true,使用(^|[^\\])前置断言避免把转义场景误判)和单行注释// ...(前置断言(^|[^\\:])保证不会吞掉://之类的路径写法)。
2. 字符串、字符与字节前缀
- 字符串模式(第 24–27 行)同时支持可选的
b前缀(字节串)、r#...形式的原始字符串(可带多个#作为定界标记),并处理\\转义。 - 字符模式(第 28–32 行)支持
\xNN十六进制转义、\u{...}Unicode 码点转义,并alias: 'string'复用字符串着色。
3. 属性(attribute)
第 33–40 行 定义了#与#[...](外部属性)的匹配,alias: 'attr-name',内部字符串单独着色。Sway 中常见的#[storage(read)]、#[test]等即由它高亮。
4. 闭包参数:避免与按位或|混淆
Sway 闭包用|x, y|声明参数,这与按位或运算符字形相同。定义在 第 42–54 行 的closure-params通过前置断言([=(,:]\s*|\bmove\s*)或前瞻(?=\s*(?:\{|->))严格限定上下文,只在确实可能是闭包形参的位置匹配,并把两端的|单独列为closure-punctuation。这是整个定义里最容易踩坑的部分,修改时务必保留这个上下文约束。
5. 格式化字符串片段与变量
第 56–61 行 定义了$name:形式的 fragment specifier 以及$\w+变量。Sway 的字符串插值语法会用到$var引用。
6. 定义类 token:fn / enum / struct / 模块声明
function-definition(第 63–67 行):fn关键字后紧跟的函数名,alias: 'function'。type-definition(第 68–72 行):enum、struct后紧跟的类型名,alias: 'class-name'。module-declaration(第 73–87 行):覆盖mod/script/contract/predicate/library声明的程序类型关键字,以及crate::、self::、super::这类路径前缀,alias: 'namespace'。
7. 关键字与内置原语
第 88–92 行 定义了两组关键字:
- 语言关键字:
as、break、const、continue、else、enum、fn、for、if、impl、in、let、match、mod、mut、priv、pub、ref、return、static、struct、trait、type、unsized、use、where等(覆盖 Sway 的程序类型关键字contract、predicate、library、script及self/Self)。 - 原语类型:
u8、u16、u32、u64、u128、usize、f32、f64、bool、char、str。
8. 函数调用、宏、常量与类名
function(第 96 行):以小写或下划线开头的标识符后紧跟((或::<),按 snake_case 约定避免大写开头误报。macro(第 97–100 行):name!形式,如log()之类,alias: 'property'。constant(第 101 行):[A-Z_][A-Z_\d]+全大写常量。class-name(第 102 行):[A-Z]\w*首字母大写类型名。namespace(第 104–109 行):形如a::b::的路径命名空间。
9. 数字:进制前缀、下划线分隔与类型后缀
第 111–112 行 是 Sway 数字字面量的完整支持:
- 十六进制
0x...、八进制0o...、二进制0b...; - 十进制(含小数与
Ee科学计数法); - 全部支持
_视觉分隔符(如1_000_000); - 可选类型后缀:
u8/u16/u32/u64/usize、f32/f64。
10. 布尔、标点与运算符
boolean(第 113 行):true/false。punctuation(第 114 行):->、..=、.../../.、::、大中小括号与逗号分号。operator(第 115 行):覆盖赋值、算术、位运算、比较与逻辑运算符,包括==、!=、&&、||、<</>>、@、?等。
最后,第 118–119 行 做了两处引用补齐:把closure-params内部剩余的rest指向整个 sway 定义以便继续递归着色,同时把attribute内部的字符串恢复为字符串 token。
三、components.json:把 Sway 注册进 Prism 构建系统
Prism 的官方构建脚本依赖一个组件清单来决定打包哪些语言与插件。components.json 即承担此角色。其中与 Sway 直接相关的声明位于 第 42–47 行:
"languages": { "sway": { "title": "Sway", "owner": "Fuel" } }其余部分是构建元信息:core指定必须引入components/prism-core.js,themes列出可选的 CSS 主题(Default、Dark、Funky、Okaidia、Twilight、Coy、Solarized Light、Tomorrow Night),plugins列出可选的增强插件(行号、工具栏、复制到剪贴板等)。当build.sh把该文件复制进 Prism 仓库后,官方构建工具就能识别sway语言并生成对应的prism-sway.js/prism-sway.min.js。
四、build.sh:完整的构建链路
build.sh 是整个流程的自动化实现,共分五步:
- 克隆 Prism 仓库(第 6–8 行):若当前目录下不存在
prism/目录,则通过git clone拉取 PrismJS 官方仓库。 - 注入 Sway 定义(第 10–11 行):将维护中的 prism-sway.js 复制为
prism/components/prism-sway.js,将 components.json 复制到 Prism 仓库根目录,覆盖其默认组件清单。 - 安装依赖(第 13 行):
npm ci按锁文件安装 Prism 的构建依赖。 - 执行官方构建(第 15 行):
npm run build调用 Prism 自身的构建脚本,基于组件清单产出压缩版语言文件。 - 回拷产物并清理(第 16–21 行):把生成的
components/prism-sway.min.js复制回本仓库根目录覆盖 prism-sway.min.js;除非命令带keep参数,否则删除克隆的prism/目录。
注意:npm ci需要本机已安装 Node.js 与 npm,且克隆 Prism 需要网络与 git 访问权限;因此构建前置条件是具备 Node 环境并能访问远程 git 仓库。
五、更新与构建:标准操作步骤
按 README.md 的指引,更新高亮规则的完整流程为:
- 编辑 prism-sway.js,按需调整上述任一 token 的正则或别名。
- 执行构建:
./build.sh- 构建成功后,根目录下的 prism-sway.min.js 即被更新为新的压缩版本。
六、本地调试:keep 模式与 test-suite.html
如果正在反复修改并希望即时验证高亮效果,README 建议保留 Prism 源码目录再构建:
./build.sh keep加上keep参数后,build.sh 跳过最后的清理步骤,prism/目录会被保留。此时可以打开 Prism 官方自带的可交互测试页面(test-suite.html,位于克隆下来的prism/目录内),在其中直接输入 Sway 代码实时查看各 token 的着色结果。因为npm run build已经把新的prism-sway.js打进了测试页依赖,所以无需手动改配置即可迭代验证正则改动,确认无误后再跑一次不带keep的./build.sh产出正式文件并自动清理临时目录。
七、与 highlight.js 集成的对照
值得一提的是,Prism 并不是本仓库唯一维护的第三方高亮集成。scripts/highlightjs/README.md 描述了一套完全平行的流程:修改sway.js→ 运行./build.sh(同样支持keep参数保留 highlight.js 仓库目录)。从仓库结构看,docs/book/theme/highlight.js 与 docs/reference/theme/highlight.js 是 mdBook 站点实际使用的 highlight.js 构建产物,说明 Sway 文档站走的是 highlight.js 路线,而 scripts/prism 则为需要 PrismJS 的场景(如第三方博客、文档生成器、代码分享工具)提供另一套官方维护的 Sway 高亮方案。两套定义的 token 设计理念一致,但正则实现相互独立,修改时需分别维护。
八、常见注意事项
- 嵌套注释层数:
prism-sway.js只支持 4 层嵌套多行注释,更深层的嵌套将无法被完整匹配;如需提升,需调整 第 3–8 行 的递归展开次数。 - 闭包参数与按位或:不要轻易放宽 closure-params 的上下文约束,否则
|x| x | y这类表达式会整体被错误着色。 - greedy 匹配顺序:注释、字符串均设为
greedy: true,Prism 会优先尝试最长匹配,这能减少注释与字符串内部关键字被二次着色的概率;新增 token 时建议同样遵循 greedy 惯例。 - 产物提交:
prism-sway.min.js是构建产物但被提交进仓库,改动源文件后应重新构建并同步更新它,避免源文件与压缩版本不一致。
通过上述机制,Sway 社区可以像使用任意主流语言一样,在基于 PrismJS 的页面中零成本获得准确、可扩展的语法着色体验。
【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考