Arborium Documentation

repository·main·Indexed 19 days ago

https://github.com/bearcove/arborium

A collection of tree-sitter grammars for syntax highlighting supporting Rust, CLI, and Browser environments. Includes the arborium-cli tool for ANSI and HTML output with multiple themes, as well as guides for using Tree-sitter bindings in Rust and web-tree-sitter in JavaScript/TypeScript environments.

Tokens
51.1K
Snippets
179
Records
240
Agent score
65%

What's inside Arborium

  1. Overview of arborium features

    main

    Arborium is a batteries-included collection of tree-sitter grammars. Key capabilities include:

    • Extensive Language Support: ~70 grammars included out of the box.
    • Permissive Licensing: Default grammars use MIT, Apache-2.0, CC0, or Unlicense.
    • WASM Support: Optimized for WebAssembly with a custom allocator fix.
    • HTML Rendering: Includes 32 built-in themes for web-based syntax highlighting.
    • Flexible Deployment: Supports CLI (terminal/HTML), Browser (script tag/ESM), and Rust library usage.
    • Granular Control: Use feature flags to include only the specific language grammars required for your project.
  2. Language Groups in Arborium

    main

    Arborium organizes languages into semantic groups. When adding a new language, place it in the appropriate group directory:

    GroupPurposeExamples
    group-acornWeb languagesJavaScript, TypeScript, HTML, CSS
    group-birchSystems languagesC, C++, Zig, Assembly
    group-cedarJVM languagesJava, Kotlin, Scala, Clojure
    group-fernFunctional languagesHaskell, Elm, OCaml, Erlang
    group-hazelScripting languagesPython, Ruby, Bash, Perl, PHP
    group-mapleData/Config languagesSQL, YAML, TOML, GraphQL
    group-mossScientific languagesJulia, MATLAB, R
    group-pineModern languagesRust, Swift, Dart, WIT
    group-sage.NET languagesC#, F#, Visual Basic
    group-willowMarkup/DocumentationMarkdown, HTML, XML, SVG
  3. Understand the language directory structure

    main

    When adding a new language to Arborium, you must follow a specific directory structure. The structure is split into two main parts: def/ (the source files you maintain) and crate/ (the auto-generated Rust code).

    Directory Layout

    • langs/<group>/<language>/def/:
      • arborium.yaml: The single source of truth for configuration.
      • grammar/: Contains grammar.js and optionally scanner.c copied from the upstream Tree-sitter repository.
      • queries/: Contains highlights.scm (required) and optionally injections.scm or locals.scm.
      • samples/: Contains example code files used for testing.
    • langs/<group>/<language>/crate/: DO NOT EDIT. This directory is automatically regenerated by the build system using cargo xtask gen and contains the compiled Rust implementation.
    langs/group-cedar/kotlin/
    ├── def/                                    # Source files (you edit these)
    │   ├── arborium.yaml                      # Configuration (EDIT THIS)
    │   ├── grammar/                           # From tree-sitter-kotlin
    │   │   ├── grammar.js                     
    │   │   └── scanner.c                      
    │   ├── queries/                           # Syntax highlighting rules
    │   │   ├── highlights.scm                 
    │   │   └── injections.scm                 
    │   └── samples/                           # Example Kotlin code
    │       └── Sequences.kt                   
    └── crate/                                  # Generated files (DO NOT EDIT)
        ├── Cargo.toml                         
        ├── build.rs                           
        └── ...
  4. How multi-grammar crates work

    main

    Some languages require multiple grammars within a single crate (e.g., XML and DTD). To support this, use the grammar_path field in arborium.yaml to point to the specific subdirectory containing that grammar's files.

    grammars:
      - id: xml
        name: XML
        # ...
    
      - id: dtd
        name: DTD
        grammar_path: dtd
        # ...
  5. Use injections.scm for embedded languages

    main

    The injections.scm file (optional) allows you to define how one language is embedded within another. This is useful for highlighting code inside template literals, HTML tags, or specific string patterns.

    Examples:

    • Highlighting JavaScript inside <script> tags in HTML.
    • Highlighting SQL inside Python string literals.
    • Highlighting Markdown inside documentation comments.
    ; Highlight template literal strings with embedded expressions
    ((template_string) @injection.content
      (#set! injection.language "javascript"))
    
    ; Highlight JSX/TSX
    ((jsx_element) @injection.content
      (#set! injection.language "jsx"))
  6. Understand the grammar repository structure

    main

    Each grammar in arborium follows a specific structure. Some files are the 'source of truth' and are committed, while others are generated by xtask gen and should be gitignored.

    Committed Files (Source of Truth):

    • arborium.kdl: Grammar configuration.
    • grammar/grammar.js: Tree-sitter grammar definition.
    • grammar/scanner.c: Custom scanner (if applicable).
    • queries/*.scm: Syntax highlighting and injection queries.
    • samples/*: Test samples.

    Generated Files (Gitignored):

    • Cargo.toml
    • build.rs
    • src/lib.rs
    • grammar/src/* (Tree-sitter generated code)
  7. How arborium syntax highlighting works on docs.rs

    main

    When using the arborium IIFE script via --html-in-header, the script performs the following logic automatically:

    1. Detection: It scans the document for code blocks identified by the class="language-*" attribute.
    2. Rust Exclusion: It automatically skips Rust code blocks. This is necessary because rustdoc already provides semantic <a links within Rust blocks that would be broken by standard highlighting engines.
    3. Highlighting: It applies tree-sitter grammars to highlight all other detected language blocks (e.g., JSON, YAML, SQL, Shell, TOML).
  8. How arborium-cli detects languages

    main

    Arborium uses a prioritized detection strategy to determine the language of the input:

    1. Explicit --lang flag: The highest priority; if provided, this overrides all other methods.
    2. File extension: If the input is a file path, the extension is used to detect the language.
    3. Shebang line: For input provided via stdin or as a literal string, the tool checks for a shebang (e.g., #!/usr/bin/env python3).
  9. Configure WASM plugin generation

    main

    To include a language in WASM builds (for browser environments), set generate_plugin: true in the arborium.yaml grammar definition.

    When to enable:

    • Popular languages (tier 1-2).
    • Languages needed in browser environments.

    When to avoid:

    • Rarely used languages (to reduce bundle size).
    • Very large grammars (>500KB WASM output).

    You can check the resulting WASM size using: ls -lh target/wasm32-unknown-unknown/release/*.wasm

  10. Choose the appropriate language group

    main

    Languages are organized into semantic groups. Choosing the right group determines the directory structure and categorization.

    • group-cedar (JVM Languages): For languages running on the Java Virtual Machine (e.g., Java, Kotlin, Scala, Clojure, Groovy).
    • group-hazel (Scripting Languages): For languages used for scripting or automation (e.g., Python, Ruby, Bash, PHP, Lua).
    • group-pine (Modern Languages): For languages designed recently with modern features (e.g., Rust, Swift, Dart, WIT).
    • group-acorn (Web): For web-centric languages (e.g., TypeScript).

    Note: Groups are semantic. If a language fits multiple groups (like Groovy), choose the one representing its primary use case (e.g., JVM interop).

    Rule: Do not create new groups without discussion.

  11. Language directory structure for grammars

    main

    When adding a language, you must follow this directory layout within your chosen language group:

    langs/group-{name}/{language}/def/
    ├── arborium.yaml          # REQUIRED: Configuration file
    ├── grammar/               # Grammar source files
    │   ├── grammar.js         # REQUIRED: Tree-sitter grammar definition
    │   └── scanner.c          # Optional: External scanner
    ├── queries/               # Tree-sitter query files
    │   ├── highlights.scm     # REQUIRED: Syntax highlighting rules
    │   ├── injections.scm     # Optional: Language injection rules
    │   └── locals.scm         # Optional: Scope/symbol tracking
    └── samples/               # Example code files
        └── example.{ext}      # REQUIRED: At least one sample file