From 78a68e2ebce866d51dbdee61c25697fe6629890e Mon Sep 17 00:00:00 2001 From: goloop Date: Fri, 29 Apr 2022 22:21:54 +0300 Subject: [PATCH] Init --- .gitignore | 17 +++ .godocdown.md | 49 +++++++ LICENSE | 24 ++++ Makefile | 59 ++++++++ README.md | 100 +++++++++++++ doc.go | 10 ++ go.mod | 5 + go.sum | 2 + lang/lang.go | 376 ++++++++++++++++++++++++++++++++++++++++++++++++ methods.go | 24 ++++ methods_test.go | 70 +++++++++ slug.go | 49 +++++++ slug_test.go | 59 ++++++++ tools.go | 57 ++++++++ tools_test.go | 63 ++++++++ 15 files changed, 964 insertions(+) create mode 100644 .gitignore create mode 100644 .godocdown.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 doc.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 lang/lang.go create mode 100644 methods.go create mode 100644 methods_test.go create mode 100644 slug.go create mode 100644 slug_test.go create mode 100644 tools.go create mode 100644 tools_test.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6fe045 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories +# vendor/ +.vscode/ +cmd/ \ No newline at end of file diff --git a/.godocdown.md b/.godocdown.md new file mode 100644 index 0000000..8a1eaf2 --- /dev/null +++ b/.godocdown.md @@ -0,0 +1,49 @@ +[//]: # (!!!Don't modify the README.md, use `make readme` to generate it!!!) + + +[![Go Report Card](https://goreportcard.com/badge/github.com/goloop/slug)](https://goreportcard.com/report/github.com/goloop/slug) [![License](https://img.shields.io/badge/license-BSD-blue)](https://github.com/goloop/slug/blob/master/LICENSE) [![License](https://img.shields.io/badge/godoc-YES-green)](https://godoc.org/github.com/goloop/slug) + +*Version: .ModuleVersion* + +# slug + +{{.EmitSynopsis}} + + +## Installation + +To install this module use `go get` as: + + $ go get -u github.com/goloop/slug + +## Quick Start + +To use this module import it as: `github.com/goloop/slug` + +### Conversion functions + +#### Fast conversion. + +Use the `Make` method to convert a string to slug. + +```go +package main + +import ( + "fmt" + + "github.com/goloop/slug" +) + +func main() { + // Simple generate slug from the string. + s := slug.Make("Hello 世界") + h := "https://example.com/" + fmt.Printf("%s%s\n", h, s) + + // Output: + // hello-shi-jie +} +``` + +{{ .EmitUsage }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1949033 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2022, GoLoop. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the GoLoop nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND CONTRIBUTORS ''AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER AND CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7ba0c0c --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +# GOLOOP +# +# Load data about the package: +# NAME +# Name of the GoLang's module; +# VERSION +# Current version. +# REPOSITORY +# The name of the repository where the package is stored, +# for example: github.com/goloop; +MODULE_NAME:=$(shell cat go.mod | grep module | awk '{split($$2,v,"/"); print v[3]}') +MODULE_VERSION:=$(shell cat doc.go | grep "const version" | awk '{gsub(/"/, "", $$4); print $$4}') +MODULE_MAJOR_VERSION:=$(shell cat doc.go | grep "const version" | awk '{gsub(/"/, "", $$4); print $$4}' | awk '{split($$0,r,"."); print r[1]}') +REPOSITORY_NAME:=$(shell cat go.mod | grep module | awk '{split($$2,v,"/"); print v[1] "/" v[2]}') + +# Help information. +define MSG_HELP +Go-package's manager of +${MODULE_NAME} v${MODULE_VERSION} + +Commands: + help + Show this help information + test + Run tests + cover + Check test coverage + readme + Create readme from the GoLang code + + Requires `godocdown`, install as: + go get github.com/robertkrimen/godocdown/godocdown + tag + Create git-tag with current version of package +endef + +# Constants. +export MSG_HELP +REPOSITORY_PATH=${REPOSITORY_NAME}/${MODULE_NAME} + +all: help +help: + @echo "$$MSG_HELP" +test: + @go clean -testcache; \ + go test ${REPOSITORY_PATH} +cover: + @go test -cover ${REPOSITORY_PATH} && \ + go test -coverprofile=/tmp/coverage.out ${REPOSITORY_PATH} && \ + go tool cover -func=/tmp/coverage.out && \ + go tool cover -html=/tmp/coverage.out +readme: +ifeq (, $(shell which godocdown)) + @go get github.com/robertkrimen/godocdown/godocdown +endif + @godocdown -plain=true -template=.godocdown.md ./ | \ + sed -e 's/\.ModuleVersion/v${MODULE_VERSION}/g' > README.md +tag: + @bash -c 'read -p "Do you want to create v${MODULE_VERSION} tag [y/n]?: " yn; case $${yn} in "y") git tag "v${MODULE_VERSION}"; exit 0;; *) exit 0;; esac' diff --git a/README.md b/README.md new file mode 100644 index 0000000..89e7719 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +[//]: # (!!!Don't modify the README.md, use `make readme` to generate it!!!) + + +[![Go Report Card](https://goreportcard.com/badge/github.com/goloop/slug)](https://goreportcard.com/report/github.com/goloop/slug) [![License](https://img.shields.io/badge/license-BSD-blue)](https://github.com/goloop/slug/blob/master/LICENSE) [![License](https://img.shields.io/badge/godoc-YES-green)](https://godoc.org/github.com/goloop/slug) + +*Version: v0.0.1-alpha* + +# slug + +Package slug generate slug from Unicode string, URL-friendly slugify with +multiple languages support. + + +## Installation + +To install this module use `go get` as: + + $ go get -u github.com/goloop/slug + +## Quick Start + +To use this module import it as: `github.com/goloop/slug` + +### Conversion functions + +#### Fast conversion. + +Use the `Make` method to convert a string to slug. + +```go +package main + +import ( + "fmt" + + "github.com/goloop/slug" +) + +func main() { + // Simple generate slug from the string. + s := slug.Make("Hello 世界") + h := "https://example.com/" + fmt.Printf("%s%s\n", h, s) + + // Output: + // hello-shi-jie +} +``` + +## Usage + +#### func Lower + + func Lower(t string) string + +Lower returns slug in lowercase. + +#### func Make + + func Make(t string) string + +Make returns slug from string. + +#### func Version + + func Version() string + +Version returns the version of the module. + +#### type Slug + + type Slug struct { + } + + +Slug is the slug constructor. + +#### func New + + func New() *Slug + +New retursn pointer to Slug. + +#### func (*Slug) Lang + + func (s *Slug) Lang(l string) *Slug + +Lang sets the type of language features to use during slugify. + +#### func (*Slug) Lower + + func (s *Slug) Lower(t string) string + +Lower returns slug in lowercase. + +#### func (*Slug) Make + + func (s *Slug) Make(t string) string + +Make returns slug from string. diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..2455cee --- /dev/null +++ b/doc.go @@ -0,0 +1,10 @@ +// Package slug generate slug from Unicode string, +// URL-friendly slugify with multiple languages support. +package slug + +const version = "0.0.1-alpha" + +// Version returns the version of the module. +func Version() string { + return "v" + version +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b5d0e5b --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/goloop/slug + +go 1.17 + +require github.com/goloop/t13n v1.0.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..198a7f6 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/goloop/t13n v1.0.0 h1:FaX8xLhJ1MR+Ua1jc+WNcFFFqQgkzTcFWKAOwLmlPZ8= +github.com/goloop/t13n v1.0.0/go.mod h1:1A8l9eGVc905TSEVbUS36ctQSEFtW7n5FBOc1Tp32r8= diff --git a/lang/lang.go b/lang/lang.go new file mode 100644 index 0000000..9c71857 --- /dev/null +++ b/lang/lang.go @@ -0,0 +1,376 @@ +package lang + +import ( + "github.com/goloop/t13n/lang" +) + +const ( + // None to ignore any language rules. + None = lang.None + // BG is Bulgarian language. + BG = lang.BG + // HR is Croatian language. + HR = lang.HR + // DA is Danish language. + DA = lang.DA + // EO is Esperanto language. + EO = lang.EO + // DE is German language. + DE = lang.DE + // HU is Hungarian language. + HU = lang.HU + // MK is Macedonian language. + MK = lang.MK + // NB is Norwegian language. + NB = lang.NB + // RU is Russian language. + RU = lang.RU + // SR is Serbian language. + SR = lang.SR + // SL is Slovenian language. + SL = lang.SL + // SV is Swedish language. + SV = lang.SV + // UK is Ukrainian language. + UK = lang.UK + // AB is Abkhazian language. + AB = lang.AB + // AA is Afar language. + AA = lang.AA + // AF is Afrikaans language. + AF = lang.AF + // AK is Akan language. + AK = lang.AK + // SQ is Albanian language. + SQ = lang.SQ + // AM is Amharic language. + AM = lang.AM + // AR is Arabic language. + AR = lang.AR + // AN is Aragonese language. + AN = lang.AN + // HY is Armenian language. + HY = lang.HY + // AS is Assamese language. + AS = lang.AS + // AV is Avaric language. + AV = lang.AV + // AE is Avestan language. + AE = lang.AE + // AY is Aymara language. + AY = lang.AY + // AZ is Azerbaijani language. + AZ = lang.AZ + // BM is Bambara language. + BM = lang.BM + // BA is Bashkir language. + BA = lang.BA + // EU is Basque language. + EU = lang.EU + // BE is Belarusian language. + BE = lang.BE + // BN is Bengali language. + BN = lang.BN + // BI is Bislama language. + BI = lang.BI + // BS is Bosnian language. + BS = lang.BS + // BR is Breton language. + BR = lang.BR + // MY is Burmese language. + MY = lang.MY + // CH is Chamorro language. + CH = lang.CH + // CE is Chechen language. + CE = lang.CE + // NY is Nyanja language. + NY = lang.NY + // CA is Catalan language. + CA = lang.CA + // ZH is Chinese language. + ZH = lang.ZH + // CU is Church Slavonic language. + CU = lang.CU + // CV is Chuvash language. + CV = lang.CV + // KW is Cornish language. + KW = lang.KW + // CO is Corsican language. + CO = lang.CO + // CR is Cree language. + CR = lang.CR + // CS is Czech language. + CS = lang.CS + // DV is Divehi, Dhivehi, Maldivian languages. + DV = lang.DV + // NL is Dutch, Flemish languages. + NL = lang.NL + // DZ is Dzongkha language. + DZ = lang.DZ + // EN is English language. + EN = lang.EN + // ET is Estonian language. + ET = lang.ET + // EE is Ewe language. + EE = lang.EE + // FO is Faroese language. + FO = lang.FO + // FJ is Fijian language. + FJ = lang.FJ + // FI is Finnish language. + FI = lang.FI + // FR is French language. + FR = lang.FR + // FY is Western Frisian language. + FY = lang.FY + // FF is Fulah language. + FF = lang.FF + // GD is Gaelic language. + GD = lang.GD + // GL is Galician language. + GL = lang.GL + // LG is Ganda language. + LG = lang.LG + // KA is Georgian language. + KA = lang.KA + // EL is Greek language. + EL = lang.EL + // KL is Kalaallisut language. + KL = lang.KL + // GN is Guarani language. + GN = lang.GN + // GU is Gujarati language. + GU = lang.GU + // HT is Haitian language. + HT = lang.HT + // HA is Hausa language. + HA = lang.HA + // HE is Hebrew language. + HE = lang.HE + // HZ is Herero language. + HZ = lang.HZ + // HI is Hindi language. + HI = lang.HI + // HO is Hiri language. + HO = lang.HO + // IS is Icelandic language. + IS = lang.IS + // IO is Ido language. + IO = lang.IO + // IG is Igbo language. + IG = lang.IG + // ID is Indonesian language. + ID = lang.ID + // IA is Interlingua language. + IA = lang.IA + // IE is Interlingue language. + IE = lang.IE + // IU is Inuktitut language. + IU = lang.IU + // IK is Inupiaq language. + IK = lang.IK + // GA is Irish language. + GA = lang.GA + // IT is Italian language. + IT = lang.IT + // JA is Japanese language. + JA = lang.JA + // JV is Javanese language. + JV = lang.JV + // KN is Kannada language. + KN = lang.KN + // KR is Kanuri language. + KR = lang.KR + // KS is Kashmiri language. + KS = lang.KS + // KK is Kazakh language. + KK = lang.KK + // KM is Khmer language. + KM = lang.KM + // KI is Kikuyu language. + KI = lang.KI + // RW is Kinyarwanda language. + RW = lang.RW + // KY is Kirghiz language. + KY = lang.KY + // KV is Komi language. + KV = lang.KV + // KG is Kongo language. + KG = lang.KG + // KO is Korean language. + KO = lang.KO + // KJ is Kuanyama language. + KJ = lang.KJ + // KU is Kurdish language. + KU = lang.KU + // LO is Lao language. + LO = lang.LO + // LA is Latin language. + LA = lang.LA + // LV is Latvian language. + LV = lang.LV + // LI is Limburgan language. + LI = lang.LI + // LN is Lingala language. + LN = lang.LN + // LT is Lithuanian language. + LT = lang.LT + // LU is Luba Katanga language. + LU = lang.LU + // LB is Luxembourgish language. + LB = lang.LB + // MG is Malagasy language. + MG = lang.MG + // MS is Malay language. + MS = lang.MS + // ML is Malayalam language. + ML = lang.ML + // MT is Maltese language. + MT = lang.MT + // GV is Manx language. + GV = lang.GV + // MI is Maori language. + MI = lang.MI + // MR is Marathi language. + MR = lang.MR + // MH is Marshallese language. + MH = lang.MH + // MN is Mongolian language. + MN = lang.MN + // NA is Nauru language. + NA = lang.NA + // NV is Navajo language. + NV = lang.NV + // ND is NorthNdebele language. + ND = lang.ND + // NR is South Ndebele language. + NR = lang.NR + // NG is Ndonga language. + NG = lang.NG + // NE is Nepali language. + NE = lang.NE + // NN is Norwegian Nynorsk language. + NN = lang.NN + // II is Sichuan Yi language. + II = lang.II + // OC is Occitan language. + OC = lang.OC + // OJ is Ojibwa language. + OJ = lang.OJ + // OR is Oriya language. + OR = lang.OR + // OM is Oromo language. + OM = lang.OM + // OS is Ossetian language. + OS = lang.OS + // PI is Pali language. + PI = lang.PI + // PS is Pashto language. + PS = lang.PS + // FA is Persian language. + FA = lang.FA + // PL is Polish language. + PL = lang.PL + // PT is Portuguese language. + PT = lang.PT + // PA is Punjabi language. + PA = lang.PA + // QU is Quechua language. + QU = lang.QU + // RO is Romanian, Moldavian, Moldovan languages. + RO = lang.RO + // RM is Romansh language. + RM = lang.RM + // RN is Rundi language. + RN = lang.RN + // SE is Northern Sami language. + SE = lang.SE + // SM is Samoan language. + SM = lang.SM + // SG is Sango language. + SG = lang.SG + // SA is Sanskrit language. + SA = lang.SA + // SC is Sardinian language. + SC = lang.SC + // SN is Shona language. + SN = lang.SN + // SD is Sindhi language. + SD = lang.SD + // SI is Sinhala language. + SI = lang.SI + // SK is Slovak language. + SK = lang.SK + // SO is Somali language. + SO = lang.SO + // ST is Southern Sotho language. + ST = lang.ST + // ES is Spanish, Castilian language. + ES = lang.ES + // SU is Sundanese language. + SU = lang.SU + // SW is Swahili language. + SW = lang.SW + // SS is Swati language. + SS = lang.SS + // TL is Tagalog language. + TL = lang.TL + // TY is Tahitian language. + TY = lang.TY + // TG is Tajik language. + TG = lang.TG + // TA is Tamil language. + TA = lang.TA + // TT is Tatar language. + TT = lang.TT + // TE is Telugu language. + TE = lang.TE + // TH is Thai language. + TH = lang.TH + // BO is Tibetan language. + BO = lang.BO + // TI is Tigrinya language. + TI = lang.TI + // TO is Tonga language. + TO = lang.TO + // TS is Tsonga language. + TS = lang.TS + // TN is Tswana language. + TN = lang.TN + // TR is Turkish language. + TR = lang.TR + // TK is Turkmen language. + TK = lang.TK + // TW is Twi language. + TW = lang.TW + // UG is Uighur, Uyghur languages. + UG = lang.UG + // UR is Urdu language. + UR = lang.UR + // UZ is Uzbek language. + UZ = lang.UZ + // VE is Venda language. + VE = lang.VE + // VI is Vietnamese language. + VI = lang.VI + // VO is Volapuk language. + VO = lang.VO + // WA is Walloon language. + WA = lang.WA + // CY is Welsh language. + CY = lang.CY + // WO is Wolof language. + WO = lang.WO + // XH is Xhosa language. + XH = lang.XH + // YI is Yiddish language. + YI = lang.YI + // YO is Yoruba language. + YO = lang.YO + // ZS is Zhuang language. + ZS = lang.ZS + // ZA is Chuang language. + ZA = lang.ZA + // ZU is Zulu language. + ZU = lang.ZU +) diff --git a/methods.go b/methods.go new file mode 100644 index 0000000..6f55651 --- /dev/null +++ b/methods.go @@ -0,0 +1,24 @@ +package slug + +import ( + "strings" + + "github.com/goloop/t13n" + "github.com/goloop/t13n/lang" +) + +// Make returns slug from string. +func Make(t string) string { + var result string + + result = t13n.Render(lang.None, t, slugRules) + result = dusepRegx.ReplaceAllString(result, "-") + result = wrongRegx.ReplaceAllString(result, "") + + return result +} + +// Lower returns slug in lowercase. +func Lower(t string) string { + return strings.ToLower(Make(t)) +} diff --git a/methods_test.go b/methods_test.go new file mode 100644 index 0000000..81e0d5e --- /dev/null +++ b/methods_test.go @@ -0,0 +1,70 @@ +package slug + +import ( + "strings" + "testing" +) + +// TestVersion tests the package version. +// Note: each time you change the major version, you need to fix the tests. +func TestVersion(t *testing.T) { + var expected = "v0." // change it for major version + + version := Version() + if strings.HasPrefix(version, expected) != true { + t.Error("incorrect version") + } + + if len(strings.Split(version, ".")) != 3 { + t.Error("version format should be as " + + "v{major_version}.{minor_version}.{patch_version}") + } +} + +// TestMake tests Make function. +func TestMake(t *testing.T) { + var tests = []struct { + value string + expected string + }{ + { + "Starlink Ілона Маска відкриє офіс в Україні", + "Starlink-Ilona-Maska-vidkriie-ofis-v-Ukrayini", + }, + {"Hellö Wörld", "Hello-World"}, + {"你好世界", "Ni-Hao-Shi-Jie"}, + {"[^你好世界$]", "Ni-Hao-Shi-Jie"}, + {"This & that", "This-and-that"}, + {"\tHellö \t Wörld\n ", "Hello-World"}, + } + + for _, test := range tests { + if v := Make(test.value); v != test.expected { + t.Errorf("expected %s but %s", test.expected, v) + } + } +} + +// TestLower tests Lower function. +func TestLower(t *testing.T) { + var tests = []struct { + value string + expected string + }{ + { + "Starlink Ілона Маска відкриє офіс в Україні", + "starlink-ilona-maska-vidkriie-ofis-v-ukrayini", + }, + {"Hellö Wörld", "hello-world"}, + {"你好世界", "ni-hao-shi-jie"}, + {"[^你好世界$]", "ni-hao-shi-jie"}, + {"This & that", "this-and-that"}, + {"\tHellö \t Wörld\n ", "hello-world"}, + } + + for _, test := range tests { + if v := Lower(test.value); v != test.expected { + t.Errorf("expected %s but %s", test.expected, v) + } + } +} diff --git a/slug.go b/slug.go new file mode 100644 index 0000000..e25a136 --- /dev/null +++ b/slug.go @@ -0,0 +1,49 @@ +package slug + +import ( + "regexp" + "strings" + + "github.com/goloop/slug/lang" + "github.com/goloop/t13n" +) + +var ( + // Characters that are not allowed in the slug. + wrongRegx = regexp.MustCompile(`([^A-Za-z0-9\-]|-$|^-)`) + + // Duplicate separator. + dusepRegx = regexp.MustCompile(`-[-]+`) +) + +// New retursn pointer to Slug. +func New() *Slug { + return &Slug{lang: lang.None} +} + +// Slug is the slug constructor. +type Slug struct { + lang string +} + +// Lang sets the type of language features to use during slugify. +func (s *Slug) Lang(l string) *Slug { + s.lang = l + return s +} + +// Make returns slug from string. +func (s *Slug) Make(t string) string { + var result string + + result = t13n.Render(s.lang, t, slugRules) + result = dusepRegx.ReplaceAllString(result, "-") + result = wrongRegx.ReplaceAllString(result, "") + + return result +} + +// Lower returns slug in lowercase. +func (s *Slug) Lower(t string) string { + return strings.ToLower(s.Make(t)) +} diff --git a/slug_test.go b/slug_test.go new file mode 100644 index 0000000..d3771bf --- /dev/null +++ b/slug_test.go @@ -0,0 +1,59 @@ +package slug + +import ( + "testing" + + "github.com/goloop/slug/lang" +) + +// TestObjMake tests Make method. +func TestObjMake(t *testing.T) { + var tests = []struct { + value string + expected string + }{ + { + "Starlink Ілона Маска відкриє офіс в Україні", + "Starlink-Ilona-Maska-vidkryie-ofis-v-Ukraini", + }, + {"Hellö Wörld", "Hello-World"}, + {"你好世界", "Ni-Hao-Shi-Jie"}, + {"[^你好世界$]", "Ni-Hao-Shi-Jie"}, + {"This & that", "This-and-that"}, + {"\tHellö \t Wörld\n ", "Hello-World"}, + } + + s := New() + s.Lang(lang.UK) + for _, test := range tests { + if v := s.Make(test.value); v != test.expected { + t.Errorf("expected %s but %s", test.expected, v) + } + } +} + +// TestObjLower tests Lower method. +func TestObjLower(t *testing.T) { + var tests = []struct { + value string + expected string + }{ + { + "Starlink Ілона Маска відкриє офіс в Україні", + "starlink-ilona-maska-vidkryie-ofis-v-ukraini", + }, + {"Hellö Wörld", "hello-world"}, + {"你好世界", "ni-hao-shi-jie"}, + {"[^你好世界$]", "ni-hao-shi-jie"}, + {"This & that", "this-and-that"}, + {"\tHellö \t Wörld\n ", "hello-world"}, + } + + s := New() + s.Lang(lang.UK) + for _, test := range tests { + if v := s.Lower(test.value); v != test.expected { + t.Errorf("expected %s but %s", test.expected, v) + } + } +} diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..2d14033 --- /dev/null +++ b/tools.go @@ -0,0 +1,57 @@ +package slug + +import ( + "strings" + + "github.com/goloop/t13n/lang" +) + +// The slugRules sets additional transliteration rules +// for the github.com/goloop/t13n module. +func slugRules(ts lang.TransState) (string, int, bool) { + var lib = map[string]string{ + " ": "-", + "~": "-", + "_": "-", + "\t": "-", + "\n": "-", + "@": "at", + "&": "and", + "#": "harp", + "%": "percentage", + } + + if v, ok := lib[ts.Value]; ok { + ts.Value = v + } else { + var ignore = [][]int{ + {0, 47}, + {58, 64}, + {91, 96}, + {123, 141}, + {143, 152}, + {155, 155}, + } + + id := int(ts.Curr) + for _, d := range ignore { + if id < d[0] { + break + } + + if id >= d[0] && id <= d[1] { + ts.Value = "" + break + } + } + } + + if len(ts.Value) > 1 && strings.HasSuffix(ts.Value, " ") { + runes := []rune(ts.Value) + if ts.Next != 0 { + ts.Value = string(runes[:len(runes)-1]) + "-" + } + } + + return ts.Value, 0, true +} diff --git a/tools_test.go b/tools_test.go new file mode 100644 index 0000000..301efa6 --- /dev/null +++ b/tools_test.go @@ -0,0 +1,63 @@ +package slug + +import ( + "testing" + + "github.com/goloop/t13n/lang" +) + +// TestSlugRules tests slugRules function. +func TestSlugRules(t *testing.T) { + var tests = []struct { + item lang.TransState + value string + seek int + ok bool + }{ + { + item: lang.TransState{Curr: ' ', Value: " "}, + value: "-", + seek: 0, + ok: true, + }, + { + item: lang.TransState{Curr: '@', Value: "@"}, + value: "at", + seek: 0, + ok: true, + }, + { + item: lang.TransState{Curr: 'i', Value: "i"}, + value: "i", + seek: 0, + ok: true, + }, + { + item: lang.TransState{Curr: '世', Value: "shi"}, + value: "shi", + seek: 0, + ok: true, + }, + { + item: lang.TransState{Curr: '㹏', Next: '㹐', Value: "jin "}, + value: "jin-", + seek: 0, + ok: true, + }, + } + + for _, test := range tests { + value, seek, ok := slugRules(test.item) + if value != test.value { + t.Errorf("expected %s but %s", test.value, value) + } + + if seek != test.seek { + t.Errorf("expected %d but %d", test.seek, seek) + } + + if ok != test.ok { + t.Errorf("expected %t but %t", test.ok, ok) + } + } +}