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