nativejsx
JSX to native DOM API transpilation.
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.
Example
Here's the scenario, Capitan:
{ return <div ="btn-group" ="group" ="Basic example"> <button ="button" ="btn btn-secondary" =>Left</button> <button ="button" ="btn btn-secondary" =>Middle</button> <button ="button" ="btn btn-secondary">Right</button> <button ="button" ="btn btn-secondary" =>Primary</button> </div> ;}
That looks awesome, right? Yeah.
Now we bake it in nativejsx
using nativejsx.parse
:
var nativejsx = ; nativejsx;
That console.log
reveals the amazing native DOM API output:
{ return { var $$a = document; $$a; $$a; $$a; var $$b = document; $$b; $$b; $$b; $$a; var $$c = document; $$b; var $$d = document; $$d; $$d; $$a; var $$e = document; thismiddleButton = ref$$e; $$d; var $$f = document; $$f; $$f; $$a; var $$g = document; $$f; var $$h = document; $$h; $$h; $$h; $$a; var $$i = document; $$h; return $$a; };}
IMPORTANT NOTES:
Tested Node Versions
- 6.10.0
Frontend Dependencies
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).
// or the minified version
- Enable inline usage with the API option,
prototypes: 'inline'
. Warning: this placessetAttributes
andappendChildren
in every file that they are needed.
API
// (String, Object) => Promise => String// (String, Object) => String// String => String
Options
- 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'}
.
Build Tools
- Shell Script:
nativejsx path-to-jsx/**/*.jsx [--output ./here]
. (Seenativejsx -h
for examples.) - Webpack: nativejsx-loader.
- Grunt: grunt-nativejsx.
- Gulp: gulp-nativejsx.
Development
Wish List
More Tests.Hardened Nodal JSXExpressions.Gulp, grunt, and webpack plugins.- Source maps.
- Support SVG elements.
- (Your suggestion.)
Terminology
- 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
?
What the heck is 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
?
What the heck is 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
?
What the heck is 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.
Why does it output everything in a closure?
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.