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>
    without whitespace:
    <span contenteditable=true id="foo" class="editable target"></span>
    (doesn't work at all)
</p>
<p>
    with whitespace:
    <span contenteditable=true id="bar" class="editable target"></span>
    (works, sort of)
</p>

CSS

.red {color: red;}
.blue{color: blue;}
.editable {
    border: 1px solid black;
    border-radius: 5px;
    padding: 5px;
}
.letter {
    border: 1px solid #aaa;
    border-radius:2px;
    background-color: #eee;
    margin: 2px;
    padding: 2px;
}

JavaScript

function isAlpha(code) { return code>=65 && code<=90; }
function newLetterHTML(c) {
    return "<span class='letter'>"+c+"</span>";
}
function newLetter(c) { return $(newLetterHTML(c)); }
function updateFields() {
    var source = $('#source').text();
    var lettersHTML = source.split('').map(newLetterHTML).join('');
    $('.editable').empty().append(lettersHTML);
    $('span:even',$('#foo')).addClass('red');
    $('span:odd',$('#foo')).addClass('blue');
    $('span:even',$('#bar')).addClass('blue');
    $('span:odd',$('#bar')).addClass('red');
}

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

var $newChar = null;

function handler(placeholder) { return function($e){
    if (!isAlpha($e.which))
        return;
    var sel = rangy.getSelection();
    if (sel.isCollapsed) {
        var parentElement = sel.focusNode.parentElement;
        var offset = sel.focusOffset;
        var r = sel.getRangeAt(0).cloneRange();
        r.selectNode(parentElement);
        r.collapse(offset==0);
        $newChar = newLetter(placeholder);
        r.insertNode($newChar[0]);
        //$newChar.insertAfter($(parentElement));
        r.selectNode($newChar[0]);
        r.collapse(false);
        sel.setSingleRange(r);
    }
}}

$('#foo').keydown(handler(''));
$('#bar').keydown(handler(' '));

updateFields();