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

@shadow-js/compiler

v0.2.0

Published

JSX compiler and transforms for ShadowJS

Readme

ShadowJS Compiler

npm version TypeScript License: MIT

The ShadowJS JSX compiler that transforms JSX code into Shadow-compatible reactive expressions. This compiler enables Shadow's fine-grained reactivity by automatically wrapping JSX expressions in reactive functions.

✨ Features

  • 🎯 JSX Transformation: Converts JSX to reactive expressions automatically
  • ⚡ Compile-time Optimization: Optimizes JSX at build time
  • 🎨 React-like Syntax: Familiar JSX syntax with reactive enhancements
  • 🔧 TypeScript Support: Full TypeScript and TSX compilation
  • 📦 Zero Runtime: All transformations happen at compile time
  • 🎭 Control Flow Enhancement: Special handling for Show, Match, For components
  • 🎯 Ref Handling: Automatic ref assignment functions
  • 🎨 Style Reactivity: Makes style objects reactive

📦 Installation

npm install @shadow-js/compiler

Usually used together with the Vite plugin:

npm install @shadow-js/compiler @shadow-js/vite

🚀 Quick Start

The compiler is typically used through the Vite plugin, but can also be used directly:

import { transformSource } from "@shadow-js/compiler";

const jsxCode = `
  const App = () => (
    <div>
      <Show when={count() > 0} fallback={<div>No items</div>}>
        <div>Count: {count()}</div>
      </Show>
    </div>
  );
`;

const transformedCode = transformSource(jsxCode);
console.log(transformedCode);

🎯 How It Works

The compiler transforms JSX in two main phases:

Phase 1: Arrow Function Transformations

Transforms JSX in arrow function bodies:

// Input
const App = () => <div>{count()}</div>;

// Output
const App = () => <div>{() => count()}</div>;

Phase 2: Return Statement Transformations

Transforms JSX in return statements:

// Input
function App() {
  return <div>{items.length}</div>;
}

// Output
function App() {
  return <div>{() => items.length}</div>;
}

🔧 API Reference

Main Functions

| Function | Description | | ------------------------------------ | ---------------------------------------------------------- | | transformSource(code) | Transform JSX source code to Shadow-compatible expressions | | transformArrowImplicitBodies(code) | Transform JSX in arrow function implicit bodies | | transformAllReturnParens(code) | Transform JSX in return statement parentheses |

Utility Functions

| Function | Description | | ---------------------------------------- | -------------------------------------- | | applyJsxTransforms(jsxContent) | Apply JSX-specific transformations | | findMatching(code, start, open, close) | Find matching brackets in code | | hasJsxTag(code) | Check if code contains JSX tags | | isFunction(code) | Check if code is a function expression |

🎯 Transformation Examples

Basic Expression Wrapping

// Input
<div>Hello {name}</div>

// Output
<div>Hello {() => name}</div>

Control Flow Enhancement

// Input
<Show when={count > 0}>
  <div>Count: {count}</div>
</Show>

// Output
<Show when={() => count > 0}>
  <div>Count: {() => count}</div>
</Show>

Ref Handling

// Input
<div ref={myRef} />

// Output
<div ref={(el) => myRef = el} />

Style Object Reactivity

// Input
<div style={{ color: "red" }} />

// Output
<div style={() => ({ color: "red" })} />

For Loop Enhancement

// Input
<For each={items}>
  {(item) => <li>{item.name}</li>}
</For>

// Output
<For each={() => items}>
  {(item) => <li>{() => item.name}</li>}
</For>

🏗️ Architecture

The compiler consists of several transformation modules:

1. Source Transformation (transformSource.ts)

Main entry point that orchestrates all transformations:

  • Coordinates arrow function and return statement processing
  • Handles error reporting and recovery
  • Provides the public API

2. Arrow Function Processing (transformArrowImplicitBodies.ts)

Handles JSX in arrow function bodies:

  • Uses simple lexer to skip strings and comments
  • Finds arrow functions with implicit JSX bodies
  • Applies JSX transformations to function bodies

3. Return Statement Processing (transformAllReturnParens.ts)

Handles JSX in return statements:

  • Finds return ( statements
  • Applies transformations to JSX content
  • Handles nested function contexts

4. JSX Transformations (applyJsxTransforms.ts)

Core JSX transformation logic:

  • Expression wrapping: Makes child expressions reactive
  • Attribute processing: Handles special attributes (ref, style, when, etc.)
  • Recursive processing: Handles nested JSX and function expressions
  • String/comment handling: Preserves code structure

5. Utility Functions

Supporting utilities for code analysis:

  • Bracket matching: Find matching parentheses, braces, brackets
  • JSX detection: Identify JSX tags in code
  • Function detection: Identify function expressions
  • Reference checking: Identify bare references vs. expressions

🔧 Advanced Usage

Custom Transformations

You can extend the compiler by creating custom transformations:

import { applyJsxTransforms } from "@shadow-js/compiler";

function customTransform(jsxContent: string): string {
  // Apply built-in transformations first
  let result = applyJsxTransforms(jsxContent);

  // Add custom transformations
  result = result.replace(/@custom/g, "customTransform");

  return result;
}

Integration with Build Tools

Vite Plugin Integration

The recommended way to use the compiler:

// vite.config.ts
import { defineConfig } from "vite";
import shadow from "@shadow-js/vite";

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

Manual Integration

For custom build setups:

import { transformSource } from "@shadow-js/compiler";

export function shadowPlugin() {
  return {
    name: "shadow-compiler",
    transform(code, id) {
      if (id.endsWith(".tsx") || id.endsWith(".jsx")) {
        return transformSource(code);
      }
    },
  };
}

Error Handling

The compiler provides detailed error messages:

try {
  const transformed = transformSource(sourceCode);
  // Use transformed code
} catch (error) {
  console.error("ShadowJS compilation failed:", error.message);
  // Handle compilation error
}

🎯 Best Practices

Code Organization

  • Keep JSX expressions simple and readable
  • Use meaningful variable names in reactive expressions
  • Avoid complex logic in JSX expressions

Performance Considerations

  • The compiler runs at build time, no runtime overhead
  • Transformations are optimized for minimal code generation
  • Use build-time analysis for optimal results

Debugging

  • Check transformed output when debugging reactivity issues
  • Use source maps for accurate error locations
  • Test transformations with simple examples first

🔍 Compiler Options

While the compiler currently has minimal configuration, future versions may include:

  • Transformation modes: Different levels of reactivity
  • Custom attribute handling: Support for custom JSX attributes
  • Optimization levels: Different compilation strategies
  • Source map generation: Enhanced debugging support

🧪 Testing

Testing Transformations

import { transformSource } from "@shadow-js/compiler";

describe("ShadowJS Compiler", () => {
  test("transforms basic JSX expressions", () => {
    const input = "<div>{name}</div>";
    const output = transformSource(input);
    expect(output).toContain("{() => name}");
  });

  test("handles control flow components", () => {
    const input = "<Show when={count > 0}><div>Count</div></Show>";
    const output = transformSource(input);
    expect(output).toContain("when={() => count > 0}");
  });
});

📊 Performance

Compilation Speed

  • Fast parsing: Simple lexer for string/comment skipping
  • Efficient transformations: Targeted regex replacements
  • Minimal passes: Usually 1-2 transformation passes

Bundle Impact

  • Zero runtime: All transformations happen at build time
  • Small overhead: Minimal additional code generated
  • Tree-shaking friendly: Generated code works with tree-shaking

🐛 Troubleshooting

Common Issues

  1. Expression not reactive: Check if expression is properly wrapped

    // Wrong
    <div>{count + 1}</div>
    
    // Right
    <div>{() => count + 1}</div>
  2. Control flow not working: Ensure conditions are wrapped in functions

    // Wrong
    <Show when={count > 0}>
    
    // Right
    <Show when={() => count > 0}>
  3. Ref not working: Check ref assignment function syntax

    // Wrong
    <div ref={myRef} />
    
    // Right - compiler transforms this automatically
    <div ref={myRef} />
    // Becomes: <div ref={(el) => myRef = el} />

Debug Mode

Enable debug mode for detailed transformation logs:

// Enable in development
process.env.SHADOW_DEBUG = "true";

const transformed = transformSource(sourceCode);
console.log("Transformation result:", transformed);

📚 Examples

See the examples documentation for:

  • Basic transformation patterns
  • Advanced usage scenarios
  • Integration examples
  • Common transformation patterns

🤝 Contributing

We welcome contributions! See the Contributing Guide for details.

Areas for contribution:

  • New transformation patterns
  • Performance optimizations
  • Additional utility functions
  • Better error messages
  • Enhanced TypeScript support

📄 License

MIT License - see LICENSE for details.

📞 Support


Built by Jehaad AL-Johani for compile-time JSX transformations.