new: unicode.visualStrlen

This commit is contained in:
minjaesong
2025-10-04 22:39:17 +09:00
parent 71102f1d70
commit 5c3a3a112c
2 changed files with 24 additions and 27 deletions

View File

@@ -1390,6 +1390,27 @@ unicode.println = (str) => {
unicode.print(str+'\n\n') unicode.print(str+'\n\n')
} }
unicode.strlen = (str) => {
// Convert string to an array of codepoints using spread operator
// This correctly handles surrogate pairs and counts each codepoint as one
return unicode.utf8toCodepoints(str).length
}
unicode.visualStrlen = (str) => {
function isTripleWidth(c) {
return (0xAC00 <= c && c <= 0xD7FF) && [1,4,8,10,13].includes(((c - 0xAC00) / 588)|0)
}
function isDoubleWidth(c) {
return (0x3000 <= c && c <= 0x303f) || (0x3100 <= c && c <= 0x312f) || (0x3200 <= c && c <= 0x33ff) ||
(0xAC00 <= c && c <= 0xD7FF) || (0xFE30 <= c && c <= 0xFE4F) || (0xFF00 <= c && c <= 0xff60)
}
// Convert string to an array of codepoints using spread operator
// This correctly handles surrogate pairs and counts each codepoint as one
return unicode.utf8toCodepoints(str).reduce((acc, c) => acc + (isTripleWidth(c) ? 3 : isDoubleWidth(c) ? 2 : 1), 0)
}
Object.freeze(unicode); Object.freeze(unicode);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -22,33 +22,9 @@ function clearSubtitleArea() {
} }
function getVisualLength(line) { function getVisualLength(line) {
// Calculate the visual length of a line excluding formatting tags // Remove HTML tags and count the remaining text using unicode.strlen()
let visualLength = 0 const withoutTags = line.replace(/<\/?[bi]>/gi, '')
let i = 0 return unicode.visualStrlen(withoutTags)
while (i < line.length) {
if (i < line.length - 2 && line[i] === '<') {
// Check for formatting tags and skip them
if (line.substring(i, i + 3).toLowerCase() === '<b>' ||
line.substring(i, i + 3).toLowerCase() === '<i>') {
i += 3 // Skip tag
} else if (i < line.length - 3 &&
(line.substring(i, i + 4).toLowerCase() === '</b>' ||
line.substring(i, i + 4).toLowerCase() === '</i>')) {
i += 4 // Skip closing tag
} else {
// Not a formatting tag, count the character
visualLength++
i++
}
} else {
// Regular character, count it
visualLength++
i++
}
}
return visualLength
} }
function displayFormattedLine(line) { function displayFormattedLine(line) {