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

@axis-dsl/language-server

v2.5.0

Published

An LSP server for Axis: diagnostics, completion, hover, formatting, semantic tokens and navigation for any editor

Readme

@axis-dsl/language-server

The Axis language server: everything @axis-dsl/language-service knows about an Axis file, spoken over the Language Server Protocol, plus the file-system work the service leaves to a host - resolving and reading imports and images, listing a directory for a path completion, and noticing when a file an Axis file reads has changed.

The VSCode extension bundles it and talks to it over node IPC. Any other editor starts the axis-language-server bin over stdio.

What it does

| Feature | Notes | | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Diagnostics | Pushed (textDocument/publishDiagnostics), debounced 250 ms after an edit. Everything a compile would report, with imports resolved; an import or image whose file is not there is reported as Cannot find "…" or Cannot find image "…" on its path. | | Re-checking | A document is checked again when a file it imports or draws is created, changed, deleted or saved, or edited unsaved in another open buffer. The server registers the file watcher itself. | | Completion | Keywords, properties in metadata, names (including those an import defines), and paths inside import "…" / image "…", read off disk. | | Hover | Keywords, builtins, and the names a file or its imports define. | | Formatting | Whole document and range. The line length is axis.format.maxLineLength from the client's settings (100 when unset). | | Semantic tokens | Full and range, over the service's SEMANTIC_TOKEN_LEGEND. | | Links | The path in an import or image, resolved to the file it names. | | Definition | Within the file, and into the imported file that defines a name. | | References, highlights | Within the file. | | Document symbols, folding ranges | |

Open documents take precedence over disk: a file that imports another you are editing sees your unsaved changes.

Paths resolve the way the compiler's hosts resolve them: relative to the file they are written in, with .axis implied on an import, and a leading / relative to the workspace folder holding the file (or its own directory, outside every workspace folder).

Running it

npm install --global @axis-dsl/language-server
axis-language-server --stdio

From a checkout of this repository, pnpm build and then node packages/language-server/dist/bin.js --stdio.

--node-ipc and --socket=<port> work too; --stdio is what editors other than VSCode use.

Settings

The server asks for the axis section with workspace/configuration:

{ "axis": { "format": { "maxLineLength": 100 } } }

Initialization options

| Option | Meaning | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | retriggerCommand | A client command that reopens the completion list, attached to a directory completion so a path is completed a segment at a time. VSCode's is editor.action.triggerSuggest. Off when absent. |

Editors

None of these editors knows Axis yet, so each snippet also declares the language for .axis files.

Neovim (0.11+)

vim.filetype.add({ extension = { axis = 'axis' } })

vim.lsp.config('axis', {
    cmd = { 'axis-language-server', '--stdio' },
    filetypes = { 'axis' },
    root_markers = { '.git' },
    settings = { axis = { format = { maxLineLength = 100 } } },
})
vim.lsp.enable('axis')

Semantic tokens colour the file with no Tree-sitter grammar; :set commentstring=//\ %s makes gc comment a line.

Helix

In languages.toml:

[language-server.axis-language-server]
command = "axis-language-server"
args = ["--stdio"]
config = { axis = { format = { maxLineLength = 100 } } }

[[language]]
name = "axis"
scope = "source.axis"
file-types = ["axis"]
roots = []
comment-token = "//"
indent = { tab-width = 4, unit = "    " }
language-servers = ["axis-language-server"]

Helix has no semantic highlighting, and there is no Tree-sitter grammar for Axis, so the file is uncoloured; everything else works.

Zed

Zed only starts a language server for a language an extension defines, so Axis needs a small dev extension (zed: install dev extension), a Rust crate depending on zed_extension_api with these three files. This sketch has not been tried against a real Zed yet; Zed may insist on a Tree-sitter grammar for the language.

# extension.toml
id = "axis"
name = "Axis"
version = "0.0.1"
schema_version = 1

[language_servers.axis-language-server]
name = "Axis"
languages = ["Axis"]
# languages/axis/config.toml
name = "Axis"
grammar = ""
path_suffixes = ["axis"]
line_comments = ["// "]
// src/lib.rs
use zed_extension_api::{self as zed, LanguageServerId, Result};

struct Axis;

impl zed::Extension for Axis {
    fn new() -> Self {
        Axis
    }

    fn language_server_command(
        &mut self,
        _id: &LanguageServerId,
        worktree: &zed::Worktree,
    ) -> Result<zed::Command> {
        Ok(zed::Command {
            command: worktree
                .which("axis-language-server")
                .ok_or("axis-language-server is not on PATH")?,
            args: vec!["--stdio".into()],
            env: Default::default(),
        })
    }
}

zed::register_extension!(Axis);

Settings go under lsp in Zed's settings.json:

{ "lsp": { "axis-language-server": { "settings": { "axis": { "format": { "maxLineLength": 100 } } } } } }

Using it as a library

import { startServer } from '@axis-dsl/language-server';

startServer(); // a connection from process.argv: --stdio, --node-ipc or --socket

startServer(connection) takes a vscode-languageserver connection of your own - over a stream pair, say, in a test - and listen(connection) is the same without the default. AxisInitializationOptions types what a client may send at initialize.