npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tree-sitter-aspx

v0.1.2

Published

Tree-sitter grammar for ASP.NET Web Forms markup

Readme

tree-sitter-aspx

A tree-sitter grammar for ASP.NET Web Forms markup: .aspx pages, .ascx user controls, .master master pages, and the directive headers of .asax, .asmx, and .ashx files.

Classic ASP (.asp with VBScript) and Razor (.cshtml, .vbhtml) are different languages and are out of scope. Code-behind files (.aspx.cs, .aspx.vb) are ordinary C# or VB.NET and are not parsed by this grammar.

The grammar parses directives, server comments, HTML comments, code nuggets, <script> and <style> elements, and tags with attributes. It does not validate HTML. Void tags (br, img, meta, and the other HTML void elements) do not swallow the following markup. An end tag closes the nearest open element; the names are not required to match. <script> and <style> bodies are raw text, so < inside JavaScript or CSS is not a tag.

Embedded C# and VB.NET

Code nuggets and server-script bodies are opaque ranges. The page Language attribute (C# or VB, any casing) is a language_value node, and the scanner labels each later nugget c_sharp_code or vb_code. When the attribute is absent, the label is c_sharp_code.

| Node | What it is | | --- | --- | | encoded_expression, output_expression, binding_expression | <%: %>, <%= %>, <%# %> | | statement_block | <% %> | | expression_builder / expression_value | <%$ %>, not C# or VB | | server_comment | <%-- --%>, not code | | c_sharp_code, vb_code | The bytes inside a nugget or a <script> body | | handler_code | Everything after a WebHandler or WebService directive that is not a <script> element |

queries/injections.scm maps those code nodes to c_sharp or vb. Statement blocks set injection.combined, so <% if (ready) { %> … <% } %> is one injected document and the markup between them is not part of it. Output, encoded, and binding nuggets are injected one by one. A <script> whose start tag has runat="server" keeps the page language. Any other <script> body is injected as JavaScript, even though the node is still c_sharp_code or vb_code. <style> bodies are injected as CSS.

A consumer that counts executable code should count c_sharp_code and vb_code bytes, and should skip a <script> body whose start tag has no runat="server". Markup, attribute text, style text, expression-builder text, and server comments are not executable code. Server comments are their own node kind.

.ashx and .asmx files are a WebHandler or WebService directive plus either a <script runat="server"> element or the rest of the file as handler_code. .asax stays markup.

Some legacy pages are UTF-16. Decode them to UTF-8 before parsing. tools/corpus-check.mjs does that.

Node package metadata

The default export exposes name, language, and nodeTypeInfo on Linux and Windows. nodeTypeInfo contains the entries from src/node-types.json.

import Parser from 'tree-sitter';
import Aspx from 'tree-sitter-aspx';

const parser = new Parser();
parser.setLanguage(Aspx);
const tree = parser.parse('<%@ Page Language="C#" %>');
console.log(tree.rootNode.toString());

Rust

let mut parser = tree_sitter::Parser::new();
parser
    .set_language(&tree_sitter_aspx::LANGUAGE.into())
    .expect("Error loading ASPX parser");

LANGUAGE is a tree_sitter_language::LanguageFn. The crate's runtime dependency is tree-sitter-language, so the consuming crate's own tree-sitter version is what parses.

Building

npm ci --ignore-scripts
npm rebuild tree-sitter-cli
npx --no-install tree-sitter generate
cargo build

Release jobs require a version tag on main matching the Cargo package version and publish from the commit that passed verification. The npm and GitHub Packages archives carry that same version in both package.json and tree-sitter.json.