Created
February 5, 2016 10:15
-
-
Save alchi/6c9fb7c284de16940461 to your computer and use it in GitHub Desktop.
Scala implicit string slugifier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package utils.implicits | |
| import java.text.Normalizer | |
| import java.util.regex.Pattern | |
| import scala.annotation.tailrec | |
| import scala.language.implicitConversions | |
| object StringImplicits { | |
| private lazy val WHITESPACE = Pattern.compile("[\\s]") | |
| private lazy val NONLATIN = Pattern.compile("[^\\w-]") | |
| private lazy val specialChars: Map[Char, String] = Map( | |
| '+' -> "plus", | |
| // Latin-1 Supplement | |
| 'ß' -> "b", | |
| // Latin Extended-A | |
| 'đ' -> "d", | |
| 'ħ' -> "h", | |
| 'ı' -> "i", | |
| 'ij' -> "ij", | |
| 'ĸ' -> "k", | |
| 'ŀ' -> "l", | |
| 'ł' -> "l", | |
| 'ʼn' -> "n", | |
| 'ŋ' -> "n", | |
| 'œ' -> "oe", | |
| 'ŧ' -> "t", | |
| 'ſ' -> "s", | |
| '€' -> "e", | |
| '£' -> "l", | |
| 'æ' -> "ae", | |
| 'ø' -> "o", | |
| // Extras | |
| '.' -> "-", | |
| '_' -> "-" | |
| ) | |
| private def generateSlug(input: String): String = { | |
| // Remove extra dashes | |
| val isDash: (Char => Boolean) = _ == '-' | |
| input | |
| .trim | |
| .toLowerCase | |
| .whiteSpaceToDash | |
| .normalize | |
| .map(ch => specialChars.getOrElse(ch, ch)) // replace strange chars | |
| .mkString("") | |
| .removeNonLatin() // remove rest of nonlatin | |
| .replaceAll("(-){2,}", "-").dropWhile(isDash).dropWhileInverse(isDash) // remove extra dashes | |
| } | |
| implicit class SlugString(s: String) { | |
| def slugify: String = generateSlug(s) | |
| def slugify(similarSlugs: (String => List[String])): String = { | |
| val baseSlug = s.slugify | |
| val existingSlugs = similarSlugs(baseSlug) | |
| @tailrec | |
| def makeUnique(num: Int, str: String): String = if (existingSlugs.contains(str)) makeUnique(num + 1, s"$str-$num") else str | |
| makeUnique(0, baseSlug) | |
| } | |
| private[utils] def dropWhileInverse(p: Char => Boolean): String = s.dropRight(suffixLength(p, expectTrue = true)) | |
| private def suffixLength(p: Char => Boolean, expectTrue: Boolean): Int = { | |
| var i = 0 | |
| while (i < s.length && p(s.apply(s.length - i - 1)) == expectTrue) i += 1 | |
| i | |
| } | |
| private[utils] def normalize: String = Normalizer.normalize(s, Normalizer.Form.NFD) | |
| private[utils] def whiteSpaceToDash: String = WHITESPACE.matcher(s).replaceAll("-") | |
| private[utils] def removeNonLatin(): String = NONLATIN.matcher(s).replaceAll("") | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment