JSX adaptation as a template system for non-React projects. Allowing to use JSX as a template everywhere adopting IDE's JSX highlight and formatting features.
Transforming JSX:
class MyElement { render() { let title = "Hello World!"; return <div>{title}</div>; } }
Into this:
class MyElement { render() { let title = "Hello World!"; return `<div>${title}</div>`; } }
Also by default transforms JSX html attributes:
class MyElement { render() { let myClass = "action"; return <label className={myClass} htmlFor="button"></label>; } }
Into regular html:
class MyElement { render() { let myClass = "action"; return `<label class="${myClass}" for="button"></label>`; } }
npm i stringify-jsx
stringifyJsx('let title = "Hello World!";let html = <div>{title}</div>;').code // let title = "Hello World!";let html = `<div>${title}</div>`;
stringifyJsx('<div></div>', { // Preserve whitespaces between tags, default => false preserveWhitespace: false, // Custom attributes replacement functionality customAttributeReplacements: {}, customAttributeReplacementFn: void 0 }, { /* babel options */ })
Read more about babel configuration.
Pass customAttributeReplacements or customAttributeReplacementFn to options to adjust replacements. If customAttributeReplacementFn is passed customAttributeReplacements is ignored.
stringifyJsx('<div className="myClass" value="hello world!"></div>', { customAttributeReplacements: { 'value': 'data-value' } }).code // `<div class="myClass" data-value="hello world!"></div>`;
stringifyJsx('<div className="myClass" value="hello world!"></div>', { customAttributeReplacementFn: (nodePath, defaultReplacement) => { if (defaultReplacement) { return defaultReplacement; } return 'x-' + nodePath.node.name; } }).code // `<div class="myClass" x-value="hello world!"></div>`
nodePath is a @babel/traverse's path.
defaultReplacement is a default transformation (such as className => class, htmlFor => html).
Code and source maps are being generated by @babel/generator. By default source map generation is turned off, to turn it on additional option should be provided:
stringifyJsx('let title = "Hello World!";let html = <div>{title}</div>;', {}, { sourceMaps: 'inline' }).code // let title = "Hello World!"; // let html = `<div>${title}</div>`; // //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVua25vd24iXSwibmFtZXMiOlsidGl0bGUiLCJodG1sIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxLQUFLLEdBQUcsY0FBWjtBQUEyQixJQUFJQyxJQUFJLHdCQUFSIiwic291cmNlc0NvbnRlbnQiOlsibGV0IHRpdGxlID0gXCJIZWxsbyBXb3JsZCFcIjtsZXQgaHRtbCA9IDxkaXY+e3RpdGxlfTwvZGl2PjsiXX0=
To provide an ability to use stringify-jsx with tagged template literals (and build upon it libraries like lit-html) all function calls that contain JSX markup as argument are being transformed into tagged template literals.
This call:
html(<div>JSX Markup!</div>);
Will be transformed to:
html`<div>JSX Markup!</div>`;
If it's necessary to pass string transformed from JSX as function argument - assign JSX to a variable first:
const markup = <div>JSX Markup!</div>; html(markup);
So function call in resulting code will remain unchanged:
const markup = `<div>JSX Markup!</div>`; html(markup);
Due to support of tagged template literals and custom attribute replacements this tool can be used together with lit-html. Explore example project for more information.
- Does not modify self-closing tags
The core of stringify-jsx was moved to babel-plugin-transform-stringify-jsx. If inline usage is not necessary please consider using combination babel + babel-plugin-transform-stringify-jsx. Explore example project.
- Babel plugin
- Tests (babel-plugin contains core so tests are located there)
- Typescript