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

@lumis-sh/lumis

v0.10.1

Published

Syntax Highlighter powered by Tree-sitter and Neovim themes

Readme

@lumis-sh/lumis

Syntax Highlighter powered by Tree-sitter and Neovim themes.

JavaScript / TypeScript package for Lumis. Works in Node.js, Bun, Deno, and browsers, with TypeScript declarations included.

Features

  • 110+ Tree-sitter languages - Fast, accurate, and updated syntax parsing
  • 200+ built-in Neovim themes - Updated and curated themes from the Neovim community
  • Built-in formatters - HTML (inline/linked), Terminal (ANSI), Multi-theme (light/dark), BBCode
  • Custom formatters - Build your own output
  • Language auto-detection - File extension, shebang, and emacs-mode support
  • Line highlighting - Mark and style individual lines, with custom HTML wrappers
  • Streaming-friendly - Handles incomplete code
  • Load parsers on demand - From the packages you install or import, including injected languages on Node; browsers load those up front

Install

npm install @lumis-sh/lumis @lumis-sh/themes
npm install @lumis-sh/wasm-javascript

Each language is its own package. Install the ones you highlight, or a bundle such as @lumis-sh/wasm-bundle-web.

Usage

import { highlight } from '@lumis-sh/lumis'
import { htmlInline } from '@lumis-sh/lumis/formatters'
import dracula from '@lumis-sh/themes/dracula'
import javascript from '@lumis-sh/wasm-javascript'

const html: string = await highlight('const x = 1', htmlInline({ language: javascript, theme: dracula }))

highlight() shares one process-wide runtime, which is what you want for a one-off. For repeated calls, createHighlighter() loads languages during setup and highlights synchronously afterwards:

import { createHighlighter } from '@lumis-sh/lumis'

const hl = await createHighlighter({ languages: [javascript] })
const html = hl.highlight('const x = 1', htmlInline({ language: javascript, theme: dracula }))

A bundle package registers a whole set at once, and each language in it still loads lazily on first use:

import web from '@lumis-sh/wasm-bundle-web'

const hl = await createHighlighter({ languages: [web] })
await hl.loadLanguage(web.typescript)

The bundles are @lumis-sh/wasm-bundle-web, -web-extra, -system, -backend, and -full.

Parsers

Each parser is an independently released package, such as @lumis-sh/wasm-javascript, holding the parser, its queries, and its SHA-256 digest. The package's default export is the language, so the same import works on Node, where Lumis reads the parser from node_modules, and in a browser, where your bundler ships it. A project loads nothing it didn't install or import unless you configure a resolver, and bytes Lumis fetches are checked against the digest before use.

Packages are named after the parser, and a parser that serves more than one language exports each by name:

import markdown, { mdx } from '@lumis-sh/wasm-markdown'
import { ejs, erb } from '@lumis-sh/wasm-embedded-template'

Importing markdown also loads markdown_inline, the grammar it depends on. On Vite 7 and older, list the parser packages you import in optimizeDeps.exclude; Vite 8 needs nothing.

On Node, a document also loads the languages injected inside it during the same pass, so a Markdown file with a fenced Rust block highlights that block without Rust being named in your code. Browsers load asynchronously, so load injected languages up front, including those from a registered bundle.

On Node, warm parsers alongside startup, without putting the compile on the boot path:

import * as languages from '@lumis-sh/lumis/languages';

await startServer()

// Not awaited. The `.catch()` is required: an unhandled rejection would
// terminate the process.
languages.load(['javascript', 'html', 'css']).catch((error) => {
  logger.warn({ error }, 'Lumis warm-up failed; languages load on demand')
})

languages.load() warms the runtime highlight() uses and keeps the languages there, persisting compiled Wasmtime modules on native Node. To compile in a build step instead, run the same call there, awaited, with LUMIS_DATA_DIR set to the directory the server uses.

Documentation

Guides for formatters, themes, integrations and recipes are at docs.lumis.sh.