or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-babel-plugin-macros

Babel plugin that enables compile-time code transformation through macros with a standardized interface

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/babel-plugin-macros@3.1.x

To install, run

npx @tessl/cli install tessl/npm-babel-plugin-macros@3.1.0

index.mddocs/

babel-plugin-macros

babel-plugin-macros is a Babel plugin that enables compile-time code transformation through macros with a standardized interface. It allows library authors to create compile-time transformations without requiring users to configure individual Babel plugins, providing a unified macro system for the JavaScript ecosystem.

Package Information

  • Package Name: babel-plugin-macros
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install --save-dev babel-plugin-macros

Core Imports

For macro authors creating macros:

const { createMacro, MacroError } = require("babel-plugin-macros");

For Babel configuration (users installing the plugin):

// babel.config.js
module.exports = {
  plugins: ["macros"]
};

For macro consumers (importing and using macros):

// ES6 imports
import myMacro from "some-library.macro";
import { namedMacro } from "some-library.macro";

// CommonJS requires
const myMacro = require("some-library.macro");
const { namedMacro } = require("some-library.macro");

Basic Usage

For Macro Authors

const { createMacro } = require("babel-plugin-macros");

module.exports = createMacro(myMacro);

function myMacro({ references, state, babel }) {
  // Transform the AST using the references
  references.default.forEach(referencePath => {
    // Perform compile-time transformation
    referencePath.replaceWithSourceString('"transformed at compile time"');
  });
}

For Macro Consumers

import transform from "./my.macro";

// This gets transformed at compile time
const result = transform("some input");

For Users (Babel Configuration)

Add to .babelrc or babel.config.js:

{
  "plugins": ["macros"]
}

Macro Behavior

Import Statement Handling

By default, macro import/require statements are removed after macro processing:

import myMacro from "./my.macro";
// This import will be removed after macro processing

Preserving Import Statements

Macros can return {keepImports: true} to preserve the import statement:

// In your macro implementation
function myMacro({ references }) {
  // Process the macro...
  
  // Return this to keep the import statement
  return { keepImports: true };
}

This is useful for macros that need to leave runtime code in place alongside their compile-time transformations.

Capabilities

Macro Creation

Creates a macro function with proper error handling and validation.

function createMacro(macro: MacroFunction, options?: MacroOptions): WrappedMacro;

interface MacroOptions {
  configName?: string;
}

interface MacroFunction {
  (args: MacroArgs): MacroResult | undefined;
}

interface MacroArgs {
  references: { [importName: string]: NodePath[] };
  source: string;
  state: BabelState;
  babel: BabelTypes;
  config: any;
  isBabelMacrosCall: boolean;
}

interface MacroResult {
  keepImports?: boolean;
}

interface WrappedMacro {
  (args: MacroArgs): MacroResult | undefined;
  isBabelMacro: true;
  options: MacroOptions;
}

Error Handling

Custom error class for macro-specific errors with proper stack traces.

class MacroError extends Error {
  constructor(message: string);
  name: "MacroError";
}

Plugin Function

Main Babel plugin function that processes macro imports and requires.

function macrosPlugin(babel: BabelCore, options?: PluginOptions): BabelPlugin;

interface PluginOptions {
  require?: (path: string) => any;
  resolvePath?: (source: string, basedir: string) => string;
  isMacrosName?: (name: string) => boolean;
  [configName: string]: any;
}

interface BabelPlugin {
  name: "macros";
  visitor: {
    Program: (path: NodePath, state: BabelState) => void;
  };
}

Configuration System

babel-plugin-macros supports configuration through multiple methods:

File-based Configuration

  • package.json with babelMacros property
  • .babel-plugin-macrosrc (JSON or YAML)
  • .babel-plugin-macrosrc.json
  • .babel-plugin-macrosrc.yaml
  • .babel-plugin-macrosrc.yml
  • .babel-plugin-macrosrc.js
  • babel-plugin-macros.config.js

Plugin Options

Configuration can be passed through Babel plugin options:

// babel.config.js
module.exports = {
  plugins: [
    ["macros", {
      myMacroConfig: {
        option1: "value1",
        option2: "value2"
      }
    }]
  ]
};

Macro-specific Configuration

Macros can access their configuration through the config parameter:

function myMacro({ config }) {
  // Access configuration specific to this macro
  const options = config || {};
}

module.exports = createMacro(myMacro, { configName: "myMacroConfig" });

Macro File Naming Convention

For a file to be recognized as a macro, it must match the pattern:

const macrosRegex = /[./]macro(\.c?js)?$/;

Valid macro names:

  • my.macro
  • my.macro.js
  • my.macro.cjs
  • my/macro
  • my/macro.js
  • my/macro.cjs
  • my/macro/index.js (imported as my/macro)

Invalid macro names:

  • my-macro
  • my.macro.is-sweet
  • my/macro/rocks

Supported File Extensions

The plugin resolves macros with the following extensions:

  • .js
  • .ts
  • .tsx
  • .mjs
  • .cjs
  • .jsx

Import Patterns

ES6 Import Declarations

import macro from "my.macro";                    // Default import
import { namedMacro } from "my.macro";          // Named import
import macro, { namedMacro } from "my.macro";   // Mixed import

CommonJS Require Statements

const macro = require("my.macro");              // Default require
const { namedMacro } = require("my.macro");     // Destructured require

Types

interface BabelState {
  file: {
    opts: {
      filename?: string;
    };
    scope: any;
  };
}

interface BabelCore {
  types: BabelTypes;
  template: any;
  traverse: any;
}

interface BabelTypes {
  // Babel types object with AST node constructors and utilities
  [key: string]: any;
}

interface NodePath {
  node: any;
  scope: any;
  remove(): void;
  replaceWith(node: any): void;
  replaceWithSourceString(code: string): void;
  // Additional Babel NodePath methods
}