Wörter und Zeichen in Rich Text zählen: Emoji, CJK und Eingabelimits

Ergänzen Sie RichTextEditor um einen anwendungsspezifischen Zähler, ohne das Dokument bei jedem Tastendruck zu ersetzen. Die Anleitung enthält ein getestetes Modul und ein vollständiges Browserbeispiel, das eine Grenze von 200 Zeichen prüft und überlange Entwürfe erhält.
Festlegen, was ein Zeichen ist
Die JavaScript-Zeichenfolgenlänge zählt UTF-16-Codeeinheiten. Ein Familien-Emoji oder ein Buchstabe mit kombiniertem Akzent kann mehrere Einheiten enthalten und wie ein Zeichen aussehen. Dieses Beispiel zählt Graphemcluster mit Intl.Segmenter, einschließlich Leerzeichen und Zeilenumbrüchen, und normalisiert CRLF oder CR zu LF.
Als Wörter zählen die für das ausdrücklich gewählte Dokumentgebietsschema erkannten wortähnlichen Segmente. Das verspricht keine Übereinstimmung mit Microsoft Word, der eingebauten Editorstatistik, SMS-Abrechnung oder sozialen Netzwerken. Trennen Sie diese Regeln und erläutern Sie den Autoren die verwendete Einheit.
Zählmodul herunterladen
Laden Sie das Textstatistikmodul herunter. Es erwartet Klartext statt HTML. Lesen Sie das Dokument mit getPlainText(), statt das von getHTMLCode() gelieferte HTML zu zählen. Tags sind keine Wörter; Absatzgrenzen und Marker Ihrer Textextraktion brauchen eigene Tests.
Das Modul benötigt Segmentierungsunterstützung im Browser oder Server. Fehlt sie, meldet es einen Fehler, statt still auf eine Trennung an Leerzeichen umzuschalten, die für Chinesisch und Japanisch ungeeignet ist.
Zähler und Prüfung beim Absenden verbinden
Stellen Sie Editor-Dateien und Modul über Ihre Anwendung bereit. Das Beispiel prüft lediglich eine Übermittlung; es sendet und speichert keine Inhalte. Während des Tippens wird die Zählung verzögert zusammengefasst, beim Absenden jedoch unmittelbar neu berechnet. Eine Ablehnung verändert den Entwurf nicht.
<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css">
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<style>body{font:16px/1.6 system-ui,sans-serif;max-width:960px;margin:24px auto;padding:0 16px}button{min-height:44px;padding:8px 16px}</style>
<h1>Word and character counter</h1>
<form id="message-form">
<div style="max-width:100%;overflow-x:auto"><div id="editor"></div></div>
<p id="counter"></p>
<p>Limit: 200 graphemes, including spaces and line breaks. This demo does not save.</p>
<button type="submit">Check submission</button>
<p id="result" role="status" aria-live="polite"></p>
</form>
<script type="module">
import { countText } from "/js/text-metrics.mjs";
const editor = new RichTextEditor("#editor", { toolbar: "full", height: "320px", showStatistics: false });
editor.setHTMLCode("<p>Write a short note.</p>");
const LOCALE = "en"; // Choose the document language, not necessarily the UI language.
const LIMIT = 200;
const counter = document.getElementById("counter");
const result = document.getElementById("result");
function updateCount() {
try {
const metrics = countText(editor.getPlainText(), LOCALE);
counter.textContent = metrics.words + " words · " + metrics.characters +
" / " + LIMIT + " characters (graphemes)";
return metrics;
} catch {
counter.textContent = "Counter unavailable. Check locale and Intl.Segmenter support.";
return null;
}
}
let timer, checkedText = null;
editor.attachEvent("change", () => {
if (editor.getPlainText() !== checkedText) result.textContent = "";
clearTimeout(timer);
timer = setTimeout(updateCount, 200);
});
document.getElementById("message-form").addEventListener("submit", event => {
event.preventDefault();
clearTimeout(timer);
const metrics = updateCount(); // Do not trust a delayed displayed count.
checkedText = editor.getPlainText();
if (!metrics) { result.textContent = "Cannot validate this count."; return; }
if (metrics.characters > LIMIT) {
result.textContent = "Too long. Shorten the draft; your content is still here.";
editor.focus();
return;
}
result.textContent = "Within limit. Ready for your server-side validation.";
// Add your authenticated save here. This demo sends no request.
});
updateCount();
// Exposed only so you can inspect this standalone demo in developer tools:
window.counterDemo = { editor, updateCount };
</script>
Die Richtlinie auf dem Server abgleichen
Wiederholen Sie die Prüfung auf dem Server anhand des übermittelten Dokuments und einer vereinbarten Textextraktion. Vertrauen Sie weder einer mitgesendeten Zahl noch einem zusätzlichen Klartextfeld. Prüfen Sie Berechtigungen, HTML-Bereinigung und Anfragegröße in Bytes unabhängig davon; 200 Grapheme bedeuten kein kleines HTML-Paket.
Nach der Klartextextraktion können Sie das Modul auch in einer modernen Node.js-Anwendung verwenden. Gleichen Sie Normalisierung und Gebietsschema ab und nutzen Sie gemeinsame Testfälle: Unicode- und Segmentierungsdaten können sich zwischen Browser- und Serverversionen unterscheiden. Bei vertraglichen Grenzen wählen und versionieren Sie eine maßgebliche serverseitige Richtlinie.
Sprachen und Eingabemethoden testen
- Prüfen Sie leeren Text, Leerzeichen, Absatzumbrüche und CRLF.
- Testen Sie Familien-Emoji, Flaggen und kombinierte Akzente. Teilen oder kürzen Sie sie nicht, um das Limit einzuhalten.
- Verwenden Sie echte chinesische und japanische Dokumente, statt Worttrennung an Leerzeichen vorauszusetzen.
- Fügen Sie überlangen Inhalt ein und senden Sie sofort ab, noch bevor sich die Anzeige aktualisiert. Die Prüfung muss ablehnen und den Entwurf bewahren.
- Löschen Sie genug Text und prüfen Sie die erneute Übermittlung. Testen Sie IME-Komposition und Rückgängig in Ihrer Integration.
Der Zähler erzwingt keine Pflichtfeldregeln und entscheidet nicht über reine Bilddokumente. Schreiben Sie dafür nicht ständig das Editor-HTML um und blockieren Sie nicht jeden Tastendruck; dies kann Auswahl, Verlauf und IME-Eingaben beschädigen.
Weiterführende Anleitungen
Siehe Klartextextraktion, Formularvalidierung, automatisches Speichern auf dem Server und Entscheidungen zur Wortzählung.