Truncate truncates s to n runes. Additional behaviors can be specified using TruncateOptions.
(s string, n int, opts ...TruncateOption)
| 57 | // Truncate truncates s to n runes. |
| 58 | // Additional behaviors can be specified using TruncateOptions. |
| 59 | func Truncate(s string, n int, opts ...TruncateOption) string { |
| 60 | var options TruncateOption |
| 61 | for _, opt := range opts { |
| 62 | options |= opt |
| 63 | } |
| 64 | if n < 1 { |
| 65 | return "" |
| 66 | } |
| 67 | runes := []rune(s) |
| 68 | if len(runes) <= n { |
| 69 | return s |
| 70 | } |
| 71 | |
| 72 | maxLen := n |
| 73 | if options&TruncateWithEllipsis != 0 { |
| 74 | maxLen-- |
| 75 | } |
| 76 | var sb strings.Builder |
| 77 | if options&TruncateWithFullWords != 0 { |
| 78 | // Convert the rune-safe prefix to a string, then find |
| 79 | // the last word boundary (byte offset within that prefix). |
| 80 | truncated := string(runes[:maxLen]) |
| 81 | lastWordBoundary := strings.LastIndexFunc(truncated, unicode.IsSpace) |
| 82 | if lastWordBoundary < 0 { |
| 83 | _, _ = sb.WriteString(truncated) |
| 84 | } else { |
| 85 | _, _ = sb.WriteString(truncated[:lastWordBoundary]) |
| 86 | } |
| 87 | } else { |
| 88 | _, _ = sb.WriteString(string(runes[:maxLen])) |
| 89 | } |
| 90 | |
| 91 | if options&TruncateWithEllipsis != 0 { |
| 92 | _, _ = sb.WriteString("…") |
| 93 | } |
| 94 | return sb.String() |
| 95 | } |
| 96 | |
| 97 | var bmPolicy = bluemonday.StrictPolicy() |
| 98 |