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:
1 parent
34ca33d365
commit
89b4a41b2a
15 files changed
+364
-1273
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user