This is a fork of NativeJSX for use cases where prototyping on HTMLElement
isn't possible, such as in the Salesforce Lightning Framework. This is accomplised using a window.nativejsx
object. If you cannot pollute the global namespace or are able to use prototypes on HTMLElement
, you should try the original NativeJSX first.
Like the idea of keeping JSX around as a general-purpose templating language? nativejsx is a well-rounded JSX feature subset that makes sense within the realm of JavaScript's native DOM API.
I know. "Why all the words?" Just show you something.
Here's the scenario, Capitan:
function template() {
return (
<div class="btn-group" role="group" aria-label="Basic example">
<button type="button" class="btn btn-secondary" onClick={eventListener}>Left</button>
<button type="button" class="btn btn-secondary" ref={(ref) => this.middleButton = ref}>Middle</button>
<button type="button" class="btn btn-secondary">Right</button>
<button type="button" class="btn btn-secondary" style={{backgroundColor: 'peachpuff'}}>Primary</button>
</div>
);
}
That looks awesome, right? Yeah.
Now we bake it in nativejsx
using nativejsx.parse
:
var nativejsx = require('nativejsx');
nativejsx.parse('dat-btn-group.js', {
declarationType: 'var',
variablePrefix: '$$'
}).then(function(transpiledGoodness) {
console.log(transpiledGoodness);
});
That console.log
reveals the amazing native DOM API output:
function template() {
return function () {
var $$a = document.createElement('div');
$$a.setAttribute('class', 'btn-group');
$$a.setAttribute('role', 'group');
$$a.setAttribute('aria-label', 'Basic example');
var $$b = document.createElement('button');
$$b.setAttribute('type', 'button');
$$b.setAttribute('class', 'btn btn-secondary');
$$b.addEventListener('click', eventListener);
$$a.appendChild($$b);
var $$c = document.createTextNode('Left');
$$b.appendChild($$c);
var $$d = document.createElement('button');
$$d.setAttribute('type', 'button');
$$d.setAttribute('class', 'btn btn-secondary');
$$a.appendChild($$d);
var $$e = document.createTextNode('Middle');
((ref) => this.middleButton = ref)($$e);
$$d.appendChild($$e);
var $$f = document.createElement('button');
$$f.setAttribute('type', 'button');
$$f.setAttribute('class', 'btn btn-secondary');
$$a.appendChild($$f);
var $$g = document.createTextNode('Right');
$$f.appendChild($$g);
var $$h = document.createElement('button');
$$h.setAttribute('type', 'button');
$$h.setAttribute('class', 'btn btn-secondary');
$$h.setStyles({ backgroundColor: 'peachpuff' });
$$a.appendChild($$h);
var $$i = document.createTextNode('Primary');
$$h.appendChild($$i);
return $$a;
}.call(this);
}
- 6.10.0
You have two choices:
- Use a very tiny JavaScript file located in
dist
,nativejsx-prototype.js
. Feel free to include it in your build steps (before any nativejsx-transpiled code runs, of course).
<script type="text/javascript" src="path/to/nativejsx-prototype.js"></script>
// or the minified version
<script type="text/javascript" src="path/to/nativejsx-prototype.min.js"></script>
- Enable inline usage with the API option,
prototypes: 'inline'
. Warning: this placessetAttributes
andappendChildren
in every file that they are needed.
// (String, Object) => Promise => String
parse(fileName, options)
// (String, Object) => String
parseSync(fileName, options)
// String => String
transpile(jsx)
- declarationType:
var
(default),const
, orlet
. - variablePrefix: Any string (defaults to
$$
) you can conjure up that produces a valid JavaScript variable. - prototypes: Either
true
(default) or'inline'
. - acorn: All acorn options are available here. Defaults to
{plugins: {jsx: true}, ecmaVersion: 6, sourceType: 'module'}
.
- Shell Script:
nativejsx path-to-jsx/**/*.jsx [--output ./here]
. (Seenativejsx -h
for examples.) - Webpack: nativejsx-loader.
- Grunt: grunt-nativejsx.
- Gulp: gulp-nativejsx.
More Tests.Hardened Nodal JSXExpressions.Gulp, grunt, and webpack plugins.- Source maps.
- Support SVG elements.
- (Your suggestion.)
- AST: Abstract syntax tree.
- Compositions: These are endgame native DOM ASTs that we plan on swapping with JSX.
- Generators: Barebone AST node types (some are combinations of node types).
- Transformers: Takes compositions and generators and actually completes the swapping.
- Walkers: Sets up the state, allocates variables, and traverses JSXElements to our liking.
appendChildren
helps clean up the mess JSXExpressions (the {} things) leave due to JavaScript's lack of static typing. I can't rightly tell if the expressions your fingers conjure up are going to return JSX, literals, or whatever else.
setAttributes
handles the JSXSpreadAttribute expression that is in the JSX Specification. In other words, <div {...attributes}></div>
, where attributes
is an object containing valid HTML attribute names and values, should just work. There isn't a convenient way to do this with native DOM.
setStyles
takes an Object
that maps keys to HTMLElement.prototype.style
and sets the corresponding value. This is a reimplementation of React's fancy style attribute.
I'm glad you stuck around to ask. Due to the imperative nature of the native DOM API, we're outputting variable allocations – you know, the "$$a" stuff. To avoid variable clobbering, our DOM goodies are tucked away into a JavaScript closure, safe and sound.