feat: Add 120-char line wrapping to plain text CV
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user