f
This commit is contained in:
@@ -552,6 +552,9 @@ func (r *DatabaseTableReader) getContentPreview(content string, maxLen int) stri
|
||||
if len(content) <= maxLen {
|
||||
return content
|
||||
}
|
||||
if maxLen > len(content) {
|
||||
maxLen = len(content)
|
||||
}
|
||||
return content[:maxLen] + "..."
|
||||
}
|
||||
|
||||
|
||||
@@ -1186,10 +1186,14 @@ func (pb *PageBuilder) drawRichTextBlock(pdf *gofpdf.Fpdf, text string, contentW
|
||||
// getContentPreview 获取内容预览(用于日志记录)
|
||||
func (pb *PageBuilder) getContentPreview(content string, maxLen int) string {
|
||||
content = strings.TrimSpace(content)
|
||||
if len(content) <= maxLen {
|
||||
if maxLen <= 0 || len(content) <= maxLen {
|
||||
return content
|
||||
}
|
||||
return content[:maxLen] + "..."
|
||||
n := maxLen
|
||||
if n > len(content) {
|
||||
n = len(content)
|
||||
}
|
||||
return content[:n] + "..."
|
||||
}
|
||||
|
||||
// wrapJSONLinesToWidth 将 JSON 文本按宽度换行,返回用于绘制的行列表(兼容中文等)
|
||||
|
||||
@@ -175,10 +175,11 @@ func (tp *TextProcessor) parseInlineSegments(block string) []inlineSeg {
|
||||
if plain == "" {
|
||||
return segs
|
||||
}
|
||||
// 在原始 block 上找加粗区间,再映射到 plain(去掉标签后的位置)
|
||||
// 在 block 上找加粗区间,再映射到 plain(去掉标签后的位置)
|
||||
// 注意:work 每次循环被截断,必须用相对 work 的索引切片,避免 work[:endInWork] 越界
|
||||
work := block
|
||||
var boldRanges [][2]int
|
||||
offset := 0
|
||||
plainOffset := 0
|
||||
for {
|
||||
idxOpen := reBoldOpen.FindStringIndex(work)
|
||||
if idxOpen == nil {
|
||||
@@ -189,34 +190,45 @@ func (tp *TextProcessor) parseInlineSegments(block string) []inlineSeg {
|
||||
if idxClose == nil {
|
||||
break
|
||||
}
|
||||
startInWork := offset + idxOpen[1]
|
||||
endInWork := offset + idxOpen[1] + idxClose[0]
|
||||
// 将 work 坐标映射到 plain:需要数 plain 中对应字符
|
||||
workBefore := work[:startInWork]
|
||||
closeLen := len(reBoldClose.FindString(afterOpen))
|
||||
// 使用相对当前 work 的字节偏移,保证 work[:endInWork] 不越界
|
||||
endInWork := idxOpen[1] + idxClose[0]
|
||||
workBefore := work[:idxOpen[1]]
|
||||
plainBefore := regexp.MustCompile(`<[^>]+>`).ReplaceAllString(workBefore, "")
|
||||
plainBefore = regexp.MustCompile(`[ \t]+`).ReplaceAllString(plainBefore, " ")
|
||||
startPlain := len([]rune(plainBefore))
|
||||
startPlain := plainOffset + len([]rune(plainBefore))
|
||||
workUntil := work[:endInWork]
|
||||
plainUntil := regexp.MustCompile(`<[^>]+>`).ReplaceAllString(workUntil, "")
|
||||
plainUntil = regexp.MustCompile(`[ \t]+`).ReplaceAllString(plainUntil, " ")
|
||||
endPlain := len([]rune(plainUntil))
|
||||
endPlain := plainOffset + len([]rune(plainUntil))
|
||||
boldRanges = append(boldRanges, [2]int{startPlain, endPlain})
|
||||
work = work[endInWork+len(reBoldClose.FindString(afterOpen)):]
|
||||
offset = endInWork + len(reBoldClose.FindString(afterOpen))
|
||||
consumed := work[:endInWork+closeLen]
|
||||
strippedConsumed := regexp.MustCompile(`<[^>]+>`).ReplaceAllString(consumed, "")
|
||||
strippedConsumed = regexp.MustCompile(`[ \t]+`).ReplaceAllString(strippedConsumed, " ")
|
||||
plainOffset += len([]rune(strippedConsumed))
|
||||
work = work[endInWork+closeLen:]
|
||||
}
|
||||
// 按 boldRanges 切分 plain
|
||||
// 按 boldRanges 切分 plain(限制区间在 [0,len(runes)] 内,防止越界)
|
||||
runes := []rune(plain)
|
||||
nr := len(runes)
|
||||
inBold := false
|
||||
var start int
|
||||
for i := 0; i <= len(runes); i++ {
|
||||
for i := 0; i <= nr; i++ {
|
||||
nowBold := false
|
||||
for _, r := range boldRanges {
|
||||
if i >= r[0] && i < r[1] {
|
||||
r0, r1 := r[0], r[1]
|
||||
if r0 < 0 {
|
||||
r0 = 0
|
||||
}
|
||||
if r1 > nr {
|
||||
r1 = nr
|
||||
}
|
||||
if r0 < r1 && i >= r0 && i < r1 {
|
||||
nowBold = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if nowBold != inBold || i == len(runes) {
|
||||
if nowBold != inBold || i == nr {
|
||||
if i > start {
|
||||
segs = append(segs, inlineSeg{Text: string(runes[start:i]), Bold: inBold})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user