Skip to content

Commit

Permalink
Merge branch 'master' into add-portuguese-lang
Browse files Browse the repository at this point in the history
  • Loading branch information
matrixik committed Feb 23, 2024
2 parents 0448e10 + a9e699c commit fbda188
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 53 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
3 changes: 2 additions & 1 deletion languages_substitution.go
Expand Up @@ -190,6 +190,7 @@ var plSub = map[rune]string{

var ptSub = map[rune]string{
'&': "e",
'@': "em",
'á': "a",
'Á': "A",
'é': "e",
Expand Down Expand Up @@ -274,7 +275,7 @@ var bgSub = map[rune]string{
'Ц': "Ts",
'Ч': "Ch",
'Ш': "Sh",
'Щ': "Sh",
'Щ': "Sht",
'Ъ': "A",
'Ь': "Y",
'Ю': "Yu",
Expand Down
17 changes: 16 additions & 1 deletion slug.go
Expand Up @@ -9,7 +9,9 @@ import (
"bytes"
"regexp"
"sort"
"strconv"
"strings"
"time"

"github.com/gosimple/unidecode"
)
Expand All @@ -36,6 +38,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 @@ -93,7 +99,7 @@ func MakeLang(s string, lang string) (slug string) {
slug = SubstituteRune(slug, nnSub)
case "pl", "pol":
slug = SubstituteRune(slug, plSub)
case "pt", "prt", "br", "bra":
case "pt", "prt", "pt-br", "br", "bra", "por":
slug = SubstituteRune(slug, ptSub)
case "ro", "rou":
slug = SubstituteRune(slug, roSub)
Expand Down Expand Up @@ -127,6 +133,10 @@ func MakeLang(s string, lang string) (slug string) {
slug = smartTruncate(slug)
}

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

return slug
}

Expand Down Expand Up @@ -177,6 +187,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
93 changes: 91 additions & 2 deletions slug_test.go
Expand Up @@ -6,6 +6,7 @@
package slug

import (
"regexp"
"testing"
)

Expand Down Expand Up @@ -74,8 +75,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 Down Expand Up @@ -126,6 +127,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 @@ -203,6 +205,7 @@ func TestSlugMakeUserSubstituteLang(t *testing.T) {
got, smust.want)
}
}
CustomSub = nil
}

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

func TestSubstituteLang(t *testing.T) {
Expand Down Expand Up @@ -340,6 +345,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 fbda188

Please sign in to comment.