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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@macro-plugin/core

v1.2.0

Published

Macro system for JavaScript and TypeScript.

Downloads

40

Readme

@macro-plugin/core

Macro system for JavaScript and TypeScript.

Install

# if you use npm
npm i -D @macro-plugin/core
# if you use pnpm
pnpm i -D @macro-plugin/core
# if you use yarn
yarn add -D @macro-plugin/core

Why

Have you ever used Rust? Rust has an impressive macro system. I'm wondering why the JavaScript world can't have one. Now you got it.

How it works

It uses swc's parser and printer, and does not make any conversions other than macors to your project by default. Of course, it can also be used as a swc plugin, so we can transform typescript and jsx.

Features

  • A new walker for macros, inspired by estree-walker
  • Built-in variable tracker plugin, which makes it easier to convert variables.
  • Very simple yet powerful APIs for creating various types of macros.
  • Factory runtime and macros for simplify creating swc AST.
  • Support automatic generation of macro declarations file. (macros.d.ts)
  • Many common built-in macros.
  • Support all web framework intergrations.

Built-in macros

The project is still in the beta stage, and there are more macros under development.

Expression Macros

Expression macros may be a very familiar macro type. It converts a CallExpression into any other Expression.

$Eval

compile time eval.

$Ast

convert anything into an ast.

$Env

read env and replace with result.

$Stringify

convert any expression or type into string

$Span

get a span like [line, column]

$Line

get current line number

$Column

get current column number

$ID

generate unique id based on [line, column, filename]

$Include

include another js, ts file into current script.

$IncludeStr

include a string from any path

$IncludeJSON

include a json, also support include a json value with key.

$WriteFile

compile time write to file

$Concat

compile time concat string

$Expr

turn code into an expression

$Quote

a template macro for create macro

$UnImplemented

mark code as unImplemented, log error when compile, throw error in client side.

$Todo

mark code as todo, log warning when compile, throw error in client side.

$UnReachable

mark code as unreachable, throw error in client side.

...

Labeled Macros

LabeledMacros are very interesting feature. It even allows you to invent your own grammar. For example:

debug: {
  console.log("something")
}

or creating states:

state: {
  var count = 0
  var name = "macro"
}

or using function decorator:

function myFunc() {
  decorator: [yourFunctionDecorator]

  doSomething()
}

you can even create macro with it.

macro: {
  var __DEV__ = true
  
  var add = $ExprMacro<(a: number, b: number) => number>(function(args) {
    const a = this.printExpr(args[0])
    const b = this.printExpr(args[1])

    if (+a < 0) return args[1]
    return this.parseExpr(`${a} + ${b}`)
  })
}

if (__DEV__) {
  const a = add(1, 2)
}

transform to

if (true) {
  const a = 1 + 2
}

To use Labeled Macros, you may need some extra config for typescript and eslint.

Typescript

{
  "compilerOptions": {
    // ...
    "allowUnusedLabels": true,
  },
}

Eslint

module.exports = {
  rules: {
    // ...
    "no-labels": 0,
  }
}

API

transform/transformAst/transformAsync

transform code with macro plugins.

createSwcPlugin

use as swc plugin.

walk

walk an ast node or node list

print/printAsync/printExpr/printType

print ast to code

parse/parseAsync/parseExpr/parseType

parse code to ast

defineConfig

define config with types

createMacro

create a macro

createLitMacro

create a literal macro

createExprMacro

create an expression macro

createTypeMacro

create a type macro

createTmplMacro

create a template macro

createLabeledMacro

create a labeled macro

isMacroPlugin

check if input is a macro plugin

FAQ

LabeldMacros confusing with JavaScript

Some people may argue about labeldMacros, confusing the original semantics of JavaScript. But in fact, labeledStatement and var are both forgotten or discarded syntax of JavaScript. So we bring something new to it. Personally, I don't think this is a bad thing.

Compare with babel

In fact, the beginning of this project based on babel's parser and generator. When I switched to swc, I did a simple test and found that the speed was at least tripled, so it must be faster.

This project is based on the AST type of swc and is not compatible with Babel's AST. And the project focuses on transforming macros. If you need the support of something like browserlist, you need to use it with swc.

Compare with swc

You can regard it as an enhanced version of swc with macro support, as well as better aapi. However, we do not use the .swcrc configuration file. The json configuration is not friendly for macros, and you should define all your swc configuration in macros.config.js or macros.config.ts.

License

MIT

Copyright (c) 2023, Raven Satir