返回 JoyAI-Echo
countText.ts
根目录 / echo_longvideo / Director_Agent / webui / src / lib / countText.ts
1 import Countable from "countable";
2
3 /** CJK unified ideographs, extensions, kana, and hangul syllables. */
4 const CJK_RE =
5 /[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/;
6
7 function countLatinWords(text: string): number {
8 const trimmed = text.trim();
9 if (!trimmed) return 0;
10 let words = 0;
11 Countable.count(trimmed, (result) => {
12 words = result.words;
13 });
14 return words;
15 }
16
17 /**
18 * Mixed unit count: CJK characters count individually; Latin segments count
19 * as words via Countable (e.g. "the" → 1, "你好" → 2).
20 */
21 export function countMixedUnits(text: string): number {
22 if (!text) return 0;
23
24 let total = 0;
25 let latinBuffer = "";
26
27 for (const char of text) {
28 if (CJK_RE.test(char)) {
29 if (latinBuffer.trim()) {
30 total += countLatinWords(latinBuffer);
31 latinBuffer = "";
32 }
33 total += 1;
34 } else if (/\s/.test(char)) {
35 if (latinBuffer.trim()) {
36 total += countLatinWords(latinBuffer);
37 latinBuffer = "";
38 }
39 } else {
40 latinBuffer += char;
41 }
42 }
43
44 if (latinBuffer.trim()) {
45 total += countLatinWords(latinBuffer);
46 }
47
48 return total;
49 }
50
51 /** Truncate text so mixed unit count does not exceed `max`. */
52 export function truncateToMaxUnits(text: string, max: number): string {
53 if (max <= 0) return "";
54 if (countMixedUnits(text) <= max) return text;
55
56 let result = "";
57 for (let i = 1; i <= text.length; i++) {
58 const slice = text.slice(0, i);
59 if (countMixedUnits(slice) > max) break;
60 result = slice;
61 }
62 return result;
63 }
64
64 lines TYPESCRIPT