Files
OpenOPC/opc/plugins/office_ui/frontend_src/lib/sessionTitle.ts
T
2026-07-01 17:56:31 +08:00

67 lines
1.9 KiB
TypeScript

function isCjkCodePoint(codePoint: number): boolean {
return (
(codePoint >= 0x3400 && codePoint <= 0x4dbf)
|| (codePoint >= 0x4e00 && codePoint <= 0x9fff)
|| (codePoint >= 0xf900 && codePoint <= 0xfaff)
|| (codePoint >= 0x3040 && codePoint <= 0x30ff)
|| (codePoint >= 0xac00 && codePoint <= 0xd7af)
)
}
function isCjkChar(ch: string): boolean {
const codePoint = ch.codePointAt(0)
return typeof codePoint === 'number' && isCjkCodePoint(codePoint)
}
function isWordChar(ch: string): boolean {
return !isCjkChar(ch) && /^[\p{L}\p{N}_]$/u.test(ch)
}
export function compactSessionTitle(input: string, maxUnits = 10, fallback = 'New Chat'): string {
const text = String(input || '').replace(/\s+/g, ' ').trim()
if (!text || maxUnits <= 0) return fallback
let units = 0
let index = 0
let cutIndex = text.length
while (index < text.length) {
const codePoint = text.codePointAt(index)
if (typeof codePoint !== 'number') break
const ch = String.fromCodePoint(codePoint)
if (/\s/.test(ch)) {
index += ch.length
continue
}
if (isCjkChar(ch)) {
units += 1
index += ch.length
if (units === maxUnits) {
cutIndex = index
break
}
continue
}
if (isWordChar(ch)) {
while (index < text.length) {
const innerCodePoint = text.codePointAt(index)
if (typeof innerCodePoint !== 'number') break
const innerChar = String.fromCodePoint(innerCodePoint)
if (!isWordChar(innerChar)) break
index += innerChar.length
}
units += 1
if (units === maxUnits) {
cutIndex = index
break
}
continue
}
index += ch.length
}
const compact = text.slice(0, cutIndex).trim() || fallback
const hasMoreUnits = Array.from(text.slice(cutIndex)).some(ch => isCjkChar(ch) || isWordChar(ch))
return hasMoreUnits ? `${compact}...` : compact
}