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 =...