feat: Add 120-char line wrapping to plain text CV

This commit is contained in:
juanatsap
2025-11-30 14:21:05 +00:00
parent 64cb990860
commit 170dba1a5b
+64 -3
View File
@@ -69,8 +69,10 @@ func (h *CVHandler) PlainText(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(text))
}
// cleanPlainText removes extra whitespace and HTML tags from plain text
// cleanPlainText removes extra whitespace, HTML tags, and wraps long lines
func cleanPlainText(text string) string {
const maxLineLength = 120
// Remove HTML tags (from safeHTML fields)
htmlTagRe := regexp.MustCompile(`<[^>]*>`)
text = htmlTagRe.ReplaceAllString(text, "")
@@ -79,11 +81,14 @@ func cleanPlainText(text string) string {
multipleNewlines := regexp.MustCompile(`\n{3,}`)
text = multipleNewlines.ReplaceAllString(text, "\n\n")
// Trim each line
// Process each line: trim and wrap
lines := strings.Split(text, "\n")
var cleanedLines []string
for _, line := range lines {
cleanedLines = append(cleanedLines, strings.TrimRight(line, " \t"))
line = strings.TrimRight(line, " \t")
// Wrap long lines
wrapped := wrapLine(line, maxLineLength)
cleanedLines = append(cleanedLines, wrapped...)
}
text = strings.Join(cleanedLines, "\n")
@@ -92,3 +97,59 @@ func cleanPlainText(text string) string {
return text
}
// wrapLine wraps a single line to maxLength, preserving leading whitespace
func wrapLine(line string, maxLength int) []string {
if len(line) <= maxLength {
return []string{line}
}
// Don't wrap separator lines (===, ---)
if strings.HasPrefix(strings.TrimSpace(line), "===") || strings.HasPrefix(strings.TrimSpace(line), "---") {
return []string{line}
}
// Detect leading whitespace for continuation lines
indent := ""
for _, r := range line {
if r == ' ' || r == '\t' {
indent += string(r)
} else {
break
}
}
// For list items, add extra indent for continuation
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "- ") {
indent += " "
}
var wrapped []string
remaining := line
for len(remaining) > maxLength {
// Find last space before maxLength
breakPoint := maxLength
for i := maxLength; i > 0; i-- {
if remaining[i] == ' ' {
breakPoint = i
break
}
}
// If no space found, force break at maxLength
if breakPoint == maxLength && !strings.Contains(remaining[:maxLength], " ") {
breakPoint = maxLength
}
wrapped = append(wrapped, remaining[:breakPoint])
remaining = indent + strings.TrimLeft(remaining[breakPoint:], " ")
}
if len(remaining) > 0 {
wrapped = append(wrapped, remaining)
}
return wrapped
}