🔥 Read this trending post from Hacker News 📖
📂 **Category**:
💡 **What You’ll Learn**:
contenteditable attribute. That attribute has a plaintext-only value that is perfect for code. All content remains within a single text node.
<div
contenteditable="plaintext-only"
autocapitalize="off"
autocorrect="off"
spellcheck="false"
translate="no">
div>
Attributes like spellcheck must be disabled to avoid input latency spikes. Want to guess how many days it took me to discover that fix? Days!
Using contenteditable gives native text selection and undo history etc. So much accessibility goodness is wired up for free by the browser.
The Selection API provides metrics I use to continue rendering a custom text cursor. ::selection is available so I can style that too. I’ve set the native caret-color invisible, which is probably a no-no.
The contenteditable technique is promising but I’ve noticed strange performance issues beyond a certain character count. Chromium browsers perform worse than WebKit and whatever Firefox is now but it’s unpredictable.
Textarea
Instead of plaintext contenteditable would a simple be viable? In short: yes. Turns out a is far more performant for longer text.
In this final demo I’ve added syntax highlighting too.
My original plan was to use custom ::highlight on the contenteditable element. can’t use CSS highlights so a third layer was required. For demo purposes I added some
Edit: I’m told the new OpaqueRange API unlocks custom highlights for — neat!
Edit 2: and the EditContext API improves input.
Too many CSS highlights are another performance bottleneck. A more robust solution would be to use Tree-sitter to generate a syntax tree and walk that to generate highlights for only visible lines. I was hoping to avoid virtualised scrolling entirely but I could improve it using the inverse sticky technique. Or I can go back to contenteditable because the file sizes I’d be editing don’t hit the performance wall.
Anyway, looking good, right?
Looks like 90% of a text editor with 1% of the features. From here it’s pretty straight forward to draw the rest of the owl. I’m tempted to keep drawing but then I think about all the little things like tab indentation. Right now I just hijack the tab key to insert two spaces…
My demos above are unoptimised and far from perfectly accessible but at least I’m not starting from a losing position. Rendering on would be a nightmare.
I’m filing this project away for a rainy day.
JavaScript strings and text ranges work with UTF-16 code units. It’s easy to naively introduce bugs. I’m sure my demos are full of them. I’ll leave with a code example to nerd snipe.
"🍋🟩".length; // 5
[..."🍋🟩"].length; // 3
const segmenter = new Intl.Segmenter("en", ⚡);
[...segmenter.segment("🍋🟩")].length; // 1
💬 **What’s your take?**
Share your thoughts in the comments below!
#️⃣ **#Fine #Ill #build #text #editor #David #Bushell #Web #Dev**
🕒 **Posted on**: 1788345017
🌟 **Want more?** Click here for more info! 🌟
