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

metalthea

v0.4.4

Published

Universal metaprogramming language to craft it yourself

Readme

Metalthea

A universal metaprogramming language to build it yourself!

Features

  • Metalthea is a metaprogramming language designed to generates code in-line using text manipulation and substitution at compile-time, like a macro system, for any programming language.
  • Metalthea has no built-in function, nor arithmetic operations, nor control structure, you have to implement that yourself, as you want it to work, in Javascript.
  • Metalthea has the parenthesized syntax of S-expressions (like the Lisp programming language).

Basic API Usage

const metalthea = require("metalthea");

const { value: output, syntaxTree, errorLogs } = metalthea.compileSourceCode('(add 1 2 3)', {
  add: (...args) => args.reduce((a, b) => `${a} + ${b}`),
});

// output == "1 + 2 + 3"

Program examples

  • A hello world (in the middle of a text):
// in source code:
"you can write anything before Metalthea..."
(log (str.join "Hello" "World" "!"))
"...and after too"

// in language implementation
const execCtx = {
  log: function(str) {
    return `console.log(${ str });`;
  },
  str: {
    join: function(...args) {
      return args.join(' ');
    }
  }
}

// the result in the output file:
"you can write anything before Metalthea..."
console.log("Hello World!");
"...and after too"

Why?

  • To add macro features in your usual language.
  • To use cool language features you want to work with (strong typing, pattern matching, tuples, etc.).
  • To transpile one source code to multiple programming language.
  • To use as a codegolfing tool.

Syntax

The Metalthea syntax is close to Lisp S-expressions:

  • an Expression is either an Atom or a List of Expressions.
  • a List is a matched pair of parentheses, with zero or more Expressions inside it.
  • an Atom is either:
    • a base 10 Number
      • i.e. 42, 3.14, -1.6
    • a base 16 Number
      • starting with 0x, can have a decimal part after a dot
      • i.e. 0x2A, 0x3.2f, -0xCC.c
    • a String
      • between double quotes "
      • i.e. "", "0", "Hello World!"
    • a Boolean
      • in lowercase
      • i.e. true, false
    • a Key
      • starting with colon :
      • i.e. :i, :myVar, :$_21
    • a Body
      • either between braces {} or between grave accents `
      • i.e. {1 + 1}, {n => n * n}, {)}, or `\n`, `substring to complete in js`
    • a Function
      • i.e. add, str2Int, __$log
    • a Lazy Node
      • a node starting with a sharp sign #
      • i.e #, #(mul 2)

you can check Grammar RegExp there

To separate Expressions you can use either the space character ( ) or a comma (,) for the same result, in example:

(Map :a 12, :b 36, :c 42)

You can also chain expressions with the character >, in example:

((add 1 1) > sqrt)

is the same thing as:

(sqrt (add 1 1))

Installation

You need Node.js to use Metalthea, so I suggest you to setup a package.json in your project, regardless of what are the other programming language(s), with npm:

npm init
npm install --save-dev metalthea

or with yarn:

yarn init
yarn add --dev metalthea

Configuration

  • in package.json:

add commands in "scripts":

"metalthea": "metalthea <PATH/TO/EXEC_CTX_FILES> <PATH/TO/INPUT_FILES> <PATH/TO/OUTPUT_DIR>",
"build": "npm run metalthea --verbose && <YOUR BUILD COMMAND>",
"watch": "metalthea --verbose --watch"
  • in metalthea.json:

TODO (dependency management and custom setup for execution context from multiple sources)

CLI Usage

command syntax:

metalthea <CTX> <SRC> <TARGET>

Options

  --verbose, -v  add logs to stdout
  --syntax-tree, -t  logs the intermediate syntax tree in stdout
  --watch, -w  watch context and source files and re-compile if any change is detected

Examples

If you have configured package.json as recommended:

npm run metalthea --verbose --watch

or included in your build flow:

npm run build

or using a shell with Metalthea installed globally (npm install -g methathea):

metalthea src/metalthea src/js dist --verbose --watch

or use the Node API from your Node.js project.

FAQ

  • How to use loops and conditions? (control structure)
    • Implement it yourself! The easiest way is to craft expression based ones, but you can implement statements as well.
    • i.e. (if (check :test) "yes!" "no"), (for 0,99,1 #(log))
  • There are missing types (list, array, character, etc.)!
    • Implement it yourself!
    • i.e. (Map :x 21, :y -42)
  • How to handle null / undefined ?
    • You can test values in javascript, you can event add a custom Null type if you wish.
    • i.e. (def :x (if (isNull :a) 0, :a))
  • How to add a comment?
    • For the moment you have to implement it yourself.
    • i.e. (comment "blaba")
  • How to use arithmetic operations *(+, -, , /, %)?
    • Implement it yourself!
    • i.e. (mul 3 (add 5 4) > sqrt)
  • I need strong typing!
    • Implement it yourself!
    • i.e. (defTyped (int :n) 42)
  • How to declare variables?
    • For the global scope you can implement it yourself, outside of function scope in javascript.
      • i.e. (in the execution context javascript file) const state = {};
    • For the local scope you can use the keyword this in javascript functions.
      • i.e. function def(varName, value) { this[varName] = value; }
  • How to use Lazy Node (#)?
    • as a function from javascript.
    • you can store it like any variable, i.e. (def :double #(mul 2)).
    • you can pass arguments while executing a Lazy Node, like for other nodes. i.e.:
// Metalthea program:  (for 0,3,1 #(js.log) > join)

// javascript context:
const execCtx = {
  for: function(from, to, step, bodyLambda) {
    let result = [];
    for (let i = from; i < to; i += step) {
      result = result.concat(bodyLambda(i, from, to));
    }
    return result;
  },
  log: function(...args) {
    return `console.log(${args.join(",")})`;
  },
  join: function(arr) {
    return arr.join("; ");
  }
};

// output == `console.log(0,0,3); console.log(1,0,3); console.log(args: 2,0,3)`

Git repository

License

MIT © Lucien Boudy

"Contributing" documentation

in CONTRIBUTING.md file