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

@icaroglauco/dsljs

v0.1.3

Published

IDSL macro system and structural expander for JavaScript

Readme

@icaroglauco/dsljs

Compile-time macros for JavaScript.

@icaroglauco/dsljs lets you define local DSLs inside a .dsljs file and expand them into plain JavaScript before runtime. The generated output is ordinary JavaScript with no additional runtime layer, which makes the tool useful for code generation, structural syntax experiments, and domain-specific authoring workflows.

This package is designed for teams that want custom authoring syntax while keeping deployment artifacts plain JavaScript.

Highlights

  • Compile custom syntax to standard JavaScript
  • Keep macro definitions close to the code that uses them
  • Generate deterministic output with zero runtime overhead
  • Use the package from the CLI, from Vite, or programmatically
  • Add editor and ESLint support for .dsljs files

Installation

For most projects this package should be installed as a development dependency:

npm install -D @icaroglauco/dsljs

The package exposes:

  • dsljs and idsl CLI commands
  • @icaroglauco/dsljs/vite for Vite integration
  • @icaroglauco/dsljs/eslint-config for ESLint
  • the parser/compiler API from @icaroglauco/dsljs

Quick Start

Create a file named hello.dsljs:

macros: {

  $macro LOG $msg #(
    console.log("[Macro Log]:", $msg);
  )#

  $macro style($text) #(
    console.log($text);
  )#

}

const project = "dsljs";

LOG `Build completed for ${project}`

style(/*css*/`
  .banner {
    padding: 16px;
    border: 1px solid #d0d7de;
  }
`)

Compile it:

npx dsljs hello.dsljs hello.js

Generated output:

const project = "dsljs";

console.log("[Macro Log]:", `Build completed for ${project}`);

console.log(/*css*/`
  .banner {
    padding: 16px;
    border: 1px solid #d0d7de;
  }
`);

How It Works

Each .dsljs source file can contain a macros: { ... } block. That block declares rewrite rules using $macro, and the rest of the file is expanded against those rules during compilation.

At a high level:

  1. The compiler reads the macros: { ... } block.
  2. Macro definitions are parsed into rewrite rules.
  3. The remaining file is transformed.
  4. The final result is emitted as standard JavaScript.

Macro definitions do not remain in the final output.

Professional Usage Examples

1. Structural Logging and Build-Time CSS

This pattern is useful when you want a concise authoring syntax while still shipping plain JavaScript:

macros: {

  $macro LOG $msg #(
    console.log("[Macro Log]:", $msg);
  )#

  $macro style($text) #(
    console.log($text);
  )#

}

LOG `Starting dashboard build`

style(/*css*/`
  #dashboard {
    display: grid;
    gap: 24px;
  }
`)

Expanded JavaScript:

console.log("[Macro Log]:", `Starting dashboard build`);

console.log(/*css*/`
  #dashboard {
    display: grid;
    gap: 24px;
  }
`);

2. Domain-Specific Factory Generation

Macros can encode a business or application-specific construction pattern.

Source:

macros: {

  $macro struct game $name[
    types: $types,
    events: $events
  ] => {
    $($prop = $value;)...
  }
  #(
    const $name = function () {
      const types = { $types };
      const events = [ $events ];
      const listeners = Object.fromEntries(
        events.map(eventName => [eventName, []])
      );

      return {
        types: () => types,
        events: () => events,
        listeners: () => listeners,
        on(eventName, listener) {
          if (!listeners[eventName]) {
            listeners[eventName] = [];
          }

          listeners[eventName].push(listener);
        },
        emit(eventName, payload) {
          for (const listener of listeners[eventName] ?? []) {
            listener(payload);
          }
        },
        $($prop: $value,)...
      };
    }
  )#

}

struct game arena[
  types: {
    state: "GameState",
    entity: "Entity",
    player: "Player"
  },
  events: ["boot", "tick", "gameover"]
] => {
  version = "0.1.0";
  initialScene = "forest";
}

const game = arena();
game.emit("boot", { scene: game.initialScene });

This style is useful when you want a compact authoring format for repetitive object or module generation.

3. HTML-Like Template Authoring

Another good fit is markup-oriented generation:

macros: {

  $macro tag [
    $tagname
    { $($attr:$value,)... }
    ( $inner )
  ] #(
    `<${$tagname}
      $(
      ${$attr}=${$value}
      )...
    >
      ${$inner}
    </${$tagname}>`
  )#

}

const card = tag[
  section
  { class: "profile-card", id: "user-42" }
  (
    `<h2>Ana</h2><p>Platform Engineer</p>`
  )
];

That gives you a lightweight way to create project-specific view or content syntaxes without introducing a custom runtime.

CLI

The package ships with the dsljs command.

dsljs <input.dsljs> [output.js]
dsljs dist <srcDir> <outDir>
dsljs watch <src> <out>
dsljs run <file.dsljs> [...args]
dsljs watch-run <file.dsljs> [...args]
dsljs shadow <file.dsljs> [file.generated.js]
dsljs watch-shadow <file.dsljs> [file.generated.js]

Common workflows:

Compile a single file:

npx dsljs src/main.dsljs dist/main.js

Print the compiled JavaScript to stdout:

npx dsljs src/main.dsljs

Compile an entire directory:

npx dsljs dist src dist

Watch and rebuild files:

npx dsljs watch src dist

Generate a shadow file for editor tooling:

npx dsljs shadow src/main.dsljs src/main.generated.js

Run a DSL file directly after expansion:

npx dsljs run scripts/task.dsljs --env production

Vite Integration

Use the Vite plugin when your project imports .dsljs files directly.

vite.config.js

import { defineConfig } from "vite";
import dsljs from "@icaroglauco/dsljs/vite";

export default defineConfig({
  plugins: [dsljs()]
});

Example module:

import "./startup.dsljs";

The plugin expands .dsljs sources before Vite continues with the rest of the pipeline.

Programmatic API

The root package exports the compiler helpers from src/parser.js.

Compile a source string:

import { compileDslSource } from "@icaroglauco/dsljs";

const source = `
macros: {
  $macro LOG $msg #( console.log($msg); )#
}

LOG "hello"
`;

const output = compileDslSource(source);
console.log(output);

Compile from a file:

import { compileDslFile } from "@icaroglauco/dsljs";

const output = compileDslFile("src/main.dsljs");
console.log(output);

Low-level helpers such as stripMacrosBlock, parseMacrosFromBlock, and expandMacros are also exported for advanced workflows.

ESLint

The package includes a ready-to-use flat config for .dsljs files:

import dsljsConfig from "@icaroglauco/dsljs/eslint-config";

export default dsljsConfig;

This config wires the custom processor and validates .dsljs sources through ESLint.

VS Code Support

On install, the package tries to set up local VS Code support automatically by:

  • installing the bundled editor extension locally
  • updating .vscode/settings.json
  • updating .vscode/extensions.json
  • creating an ESLint config proxy if one does not exist
  • creating a minimal jsconfig.json if one does not exist

If you need to skip this behavior, set the DSLJS_SKIP_VSCODE_SETUP=1 environment variable before installation.

The editor support is designed around .dsljs and .idsl files, while the Vite plugin currently targets .dsljs imports.

Repository Examples

The repository includes real examples you can use as reference:

  • example/example.dsljs
  • example/game.dsljs

Notes

  • Expansion happens at compile time, not at runtime
  • Generated output is standard JavaScript
  • Macro design is intentionally flexible and low-level
  • The best results come from keeping macros small, explicit, and domain-focused