JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://rangy.googlecode.com/svn/trunk/dev/rangy-core.js"></script>
<script src="http://rangy.googlecode.com/svn/trunk/dev/rangy-textrange.js"></script>
<p>
    source:
    <span contenteditable=true id="source" class="editable">testing...</span>
<p>
    <span contenteditable=true id="foo" class="editable letter-container target"></span>
</p>

CSS

.red {color: red;}
.blue{color: blue;}
.editable {
    border: 1px solid black;
    border-radius: 5px;
    padding: 5px;
}

.letter {
    
    border: 1px solid #eee;
    border-radius:2px;
    padding: 1px;
}
.letter.new {
    text-shadow: 2px 2px 5px #666;
}
}
/*
.letter.blank:before {
    content: '\200B';
}
.letter.blank:after {
    content: '\200B';
}
*/

JavaScript

function isAlpha(code) { return code>=65 && code<=90; }
function isMovement(code) { return code>=37 && code <=40; }
function isModifier(code) { return (code>=16 && code <=20) || code==91; }
function isDeletion(code) { return code==8 || code==46; }

function letterHTML(c) {
    console.log("making letter for char " + c);
    return "<span class='letter'>"+c+"</span>";
}
function makeNewLetter(c) { if (!c) c=''; return $(letterHTML(c)).addClass('new'); }
function makeBlankLetter() {return makeNewLetter('&#8203;');}
function parentLetter(node) {
    var letter = node;
    while (letter.nodeType != 6
            && letter.tagName !== "SPAN"
            && letter.parentNode)
        letter = letter.parentNode;
    if (letter.className.split(' ').indexOf('letter')<0)
        return null;
    return letter;
}
function updateFields() {
    var source = $('#source').text();
    var lettersHTML = source.split('')
        .map(letterHTML)
        .join('');
    $('.editable').empty().append(lettersHTML);
    $('span:even',$('#foo')).addClass('red');
    $('span:odd',$('#foo')).addClass('blue');
}

$('#source').keydown(function($e){
    if ($e.which==13) {
        updateFields();
        $e.preventDefault();
    }
});

function downHandler($e) {
    console.log("which: " + $e.which);
    if (isMovement($e.which) || isModifier($e.which) || isDeletion($e.which))
        return;
    var sel = rangy.getSelection();
    var r = sel.getRangeAt(0).cloneRange();
    var anc = r.commonAncestorContainer;
    var fN = sel.focusNode;
    if (anc.nodeType == 3) {
        console.log("focusing text node, text = " + anc.textContent);
        var parent = parentLetter(fN);
        if (parent) {
            console.log("offset: " + sel.focusOffset);
            var $parent = $(parent);
            if ($parent.hasClass('new')) {
                console.log("already in new letter");
            }
            else {
                var $newLetter = makeBlankLetter();
                if...