JSFiddle - React, Tailwind, and code Playground

by ninty9notout

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.2.0/handlebars.min.js"></script>
<section class="section">
    <h2 class="section__title">Template</h2>

    {{#if GermanNumbers}}
        <p>Counting to 10 in German:</p>
        <ul>
            {{#each GermanNumbers}}
                <li>{{this}}</li>
            {{/each}}
        </ul>
    {{/if}}

    {{#if GermanNumbers}}
        <p>Counting to 5 in German:</p>
        <ul>
            {{#each (limit GermanNumbers 5)}}
                <li>{{@index}} => {{this}}</li>
            {{/each}}
        </ul>
    {{/if}}

    {{#if Person}}
        <p>A person called {{Person.First}} {{Person.Last}}.</p>
    {{/if}}

    {{#with Person}}
        <p>This is {{{First}}}s greatest idea!</p>
    {{/with}}

    {{#with (last GermanNumbers)}}
        <p>{{this}}</p>
    {{/with}}

    {{#if Button}}{{#with Button}}
        <p><a href="{{Link}}" title="{{att Title}}">{{{Title}}}</a></p>
    {{/with}}{{/if}}
</section>

JavaScript

const template = document.querySelector('.section').innerHTML;

const { Exceptions, createFrame } = Handlebars;

Handlebars.registerHelper('limit', function (array, limit) {
	if (Handlebars.Utils.isFunction(array)) {
    	array = array.call(this);
    }

	if (Handlebars.Utils.isArray(array)) {
        return array.slice(0, limit);
    }

	return [];
});

Handlebars.registerHelper('first', function (array) {
	if (Handlebars.Utils.isFunction(array)) {
    	array = array.call(this);
    }

	if (Handlebars.Utils.isArray(array)) {
        return array[0];
    }

	return null;
});

Handlebars.registerHelper('last', function (array) {
	if (Handlebars.Utils.isFunction(array)) {
    	array = array.call(this);
    }

	if (Handlebars.Utils.isArray(array)) {
        return array[array.length - 1];
    }

	return [];
});

Handlebars.registerHelper('att', function (str) {
	return Handlebars.Utils.escapeExpression(str);
});

Handlebars.registerHelper('each', function (context, options) {
    if (!options) {
		throw new Exception('Must pass iterator to #each');
	}

	let
    	fn = options.fn
    	inverse = options.inverse,
        i = 0,
        ret = '',
        data = null;

	if (Handlebars.Utils.isFunction(context)) {
    	context = context.call(this);
	}

	if (options.data) {
		data = createFrame(options.data);
    }

	function execIteration(field, index, last) {
        if (data) {
            data.key = field;
            
            data.index = index;
            
            data.first = index === 0;
            
            data.last = !!last;
            
            data.firstlast = () => {
            	if (data.first && data.last) {
                    return 'first last';
                }

                if (data.first) {
                    return 'first';
                }

                if (data.last) {
                    return 'last';
                }

                return null;
            }

            data.middle = !data.first &&...