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

recipe-lsp

v0.2.2

Published

Language Server Protocol server for the recipe (.recipe) pharmacological notation language.

Readme

recipe-lsp

NPM JSR

A Language Server Protocol implementation for the Recipe (.recipe) pharmacological-notation language.
Published to npm (recipe-lsp) and JSR (jsr:@kjanat/recipe-lsp), with three entrypoints:

| Import | What it is | | -------------------- | ------------------------------------------------------------------------ | | recipe-lsp | The analyzer library — parse recipes, get diagnostics/hover/completions. | | recipe-lsp (bin) | The Node CLI that runs the language server over a transport. | | recipe-lsp/browser | A Web Worker entrypoint that runs the server in the browser. |

Install

npm install recipe-lsp        # or: bun add / pnpm add / yarn add
deno add jsr:@kjanat/recipe-lsp

Features

  • Tree-sitter-backed syntax diagnostics
  • Section-order warnings (R/Da/S/)
  • Document symbols for recipe sections
  • Hover help that expands Latin abbreviations to their meaning (e.g. d.i.m.m.da in mano medici / "in handen van de arts"), plus markers and dose units
  • Context-aware completions: section markers at line start, dose units right after a number, and abbreviations scoped to the R//Da//S/ section the cursor sits in
  • Markdown diagnostic messages for clients that advertise textDocument.diagnostic.markupMessageSupport (plain strings otherwise)
  • Semantic tokens, folding ranges, and selection ranges

Library

The default entrypoint is runtime-agnostic: getRecipeAnalyzer() detects browser vs Node/Deno and lazily loads the matching analyzer.

import { getRecipeAnalyzer } from "recipe-lsp";

const analyzer = await getRecipeAnalyzer();
const analysis = analyzer.analyzeRecipe(
  "R/ amoxicilline 500 mg\nS/ 3 dd 1 tablet",
);

console.log(analysis.diagnostics, analysis.symbols);

To run a full language server, wire an analyzer to a connection with startRecipeServer; to drive the parser against a Parser you configured yourself, use createRecipeAnalyzer.

CLI

The Node server needs exactly one transport flag:

recipe-lsp --stdio
recipe-lsp --node-ipc
recipe-lsp --socket=3000
recipe-lsp --help

Argument parsing, help, and friendly errors are handled by @kjanat/dreamcli; running the binary with no transport, more than one, or an unknown flag prints a short message instead of a stack trace. This path requires Node ≥ 22.22.2 (dreamcli's floor).

Browser worker

recipe-lsp/browser is a self-contained module Web Worker: every dependency is bundled in, and the two wasm grammars ship next to dist/browser.js and are loaded relative to the bundle's own URL. So it runs from a bare new Worker(url) with no import map, bundler, or dependency resolution.

Load it from a CDN that serves the package files flat (so the sibling .wasm assets resolve), e.g. jsDelivr:

new Worker("https://cdn.jsdelivr.net/npm/recipe-lsp/dist/browser.js", {
  type: "module",
});

The worker speaks LSP over the worker message channel (postMessage the JSON-RPC initialize, then textDocument/didOpen, …).

A re-exporting CDN that relocates modules into a transformed subpath (e.g. esm.sh/recipe-lsp/browser) breaks the sibling-relative wasm URLs — use a flat file CDN, or import the worker through your own bundler.

Notes

  • The server reparses the whole document on change. Recipe files are tiny; simple wins.
  • Tree-sitter reports positions in UTF-8 bytes; recipe-lsp converts them to LSP UTF-16 positions so diagnostics and hovers stay correct on accented text.
  • Analysis code is runtime-agnostic; only server.ts and src/runtime/node-analyzer.ts are Node-specific.