code.gitea.io/gitea@v1.19.3/modules/util/truncate.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package util
     5  
     6  import "unicode/utf8"
     7  
     8  // in UTF8 "…" is 3 bytes so doesn't really gain us anything...
     9  const (
    10  	utf8Ellipsis  = "…"
    11  	asciiEllipsis = "..."
    12  )
    13  
    14  // SplitStringAtByteN splits a string at byte n accounting for rune boundaries. (Combining characters are not accounted for.)
    15  func SplitStringAtByteN(input string, n int) (left, right string) {
    16  	if len(input) <= n {
    17  		return input, ""
    18  	}
    19  
    20  	if !utf8.ValidString(input) {
    21  		if n-3 < 0 {
    22  			return input, ""
    23  		}
    24  		return input[:n-3] + asciiEllipsis, asciiEllipsis + input[n-3:]
    25  	}
    26  
    27  	end := 0
    28  	for end <= n-3 {
    29  		_, size := utf8.DecodeRuneInString(input[end:])
    30  		if end+size > n-3 {
    31  			break
    32  		}
    33  		end += size
    34  	}
    35  
    36  	return input[:end] + utf8Ellipsis, utf8Ellipsis + input[end:]
    37  }
    38  
    39  // SplitStringAtRuneN splits a string at rune n accounting for rune boundaries. (Combining characters are not accounted for.)
    40  func SplitStringAtRuneN(input string, n int) (left, right string) {
    41  	if !utf8.ValidString(input) {
    42  		if len(input) <= n || n-3 < 0 {
    43  			return input, ""
    44  		}
    45  		return input[:n-3] + asciiEllipsis, asciiEllipsis + input[n-3:]
    46  	}
    47  
    48  	if utf8.RuneCountInString(input) <= n {
    49  		return input, ""
    50  	}
    51  
    52  	count := 0
    53  	end := 0
    54  	for count < n-1 {
    55  		_, size := utf8.DecodeRuneInString(input[end:])
    56  		end += size
    57  		count++
    58  	}
    59  
    60  	return input[:end] + utf8Ellipsis, utf8Ellipsis + input[end:]
    61  }