mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-21 15:42:19 +02:00
Squash Odysseus development history
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Unicode-aware text statistics shared by source and rich-text documents.
|
||||
|
||||
let _wordSegmenter;
|
||||
let _graphemeSegmenter;
|
||||
|
||||
function _segmenter(granularity) {
|
||||
if (typeof Intl === 'undefined' || typeof Intl.Segmenter !== 'function') return null;
|
||||
try {
|
||||
if (granularity === 'word') {
|
||||
_wordSegmenter ||= new Intl.Segmenter(undefined, { granularity: 'word' });
|
||||
return _wordSegmenter;
|
||||
}
|
||||
_graphemeSegmenter ||= new Intl.Segmenter(undefined, { granularity: 'grapheme' });
|
||||
return _graphemeSegmenter;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function countDocumentWords(value) {
|
||||
const text = String(value ?? '');
|
||||
if (!text.trim()) return 0;
|
||||
const segmenter = _segmenter('word');
|
||||
if (segmenter) {
|
||||
let count = 0;
|
||||
for (const segment of segmenter.segment(text)) {
|
||||
if (segment.isWordLike) count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return (text.match(/[\p{L}\p{N}\p{M}]+(?:['’][\p{L}\p{N}\p{M}]+)*/gu) || []).length;
|
||||
}
|
||||
|
||||
export function countDocumentCharacters(value) {
|
||||
const text = String(value ?? '');
|
||||
const segmenter = _segmenter('grapheme');
|
||||
if (segmenter) return Array.from(segmenter.segment(text)).length;
|
||||
return Array.from(text).length;
|
||||
}
|
||||
|
||||
export function getDocumentStats(value) {
|
||||
const text = String(value ?? '').replace(/\r\n?/g, '\n');
|
||||
const words = countDocumentWords(text);
|
||||
const characters = countDocumentCharacters(text);
|
||||
const charactersNoSpaces = countDocumentCharacters(text.replace(/\s/gu, ''));
|
||||
const lineText = text.replace(/\n+$/u, '');
|
||||
const lines = lineText ? lineText.split('\n').length : 0;
|
||||
return {
|
||||
words,
|
||||
characters,
|
||||
charactersNoSpaces,
|
||||
lines,
|
||||
readingMinutes: words ? Math.max(1, Math.ceil(words / 225)) : 0,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user