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 placessetAttributesandappendChildrenin 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 -hfor 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.