Skip to content

Instantly share code, notes, and snippets.

@roryabraham
Created May 12, 2023 00:42
Show Gist options
  • Save roryabraham/7d81f8f71add386555fcb7b2682c142a to your computer and use it in GitHub Desktop.
Save roryabraham/7d81f8f71add386555fcb7b2682c142a to your computer and use it in GitHub Desktop.
contenteditable POC
body {
font-family: sans-serif;
}
#editor {
background-color: #f0f0f0;
min-height: 20rem;
padding: 1rem;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script defer src="index.js"></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="editor" contenteditable></div>
</body>
</html>
const markdownRegex = /(\*.+?\*)/g
document.addEventListener('DOMContentLoaded', () => {
const editor = document.getElementById('editor');
editor.addEventListener('input', () => {
const textContent = editor.textContent ?? '';
const htmlContent = textContent.replaceAll(markdownRegex, match => `<strong>${match}</strong>`);
const selection = document.getSelection();
const prevCaretPos = selection.anchorOffset;
editor.innerHTML = htmlContent;
const range = document.createRange();
let charCount = 0;
for (let nodeIndex = 0; nodeIndex < editor.childNodes.length; nodeIndex++) {
let node = editor.childNodes[nodeIndex];
for (let caretPos = 0; caretPos <= node.textContent.length; caretPos++) {
if (charCount === prevCaretPos) {
if (node.nodeName !== '#text') {
node = node.firstChild;
caretPos += 1;
}
range.setStart(node, caretPos);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
break;
}
charCount++;
}
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment