Skip to content

Instantly share code, notes, and snippets.

@alchi
Created February 5, 2016 10:15
Show Gist options
  • Select an option

  • Save alchi/6c9fb7c284de16940461 to your computer and use it in GitHub Desktop.

Select an option

Save alchi/6c9fb7c284de16940461 to your computer and use it in GitHub Desktop.
Scala implicit string slugifier
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