diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-04-04 00:58:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-03 12:58:09 -0400 |
commit | 19de52e0f4cbd2d62f9d41589fe8815c2c3ceef2 (patch) | |
tree | f5e2f0a5431f315946aed6d72e40e5e9893dabc0 /modules | |
parent | 01d9466bfdbb2e043a03368ca7872944db211f49 (diff) | |
download | gitea-19de52e0f4cbd2d62f9d41589fe8815c2c3ceef2.tar.gz gitea-19de52e0f4cbd2d62f9d41589fe8815c2c3ceef2.zip |
Introduce GiteaLocaleNumber custom element to handle number localization on pages. (#23861)
Follow #21429 & #22861
Use `<gitea-locale-number>` instead of backend `PrettyNumber`. All old
`PrettyNumber` related functions are removed. A lot of code could be
simplified.
And some functions haven't been used for long time (dead code), so they
are also removed by the way (eg: `SplitStringAtRuneN`, `Dedent`)
This PR only tries to improve the `PrettyNumber` rendering problem, it
doesn't touch the "plural" problem.
Screenshot:
![image](https://user-images.githubusercontent.com/2114189/229290804-1f63db65-1e34-4a54-84ba-e00b44331b17.png)
![image](https://user-images.githubusercontent.com/2114189/229290911-c88dea00-b11d-48dd-accb-9f52edd73ce4.png)
Diffstat (limited to 'modules')
-rw-r--r-- | modules/base/tool.go | 7 | ||||
-rw-r--r-- | modules/base/tool_test.go | 7 | ||||
-rw-r--r-- | modules/templates/helper.go | 93 | ||||
-rw-r--r-- | modules/util/truncate.go | 24 | ||||
-rw-r--r-- | modules/util/truncate_test.go | 14 | ||||
-rw-r--r-- | modules/util/util.go | 58 | ||||
-rw-r--r-- | modules/util/util_test.go | 7 |
7 files changed, 43 insertions, 167 deletions
diff --git a/modules/base/tool.go b/modules/base/tool.go index 94f19576b4..bd3a8458ee 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -22,7 +22,6 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" "github.com/dustin/go-humanize" "github.com/minio/sha256-simd" @@ -142,12 +141,6 @@ func FileSize(s int64) string { return humanize.IBytes(uint64(s)) } -// PrettyNumber produces a string form of the given number in base 10 with -// commas after every three orders of magnitude -func PrettyNumber(i interface{}) string { - return humanize.Comma(util.NumberIntoInt64(i)) -} - // Subtract deals with subtraction of all types of number. func Subtract(left, right interface{}) interface{} { var rleft, rright int64 diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go index 81f4b464e6..33677a910c 100644 --- a/modules/base/tool_test.go +++ b/modules/base/tool_test.go @@ -114,13 +114,6 @@ func TestFileSize(t *testing.T) { assert.Equal(t, "2.0 EiB", FileSize(size)) } -func TestPrettyNumber(t *testing.T) { - assert.Equal(t, "23,342,432", PrettyNumber(23342432)) - assert.Equal(t, "23,342,432", PrettyNumber(int32(23342432))) - assert.Equal(t, "0", PrettyNumber(0)) - assert.Equal(t, "-100,000", PrettyNumber(-100000)) -} - func TestSubtract(t *testing.T) { toFloat64 := func(n interface{}) float64 { switch v := n.(type) { diff --git a/modules/templates/helper.go b/modules/templates/helper.go index a8343428dc..54c85863bd 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -19,7 +19,6 @@ import ( "reflect" "regexp" "runtime" - "strconv" "strings" texttmpl "text/template" "time" @@ -112,18 +111,17 @@ func NewFuncMap() []template.FuncMap { "IsShowFullName": func() bool { return setting.UI.DefaultShowFullName }, - "Safe": Safe, - "SafeJS": SafeJS, - "JSEscape": JSEscape, - "Str2html": Str2html, - "TimeSince": timeutil.TimeSince, - "TimeSinceUnix": timeutil.TimeSinceUnix, - "FileSize": base.FileSize, - "PrettyNumber": base.PrettyNumber, - "JsPrettyNumber": JsPrettyNumber, - "Subtract": base.Subtract, - "EntryIcon": base.EntryIcon, - "MigrationIcon": MigrationIcon, + "Safe": Safe, + "SafeJS": SafeJS, + "JSEscape": JSEscape, + "Str2html": Str2html, + "TimeSince": timeutil.TimeSince, + "TimeSinceUnix": timeutil.TimeSinceUnix, + "FileSize": base.FileSize, + "LocaleNumber": LocaleNumber, + "Subtract": base.Subtract, + "EntryIcon": base.EntryIcon, + "MigrationIcon": MigrationIcon, "Add": func(a ...int) int { sum := 0 for _, val := range a { @@ -410,62 +408,9 @@ func NewFuncMap() []template.FuncMap { "Join": strings.Join, "QueryEscape": url.QueryEscape, "DotEscape": DotEscape, - "Iterate": func(arg interface{}) (items []uint64) { - count := uint64(0) - switch val := arg.(type) { - case uint64: - count = val - case *uint64: - count = *val - case int64: - if val < 0 { - val = 0 - } - count = uint64(val) - case *int64: - if *val < 0 { - *val = 0 - } - count = uint64(*val) - case int: - if val < 0 { - val = 0 - } - count = uint64(val) - case *int: - if *val < 0 { - *val = 0 - } - count = uint64(*val) - case uint: - count = uint64(val) - case *uint: - count = uint64(*val) - case int32: - if val < 0 { - val = 0 - } - count = uint64(val) - case *int32: - if *val < 0 { - *val = 0 - } - count = uint64(*val) - case uint32: - count = uint64(val) - case *uint32: - count = uint64(*val) - case string: - cnt, _ := strconv.ParseInt(val, 10, 64) - if cnt < 0 { - cnt = 0 - } - count = uint64(cnt) - } - if count <= 0 { - return items - } - for i := uint64(0); i < count; i++ { + "Iterate": func(arg interface{}) (items []int64) { + count := util.ToInt64(arg) + for i := int64(0); i < count; i++ { items = append(items, i) } return items @@ -1067,10 +1012,8 @@ func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteNa return a } -// JsPrettyNumber renders a number using english decimal separators, e.g. 1,200 and subsequent -// JS will replace the number with locale-specific separators, based on the user's selected language -func JsPrettyNumber(i interface{}) template.HTML { - num := util.NumberIntoInt64(i) - - return template.HTML(`<span class="js-pretty-number" data-value="` + strconv.FormatInt(num, 10) + `">` + base.PrettyNumber(num) + `</span>`) +// LocaleNumber renders a number with a Custom Element, browser will render it with a locale number +func LocaleNumber(v interface{}) template.HTML { + num := util.ToInt64(v) + return template.HTML(fmt.Sprintf(`<gitea-locale-number data-number="%d">%d</gitea-locale-number>`, num, num)) } diff --git a/modules/util/truncate.go b/modules/util/truncate.go index 032a6c0872..f41d27d8b7 100644 --- a/modules/util/truncate.go +++ b/modules/util/truncate.go @@ -35,27 +35,3 @@ func SplitStringAtByteN(input string, n int) (left, right string) { return input[:end] + utf8Ellipsis, utf8Ellipsis + input[end:] } - -// SplitStringAtRuneN splits a string at rune n accounting for rune boundaries. (Combining characters are not accounted for.) -func SplitStringAtRuneN(input string, n int) (left, right string) { - if !utf8.ValidString(input) { - if len(input) <= n || n-3 < 0 { - return input, "" - } - return input[:n-3] + asciiEllipsis, asciiEllipsis + input[n-3:] - } - - if utf8.RuneCountInString(input) <= n { - return input, "" - } - - count := 0 - end := 0 - for count < n-1 { - _, size := utf8.DecodeRuneInString(input[end:]) - end += size - count++ - } - - return input[:end] + utf8Ellipsis, utf8Ellipsis + input[end:] -} diff --git a/modules/util/truncate_test.go b/modules/util/truncate_test.go index 912bfb3d5f..05e2bc0301 100644 --- a/modules/util/truncate_test.go +++ b/modules/util/truncate_test.go @@ -43,18 +43,4 @@ func TestSplitString(t *testing.T) { {"\xef\x03", 1, "\xef\x03", ""}, } test(tc, SplitStringAtByteN) - - tc = []*testCase{ - {"abc123xyz", 0, "", utf8Ellipsis}, - {"abc123xyz", 1, "", utf8Ellipsis}, - {"abc123xyz", 4, "abc", utf8Ellipsis}, - {"啊bc123xyz", 4, "啊bc", utf8Ellipsis}, - {"啊bc123xyz", 6, "啊bc12", utf8Ellipsis}, - {"啊bc", 3, "啊bc", ""}, - {"啊bc", 4, "啊bc", ""}, - {"abc\xef\x03\xfe", 3, "", asciiEllipsis}, - {"abc\xef\x03\xfe", 4, "a", asciiEllipsis}, - {"\xef\x03", 1, "\xef\x03", ""}, - } - test(tc, SplitStringAtRuneN) } diff --git a/modules/util/util.go b/modules/util/util.go index 9d3a8dcfac..9c7097ad34 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -7,8 +7,9 @@ import ( "bytes" "crypto/rand" "errors" + "fmt" "math/big" - "regexp" + "os" "strconv" "strings" @@ -200,40 +201,14 @@ func ToTitleCaseNoLower(s string) string { return titleCaserNoLower.String(s) } -var ( - whitespaceOnly = regexp.MustCompile("(?m)^[ \t]+$") - leadingWhitespace = regexp.MustCompile("(?m)(^[ \t]*)(?:[^ \t\n])") -) - -// Dedent removes common indentation of a multi-line string along with whitespace around it -// Based on https://github.com/lithammer/dedent -func Dedent(s string) string { - var margin string - - s = whitespaceOnly.ReplaceAllString(s, "") - indents := leadingWhitespace.FindAllStringSubmatch(s, -1) - - for i, indent := range indents { - if i == 0 { - margin = indent[1] - } else if strings.HasPrefix(indent[1], margin) { - continue - } else if strings.HasPrefix(margin, indent[1]) { - margin = indent[1] - } else { - margin = "" - break - } - } - - if margin != "" { - s = regexp.MustCompile("(?m)^"+margin).ReplaceAllString(s, "") - } - return strings.TrimSpace(s) +func logError(msg string, args ...any) { + // TODO: the "util" package can not import the "modules/log" package, so we use the "fmt" package here temporarily. + // In the future, we should decouple the dependency between them. + _, _ = fmt.Fprintf(os.Stderr, msg, args...) } -// NumberIntoInt64 transform a given int into int64. -func NumberIntoInt64(number interface{}) int64 { +// ToInt64 transform a given int into int64. +func ToInt64(number interface{}) int64 { var value int64 switch v := number.(type) { case int: @@ -246,6 +221,23 @@ func NumberIntoInt64(number interface{}) int64 { value = int64(v) case int64: value = v + case uint: + value = int64(v) + case uint8: + value = int64(v) + case uint16: + value = int64(v) + case uint32: + value = int64(v) + case uint64: + value = int64(v) + case string: + var err error + if value, err = strconv.ParseInt(v, 10, 64); err != nil { + logError("strconv.ParseInt failed for %q: %v", v, err) + } + default: + logError("unable to convert %q to int64", v) } return value } diff --git a/modules/util/util_test.go b/modules/util/util_test.go index 34fe070d22..8cceafa2f6 100644 --- a/modules/util/util_test.go +++ b/modules/util/util_test.go @@ -224,10 +224,3 @@ func TestToTitleCase(t *testing.T) { assert.Equal(t, ToTitleCase(`foo bar baz`), `Foo Bar Baz`) assert.Equal(t, ToTitleCase(`FOO BAR BAZ`), `Foo Bar Baz`) } - -func TestDedent(t *testing.T) { - assert.Equal(t, Dedent(` - foo - bar - `), "foo\n\tbar") -} |