From 6732d2a7e4c7802479882f84d59b7413b3304f94 Mon Sep 17 00:00:00 2001 From: Romain Poirot <32273490+Redlinkk@users.noreply.github.com> Date: Fri, 30 Sep 2022 18:21:23 +0000 Subject: [PATCH] Fix edge case in truncate function allowing too long slugs (#74) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #72 * Add more TestSlugMakeSmartTruncate cases Co-authored-by: Romain Poirot Co-authored-by: Dobrosław Żybort --- slug.go | 22 ++++++++-------------- slug_test.go | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/slug.go b/slug.go index c44e31d..5a2b284 100644 --- a/slug.go +++ b/slug.go @@ -160,25 +160,19 @@ func SubstituteRune(s string, sub map[rune]string) string { } func smartTruncate(text string) string { - if len(text) < MaxLength { + if len(text) <= MaxLength { return text } - var truncated string - words := strings.SplitAfter(text, "-") - // If MaxLength is smaller than length of the first word return word - // truncated after MaxLength. - if len(words[0]) > MaxLength { - return words[0][:MaxLength] - } - for _, word := range words { - if len(truncated)+len(word)-1 <= MaxLength { - truncated = truncated + word - } else { - break + // If slug is too long, we need to find the last '-' before MaxLength, and + // we cut there. + // If we don't find any, we have only one word, and we cut at MaxLength. + for i := MaxLength; i >= 0; i-- { + if text[i] == '-' { + return text[:i] } } - return strings.Trim(truncated, "-") + return text[:MaxLength] } // IsSlug returns True if provided text does not contain white characters, diff --git a/slug_test.go b/slug_test.go index a346348..88cb2fa 100644 --- a/slug_test.go +++ b/slug_test.go @@ -283,12 +283,39 @@ func TestSlugMakeSmartTruncate(t *testing.T) { want string smartTruncate bool }{ - {"DOBROSLAWZYBORT", 100, "dobroslawzybort", true}, - {"Dobroslaw Zybort", 100, "dobroslaw-zybort", true}, + {"Dobrosław Żybort", 5, "dobro", true}, + {"Dobroslaw Zybort", 9, "dobroslaw", true}, {"Dobroslaw Zybort", 12, "dobroslaw", true}, + {"Dobroslaw Zybort", 15, "dobroslaw", true}, + {"Dobroslaw Zybort", 16, "dobroslaw-zybort", true}, + {"Dobroslaw Zybort", 17, "dobroslaw-zybort", true}, + {"Dobroslaw Zybort", 100, "dobroslaw-zybort", true}, + {"abc", 2, "ab", true}, + {"-abc", 2, "ab", true}, + {"abc-", 2, "ab", true}, + {"abc", 3, "abc", true}, + {"-abc", 3, "abc", true}, + {"abc", 4, "abc", true}, + {"abc-", 4, "abc", true}, + {"-abc-", 4, "abc", true}, + {"----abc----", 4, "abc", true}, + {"abc-de", 4, "abc", true}, + {"abc-de", 5, "abc", true}, + {"abc-de", 6, "abc-de", true}, + {"abc-de", 7, "abc-de", true}, + {"abc-de-fg", 6, "abc-de", true}, + {"abc-de-fg", 7, "abc-de", true}, + {"abc-de-fg", 8, "abc-de", true}, + {"abc-de-fg", 9, "abc-de-fg", true}, + {"abc-de-fg", 10, "abc-de-fg", true}, + + {"DOBROSLAWZYBORT", 9, "dobroslaw", true}, + {"DOBROSLAWZYBORT", 15, "dobroslawzybort", true}, + {"DOBROSLAWZYBORT", 100, "dobroslawzybort", true}, {" Dobroslaw Zybort ?", 12, "dobroslaw", true}, {"Ala ma 6 kotów.", 10, "ala-ma-6", true}, - {"Dobrosław Żybort", 5, "dobro", true}, + + // No smart truncate {"Long branch-name", 14, "long-branch-na", false}, {"Long branch-name", 12, "long-branch", false}, }