Editor
<pre contenteditable="plaintext-only">. Edits trigger a re-parse; highlights update without mutating the DOM, so the caret stays put.
// Tiny reactive store
class Store {
#state;
#listeners = new Set();
constructor(initial) {
this.#state = initial;
}
get() {
return this.#state;
}
set(next) {
const prev = this.#state;
this.#state = typeof next === 'function' ? next(prev) : next;
if (!Object.is(this.#state, prev)) {
for (const listen of this.#listeners) listen(this.#state, prev);
}
}
subscribe(fn) {
this.#listeners.add(fn);
return () => this.#listeners.delete(fn);
}
}
const counter = new Store(0);
counter.subscribe((next) => console.log('count:', next));
counter.set((n) => n + 1);