API Stability Notice

Macroforge is under active development. The API is not yet stable and may change between versions. Some documentation sections may be outdated.

Svelte Preprocessor

The Svelte preprocessor expands Macroforge macros in <script> blocks before Svelte compilation, enabling seamless macro usage in Svelte components.

Installation

Bash
npm install -D @macroforge/svelte-preprocessor

Configuration

Add the preprocessor to your svelte.config.js:

svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import { macroforgePreprocess } from '@macroforge/svelte-preprocessor';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: [
    macroforgePreprocess(),  // Expand macros FIRST
    vitePreprocess()          // Then handle TypeScript/CSS
  ],

  kit: {
    adapter: adapter()
  }
};

export default config;
Warning
Always place macroforgePreprocess() before other preprocessors like vitePreprocess(). This ensures macros are expanded before TypeScript compilation.

Usage

Use @derive decorators directly in your Svelte component scripts:

UserCard.svelte
<script lang="ts">
  /** @derive(Debug, Clone) */
  class User {
    name: string;
    email: string;

    constructor(name: string, email: string) {
      this.name = name;
      this.email = email;
    }
  }

  let user = new User("Alice", "[email protected]");
  console.log(user.toString());  // Generated by Debug macro
</script>

<p>User: {user.name}</p>

Options

TypeScript
macroforgePreprocess({
  // Keep @derive decorators in output (for debugging)
  keepDecorators: false,

  // Process JavaScript files (not just TypeScript)
  processJavaScript: false
})

Option Reference

OptionTypeDefaultDescription
keepDecoratorsbooleanfalseKeep decorators in output
processJavaScriptbooleanfalseProcess <script> blocks without lang="ts"

How It Works

The preprocessor:

  1. Intercepts <script lang="ts"> blocks in .svelte files
  2. Checks for @derive decorators (skips files without them)
  3. Expands macros using the native Macroforge binary
  4. Returns the transformed code for Svelte compilation
Tip
Files without @derive decorators are passed through unchanged with zero overhead.

SvelteKit Integration

For SvelteKit projects, you can use both the preprocessor (for .svelte files) and the Vite plugin (for standalone .ts files):

svelte.config.js
// svelte.config.js
import { macroforgePreprocess } from '@macroforge/svelte-preprocessor';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

export default {
  preprocess: [
    macroforgePreprocess(),
    vitePreprocess()
  ]
};
vite.config.ts
// vite.config.ts
import macroforge from '@macroforge/vite-plugin';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    macroforge(),  // For .ts files
    sveltekit()
  ]
});

Using with Vitest

The preprocessor works seamlessly with Vitest for testing Svelte components:

vitest.config.ts
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import { sveltekit } from '@sveltejs/kit/vite';
import { svelteTesting } from '@testing-library/svelte/vite';
import macroforge from '@macroforge/vite-plugin';

export default defineConfig({
  plugins: [
    macroforge(),
    sveltekit(),
    svelteTesting()
  ],
  test: {
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,ts}']
  }
});

Svelte 5 Runes Compatibility

The preprocessor is fully compatible with Svelte 5 runes ($state, $derived, $props, etc.). Files using runes but without @derive decorators are skipped entirely.

<script lang="ts">
  // Runes work normally
  let count = $state(0);
  let doubled = $derived(count * 2);

  // Macros expand correctly
  /** @derive(Debug) */
  class Counter {
    value: number;
    constructor(value: number) {
      this.value = value;
    }
  }
</script>