Skip to main content

tree-sitter-cfml

npm crates.io "Buy Me A Coffee"

Tree-sitter grammars for ColdFusion Markup Language (CFML).

There are three grammars: two for CFML in .cfc/.cfm and .cfs files, and one for SQL inside <cfquery> (embedded dialect).

Grammar Scope File types Description
cfml source.cfml .cfc, .cfm ColdFusion components and template files - CFScript, tag-based components, and HTML with embedded CF tags
cfscript source.cfscript .cfs Pure CFScript files
cfquery source.cfquery (embedded) SQL inside <cfquery> bodies (including QueryExecute-style usage), with #hash# interpolation and CF tags in the body

Playground

Browser demo: cfmleditor.github.io/tree-sitter-cfml

Installation

Node.js

npm install @cfmleditor/tree-sitter-cfml
const {
  cfml,
  cfscript,
  cfquery,
} = require("@cfmleditor/tree-sitter-cfml");
const Parser = require("tree-sitter");

const parser = new Parser();
parser.setLanguage(cfml.language);

const tree = parser.parse("<cfif condition>#value#</cfif>");
console.log(tree.rootNode.toString());

Rust

[dependencies]
tree-sitter = "0.25"
tree-sitter-cfml = "0.26.43"

The tree-sitter crate should be 0.25+ so the ABI matches the generated parsers (see LANGUAGE_VERSION in cf*/src/parser.c).

use tree_sitter_cfml::LANGUAGE_CFML;

let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE_CFML.into())
    .expect("Error loading CFML grammar");
// LANGUAGE_CFSCRIPT, LANGUAGE_CFQUERY load the same way.

Python

pip install tree-sitter-cfml
import tree_sitter_cfml as ts_cfml
from tree_sitter import Language, Parser

# cfml for .cfc and .cfm files
parser = Parser(Language(ts_cfml.language_cfml()))
tree = parser.parse(b'<cfif x GT 0>#x#</cfif>')

# cfscript for .cfs pure script files
parser = Parser(Language(ts_cfml.language_cfscript()))

# cfquery SQL dialect (embedded)
parser = Parser(Language(ts_cfml.language_cfquery()))

Go

import (
    tree_sitter_cfml "github.com/cfmleditor/tree-sitter-cfml/bindings/go"
    sitter "github.com/tree-sitter/go-tree-sitter"
)

// cfml for .cfc and .cfm files
parser := sitter.NewParser()
parser.SetLanguage(sitter.NewLanguage(tree_sitter_cfml.LanguageCfml()))

// cfscript for .cfs pure script files
parser.SetLanguage(sitter.NewLanguage(tree_sitter_cfml.LanguageCfscript()))

// cfquery SQL dialect (embedded)
parser.SetLanguage(sitter.NewLanguage(tree_sitter_cfml.LanguageCfquery()))

Java

Needs JDK 23+ — the binding is built on the Foreign Function & Memory API, through jtreesitter.

<dependency>
  <groupId>io.github.cfmleditor</groupId>
  <artifactId>tree-sitter-cfml</artifactId>
  <version>0.26.31</version>
</dependency>
import io.github.cfmleditor.jtreesitter.cfml.TreeSitterCfml;
import io.github.cfmleditor.jtreesitter.cfscript.TreeSitterCfscript;
import io.github.cfmleditor.jtreesitter.cfquery.TreeSitterCfquery;
import io.github.treesitter.jtreesitter.Language;
import io.github.treesitter.jtreesitter.Parser;

// cfml for .cfc and .cfm files
try (var parser = new Parser(new Language(TreeSitterCfml.language()))) {
    var tree = parser.parse("<cfif x GT 0>#x#</cfif>").orElseThrow();
}

// cfscript for .cfs pure script files
var cfscript = new Language(TreeSitterCfscript.language());

// cfquery SQL dialect (embedded)
var cfquery = new Language(TreeSitterCfquery.language());

Unlike the other bindings, this one does not compile the C for you. It loads four shared libraries at runtime — libtree-sitter plus one per grammar — so they have to be somewhere the loader looks (LD_LIBRARY_PATH, java.library.path, or a system library directory). Either install them:

make && sudo make install    # libtree-sitter-{cfml,cfscript,cfquery}

or, from a checkout, build all four (including the tree-sitter runtime, pinned by package-lock.json) into build/native/:

npm install && npm run build:native
java --enable-native-access=ALL-UNNAMED -Djava.library.path=build/native …

Run the binding's own tests with mvn test — it points java.library.path at both locations.

The artifact is not on Maven Central yet; see the note on publish-maven in .github/workflows/release.yml.

Development

Each dialect has grammar.js, generated C under src/, corpus tests under test/corpus/, and queries under queries/. Shared scanner code is under common/. The multi-grammar CLI and playground config is tree-sitter.json. Upstream docs: Creating parsers, CLI.

Setup

git clone https://github.com/cfmleditor/tree-sitter-cfml.git
cd tree-sitter-cfml

Use Node >=18 and <24 (package.json engines). Optional: .nvmrc with nvm / fnm (nvm use).

npm install

That installs dependencies, builds the Node native addon (node-gyp-build), and runs postinstall, which downloads the tree-sitter CLI binary into node_modules/tree-sitter-cli/ when needed. Repo npm scripts do not require a global tree-sitter on PATH.

npm test          # all three grammars
npm run lint      # ESLint
npm run build     # regenerate parsers + rebuild native addon (after grammar edits)

Windows

Put GCC from MinGW-w64 on your PATH (gcc / g++). This repo uses GCC for npm test (tree-sitter compile), the Node native binding, Python extension builds, and Go CGO — not MSVC.

Standalone toolchain (recommended): install WinLibs with winget, then add the extracted mingw64\bin directory (contains gcc.exe) to your user PATH, open a new terminal, and verify:

gcc --version

Example package (UCRT, POSIX threads):

winget install BrechtSanders.WinLibs.POSIX.UCRT

The installer path varies by machine; locate mingw64\bin under the WinLibs folder (or under %LOCALAPPDATA%\Microsoft\WinGet\Packages\ after install) and add that bin to PATH.

Alternatively: MSYS2 with pacman -S mingw-w64-x86_64-gcc, then prepend msys64\mingw64\bin to PATH (or develop from an MSYS2 MinGW64 shell).

If node-gyp still picks Visual Studio instead of MinGW, set CC / CXX to your MinGW gcc / g++ for npm install / npm rebuild, or keep MinGW’s bin before MSVC entries on PATH.

macOS

Install the Xcode command-line tools:

xcode-select --install
Homebrew
brew install gcc

Linux

Install a C/C++ toolchain (for example build-essential on Debian/Ubuntu, gcc / clang plus development headers on other distributions).

CI

CI (.github/workflows/ci.yml): npm install, npm test, npm run lint on Ubuntu, macOS, and Windows. It does not run npm run build; generated cf*/src/ files are committed.

Tree-sitter CLI

Scripts use scripts/tree-sitter-cli.cjs (node node_modules/tree-sitter-cli/cli.js). A global tree-sitter-cli install is optional. If the binary is missing after install:

node scripts/ensure-tree-sitter-cli-binary.js

From a dialect directory (after npm install at repo root):

cd cfml
node ../node_modules/tree-sitter-cli/cli.js test
node ../node_modules/tree-sitter-cli/cli.js generate
node ../node_modules/tree-sitter-cli/cli.js parse path/to/file.cfc

Dependency versions

Pinned in package.json / tree-sitter.json; approximate roles:

Role Package Version
Native binding (peer / dev) tree-sitter 0.25.0
Parser CLI tree-sitter-cli 0.26.8
Native addon node-addon-api ^8.3.0
Native addon node-gyp-build ^4.8.4
Prebuild prebuildify ^6.0.1
Runtime Node.js >=18 <24
Java binding (pom.xml) jtreesitter 0.26.1
Java binding JDK >=23

CFML engines

Corpus and behavior are checked mainly against Lucee. Overlapping Adobe ColdFusion syntax should still parse in a reasonable way. Avoid Adobe-only or Lucee-only assumptions in examples or grammar design where portable CFML is enough.

Building

After changing common/define-grammar.js or a grammar.js:

npm run build

On Unix, make generate at the repo root works if tree-sitter is on your PATH; otherwise use npm run build.

tree-sitter generate may warn about “unnecessary conflicts” (expressions vs _property_name, cfscript declaration / primary_expression, cfquery hash rules, etc.). Those come from common/define-grammar.js. If npm run build and npm test succeed, the warnings can be ignored.

Testing and helpers

See Setup for npm test, npm run lint, and npm run build.

npm run testbindings  # Node binding smoke test
npm run probe         # real-world construct probes (test/probes/)
npm run build:native && mvn test  # Java binding smoke test (JDK 23+)

One grammar only: run test via the CLI from that dialect’s directory (above), or npm test for all three.

Real-world corpus: npm run corpus:fetch shallow-clones ~25 public CFML projects into a gitignored corpus/, npm run scan corpus reports every ERROR/MISSING node, and npm run corpus:report clusters those into distinct failure sites. See CORPUS.md for the current results and the known gaps they turned up.

Parse a file: from the dialect folder (e.g. cfml for .cfc), use the parse subcommand with the same node ../node_modules/.../cli.js pattern.

Playground / WebAssembly (WASM)

  • npm start — playground at repo root (tree-sitter.json). Run npm run prestart first if WASM is stale.
  • npm run prestart — tree-sitter build --wasm
  • npm run playground — playground in each of cfml/, cfscript/, cfquery/
  • npm run docswasm — writes docs/tree-sitter-{cfml,cfscript,cfquery}.wasm for docs/ (e.g. GitHub Pages)

Releasing

npm run release -- 0.26.18
npm run release -- 0.26.18 --user=ghedwards  # optional: switch gh auth before push

The release script (scripts/release.js) will:

  1. Validate version format and ensure it's greater than current
  2. Ensure the working tree is clean and local branch is not behind remote
  3. Verify tag v<version> doesn't already exist
  4. Verify CHANGELOG.md has a ## [<version>] or ## [Unreleased] entry with notes
  5. Update the version in package.json, Cargo.toml, pyproject.toml, tree-sitter.json and pom.xml
  6. Run npm run build (regenerate parsers)
  7. Run npm run lint (ESLint)
  8. Run npm test (all three grammars)
  9. Run npm run docswasm (rebuild playground WASM)
  10. Run npm run install (rebuild native addon)
  11. Commit all changes and create a v<version> tag (prompted)
  12. Push commit and tag (prompted)

Once the tag is pushed, the GitHub Release workflow (.github/workflows/release.yml) will automatically publish to npm, PyPI, crates.io, and create a GitHub Release with the changelog notes. Maven Central is wired up but disabled — see publish-maven in that workflow.

Grammar structure

Shared rules: common/define-grammar.js. External scanner: common/scanner.h (implicit end tags, CF tag names, hash expressions, raw text).

common/
  define-grammar.js
  scanner.h
  tag.h

cfml/          # .cfc, .cfm
  grammar.js
  src/         # generated
  queries/

cfscript/      # .cfs
  grammar.js
  src/
  queries/

cfquery/       # embedded SQL
  grammar.js
  src/
  queries/

Queries

Grammar Highlights Indents Injections Tags
cfml yes yes yes yes
cfscript yes no no yes
cfquery yes no no yes

Contributing

See CONTRIBUTING.md.

Security

See SECURITY.md.

Agent and AI assistant guidance

See AGENTS.md.

License

MIT

Metadata

Release files for tree-sitter-cfml 0.26.43

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tree-sitter-cfml 0.26.43
File Size Uploaded Provenance
tree_sitter_cfml-0.26.43.tar.gz 1.6 MB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for tree-sitter-cfml 0.26.43
File
tree_sitter_cfml-0.26.43-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
tree_sitter_cfml-0.26.43-cp310-abi3-win32.whl CPython 3.10 abi3 Windows x86-32 Details
tree_sitter_cfml-0.26.43-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details
tree_sitter_cfml-0.26.43-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
tree_sitter_cfml-0.26.43-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 4.7 MB

Release files / tree_sitter_cfml-0.26.43.tar.gz

Download URL tree_sitter_cfml-0.26.43.tar.gz
Size 1.6 MB
Tags Source
SHA-256 checksum
How to use checksums
57d8f19543b47055ef53e2a0014aed770b43f4bb7ac85ca11fe6b7e51a48a7e3
BLAKE2b-256 checksum
How to use checksums
d04add3f66d6ffbdfcd4d3868680449f8c6f72b8c2aceee59cea8d50ef047680
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / tree_sitter_cfml-0.26.43-cp310-abi3-win_amd64.whl

Download URL tree_sitter_cfml-0.26.43-cp310-abi3-win_amd64.whl
Size 535.1 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
6be855774b4752a1902e2bea8a0b5085f993fde63363dfba56fbf535c4dcd7cd
BLAKE2b-256 checksum
How to use checksums
eb744842e20312531b104ec24857721ec22aa5174401cc4421701f71f3aeb6a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / tree_sitter_cfml-0.26.43-cp310-abi3-win32.whl

Download URL tree_sitter_cfml-0.26.43-cp310-abi3-win32.whl
Size 532.8 kB
Tags CPython 3.10 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
9fc61c070d511b172b396f76dcf702649e3e8d619cb2838db2bd3acd4e428dee
BLAKE2b-256 checksum
How to use checksums
07647fc3a893071e323a5bd31cc515ef701996ac0177404de4c26c10bf0ddd08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / tree_sitter_cfml-0.26.43-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL tree_sitter_cfml-0.26.43-cp310-abi3-musllinux_1_2_x86_64.whl
Size 715.1 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
48bfd41122df94d0817e679cdad71766712c935cb2b0c2ea5d87ba8c3b8235df
BLAKE2b-256 checksum
How to use checksums
b6b4101962cb93fa6d0c89803bb40f2d349c7ec851f41253ab0296d0486b959e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / tree_sitter_cfml-0.26.43-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL tree_sitter_cfml-0.26.43-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 718.4 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
ec5d758e902b00325efee2274edff9098f8d965b1732f192bbcec0a6ddcece78
BLAKE2b-256 checksum
How to use checksums
915bc64eaa0a7813f2c3ccaf99a6037da5d2d4bddb04da8e5a4546bf38bcdc59
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / tree_sitter_cfml-0.26.43-cp310-abi3-macosx_11_0_arm64.whl

Download URL tree_sitter_cfml-0.26.43-cp310-abi3-macosx_11_0_arm64.whl
Size 587.5 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
164c8e9f06aaf3280acb9cc1bf9d5cc4fd2de89b3a52ef111f98a54b55899bdc
BLAKE2b-256 checksum
How to use checksums
5dd876bf945b0322b2030f442e71d404a8f8a37c6cd6e281a10cadba8f8c12aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Security for tree-sitter-cfml 0.26.43

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for tree_sitter_cfml-0.26.43.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page