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

gingerly-tree

v0.0.2

Published

Syntax highlighting for assign-gingerly tree`…` tagged templates, in JS/TS files, HTML script tags, Markdown code blocks and the Markdown Preview.

Readme

Gingerly Tree

Syntax highlighting for assign-gingerly's tree`…` tagged templates, which produce builtIns.tree element specifications from lit-like markup.

import { tree, each } from 'assign-gingerly/DX/tree.js';

const map = {
    launch: tree`
        <article class="card" aria-label=${p.label}>
            <h3 class="title">${p.name}</h3>
            <p>Launched ${p.date} by ${'?.rocket'}</p>
            <ul ${each(p.crew, { key: '?.id' })}>
                <li>${'?.name'}</li>
            </ul>
            <button @click=${{ call: 'launch' }}>Launch</button>
        </article>`,
};

This extension has no extension-host code: TextMate grammars, plus a script and stylesheet that run inside the Markdown Preview. So it also works in VS Code for the Web (vscode.dev, github.dev) and in untrusted workspaces.

Where it works

| Host | Covered | |---|---| | Script files | .js, .mjs, .cjs, .jsx, .ts, .mts, .cts, .tsx | | HTML | inline <script> and <script type="module"> | | Markdown, while editing | fenced code blocks marked js, javascript, mjs, cjs, jsx, ts, typescript, tsx, and <script> tags inside html blocks (fence names are case-insensitive, so ```JavaScript works too) | | Markdown Preview | the same code blocks, plus mts and cts (see below) |

Recognized tags

  • tree`…`
  • 🌲`…`
  • DX.tree`…`

A grammar matches by name, so other aliases (import { tree as t }) aren't highlighted.

What's highlighted

  • Markup: tags, attributes, quoted and unquoted values, entities, comments.
  • Binding prefixes, each with its own scope:
    • .prop=${…}: a property;
    • @event=${…}: an event binding;
    • ish=${Manager}: the itemscope manager header.
  • ${…}: colored as TypeScript/JavaScript. That covers ${p.name}, ${each(…)}, pattern spreads ${{ … }}, and nested ${tree`…`}.
  • ?. path strings inside ${…}, e.g. ${'?.name'}, '$parent?.upcoming' or '?.date_utc?.parseDate?.longUtc'. They're scoped as variables rather than strings, so most themes show them in a different color from ordinary strings.

In the Markdown Preview

The preview doesn't use TextMate grammars: it colors code blocks with highlight.js, which shows a tagged template as one plain string. So this extension adds a small script to the preview (preview/gingerly-tree-preview.js). It finds the tree templates in JS/TS code blocks and in <script> tags of HTML code blocks, and re-renders them with the same rules as the grammar. Markup uses the preview's own highlight.js colors. .prop, @event, ish, ${…} and ?. paths get Dark+ / Light+ colors from preview/gingerly-tree-preview.css.

The preview isn't affected by editor.tokenColorCustomizations. To restyle it, point markdown.styles at your own CSS, targeting .gt-path-segment, .gt-path-root, .gt-path-accessor, .gt-prefix, .gt-event, .gt-prop, .gt-ish, .gt-subst, .gt-entity or .gt-escape.

GitHub's own rendering of Markdown uses its own highlighter, which no extension can change.

Customizing colors

All scopes end in .gingerly-tree, so they can be targeted in settings.json:

"editor.tokenColorCustomizations": {
    "textMateRules": [
        { "scope": "meta.path.gingerly-tree", "settings": { "foreground": "#4EC9B0" } },
        { "scope": "punctuation.accessor.optional.path.gingerly-tree", "settings": { "foreground": "#808080" } },
        { "scope": "entity.other.attribute-name.event.gingerly-tree", "settings": { "fontStyle": "italic" } },
        { "scope": "entity.other.attribute-name.property.gingerly-tree", "settings": { "fontStyle": "italic" } },
        { "scope": "entity.other.attribute-name.ish.gingerly-tree", "settings": { "fontStyle": "bold" } }
    ]
}

| Scope | What | |---|---| | meta.embedded.block.gingerly-tree | the template's content | | meta.path.gingerly-tree | a whole ?. path string | | variable.language.path-root.gingerly-tree | $parent, $root, $0 at the start of a path | | punctuation.accessor.optional.path.gingerly-tree | each ?. in a path | | variable.other.property.path.gingerly-tree | each segment of a path | | entity.other.attribute-name.property.gingerly-tree | prop in .prop= | | entity.other.attribute-name.event.gingerly-tree | event in @event= | | punctuation.definition.attribute-name.{property,event}.gingerly-tree | the . / @ prefix | | entity.other.attribute-name.ish.gingerly-tree | ish |

Not included

Diagnostics (the tag's TreeTemplateErrors), hover previews of the produced tree notation and completions need code, so they're planned for a separate extension, Gingerly Tree Analyzer, which will depend on this one for highlighting.

Development

npm install
npm test          # runs both test suites below
node test/run.mjs                    # tokenizes test/fixtures with VS Code's built-in grammars plus these, and checks scopes
node test/preview.mjs                # renders test/fixtures/preview.md as the preview does (markdown-it + highlight.js), runs the preview script in jsdom, checks the spans
node test/run.mjs --dump sample.md   # prints every token of a fixture

The tests load the built-in grammars from the local VS Code install. If it isn't found, set VSCODE_EXTENSIONS_DIR to <VS Code>/resources/app/extensions.

To try the extension, open this folder in VS Code and press F5 (Run Extension), or install a packaged .vsix (see StepsToPublish.md).