ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nueyaml 语法完全参考:为可预测性而设计的精简 YAML 解析器

Nueyaml 语法完全参考:为可预测性而设计的精简 YAML 解析器 Nueyaml 语法完全参考为可预测性而设计的精简 YAML 解析器【免费下载链接】nueFastest way to build modern websites项目地址: https://gitcode.com/GitHub_Trending/nu/nueNueyaml 是 Nue 生态中去掉问题的 YAML——它砍掉了标准 YAML 规范中 80 页容易引发歧义的特性只保留配置场景真正需要的类型与结构。本文是 yaml-syntax.md 的完整参考解读结合 nueyaml.js 的源码实现与 nueyaml.test.js 的测试用例系统讲解 Nueyaml 的文件结构、六大数据类型、多行字符串、属性名、缩进、注释、错误处理与全部限制。读完本文你将能零歧义地编写和排查 Nueyaml 配置文件并理解它为何能作为 Nue Kit 站点配置site.yaml与 Nuemark 文档元数据的底层解析引擎。Nueyaml 的设计哲学一个规则可预测标准 YAML 的一个核心痛点是它猜测你的意思而且经常猜错详见 nueyaml.md# 标准 YAML 的意外 country: NO # 可能变成 false挪威问题 time: 12:30 # 可能变成 750分钟数 version: 1.10 # 可能变成 1.1浮点精度 port: 08080 # 可能变成 4176八进制Nueyaml 只有一条规则对普通人来说看起来像字符串的就是字符串。只有一眼就能看出的数字123、45.67才是数字只有true和false才是布尔值其余一律保持字符串。这一点在源码 nueyaml.js 的parseValue中体现得淋漓尽致isNumber使用严格的正则/^-?\d(\.\d)?$/判断且显式拒绝以0开头的值str[0] 0直接返回 false从而从根上消除了前导零被当作八进制解析的隐患。文件结构所有 Nueyaml 文件必须以根级对象开头。解析器永远返回一个对象绝不返回数组或原始值源码 nueyaml.js 中parseYAML最终由buildObject构建结果天然保证返回值是对象# 合法 - 根对象 name: My App version: 1.0.0 # 非法 - 根数组 \- item1 \- item2文件统一使用UTF-8编码。数据类型Nueyaml 只支持六种类型字符串、数字、布尔、日期、Null、数组与对象——没有二进制数据、没有集合、没有有序映射、没有自定义类型、没有挪威问题这正是 nueyaml.md 中简单类型系统一节的承诺。字符串默认一切都是字符串无需引号除非需要强制一个看起来像其他类型的值name: John Doe title: Senior Developer message: Hello world country: NO # 字符串 NO不是 false time: 12:30 # 字符串 12:30不是 750 分钟带引号的字符串会自动解包为兼容 YAML 习惯message: Hello world # 变成: Hello world note: a quoted word # 变成: a quoted word force: 123 # 保持字符串 123不是数字源码中parseValue的引号处理逻辑nueyaml.js会先判断值是否以或开头和结尾若是则去掉首尾引号返回内部内容测试 nueyaml.test.js 覆盖了双引号、单引号和中间夹引号三种情形。数字只有整数和小数会被解析为数字且必须看起来像人眼可识别的数字age: 30 # 整数 price: 19.99 # 小数 count: 0 # 零 negative: -42 # 负整数不支持的写法全部退化为字符串scientific: 1.2e3 # 字符串 1.2e3 octal: 0o755 # 字符串 0o755 hex: 0xFF # 字符串 0xFF underscore: 1_000 # 字符串 1_000isNumber的实现nueyaml.js同时排除了空字符串、单独的-/以及任何以0开头的值测试 nueyaml.test.js 验证了00800、hello、空串和-都不是数字。布尔只有true和false会被解析为布尔值其余全是字符串enabled: true visible: false active: yes # 字符串 yes on: ON # 字符串 ONparseValue中nueyaml.js对true/false的匹配是大小写敏感的精确字符串比较这正是它拒绝yes、YES、on、True等 YAML 替代布尔字面量的原因。日期仅支持单一 ISO 格式YYYY-MM-DD或YYYY-MM-DDTHH:MM:SSZcreated: 2024-01-15 updated: 2024-01-15T10:30:00Z其他格式一律成为字符串us_date: 01/15/2024 # 字符串 euro_date: 15.01.2024 # 字符串 text_date: Jan 15, 2024 # 字符串日期判定由正则/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}Z)?$/完成匹配后返回new Date(val)nueyaml.js测试 nueyaml.test.js 确认两种格式都解析为对应的Date对象。Null空值变为 nulldescription: # null avatar: # nullparseValue的第一行就是if (val ) return nullnueyaml.js而在buildObject中一个没有子级的空键值对同样会落到value null分支nueyaml.js这保证了空键、空值两种写法结果一致。数组同时支持内联和块两种语法# 内联数组 tags: [frontend, javascript, react] numbers: [1, 2, 3] mixed: [hello, 42, true] # 块数组 tags: - frontend - javascript - react # 嵌套数组 matrix: - [1, 2, 3] - [4, 5, 6] - [7, 8, 9]内联数组由parseYAMLArray处理nueyaml.js它要求整行匹配/^\s*\w\s*:\s*\[(.*)\]$/即键名 冒号 方括号的形式然后对逗号分隔的每一项递归调用parseValue因此[hello, 42, true]会得到[hello, 42, true]这样的混合类型数组。测试还专门验证了看起来像数组但不是数组的情况nueyaml.test.js如hey [foo]没有冒号、hey: [foo]被引号包裹都会安全地返回 null 而非误解析。对象仅支持块语法不支持内联对象# 合法 - 块对象 user: name: John Doe age: 30 active: true # 非法 - 内联对象 user: {name: John, age: 30} # 变成字符串对象层级完全由缩进驱动buildObjectnueyaml.js在遇到空值的键值对时向前看把所有缩进大于当前层的块收拢为子级再根据子级首块的类型决定构建数组、多行字符串还是嵌套对象。测试 nueyaml.test.js 验证了对象数组这一最复杂的结构users下每个- name:项连同缩进更深的age: 30被正确组装为{ name: John, age: 30 }。多行字符串当值在下一行以更大缩进继续时它就变成多行字符串description: This is a multi-line string that preserves line breaks exactly as written. # 结果: This is a multi-line\nstring that preserves\nline breaks exactly\nas written.多行字符串完整保留换行相对首行的缩进每行的尾部空白内容中的空行code_example: function hello() { console.log(Hello) } hello() # 保留空行与缩进实现上detectStructure会把无冒号、非数组项的缩进行标记为multiline块nueyaml.jsbuildObject则将连续的 multiline 子块用\n连接nueyaml.js。集成测试 nueyaml.test.js 确认description:\n Multi-line\n string content解析为Multi-line\nstring content。注意一个细节连接时各行已经按stripComments后的内容处理且每行以trim()后的值参与拼接所以相对首行的缩进以每行自身内容为基准。属性名属性名可以包含任意字符包括冒号和特殊字符。解析器以:冒号后跟空格作为键值分隔符# 键中的特殊字符 /api/users/:id: getUserHandler /api/posts: getPostsHandler media (max-width: 768px): mobile-styles users[0].name: John api:key: secret-value with spaces: allowed唯一的硬性要求是存在:分隔符key:value # 非法 - 冒号后没有空格 key: value # 合法 key : value # 合法 - 多余空格可以 complex:key: value # 合法 - 键名中的冒号Nueyaml 不支持带引号的属性名quoted key: value # 不支持 单引号键: value # 不支持detectStructure中的键值对拆分逻辑nueyaml.js会优先查找: 冒号空格找不到才回退到第一个裸冒号因此/api/users/:id: getUserHandler能被正确地切分为键/api/users/:id和值getUserHandler。测试 nueyaml.test.js 与集成测试nueyaml.test.js都覆盖了这类复杂键。Nue Kit 正是利用这一特性在 svg.js 等处直接以路径、媒体查询作为配置键。缩进与空白缩进只能用空格不允许使用 Tab# 合法 - 一致的 2 空格缩进 app: name: Test config: debug: true # 合法 - 一致的 4 空格缩进 app: name: Test config: debug: true # 非法 - 混用缩进 app: name: Test config: mixed # 错误: 不是 2 的倍数解析器从第一个缩进行检测缩进大小并强制全文保持一致的倍数。源码validateIndentationnueyaml.js分两步执行先扫描每行行首空白若含 Tab 立即抛出Tabs not allowed for indentation. Use spaces only. Line N再由detectIndentSize从首个非空、非注释的缩进行得到基准缩进默认为 2收集所有缩进级别并逐一验证是否为基准值的整数倍否则抛出Inconsistent indentation. Expected multiples of N spaces.。测试 nueyaml.test.js 同时验证了 Tab 缩进报错、字符串值内 Tab 合法、以及 3 空格对 2 空格基准不匹配三种情形。空白规则汇总尾部空格被忽略空行允许出现在任何位置字符串值内允许出现 TabTab 不能用于结构性缩进注释使用#写注释。注释必须由空白引导以避免与包含#的值冲突# 整行注释 name: John Doe # 行内注释 password: secret#123 # password 中的 # 不是注释 api_key: sk-1234#abcd # 对密钥类值安全多行注释需要每行一个#。注释判定规则valid # comment # # 前有空格是注释 no#comment # 无空格# 属于值 also#not#comment # 无空格的多重 # 全部保留stripComments的实现nueyaml.js正是这一规则的直接体现整行以#开头则返回空串否则用正则/\s#/查找空白 #的第一个位置从其索引处截断。测试 nueyaml.test.js 覆盖了无注释、行内注释、整行注释、值内#四种情况而集成测试 nueyaml.test.js 进一步确认password: secret#123#abc整体保留。错误处理解析器提供带行号的清晰错误信息# 错误示例: user: name: John age: 30 # 错误: Line 3: 缩进不一致 data: - item1 item2 # 错误: Line 3: 期望数组项指示符 (-)需要说明的是validateIndentation抛出的 Tab 错误会带行号Line ${i 1}缩进倍数错误会给出期望的空格倍数而期望数组项指示符这类错误在实际实现中表现为detectStructure遇到item2无-前缀、无:分隔符时将其归类为multiline块当它出现在数组上下文中时会被多行字符串逻辑接管——这正是文档建议在编写时保持数组项格式一致的用意。测试 nueyaml.test.js 用parseYAML的集成断言验证了 Tab 与缩进不一致两类错误的抛出。限制不支持的 YAML 特性标准 YAML 中不支持的部分锚点与引用anchor、*reference合并键: *defaults标签!!str、!!timestamp多文档---、...跨多行的流式集合块标量指示符|、、|-、转义序列\n、\t、\u0041替代布尔值yes、no、on、off、YES、True多种日期格式二进制数据集合与有序映射指令%YAML、%TAG有意的限制根必须是对象不能是数组或标量不支持{}内联对象不支持带引号的属性名不支持科学计数法不支持八进制或十六进制数字Tab 仅用于内容不可用于缩进仅支持单一日期格式这些限制不是缺陷而是可预测性的代价与保障。正如 nueyaml.md 的 FAQ 所述Nueyaml 是合法的 YAML但并非所有 YAML 都是合法的 Nueyaml——它保留有用子集、拒绝危险部分而现实中绝大多数配置文件本就不使用锚点、标签和多日期格式因此现有 YAML 文件通常已经天然兼容 Nueyaml。完整示例以下示例覆盖了上述全部特性可直接作为配置文件模板# 应用配置 app: name: My Application version: 1.2.0 debug: false launched: 2024-01-15 # 数据库设置 database: host: localhost port: 5432 credentials: username: admin password: # null留给环境变量 connection_string: postgresql://adminlocalhost:5432/myapp ?ssltruetimeout10 # API 路由 - 键中的特殊字符 /api/users/:id: getUserHandler /api/posts: getPostsHandler /api/auth/login: loginHandler # 安全 api_keys: github: ghp_xxxxxxxxxxxxxxxxxxxx stripe: sk-test_################# aws: AKIA############# # 功能数组 features: [auth, analytics, caching] experimental: - new-dashboard - dark-mode - websockets # 响应式断点 breakpoints: media (max-width: 768px): mobile media (max-width: 1024px): tablet media (min-width: 1025px): desktop # 多行内容 welcome_message: Welcome to our application! This message spans multiple lines and preserves blank lines and indentation exactly as written. # 服务器配置对象数组 servers: - name: web-01 ip: 192.168.1.10 active: true roles: [web, api] - name: web-02 ip: 192.168.1.11 active: false roles: [web] - name: db-01 ip: 192.168.1.20 active: true roles: [database, cache] # 元数据前导下划线完全合法 _internal: build_number: 4567 commit: abc123def timestamp: 2024-01-15T10:30:00Z源码解析管线从文本到对象理解 Nueyaml 的整体流程有助于排查配置问题。parseYAMLnueyaml.js只有四步validateIndentation全文校验 Tab 缩进与缩进倍数一致性nueyaml.jsdetectStructure逐行剥离注释后将每行归类为keyvalue键值对、arrayitem数组项或multiline多行字符串延续三种块之一nueyaml.jsbuildObject递归地把块按缩进层级组装成嵌套对象、数组与多行字符串nueyaml.jsparseValue在组装过程中负责把单个值文本转换为字符串、数字、布尔、日期或 nullnueyaml.js。值得留意的是detectStructure对数组项的判定优先于键值对nueyaml.js以-开头的行会先尝试解析- key: value的对象项否则按纯值项处理这与集成测试中列表项带注释、嵌套 cron 数组的复杂用例nueyaml.test.js互相印证说明解析器对真实世界配置的容忍度。在 Nue 生态中的实际应用Nueyaml 并非孤立组件它是 Nue 工具链的配置基座package.json 中版本为 0.1.0入口为 nueyaml.jsNue Kit 站点配置conf.js 通过parseYAML读取站点根目录的site.yaml合并出site、design、server、collections、production、port等配置项并支持conf.site?.skip追加忽略列表——你完全可以对照本语法参考来扩展自己的站点配置资源与渲染asset.js 同样依赖parseYAML解析资源元数据svg.js 则直接导入parseYAMLArray处理 SVG 组件的数组式参数Nuemark 文档解析parse-blocks.js 与 parse-document.js 用parseYAML解析 Markdown 文档的元数据块配合本文所述的特殊字符键名让media断点、API 路由这类键可以原样书写。安装与使用详见 nueyaml.md 的 Installation 一节bun install nueyamlimport { parseYAML } from nueyaml const config parseYAML(yamlString)小结Nueyaml 用可预测一个原则换来了零意外配置字符串、数字、布尔、日期、Null、数组与对象六种类型边界清晰属性名自由、注释规则简单、缩进强制一致、错误信息带行号同时坚决拒绝锚点、标签、多文档等复杂 YAML 特性。无论你是为 Nue Kit 编写site.yaml还是在 Nuemark 文档中维护元数据抑或只是想要一个没有挪威问题的配置解析器本文所覆盖的语法要点都足以让你写出既符合规范、又完全可预期的配置文件。【免费下载链接】nueFastest way to build modern websites项目地址: https://gitcode.com/GitHub_Trending/nu/nue创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表