Editor

HTML

<div id="editor" contentEditable="true" oninput="change(this)" spellcheck="false">Try typing something.  All numbers you type should be green.</div>

CSS

#editor {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  padding: 16px;
  outline: none;
  font-family: monospace;
}

#editor .number {
  color: green;
}

JavaScript

function change(element) {
	const text = setCursorMarker(element.innerText, element);
	const html = manipulate(text);
  
  element.innerHTML = html;
  const index = findCursorIndex(element);
  
  document.getSelection().collapse(element, index)
}


function setCursorMarker(text, element) {
	const [pos] = getCaretPosition(element)
  
  console.log(pos)
  
  text = text.slice(0, pos + 1)  + '<span id="caret-position"></span>' + text.slice(pos + 1, text.length);
  
	return text;
}

function findCursorIndex(element) {
	return childIndexInParent(element.children.namedItem('caret-position'))
}

function childIndexInParent(element){
	if (element == null) return 0;

  let i = 0;
  while((element = element.previousSibling) != null) ++i;
  return i;
}

function manipulate(str) {
	str = str.replace(/([0-9])/g, '<span class="number">$1</span>');
  str = str.replace(/(?:\r\n|\r|\n)/g, '<br>');
    
  // your syntax highlighter code...
  
  return str;
}


// Below this line is code from https://stackoverflow.com/a/53128599/10533154
// -------------------------------------

// node_walk: walk the element tree, stop when func(node) returns false
function node_walk(node, func) {
  var result = func(node);
  for(node = node.firstChild; result !== false && node; node = node.nextSibling)
    result = node_walk(node, func);
  return result;
}

// getCaretPosition: return [start, end] as offsets to elem.textContent that
//   correspond to the selected portion of text
//   (if start == end, caret is at given position and no text is selected)
function getCaretPosition(elem) {
  var sel = window.getSelection();
  var cum_length = [0, 0];

  if(sel.anchorNode == elem)
    cum_length = [sel.anchorOffset, sel.extentOffset];
  else {
    var nodes_to_find = [sel.anchorNode, sel.extentNode];
    if(!elem.contains(sel.anchorNode) || !elem.contains(sel.extentNode))
      return undefined;
    else {
      var found = [0,0];
      var i;
      node_walk(elem, function(node) {
        for(i = 0;...