JSFiddle - React, Tailwind, and code Playground
by Jason Miller
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify.min.js"></script>
<textarea id="input"></textarea>
<h4>Output:</h4>
<pre id="out"></pre>
<h4>Beautified:</h4>
<pre id="beautified"></pre>
<pre id="log"></pre>
SCSS
html, body { height:100%; margin:0; overflow:visible; }
body { padding-bottom:90vh; }
pre { margin:0; padding:10px; overflow:auto; }
h4 { margin:0; padding:10px 5px 0; }
#input {
box-sizing: border-box;
padding: 5px;
margin: 5px;
width: calc(100% - 10px);
height: 11em;
border: 1px solid #aaa;
font: 13px hack,'Source Sans Pro',menlo,monospace,courier;
white-space: pre;
}
#log {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
max-height: 40vh;
background: #f4f4f4;
border-top: 1px dashed #999;
color: #977;
transition: all 500ms ease;
}
#log:empty {
opacity: 0;
}
JavaScript
function transpileLite(code, C) {
return (C=0),code.replace(/(^\s*|\n\s*)(static\s+)?((?:async\s+)?)((?:[sg]et\s+)?)((?:\*\s*)?)([a-zA-Z0-9$_]+)\(([^()]*?)\)\s*\{/g, (s, out, isStatic, async, desc, gen, name, args) => {
let id = '', ctx = isStatic ? 'this' : 'this.prototype';
if (desc) out += `Object.defineProperty(${ctx},'${name}',{${desc}:${id=(' $t'+C++)}});`;
else out += `${ctx}.${name}=`;
return out + `${async}function${gen}${id}(${args}){`;
}).replace(/class\s+([a-zA-Z0-9$_]+)?\s*\{/g, (s, n) =>
`$t${C}.call(${n||'c'});function ${n||'c'}(){var x=${n||'c'}.prototype.constructor;if(x&&x!=${n||'c'})return x.apply(this,arguments)}function $t${C++}(){`
).replace(/(^|\s|;)(?:let|const)(\s)/gm, '$1var$2');
}
input.value = `
class Foo {
constructor(a, b) {
console.log(a, b)
this.a = a
this.b = b
}
static get properties() { return [1,2,3] }
render() {
return ['stuff', Foo.properties, this.a + this.b]
}
}
Foo
`.trim();
const now = typeof performance==='object' && performance.now ? performance.now.bind(performance) : Date.now.bind(Date);
input.oninput = () => {
let originalCode = input.value;
let startTime = now();
let code = transpileLite(originalCode);
let elapsed = now() - startTime;
out.textContent = code;
beautified.textContent = js_beautify(code);
let orig;
try { String.asdfasdf() } catch(e) {
orig = e.stack.match(/:(\d+):(\d+)\)/)[1];
}
try {
let ret = eval(code);
console.log('eval return value: ', ret);
log.textContent = `✅ compiled in ${(elapsed*1000).toPrecision(4)} µs
static:\n ${Object.keys(ret).map(k=>k+': '+typeof ret[k]).join('\n ')}
proto:\n ${Object.keys(ret.prototype).map(k=>k+': '+typeof ret.prototype[k]).join('\n ')}
new Foo(): ${new ret('a','b')}
new Foo('a','b').render(): ${JSON.stringify(new ret('a','b').render())}
`.replace(/^\t+/gm,'');
} catch (e) {
let n = e.stack.match(/:(\d+):(\d+)\)/);
let line = n[1]-orig-4, offset = n[2]|0;
log.textContent =...