{-# LANGUAGE OverloadedStrings #-}
module Text.Slugify (
SlugMode(SlugAscii, SlugUnicode)
, isWordSeparator, isWordChar, isRetainChar
, slugify, slugifyUnicode, slugifyWith
) where
import Data.Char(GeneralCategory(LowercaseLetter, ModifierLetter, OtherLetter, UppercaseLetter, TitlecaseLetter, DecimalNumber, LetterNumber, OtherNumber, LineSeparator, ParagraphSeparator, Space), isAscii, generalCategory)
import Data.Text(Text, dropAround, intercalate, split, toLower)
import qualified Data.Text as T
import Data.Text.Normalize(NormalizationMode(NFKC, NFKD), normalize)
data SlugMode
= SlugAscii
| SlugUnicode
deriving (SlugMode
SlugMode -> SlugMode -> Bounded SlugMode
forall a. a -> a -> Bounded a
maxBound :: SlugMode
$cmaxBound :: SlugMode
minBound :: SlugMode
$cminBound :: SlugMode
Bounded, Int -> SlugMode
SlugMode -> Int
SlugMode -> [SlugMode]
SlugMode -> SlugMode
SlugMode -> SlugMode -> [SlugMode]
SlugMode -> SlugMode -> SlugMode -> [SlugMode]
(SlugMode -> SlugMode)
-> (SlugMode -> SlugMode)
-> (Int -> SlugMode)
-> (SlugMode -> Int)
-> (SlugMode -> [SlugMode])
-> (SlugMode -> SlugMode -> [SlugMode])
-> (SlugMode -> SlugMode -> [SlugMode])
-> (SlugMode -> SlugMode -> SlugMode -> [SlugMode])
-> Enum SlugMode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SlugMode -> SlugMode -> SlugMode -> [SlugMode]
$cenumFromThenTo :: SlugMode -> SlugMode -> SlugMode -> [SlugMode]
enumFromTo :: SlugMode -> SlugMode -> [SlugMode]
$cenumFromTo :: SlugMode -> SlugMode -> [SlugMode]
enumFromThen :: SlugMode -> SlugMode -> [SlugMode]
$cenumFromThen :: SlugMode -> SlugMode -> [SlugMode]
enumFrom :: SlugMode -> [SlugMode]
$cenumFrom :: SlugMode -> [SlugMode]
fromEnum :: SlugMode -> Int
$cfromEnum :: SlugMode -> Int
toEnum :: Int -> SlugMode
$ctoEnum :: Int -> SlugMode
pred :: SlugMode -> SlugMode
$cpred :: SlugMode -> SlugMode
succ :: SlugMode -> SlugMode
$csucc :: SlugMode -> SlugMode
Enum, SlugMode -> SlugMode -> Bool
(SlugMode -> SlugMode -> Bool)
-> (SlugMode -> SlugMode -> Bool) -> Eq SlugMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SlugMode -> SlugMode -> Bool
$c/= :: SlugMode -> SlugMode -> Bool
== :: SlugMode -> SlugMode -> Bool
$c== :: SlugMode -> SlugMode -> Bool
Eq, Eq SlugMode
Eq SlugMode
-> (SlugMode -> SlugMode -> Ordering)
-> (SlugMode -> SlugMode -> Bool)
-> (SlugMode -> SlugMode -> Bool)
-> (SlugMode -> SlugMode -> Bool)
-> (SlugMode -> SlugMode -> Bool)
-> (SlugMode -> SlugMode -> SlugMode)
-> (SlugMode -> SlugMode -> SlugMode)
-> Ord SlugMode
SlugMode -> SlugMode -> Bool
SlugMode -> SlugMode -> Ordering
SlugMode -> SlugMode -> SlugMode
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SlugMode -> SlugMode -> SlugMode
$cmin :: SlugMode -> SlugMode -> SlugMode
max :: SlugMode -> SlugMode -> SlugMode
$cmax :: SlugMode -> SlugMode -> SlugMode
>= :: SlugMode -> SlugMode -> Bool
$c>= :: SlugMode -> SlugMode -> Bool
> :: SlugMode -> SlugMode -> Bool
$c> :: SlugMode -> SlugMode -> Bool
<= :: SlugMode -> SlugMode -> Bool
$c<= :: SlugMode -> SlugMode -> Bool
< :: SlugMode -> SlugMode -> Bool
$c< :: SlugMode -> SlugMode -> Bool
compare :: SlugMode -> SlugMode -> Ordering
$ccompare :: SlugMode -> SlugMode -> Ordering
$cp1Ord :: Eq SlugMode
Ord, ReadPrec [SlugMode]
ReadPrec SlugMode
Int -> ReadS SlugMode
ReadS [SlugMode]
(Int -> ReadS SlugMode)
-> ReadS [SlugMode]
-> ReadPrec SlugMode
-> ReadPrec [SlugMode]
-> Read SlugMode
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SlugMode]
$creadListPrec :: ReadPrec [SlugMode]
readPrec :: ReadPrec SlugMode
$creadPrec :: ReadPrec SlugMode
readList :: ReadS [SlugMode]
$creadList :: ReadS [SlugMode]
readsPrec :: Int -> ReadS SlugMode
$creadsPrec :: Int -> ReadS SlugMode
Read, Int -> SlugMode -> ShowS
[SlugMode] -> ShowS
SlugMode -> String
(Int -> SlugMode -> ShowS)
-> (SlugMode -> String) -> ([SlugMode] -> ShowS) -> Show SlugMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SlugMode] -> ShowS
$cshowList :: [SlugMode] -> ShowS
show :: SlugMode -> String
$cshow :: SlugMode -> String
showsPrec :: Int -> SlugMode -> ShowS
$cshowsPrec :: Int -> SlugMode -> ShowS
Show)
isWordSeparator
:: Char
-> Bool
isWordSeparator :: Char -> Bool
isWordSeparator Char
'-' = Bool
True
isWordSeparator Char
'\x0b' = Bool
True
isWordSeparator Char
'\x0c' = Bool
True
isWordSeparator Char
'\x1c' = Bool
True
isWordSeparator Char
'\x85' = Bool
True
isWordSeparator Char
'\t' = Bool
True
isWordSeparator Char
'\r' = Bool
True
isWordSeparator Char
'\x1d' = Bool
True
isWordSeparator Char
'\x1f' = Bool
True
isWordSeparator Char
'\x1e' = Bool
True
isWordSeparator Char
'\n' = Bool
True
isWordSeparator Char
c = case Char -> GeneralCategory
generalCategory Char
c of
GeneralCategory
LineSeparator -> Bool
True
GeneralCategory
ParagraphSeparator -> Bool
True
GeneralCategory
Space -> Bool
True
GeneralCategory
_ -> Bool
False
isWordChar
:: Char
-> Bool
isWordChar :: Char -> Bool
isWordChar Char
'_' = Bool
True
isWordChar Char
'\125259' = Bool
True
isWordChar Char
'\72162' = Bool
False
isWordChar Char
'\123215' = Bool
False
isWordChar Char
c = case Char -> GeneralCategory
generalCategory Char
c of
GeneralCategory
LowercaseLetter -> Bool
True
GeneralCategory
ModifierLetter -> Bool
True
GeneralCategory
OtherLetter -> Bool
True
GeneralCategory
UppercaseLetter -> Bool
True
GeneralCategory
TitlecaseLetter -> Bool
True
GeneralCategory
DecimalNumber -> Bool
True
GeneralCategory
LetterNumber -> Bool
True
GeneralCategory
OtherNumber -> Bool
True
GeneralCategory
_ -> Bool
False
_postDrop :: Char -> Bool
_postDrop :: Char -> Bool
_postDrop Char
'_' = Bool
True
_postDrop Char
'-' = Bool
True
_postDrop Char
_ = Bool
False
isRetainChar
:: Char
-> Bool
isRetainChar :: Char -> Bool
isRetainChar Char
c = Char -> Bool
isWordChar Char
c Bool -> Bool -> Bool
|| Char -> Bool
isWordSeparator Char
c
_slugify' :: Text -> Text
_slugify' :: Text -> Text
_slugify' = (Char -> Bool) -> Text -> Text
dropAround Char -> Bool
_postDrop (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> Text
intercalate Text
"-" ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null) ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> [Text]
split Char -> Bool
isWordSeparator (Text -> [Text]) -> (Text -> Text) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
T.filter Char -> Bool
isRetainChar (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
toLower
slugifyUnicode
:: Text
-> Text
slugifyUnicode :: Text -> Text
slugifyUnicode = Text -> Text
_slugify' (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NormalizationMode -> Text -> Text
normalize NormalizationMode
NFKC
slugify
:: Text
-> Text
slugify :: Text -> Text
slugify = Text -> Text
_slugify' (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
T.filter Char -> Bool
isAscii (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NormalizationMode -> Text -> Text
normalize NormalizationMode
NFKD
slugifyWith
:: SlugMode
-> Text
-> Text
slugifyWith :: SlugMode -> Text -> Text
slugifyWith SlugMode
SlugAscii = Text -> Text
slugify
slugifyWith SlugMode
SlugUnicode = Text -> Text
slugifyUnicode