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

jsxmin

v3.0.1-jsxish

Published

Minimal jsx templating: no React or other runtime libraries, transpile jsx to plain javascript strings.

Downloads

4

Readme

Heads up! This package (and its subpackages) has recently undergone a significant restructuring and there may be some missing functionality, missing documentation, or all of the above. Generally speaking, it is functional and usable, but stay tuned for continued updates.

jsxmin — minimal jsx templating.

jsxmin allows you to write JSX and transpile it to plain, vanilla javascript without React or any other runtime libraries.

Motivation

JSX provides an intuitive and straightforward syntax that's easy to learn, battle-tested, and capable of scaling to large teams and production implementations. However, there are times when using all of React isn't available on your toolchain or environment, or you may be looking for something that is ultra-portable, or maybe you just want to go back to the old days of simple js templating (🤗).

This project attempts to take JSX syntax and transpile it to plain javascript via template literals and function calls.

Example

A basic example:

const Button = (props) => <button class="btn primary">{props.label || props.children}</button>

Will output:

const Button = (props) => '<button class="btn primary">' + (props.label || props.children) + '</button>';

Which can then be called like this:

console.log(Button({
  label: 'Hello World'
}));
// '<button class="btn primary">Hello World</button>'

Slightly more advanced example using custom elements:

import { Button } from './ui';

class HighFive extends HTMLElement {
  constructor() {
    super();
    this.innerHTML = <Button>🖐</Button>
    this.addEventListener('click', () => {
      console.log('High five!!');
    });
  }
}
customElements.define('high-five', HighFive);

And can be called like this (as a quick example):

<html>
  <body>
    <high-five></high-five> // High five!!
    <script src="..."></script>
  </body>
</html>

Slightly more advanced example in the vein of SPAs:

import { Button } from './ui';

const App = ({name}) => <>
    <p>Hello{name ? ' ' + name : ''}!</p>
    <Button>🖐</Button>
</>

document.body.innerHTML = <App/>

And can be called like this (as a quick example):

<html>
  <body>
    <script src="..."></script>
  </body>
</html>

See tests/test.js for more examples.

API

.transform(source, opts)

Transforms a string with jsx to plain javascript and is the primary function of this library.

source should be a string.

opts is an object with properties as defined below.


.execute(source, opts)

Transform and execute a string with jsx and get the resulting output.

source should be a string.

opts is an object with properties as defined below.

Note: Whatever [valid] JavaScript statement is on the last line is what will be returned. See Dynamic usage example below.

Options

allowReferencedTagsAsFunctions[=true]

Checks if a tag is a function (within the current scope) and, if so, evaluates it and uses its return value as the output.

allowScopedParameterAccess[=false]

Pass along the props (the first parameter) to each subsequent function call.

reactCompat[=true|'strict']

Enables a compatability mode

| Compat Mode | Property | Input | Output | Implemented? | |-------------|---------------------------|----------------------------------------------------------|----------------------------------------|--------------| | all | className | className={{container: true, content: false}} | class="container" | ✔️ | | strict | className | className={{container: true}} | class="[object Object]" | ✔️ | | all | style | style={{color: 'red', height: 10}} | style="color: red; height: 10px;" | ✔️ | | strict | style | style={{color: 'red', height: 10}} | style="color: red; height: 10px;" | ✔️ | | all | any | data-model={{id: 12345}} | data-model="{&quot;id&quot;: 12345}" | ✔️ | | strict | any | data-model={{id: 12345}} | data-model="[object Object]" | ✔️ | | all | dangerouslySetInnerHTML | dangerouslySetInnerHTML={'<a onclick=alert(1)>:)</a>'} | - | 𝘅 | | all | htmlFor | htmlFor="id" | for="id" | ✔️ | | all | selected | selected | selected="selected" | ✔️ | See below for usage examples

Installation

To install and use as a module in your Nodejs/Babel toolchain, run:

npm install jsxmin

Or to install the babel plug-in, run:

npm install babel-plugin-jsxmin

And add this to your Babel configuration:

{
  ...
  plugins:  ['babel-plugin-jsxmin']
  ...
}

See babel-plugin-jsxmin/README for more details.

Direct Usage

Dynamic usage:

const Jsxmin = require('jsxmin');

const tmpl = await Jsxmin.execute(`
    ({name}) => <p>Hello {name || 'world'}</p>
`, {
  // NOTE: these are the default values and are only being passed here for demonstration purposes.
  allowReferencedTagsAsFunctions: true,
  reactCompat: true
});

console.log(tmpl({name: 'Github'})) // '<p>Hello Github</p>'

Build-time usage:


const Jsxmin = require('jsxmin');
const Fs = require('fs');

const source = Fs.readFileSync('./ui.jsx', 'utf-8');
const compiled = await Jsxmin.transform(source);

Fs.writeFileSync('./ui.js', compiled);

Integrations

Security

~~jsxmin does not currently escape or otherwise sanitize user input and thus could be vulnerable to content injection or XSS attacks (or a myriad of other attack vectors).~~ ~~Please ensure all user generated content has been sanitized before passing to any jsxmin compiled template or function. This project should probably not be considered production-ready until then.~~

TODO

  • [x] ~~Finalize the main api (transpileFile vs transpileSource vs run) and add documentation.~~
  • [x] Support compiling jsx as ES modules (specifically importing and exporting)
    • [x] Support ES modules and additional Babel plugins in Fastify and Express plugins
    • [x] Resolve TODO on line 28 of babel-plugin/index.js
  • [x] Support async/await in Fastify and Express plugins
  • [x] Support spread operator for attributes (e.g., <Button {...props}></Button>)
  • [x] Use template literals instead of string literals for everything
  • [ ] Clean up internal directory structure:
    • Make releasing and incrementing on individual packages easier
    • Resolve relative vs absolute package name references
    • Ensure everything is installable and runnable
  • [x] Security and XSS sanitization
  • [ ] Add warnings for unsupported attributes (like className, dangerouslySetInnerHTML, htmlFor, onClick and other event listeners)
  • [ ] Add more examples
    • See tests/test.js for basic and advanced usecases (like partials, control flows, and plugin options)
  • [ ] Add more integrations
  • [x] Add support for including a shared/common util that could do the following:
    • Handle escaping and sanitizing user input
    • Add support for control structures and loops, etc
    • Reduce various manual checks
  • [ ] Support additional syntax via Babel plugin (e.g. @babel/plugin-syntax-decorators)
  • [ ] ...?

License

MIT