Character codes in typed text; the site and relay at app.kokkoja.com

With the Text tool, Klammertext's codes give letters a keyboard lacks:
^o" is ö, ^s^ ß, ^a1 ā, ^130ED^ a code point of 4 to 6 digits,
^9053 53EF^ a sequence, ^^ a caret, replaced as each code is completed.
The public site and relay moved to app.kokkoja.com; the old name
redirects.  The Markdown documentation is withdrawn from the release
while it is converted to Klammertext; the README's links to it are
stale until then.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ackandClaude Fable 5.1 committed 2026-10-13 20:40:09 +02:00
1 parent 34ca33d365
commit 89b4a41b2a
15 files changed
+364 -1273

No files matched your search

+32 -1
View File
@@ -9,6 +9,7 @@
* shows it; everyone else sees it drawn, updated at every keystroke.
*/
import { codeAtEnd } from './character_codes.js';
import { randomId } from './crypto.js';
import { textBounds } from './page_model.js';
import { TEXT_FRAME_WIDTH, TEXT_MARK } from './page_file.js';
@@ -51,7 +52,13 @@ export class TextEditor {
this.field.className = 'text_field';
this.field.spellcheck = false;
this.field.hidden = true;
this.field.addEventListener('input', () => this.changed());
/** True while a character code is being replaced in the field. */
this.replacing = false;
this.field.addEventListener('input', () => {
if (this.replacing) return;
this.replaceCode();
this.changed();
});
this.watchForHold();
this.field.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
@@ -231,6 +238,30 @@ export class TextEditor {
return block;
}
/**
* The text before the caret ends with one of Klammertext's character
* codes (character_codes.js): replace it by the character it stands
* for. Done through the browser's own editing command so that its
* undo history survives (assigning the field's value would discard
* it); the command fires an input event of its own, ignored here.
*/
replaceCode() {
const field = this.field;
const caret = field.selectionStart;
if (caret !== field.selectionEnd) return;
const code = codeAtEnd(field.value.slice(0, caret));
if (!code) return;
field.setSelectionRange(caret - code.length, caret);
this.replacing = true;
try {
if (!document.execCommand('insertText', false, code.character)) {
field.setRangeText(code.character, caret - code.length, caret, 'end');
}
} finally {
this.replacing = false;
}
}
/** The text, position or width changed: lay it out and tell the page. */
changed() {
const block = this.block;