There are two ways to add custom parsers to your application:
Use addDefaultParsers() to add parsers globally before initializing any clients. This is useful when you want all Tree-Sitter clients in your application to support the same languages.
import { addDefaultParsers, getTreeSitterClient } from "@opentui/core"
// Add Python parser globally
addDefaultParsers([
{
filetype: "python",
wasm: "https://github.com/tree-sitter/tree-sitter-python/releases/download/v0.23.6/tree-sitter-python.wasm",
queries: {
highlights: ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/master/queries/highlights.scm"],
},
},
])
// Now all clients will have Python support
const client = getTreeSitterClient()
await client.initialize()
// Highlight Python code
const pythonCode = 'def hello():\n print("world")'
const result = await client.highlightOnce(pythonCode, "python")Use client.addFiletypeParser() to add parsers to a specific client instance. This is useful when different parts of your application need different language support.
import { TreeSitterClient } from "@opentui/core"
const client = new TreeSitterClient({ dataPath: "./cache" })
await client.initialize()
// Add Rust parser to this specific client
client.addFiletypeParser({
filetype: "rust",
wasm: "https://github.com/tree-sitter/tree-sitter-rust/releases/download/v0.23.2/tree-sitter-rust.wasm",
queries: {
highlights: ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/master/queries/highlights.scm"],
},
})
// Highlight Rust code
const rustCode = 'fn main() {\n println!("Hello, world!");\n}'
const result = await client.highlightOnce(rustCode, "rust")The FiletypeParserOptions interface defines how to configure a parser:
interface FiletypeParserOptions {
filetype: string // The filetype identifier (e.g., "python", "rust")
wasm: string // URL or local file path to the .wasm parser file
queries: {
highlights: string[] // Array of URLs or local file paths to .scm query files
}
}Most popular languages have official parsers:
// Official parsers follow this pattern:
const parserUrl =
"https://github.com/tree-sitter/tree-sitter-{language}/releases/download/v{version}/tree-sitter-{language}.wasm"
// Examples:
// Python: https://github.com/tree-sitter/tree-sitter-python/releases/download/v0.23.6/tree-sitter-python.wasm
// Rust: https://github.com/tree-sitter/tree-sitter-rust/releases/download/v0.23.2/tree-sitter-rust.wasm
// Go: https://github.com/tree-sitter/tree-sitter-go/releases/download/v0.23.4/tree-sitter-go.wasmHighlight queries are usually found in the parser repository's queries/ directory:
// Official queries:
const queryUrl = "https://raw.githubusercontent.com/tree-sitter/tree-sitter-{language}/master/queries/highlights.scm"
// Or from nvim-treesitter (often more comprehensive):
const nvimQueryUrl =
"https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/master/queries/{language}/highlights.scm"Some languages require multiple query files. For example, TypeScript uses JavaScript queries plus TypeScript-specific queries:
addDefaultParsers([
{
filetype: "typescript",
wasm: "https://github.com/tree-sitter/tree-sitter-typescript/releases/download/v0.23.2/tree-sitter-typescript.wasm",
queries: {
highlights: [
// Base ECMAScript/JavaScript queries
"https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/master/queries/ecma/highlights.scm",
// TypeScript-specific queries
"https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/master/queries/typescript/highlights.scm",
],
},
},
])For better performance and offline support, you can bundle parsers and queries with your application:
// Using Bun's file import
import pythonWasm from "./parsers/tree-sitter-python.wasm" with { type: "file" }
import pythonHighlights from "./queries/python/highlights.scm" with { type: "file" }
addDefaultParsers([
{
filetype: "python",
wasm: pythonWasm,
queries: {
highlights: [pythonHighlights],
},
},
])You can automate parser downloads and import generation using the updateAssets utility. This is especially useful when supporting multiple languages or integrating parser management into your build pipeline.
Create a parsers-config.json file in your project:
{
"parsers": [
{
"filetype": "python",
"wasm": "https://github.com/tree-sitter/tree-sitter-python/releases/download/v0.23.6/tree-sitter-python.wasm",
"queries": {
"highlights": ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/master/queries/highlights.scm"]
}
},
{
"filetype": "rust",
"wasm": "https://github.com/tree-sitter/tree-sitter-rust/releases/download/v0.23.2/tree-sitter-rust.wasm",
"queries": {
"highlights": ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/master/queries/highlights.scm"]
}
}
]
}Add the update script to your package.json:
{
"scripts": {
"prebuild": "bun node_modules/@opentui/core/lib/tree-sitter/assets/update.ts --config ./parsers-config.json --assets ./src/parsers --output ./src/parsers.ts",
"build": "bun build ./src/index.ts"
}
}Or call it programmatically in your build script:
import { updateAssets } from "@opentui/core"
await updateAssets({
configPath: "./parsers-config.json",
assetsDir: "./src/parsers",
outputPath: "./src/parsers.ts",
})The script generates a TypeScript file with all parsers pre-configured:
import { addDefaultParsers, getTreeSitterClient } from "@opentui/core"
import { getParsers } from "./parsers" // Generated file
addDefaultParsers(getParsers())
const client = getTreeSitterClient()
await client.initialize()
const result = await client.highlightOnce('def hello():\n print("world")', "python")import { addDefaultParsers, getTreeSitterClient, SyntaxStyle } from "@opentui/core"
// Add support for multiple languages before initializing
addDefaultParsers([
{
filetype: "python",
wasm: "https://github.com/tree-sitter/tree-sitter-python/releases/download/v0.23.6/tree-sitter-python.wasm",
queries: {
highlights: ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-python/master/queries/highlights.scm"],
},
},
{
filetype: "rust",
wasm: "https://github.com/tree-sitter/tree-sitter-rust/releases/download/v0.23.2/tree-sitter-rust.wasm",
queries: {
highlights: ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/master/queries/highlights.scm"],
},
},
{
filetype: "go",
wasm: "https://github.com/tree-sitter/tree-sitter-go/releases/download/v0.23.4/tree-sitter-go.wasm",
queries: {
highlights: ["https://raw.githubusercontent.com/tree-sitter/tree-sitter-go/master/queries/highlights.scm"],
},
},
])
// Initialize the client
const client = getTreeSitterClient()
await client.initialize()
// Use with different languages
const syntaxStyle = new SyntaxStyle()
const pythonResult = await client.highlightOnce('def hello():\n print("world")', "python")
const rustResult = await client.highlightOnce('fn main() {\n println!("Hello");\n}', "rust")
const goResult = await client.highlightOnce('func main() {\n fmt.Println("Hello")\n}', "go")The CodeRenderable component automatically uses the Tree-Sitter client for syntax highlighting:
import { CodeRenderable, getTreeSitterClient } from "@opentui/core"
// Initialize the client with custom parsers
const client = getTreeSitterClient()
await client.initialize()
// Create a code renderable
const codeBlock = new CodeRenderable("code-1", {
content: 'def hello():\n print("world")',
filetype: "python",
width: 40,
height: 10,
})
// The CodeRenderable will automatically use the Tree-Sitter client
// to highlight the codeParser and query files are automatically cached in the dataPath directory to avoid re-downloading them.
You can customize the cache location when creating a client:
const client = new TreeSitterClient({
dataPath: "./my-custom-cache",
})OpenTUI provides utilities to automatically determine filetypes from file paths:
import { pathToFiletype, extToFiletype } from "@opentui/core"
// Get filetype from file path
const ft1 = pathToFiletype("src/main.rs") // "rust"
const ft2 = pathToFiletype("app.py") // "python"
// Get filetype from extension
const ft3 = extToFiletype("ts") // "typescript"
const ft4 = extToFiletype("js") // "javascript"Built-in mappings include: js, jsx, ts, tsx, py, rb, go, rs, c, cpp, html, css, and more.