biome-developer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Purpose

目的

This skill provides general development best practices, common gotchas, and Biome-specific patterns that apply across different areas of the codebase. Use this as a reference when you encounter unfamiliar APIs or need to avoid common mistakes.
本技能提供适用于代码库不同领域的Biome通用开发最佳实践、常见陷阱及专属模式。当你遇到不熟悉的API或需要规避常见错误时,可将其作为参考。

Prerequisites

前置要求

  • Basic familiarity with Rust
  • Understanding of Biome's architecture (parser, analyzer, formatter)
  • Development environment set up (see CONTRIBUTING.md)
  • 基本熟悉Rust
  • 了解Biome的架构(解析器、分析器、格式化器)
  • 已搭建开发环境(详见CONTRIBUTING.md)

Common Gotchas and Best Practices

常见陷阱与最佳实践

Working with AST and Syntax Nodes

处理AST与语法节点

DO:
  • ✅ Use parser crate's
    quick_test
    to inspect AST structure before implementing
  • ✅ Understand the node hierarchy and parent-child relationships
  • ✅ Check both general cases AND specific types (e.g., Vue has both
    VueDirective
    and
    VueV*ShorthandDirective
    )
  • ✅ Verify your solution works for all relevant variant types, not just the first one you find
DON'T:
  • ❌ Build the full Biome binary just to inspect syntax (expensive) - use parser crate's
    quick_test
    instead
  • ❌ Assume syntax patterns without inspecting the AST first
Example - Inspecting AST:
rust
// In crates/biome_html_parser/tests/quick_test.rs
// Modify the quick_test function:
#[test]
pub fn quick_test() {
    let code = r#"<button on:click={handleClick}>Click</button>"#;
    let source_type = HtmlFileSource::svelte();
    let options = HtmlParseOptions::from(&source_type);
    let root = parse_html(code, options);
    dbg!(&root.syntax());  // Shows full AST structure
}
Run:
just qt biome_html_parser
建议:
  • ✅ 在实现前使用parser crate的
    quick_test
    检查AST结构
  • ✅ 理解节点层级与父子关系
  • ✅ 同时检查通用情况和特定类型(例如Vue同时有
    VueDirective
    VueV*ShorthandDirective
  • ✅ 验证你的解决方案适用于所有相关变体类型,而非仅你找到的第一个类型
禁止:
  • ❌ 仅为检查语法就构建完整的Biome二进制文件(成本高昂)——改用parser crate的
    quick_test
  • ❌ 未先检查AST就假设语法模式
示例 - 检查AST:
rust
// In crates/biome_html_parser/tests/quick_test.rs
// Modify the quick_test function:
#[test]
pub fn quick_test() {
    let code = r#"<button on:click={handleClick}>Click</button>"#;
    let source_type = HtmlFileSource::svelte();
    let options = HtmlParseOptions::from(&source_type);
    let root = parse_html(code, options);
    dbg!(&root.syntax());  // Shows full AST structure
}
运行:
just qt biome_html_parser

String Extraction and Text Handling

字符串提取与文本处理

DO:
  • ✅ Use
    inner_string_text()
    when extracting content from quoted strings (removes quotes)
  • ✅ Use
    text_trimmed()
    when you need the full token text without leading/trailing whitespace
  • ✅ Use
    token_text_trimmed()
    on nodes like
    HtmlAttributeName
    to get the text content
  • ✅ Verify whether values use
    HtmlString
    (quotes) or
    HtmlTextExpression
    (curly braces)
DON'T:
  • ❌ Use
    text_trimmed()
    when you need
    inner_string_text()
    for extracting quoted string contents
Example - String Extraction:
rust
// WRONG: text_trimmed() includes quotes
let html_string = value.as_html_string()?;
let content = html_string.value_token()?.text_trimmed(); // Returns: "\"handler\""

// CORRECT: inner_string_text() removes quotes
let html_string = value.as_html_string()?;
let inner_text = html_string.inner_string_text().ok()?;
let content = inner_text.text(); // Returns: "handler"
建议:
  • ✅ 从带引号的字符串提取内容时使用
    inner_string_text()
    (会移除引号)
  • ✅ 需要无首尾空白的完整令牌文本时使用
    text_trimmed()
  • ✅ 从
    HtmlAttributeName
    等节点获取文本内容时使用
    token_text_trimmed()
  • ✅ 验证值使用的是
    HtmlString
    (带引号)还是
    HtmlTextExpression
    (大括号)
禁止:
  • ❌ 提取带引号的字符串内容时使用
    text_trimmed()
    (应使用
    inner_string_text()
示例 - 字符串提取:
rust
// WRONG: text_trimmed() includes quotes
let html_string = value.as_html_string()?;
let content = html_string.value_token()?.text_trimmed(); // Returns: "\"handler\""

// CORRECT: inner_string_text() removes quotes
let html_string = value.as_html_string()?;
let inner_text = html_string.inner_string_text().ok()?;
let content = inner_text.text(); // Returns: "handler"

Working with Embedded Languages

处理嵌入式语言

DO:
  • ✅ Verify changes work for different value formats (quoted strings vs text expressions) when handling multiple frameworks
  • ✅ Use appropriate
    EmbeddingKind
    for context (Vue, Svelte, Astro, etc.)
  • ✅ Check if embedded content needs
    is_source: true
    (script tags) vs
    is_source: false
    (template expressions)
  • ✅ Calculate offsets correctly: token start + 1 for opening quote, or use
    text_range().start()
    for text expressions
DON'T:
  • ❌ Assume all frameworks use the same syntax (Vue uses quotes, Svelte uses curly braces)
  • ❌ Implement features for "widely used" patterns without evidence - ask the user first
Example - Different Value Formats:
rust
// Vue directives use quoted strings: @click="handler"
let html_string = value.as_html_string()?;
let inner_text = html_string.inner_string_text().ok()?;

// Svelte directives use text expressions: on:click={handler}
let text_expression = value.as_html_attribute_single_text_expression()?;
let expression = text_expression.expression().ok()?;
建议:
  • ✅ 处理多框架时,验证更改适用于不同的值格式(带引号的字符串 vs 文本表达式)
  • ✅ 根据上下文使用合适的
    EmbeddingKind
    (Vue、Svelte、Astro等)
  • ✅ 检查嵌入式内容是否需要
    is_source: true
    (脚本标签)或
    is_source: false
    (模板表达式)
  • ✅ 正确计算偏移量:令牌起始位置+1(针对开头引号),或对文本表达式使用
    text_range().start()
禁止:
  • ❌ 假设所有框架使用相同的语法(Vue使用引号,Svelte使用大括号)
  • ❌ 无依据地为“广泛使用”的模式实现功能——先询问用户
示例 - 不同值格式:
rust
// Vue directives use quoted strings: @click="handler"
let html_string = value.as_html_string()?;
let inner_text = html_string.inner_string_text().ok()?;

// Svelte directives use text expressions: on:click={handler}
let text_expression = value.as_html_attribute_single_text_expression()?;
let expression = text_expression.expression().ok()?;

Borrow Checker and Temporary Values

借用检查器与临时值

DO:
  • ✅ Use intermediate
    let
    bindings to avoid temporary value borrows that get dropped
  • ✅ Store method results that return owned values before calling methods on them
DON'T:
  • ❌ Create temporary value borrows that get dropped before use
Example - Avoiding Borrow Issues:
rust
// WRONG: Temporary borrow gets dropped
let html_string = value.value().ok()?.as_html_string()?;
let token = html_string.value_token().ok()?; // ERROR: html_string dropped

// CORRECT: Store intermediate result
let value_node = value.value().ok()?;
let html_string = value_node.as_html_string()?;
let token = html_string.value_token().ok()?; // OK
建议:
  • ✅ 使用中间
    let
    绑定避免临时值被提前释放导致的借用问题
  • ✅ 在调用方法前先存储返回自有值的方法结果
禁止:
  • ❌ 创建会在使用前被释放的临时值借用
示例 - 避免借用问题:
rust
// WRONG: Temporary borrow gets dropped
let html_string = value.value().ok()?.as_html_string()?;
let token = html_string.value_token().ok()?; // ERROR: html_string dropped

// CORRECT: Store intermediate result
let value_node = value.value().ok()?;
let html_string = value_node.as_html_string()?;
let token = html_string.value_token().ok()?; // OK

Clippy and Code Style

Clippy与代码风格

DO:
  • ✅ Use
    let
    chains to collapse nested
    if let
    statements (cleaner and follows Rust idioms)
  • ✅ Run
    just l
    before committing to catch clippy warnings
  • ✅ Fix clippy suggestions unless there's a good reason not to
DON'T:
  • ❌ Ignore clippy warnings - they often catch real issues or suggest better patterns
Example - Collapsible If:
rust
// WRONG: Nested if let (clippy::collapsible_if warning)
if let Some(directive) = VueDirective::cast_ref(&element) {
    if let Some(initializer) = directive.initializer() {
        // ... do something
    }
}

// CORRECT: Use let chains
if let Some(directive) = VueDirective::cast_ref(&element)
    && let Some(initializer) = directive.initializer()
{
    // ... do something
}
建议:
  • ✅ 使用
    let
    链合并嵌套的
    if let
    语句(更简洁且符合Rust惯用写法)
  • ✅ 提交前运行
    just l
    捕获Clippy警告
  • ✅ 除非有充分理由,否则修复Clippy建议的问题
禁止:
  • ❌ 忽略Clippy警告——它们通常能发现实际问题或提供更优模式
示例 - 合并条件语句:
rust
// WRONG: Nested if let (clippy::collapsible_if warning)
if let Some(directive) = VueDirective::cast_ref(&element) {
    if let Some(initializer) = directive.initializer() {
        // ... do something
    }
}

// CORRECT: Use let chains
if let Some(directive) = VueDirective::cast_ref(&element)
    && let Some(initializer) = directive.initializer()
{
    // ... do something
}

Legacy and Deprecated Syntax

遗留与已弃用语法

DO:
  • ✅ Ask users before implementing deprecated/legacy syntax support
  • ✅ Wait for user demand before spending time on legacy features
  • ✅ Document when features are intentionally not supported due to being legacy
DON'T:
  • ❌ Implement legacy/deprecated syntax without checking with the user first
  • ❌ Claim patterns are "widely used" or "common" without evidence
Example: Svelte's
on:click
event handler syntax is legacy (Svelte 3/4). Modern Svelte 5 runes mode uses regular attributes. Unless users specifically request it, don't implement legacy syntax support.
建议:
  • ✅ 实现遗留/已弃用语法支持前先询问用户
  • ✅ 有用户需求再投入时间开发遗留功能
  • ✅ 记录因属于遗留特性而故意不支持的功能
禁止:
  • ❌ 未先与用户确认就实现遗留/已弃用语法
  • ❌ 无依据地宣称模式“广泛使用”或“常见”
示例: Svelte的
on:click
事件处理器语法属于遗留特性(Svelte 3/4)。现代Svelte 5的runes模式使用常规属性。除非用户明确要求,否则不要实现遗留语法支持。

Testing and Development

测试与开发

DO:
  • ✅ Use
    just qt <package>
    to run quick tests (handles test execution automatically)
  • ✅ Review snapshot changes carefully - don't blindly accept
  • ✅ Test with multiple variants when working with enums (e.g., all
    VueV*ShorthandDirective
    types)
  • ✅ Add tests for both valid and invalid cases
  • ✅ Use CLI tests for testing embedded languages (Vue/Svelte directives, etc.)
DON'T:
  • ❌ Blindly accept all snapshot changes
  • ❌ Try to test embedded languages in analyzer packages (they don't have embedding capabilities)
建议:
  • ✅ 使用
    just qt <package>
    运行快速测试(自动处理测试执行)
  • ✅ 仔细审查快照变更——不要盲目接受
  • ✅ 处理枚举时测试多个变体(例如所有
    VueV*ShorthandDirective
    类型)
  • ✅ 为有效和无效案例都添加测试
  • ✅ 使用CLI测试嵌入式语言(Vue/Svelte指令等)
禁止:
  • ❌ 盲目接受所有快照变更
  • ❌ 尝试在分析器包中测试嵌入式语言(它们不具备嵌入能力)

Pattern Matching Tips

模式匹配技巧

Working with Node Variants

处理节点变体

When working with enum variants (like
AnySvelteDirective
), check if there are also non-enum types that need handling:
rust
// Check AnySvelteDirective enum (bind:, class:, style:, etc.)
if let Some(directive) = AnySvelteDirective::cast_ref(&element) {
    // Handle special Svelte directives
}

// But also check regular HTML attributes with specific prefixes
if let Some(attribute) = HtmlAttribute::cast_ref(&element) {
    if let Ok(name) = attribute.name() {
        // Some directives might be parsed as regular attributes
    }
}
处理枚举变体(如
AnySvelteDirective
)时,检查是否还有非枚举类型需要处理:
rust
// Check AnySvelteDirective enum (bind:, class:, style:, etc.)
if let Some(directive) = AnySvelteDirective::cast_ref(&element) {
    // Handle special Svelte directives
}

// But also check regular HTML attributes with specific prefixes
if let Some(attribute) = HtmlAttribute::cast_ref(&element) {
    if let Ok(name) = attribute.name() {
        // Some directives might be parsed as regular attributes
    }
}

Checking Multiple Variant Types

检查多种变体类型

For frameworks with multiple directive syntaxes, handle each type:
rust
// Vue has multiple shorthand types
if let Some(directive) = VueVOnShorthandDirective::cast_ref(&element) {
    // Handle @click
}
if let Some(directive) = VueVBindShorthandDirective::cast_ref(&element) {
    // Handle :prop
}
if let Some(directive) = VueVSlotShorthandDirective::cast_ref(&element) {
    // Handle #slot
}
if let Some(directive) = VueDirective::cast_ref(&element) {
    // Handle v-if, v-show, etc.
}
针对有多种指令语法的框架,处理每种类型:
rust
// Vue has multiple shorthand types
if let Some(directive) = VueVOnShorthandDirective::cast_ref(&element) {
    // Handle @click
}
if let Some(directive) = VueVBindShorthandDirective::cast_ref(&element) {
    // Handle :prop
}
if let Some(directive) = VueVSlotShorthandDirective::cast_ref(&element) {
    // Handle #slot
}
if let Some(directive) = VueDirective::cast_ref(&element) {
    // Handle v-if, v-show, etc.
}

Common API Confusion

常见API混淆点

String/Text Methods

字符串/文本方法

MethodUse WhenReturns
inner_string_text()
Extracting content from quoted stringsContent without quotes
text_trimmed()
Getting token text without whitespaceFull token text
token_text_trimmed()
Getting text from nodes like
HtmlAttributeName
Node text content
text()
Getting raw textExact text as written
方法使用场景返回值
inner_string_text()
从带引号的字符串提取内容不带引号的内容
text_trimmed()
获取无空白的令牌文本完整令牌文本
token_text_trimmed()
HtmlAttributeName
等节点获取文本
节点文本内容
text()
获取原始文本与书写完全一致的文本

Value Extraction Methods

值提取方法

TypeMethodFramework
HtmlString
inner_string_text()
Vue (quotes)
HtmlAttributeSingleTextExpression
expression()
Svelte (curly braces)
HtmlTextExpression
html_literal_token()
Template expressions
类型方法框架
HtmlString
inner_string_text()
Vue(带引号)
HtmlAttributeSingleTextExpression
expression()
Svelte(大括号)
HtmlTextExpression
html_literal_token()
模板表达式

References

参考资料

  • Main contributing guide:
    ../../CONTRIBUTING.md
  • Testing workflows:
    ../testing-codegen/SKILL.md
  • Parser development:
    ../parser-development/SKILL.md
  • Biome internals docs: https://biomejs.dev/internals
  • 主要贡献指南:
    ../../CONTRIBUTING.md
  • 测试工作流:
    ../testing-codegen/SKILL.md
  • 解析器开发:
    ../parser-development/SKILL.md
  • Biome内部文档:https://biomejs.dev/internals

Documentation and Markdown Formatting

文档与Markdown格式

DO:
  • ✅ Use spaces around table separators:
    | --- | --- | --- |
    (not
    |---|---|---|
    )
  • ✅ Ensure all Markdown tables follow "compact" style with proper spacing
  • ✅ Test documentation changes with markdown linters before committing
DON'T:
  • ❌ Use compact table separators without spaces (causes CI linting failures)
Example - Table Formatting:
markdown
<!-- WRONG: No spaces around separators -->
| Method | Use When | Returns |
|--------|----------|---------|

<!-- CORRECT: Spaces around separators -->
| Method | Use When | Returns |
| --- | --- | --- |
The CI uses
markdownlint-cli2
which enforces the "compact" style requiring spaces.
建议:
  • ✅ 表格分隔符前后使用空格:
    | --- | --- | --- |
    (而非
    |---|---|---|
  • ✅ 确保所有Markdown表格遵循“紧凑”风格并使用正确的空格
  • ✅ 提交前使用markdown检查器测试文档变更
禁止:
  • ❌ 使用无空格的紧凑表格分隔符(会导致CI检查失败)
示例 - 表格格式:
markdown
<!-- WRONG: No spaces around separators -->
| Method | Use When | Returns |
|--------|----------|---------|

<!-- CORRECT: Spaces around separators -->
| Method | Use When | Returns |
| --- | --- | --- |
CI使用
markdownlint-cli2
,它强制要求使用带空格的“紧凑”风格。

When to Use This Skill

何时使用本技能

Load this skill when:
  • Working with unfamiliar Biome APIs
  • Getting borrow checker errors with temporary values
  • Extracting strings or text from syntax nodes
  • Implementing support for embedded languages (Vue, Svelte, etc.)
  • Wondering why your AST inspection doesn't match expectations
  • Making decisions about legacy/deprecated syntax support
  • Writing or updating markdown documentation
在以下场景加载本技能:
  • 处理不熟悉的Biome API
  • 遇到临时值导致的借用检查器错误
  • 从语法节点提取字符串或文本
  • 实现嵌入式语言支持(Vue、Svelte等)
  • 疑惑为何AST检查结果与预期不符
  • 对遗留/已弃用语法支持做决策
  • 编写或更新Markdown文档