fix(parser): keep the full headword in the display text

The display form was truncated at the first formatting tag, so headwords
with a mid-word stress mark displayed as their prefix only. Build the
display from the full text with tags stripped and render stress marks as
a combining acute accent. Bump the index version so existing indexes
rebuild.
This commit is contained in:
OneWay committed 2026-10-06 12:23:50 +08:00
1 parent 37127b7bc9
commit cea46c0955
3 files changed
+16 -33

No files matched your search

@@ -60,7 +60,10 @@ fun String.extractDictionaryPrefix(): String {
}
fun String.removeAccentTagsForIndexing(): String {
fun String.removeAccentTagsForIndexing(): String =
rewriteAccentTags { builder, from, to -> builder.append(this, from, to) }
internal inline fun String.rewriteAccentTags(appendInner: (StringBuilder, Int, Int) -> Unit): String {
val firstOpen = indexOf("[']")
if (firstOpen < 0) return this
@@ -80,7 +83,7 @@ fun String.removeAccentTagsForIndexing(): String {
builder = StringBuilder(length)
}
builder.append(this, appendStart, index)
builder.append(this, index + 3, scan)
appendInner(builder, index + 3, scan)
index = scan + 4
appendStart = index
continue
@@ -94,7 +97,7 @@ fun String.removeAccentTagsForIndexing(): String {
}?.toString() ?: this
}
private fun String.startsWithAt(start: Int, literal: String): Boolean {
internal fun String.startsWithAt(start: Int, literal: String): Boolean {
if (start < 0 || start + literal.length > length) return false
for (i in literal.indices) {
if (this[start + i] != literal[i]) return false
@@ -1,5 +1,8 @@
package com.example.research.data.parser
import com.example.research.core.util.rewriteAccentTags
import com.example.research.core.util.startsWithAt
object DslHeadwordParser {
private val FORMATTING_LITERAL_TAGS = arrayOf(
@@ -117,12 +120,12 @@ object DslHeadwordParser {
}
private fun reconstructDisplayPrefix(value: String): String {
val reconstructed = removeCurlyBraceDelimiters(value)
val formattingTagIndex = firstFormattingTagIndex(reconstructed)
return if (formattingTagIndex >= 0) {
reconstructed.substring(0, formattingTagIndex).trim()
} else {
reconstructed.trim()
return removeFormattingTags(removeCurlyBraceDelimiters(value).applyAccentMarks()).trim()
}
private fun String.applyAccentMarks(): String = rewriteAccentTags { builder, from, to ->
if (to > from) {
builder.append(this[from]).append('\u0301').append(this, from + 1, to)
}
}
@@ -145,21 +148,6 @@ object DslHeadwordParser {
}
}
private fun firstFormattingTagIndex(value: String): Int {
var index = 0
while (index < value.length) {
if (value[index] == '\\' && index + 1 < value.length) {
index += 2
continue
}
if (value[index] == '[' && formattingTagEnd(value, index) > index) {
return index
}
index++
}
return -1
}
private fun firstCurlyContent(value: String): String? {
var index = 0
while (index < value.length) {
@@ -346,14 +334,6 @@ object DslHeadwordParser {
return if (index < value.length && value[index] == ']') index + 1 else -1
}
private fun String.startsWithAt(start: Int, literal: String): Boolean {
if (start < 0 || start + literal.length > length) return false
for (i in literal.indices) {
if (this[start + i] != literal[i]) return false
}
return true
}
private fun Char.isTagWhitespace(): Boolean {
return this == ' ' ||
this == '\t' ||
@@ -24,7 +24,7 @@ class DslIndexer(context: Context? = null) {
companion object {
private const val TAG = "DslIndexer"
const val INDEX_VERSION = 6
const val INDEX_VERSION = 7
const val BUFFER_SIZE = 1048576
const val BATCH_BUFFER_SIZE = 524288
private const val INDEX_SORT_PARALLELISM = 1