Skip to content

Commit

Permalink
Merge branch 'master' into add-make-slug-with-random-number
Browse files Browse the repository at this point in the history
  • Loading branch information
tuncaydamlar committed Feb 27, 2024
2 parents 6c717e3 + 412e31a commit dfb2d85
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 52 deletions.
22 changes: 0 additions & 22 deletions .github/workflows/rebase.yml

This file was deleted.

40 changes: 13 additions & 27 deletions .github/workflows/tests.yml
Expand Up @@ -20,51 +20,37 @@ jobs:
matrix:
go-version: [1.18.x, 1.x]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: WillAbides/setup-go-faster@v1
with:
go-version: ${{ matrix.go-version }}
- uses: actions/checkout@v4

- uses: actions/cache@v3
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
# In order:
# * Module download cache
# * Build cache (Linux)
# * Build cache (Mac)
# * Build cache (Windows)
path: |
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
%LocalAppData%\go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
go-version: ${{ matrix.go-version }}

- name: Test with race and coverage
run: |
go test -race -coverprofile=coverage.out -covermode=atomic
go tool cover -func=coverage.out
- uses: codecov/codecov-action@v3
- uses: codecov/codecov-action@v4
with:
files: ./coverage.out
token: ${{ secrets.CODECOV_TOKEN }} # required

lint:
name: "Run static analysis"
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: WillAbides/setup-go-faster@v1
- uses: actions/checkout@v4

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: "1.x"

- run: "go vet ./..."

- uses: dominikh/staticcheck-action@v1
- name: Staticcheck
uses: dominikh/staticcheck-action@v1.3.0
with:
version: "2022.1.3"
install-go: false
22 changes: 21 additions & 1 deletion languages_substitution.go
Expand Up @@ -26,6 +26,7 @@ func init() {
&nlSub,
&nnSub,
&plSub,
&ptSub,
&roSub,
&slSub,
&svSub,
Expand Down Expand Up @@ -187,6 +188,25 @@ var plSub = map[rune]string{
'@': "na",
}

var ptSub = map[rune]string{
'&': "e",
'@': "em",
'á': "a",
'Á': "A",
'é': "e",
'É': "E",
'í': "i",
'Í': "I",
'ó': "o",
'Ó': "O",
'ö': "o",
'Ö': "O",
'ú': "u",
'Ú': "U",
'ü': "u",
'Ü': "U",
}

var roSub = map[rune]string{
'&': "si",
'Ă': "A",
Expand Down Expand Up @@ -255,7 +275,7 @@ var bgSub = map[rune]string{
'Ц': "Ts",
'Ч': "Ch",
'Ш': "Sh",
'Щ': "Sh",
'Щ': "Sht",
'Ъ': "A",
'Ь': "Y",
'Ю': "Yu",
Expand Down
15 changes: 15 additions & 0 deletions slug.go
Expand Up @@ -39,6 +39,10 @@ var (
// Default is true.
Lowercase = true

// Append timestamp to the end in order to make slug unique
// Default is false
AppendTimestamp = false

regexpNonAuthorizedChars = regexp.MustCompile("[^a-zA-Z0-9-_]")
regexpMultipleDashes = regexp.MustCompile("-+")
)
Expand Down Expand Up @@ -96,6 +100,8 @@ func MakeLang(s string, lang string) (slug string) {
slug = SubstituteRune(slug, nnSub)
case "pl", "pol":
slug = SubstituteRune(slug, plSub)
case "pt", "prt", "pt-br", "br", "bra", "por":
slug = SubstituteRune(slug, ptSub)
case "ro", "rou":
slug = SubstituteRune(slug, roSub)
case "sl", "slv":
Expand Down Expand Up @@ -128,6 +134,10 @@ func MakeLang(s string, lang string) (slug string) {
slug = smartTruncate(slug)
}

if AppendTimestamp {
slug = slug + "-" + timestamp()
}

return slug
}

Expand Down Expand Up @@ -178,6 +188,11 @@ func smartTruncate(text string) string {
return text[:MaxLength]
}

// timestamp returns current timestamp as string
func timestamp() string {
return strconv.FormatInt(time.Now().Unix(), 10)
}

// IsSlug returns True if provided text does not contain white characters,
// punctuation, all letters are lower case and only from ASCII range.
// It could contain `-` and `_` but not at the beginning or end of the text.
Expand Down
94 changes: 92 additions & 2 deletions slug_test.go
Expand Up @@ -8,6 +8,7 @@ package slug
import (
"strconv"
"strings"
"regexp"
"testing"
)

Expand Down Expand Up @@ -76,8 +77,8 @@ func TestSlugMakeLang(t *testing.T) {
want string
lowercase bool
}{
{"bg", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя", "abvgdezhziyklmnoprstufhtschshshayyuyaabvgdezhziyklmnoprstufhtschshshtayyuya", true},
{"bg", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя", "ABVGDEZhZIYKLMNOPRSTUFHTsChShShAYYuYaabvgdezhziyklmnoprstufhtschshshtayyuya", false},
{"bg", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя", "abvgdezhziyklmnoprstufhtschshshtayyuyaabvgdezhziyklmnoprstufhtschshshtayyuya", true},
{"bg", "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя", "ABVGDEZhZIYKLMNOPRSTUFHTsChShShtAYYuYaabvgdezhziyklmnoprstufhtschshshtayyuya", false},
{"cs", "ěščřžýáíéúůóňťĚŠČŘŽÝÁÍÉÚŮÓŇŤ", "escrzyaieuuontescrzyaieuuont", true},
{"cs", "ěščřžýáíéúůóňťĚŠČŘŽÝÁÍÉÚŮÓŇŤ", "escrzyaieuuontESCRZYAIEUUONT", false},
{"ces", "ěščřžýáíéúůóňťĚŠČŘŽÝÁÍÉÚŮÓŇŤ", "escrzyaieuuontescrzyaieuuont", true},
Expand All @@ -97,6 +98,7 @@ func TestSlugMakeLang(t *testing.T) {
{"hu", "SzÉlÜtÖtt ŰrÚjsÁgírÓnŐ", "SzElUtOtt-UrUjsAgirOnO", false},
{"kk", "әғһіңөқұүӘҒҺІҢӨҚҰҮ", "aghinoquuaghinoquu", true},
{"kk", "әғһіңөқұүӘҒҺІҢӨҚҰҮ", "aghinoquuAGHINOQUU", false},
{"pt", "áÁéÉíÍóÓöÖúÚüÜ", "aAeEiIoOoOuUuU", false},
{"ro", "ĂăÂăÎîȘșȚț", "aaaaiisstt", true},
{"ro", "ĂăÂăÎîȘșȚț", "AaAaIiSsTt", false},
{"tr", "şüöğıçŞÜÖİĞÇ", "suogicsuoigc", true},
Expand Down Expand Up @@ -128,6 +130,7 @@ func TestSlugMakeLang(t *testing.T) {
{"kk", "This @ that", "this-that", true},
{"nl", "This & that", "this-en-that", true},
{"pl", "This & that", "this-i-that", true},
{"pt", "This & that", "this-e-that", true},
{"pol", "This & that", "this-i-that", true},
{"sv", "This & that", "this-och-that", true},
{"sv", "This @ that", "this-snabel-a-that", true},
Expand Down Expand Up @@ -205,6 +208,7 @@ func TestSlugMakeUserSubstituteLang(t *testing.T) {
got, smust.want)
}
}
CustomSub = nil
}

func TestSlugMakeSubstituteOrderLang(t *testing.T) {
Expand Down Expand Up @@ -232,6 +236,8 @@ func TestSlugMakeSubstituteOrderLang(t *testing.T) {
got, smsot.want)
}
}
CustomRuneSub = nil
CustomSub = nil
}

func TestSubstituteLang(t *testing.T) {
Expand Down Expand Up @@ -342,6 +348,90 @@ func TestSlugMakeSmartTruncate(t *testing.T) {
}
}

func TestSlugMakeAppendTimestamp(t *testing.T) {
testCases := []struct {
in string
want string
appendTimestamp bool
}{
{"DOBROSLAWZYBORT", "dobroslawzybort", true},
{"Dobroslaw Zybort", "dobroslaw-zybort", true},
{" Dobroslaw Zybort ?", "dobroslaw-zybort", true},
{"Dobrosław Żybort", "dobroslaw-zybort", true},
{"Ala ma 6 kotów.", "ala-ma-6-kotow", true},

{"áÁàÀãÃâÂäÄąĄą̊Ą̊", "aaaaaaaaaaaaaa", true},
{"ćĆĉĈçÇčČ", "cccccccc", true},
{"éÉèÈẽẼêÊëËęĘěĚ", "eeeeeeeeeeeeee", true},
{"íÍìÌĩĨîÎïÏįĮ", "iiiiiiiiiiii", true},
{"łŁ", "ll", true},
{"ńŃ", "nn", true},
{"óÓòÒõÕôÔöÖǫǪǭǬø", "ooooooooooooooo", true},
{"śŚšŠ", "ssss", true},
{"řŘ", "rr", true},
{"ťŤ", "tt", true},
{"úÚùÙũŨûÛüÜųŲůŮ", "uuuuuuuuuuuuuu", true},
{"y̨Y̨ýÝ", "yyyy", true},
{"źŹżŹžŽ", "zzzzzz", true},
{"·/,:;`˜'\"", "", true},
{"2000–2013", "2000-2013", true},
{"style—not", "style-not", true},
{"test_slug", "test_slug", true},
{"_test_slug_", "test_slug", true},
{"-test-slug-", "test-slug", true},
{"Æ", "ae", true},
{"Ich heiße", "ich-heisse", true},
{"𐀀", "", true}, // Bug #53
{"% 5 @ 4 $ 3 / 2 & 1 & 2 # 3 @ 4 _ 5", "5-at-4-3-2-and-1-and-2-3-at-4-_-5", true},

{"This & that", "this-and-that", true},
{"fácil €", "facil-eu", true},
{"smile ☺", "smile", true},
{"Hellö Wörld хелло ворлд", "hello-world-khello-vorld", true},
{"\"C'est déjà l’été.\"", "cest-deja-lete", true},
{"jaja---lol-méméméoo--a", "jaja-lol-mememeoo-a", true},
{"影師", "ying-shi", true},
{"Đanković & Kožušček", "dankovic-and-kozuscek", true},
{"ĂăÂâÎîȘșȚț", "aaaaiisstt", true},

// No append timestamp
{"DOBROSLAWZYBORT", "dobroslawzybort", false},
{"Dobroslaw Zybort", "dobroslaw-zybort", false},
{" Dobroslaw Zybort ?", "dobroslaw-zybort", false},
{"Dobrosław Żybort", "dobroslaw-zybort", false},
{"Ala ma 6 kotów.", "ala-ma-6-kotow", false},
}

MaxLength = 0
EnableSmartTruncate = true
CustomRuneSub = nil
CustomSub = nil
Lowercase = true
for index, st := range testCases {
if st.appendTimestamp {
AppendTimestamp = true
} else {
AppendTimestamp = false
}
got := Make(st.in)
if st.appendTimestamp {
want := regexp.MustCompile(`^` + st.want + `-\d{10}$`)
if !want.MatchString(got) {
t.Errorf(
"%d. AppendTimestamp = %v; Make(%#v) = %#v; want %#v",
index, st.appendTimestamp, st.in, got, want,
)
}
continue
}
if got != st.want {
t.Errorf(
"%d. Make(%#v) = %#v; want %#v",
index, st.in, got, st.want)
}
}
}

func TestIsSlug(t *testing.T) {
MaxLength = 0
type args struct {
Expand Down

0 comments on commit dfb2d85

Please sign in to comment.