commit e39a0b1334e3de54605d1c216322ff84c0908460 Author: Dobrosław Żybort Date: Wed Mar 13 15:14:21 2013 +0100 Add code diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..f9ccb39 --- /dev/null +++ b/.hgignore @@ -0,0 +1,30 @@ +## Defaults +syntax: glob +## Special files +*~ +[_]* + +## Compiled Go source +[568vq].out +*.[568vq] +*.[ao] +*.exe + +## Compiled Cgo source +*.cgo* +*.dll +*.so + +## Data +*.bin + +## Logs and databases +*.db +*.log +*.sql +*.sqlite + +## OS generated files +Icon? + +# * * * diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c34a71 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +slug +==== + +Package `slug` generate slug from unicode string. URL-friendly slugify with +multiple languages support. + +[Documentation online](http://godoc.org/bitbucket.org/gosimple/slug) + +## Example + + package main + + import( + "bitbucket.org/gosimple/slug" + "fmt" + ) + + text := slug.Make("Hellö Wörld хелло ворлд") + fmt.Println(text) // Will print: hello-world-khello-vorld + + someText := slug.Make("影師") + fmt.Println(someText) // Will print: ying-shi + + enText := slug.MakeLang("This & that", "en") + fmt.Println(enText) // Will print: this-and-that + + deText := slug.MakeLang("Diese & Dass", "de") + fmt.Println(deText) // Will print: diese-und-dass + +### Requests or bugs? + + +## Installation + + go get -u bitbucket.org/gosimple/slug + +## License + +The source files are distributed under the +[Mozilla Public License, version 2.0](http://mozilla.org/MPL/2.0/), +unless otherwise noted. +Please read the [FAQ](http://www.mozilla.org/MPL/2.0/FAQ.html) +if you have further questions regarding the license. diff --git a/default_substitution.go b/default_substitution.go new file mode 100644 index 0000000..847c85d --- /dev/null +++ b/default_substitution.go @@ -0,0 +1,16 @@ +// Copyright 2013 by Dobrosław Żybort. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package slug + +var defaultSub = map[rune]string{ + '"': "", + '\'': "", + '’': "", + '‒': "-", // figure dash + '–': "-", // en dash + '—': "-", // em dash + '―': "-", // horizontal bar +} diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..9f1ed8c --- /dev/null +++ b/doc.go @@ -0,0 +1,35 @@ +// Copyright 2013 by Dobrosław Żybort. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* +Package slug generate slug from unicode string. URL-friendly slugify with +multiple languages support. + +Example: + + package main + + import( + "bitbucket.org/gosimple/slug" + "fmt" + ) + + text := slug.Make("Hellö Wörld хелло ворлд") + fmt.Println(text) // Will print hello-world-khello-vorld + + someText := slug.Make("影師") + fmt.Println(someText) // Will print: ying-shi + + enText := slug.MakeLang("This & that", "en") + fmt.Println(enText) // Will print 'this-and-that' + + deText := slug.MakeLang("Diese & Dass", "de") + fmt.Println(deText) // Will print 'diese-und-dass' + +Requests or bugs? + +https://bitbucket.org/gosimple/slug/issues +*/ +package slug diff --git a/languages_substitution.go b/languages_substitution.go new file mode 100644 index 0000000..8671643 --- /dev/null +++ b/languages_substitution.go @@ -0,0 +1,21 @@ +// Copyright 2013 by Dobrosław Żybort. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package slug + +var deSub = map[rune]string{ + '&': "und", + '@': "an", +} + +var enSub = map[rune]string{ + '&': "and", + '@': "at", +} + +var plSub = map[rune]string{ + '&': "i", + '@': "na", +} diff --git a/slug.go b/slug.go new file mode 100644 index 0000000..5001e42 --- /dev/null +++ b/slug.go @@ -0,0 +1,61 @@ +// Copyright 2013 by Dobrosław Żybort. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package slug + +import ( + "github.com/fiam/gounidecode/unidecode" + "regexp" + "strings" +) + +//============================================================================= + +// Make returns slug generated from provided string. Will use "en" as language +// substitution. +func Make(s string) (slug string) { + return MakeLang(s, "en") +} + +// MakeLang returns slug generated from provided string and will use provided +// language for chars substitution. +func MakeLang(s string, lang string) (slug string) { + slug = strings.TrimSpace(s) + + // Select substitution language + switch lang { + case "de": + slug = substitute(slug, deSub) + case "en": + slug = substitute(slug, enSub) + case "pl": + slug = substitute(slug, plSub) + default: // fallback to "en" if lang not found + slug = substitute(slug, enSub) + } + + slug = substitute(slug, defaultSub) + + slug = unidecode.Unidecode(slug) + + slug = strings.ToLower(slug) + + slug = regexp.MustCompile("[^a-z0-9-_]").ReplaceAllString(slug, "-") + slug = regexp.MustCompile("-+").ReplaceAllString(slug, "-") + slug = strings.Trim(slug, "-") + return slug +} + +// Substitute string chars with provided substitution map. +func substitute(s string, sub map[rune]string) (buf string) { + for _, c := range s { + if d, ok := sub[c]; ok { + buf += d + } else { + buf += string(c) + } + } + return +} diff --git a/slug_test.go b/slug_test.go new file mode 100644 index 0000000..77d63aa --- /dev/null +++ b/slug_test.go @@ -0,0 +1,80 @@ +// Copyright 2013 by Dobrosław Żybort. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package slug + +import ( + "testing" +) + +//============================================================================= + +var SlugMakeTests = []struct { + in string + out string +}{ + {"DOBROSLAWZYBORT", "dobroslawzybort"}, + {"Dobroslaw Zybort", "dobroslaw-zybort"}, + {" Dobroslaw Zybort ?", "dobroslaw-zybort"}, + {"Dobrosław Żybort", "dobroslaw-zybort"}, + {"Ala ma 6 kotów.", "ala-ma-6-kotow"}, + + {"áÁàÀãÃâÂäÄąĄą̊Ą̊", "aaaaaaaaaaaaaa"}, + {"ćĆĉĈçÇ", "cccccc"}, + {"éÉèÈẽẼêÊëËęĘ", "eeeeeeeeeeee"}, + {"íÍìÌĩĨîÎïÏįĮ", "iiiiiiiiiiii"}, + {"łŁ", "ll"}, + {"ńŃ", "nn"}, + {"óÓòÒõÕôÔöÖǫǪǭǬø", "ooooooooooooooo"}, + {"śŚ", "ss"}, + {"úÚùÙũŨûÛüÜųŲ", "uuuuuuuuuuuu"}, + {"y̨Y̨", "yy"}, + {"źŹżŹ", "zzzz"}, + {"·/,:;`˜'\"", ""}, + {"2000–2013", "2000-2013"}, + {"style—not", "style-not"}, + {"test_slug", "test_slug"}, + {"Æ", "ae"}, + {"Ich heiße", "ich-heisse"}, + + {"This & that", "this-and-that"}, + {"fácil €", "facil-eu"}, + {"smile ☺", "smile"}, + {"Hellö Wörld хелло ворлд", "hello-world-khello-vorld"}, + {"\"C'est déjà l’été.\"", "cest-deja-lete"}, + {"jaja---lol-méméméoo--a", "jaja-lol-mememeoo-a"}, + {"影師", "ying-shi"}, +} + +func TestSlugMake(t *testing.T) { + for index, st := range SlugMakeTests { + slug := Make(st.in) + if st.out != slug { + t.Errorf( + "%d. Make(%v) => out = %v, want %v", + index, st.in, slug, st.out) + } + } +} + +var SlugMakeLangTests = []struct { + lang string + in string + out string +}{ + {"en", "This & that", "this-and-that"}, + {"de", "This & that", "this-und-that"}, +} + +func TestSlugMakeLang(t *testing.T) { + for index, smlt := range SlugMakeLangTests { + slug := MakeLang(smlt.in, smlt.lang) + if smlt.out != slug { + t.Errorf( + "%d. MakeLang(%v, \"%v\") => out = %v, want %v", + index, smlt.in, smlt.lang, slug, smlt.out) + } + } +}