packages feed

willow-0.1.0.0: src/Web/Willow/Common/Encoding/Character.hs

{-# HLINT ignore "Use String" #-}

{-|
Description:    Iconic names and categories for various characters.

Copyright:      (c) 2020-2021 Sam May
License:        MPL-2.0
Maintainer:     ag.eitilt@gmail.com

Stability:      experimental
Portability:    portable
-}
module Web.Willow.Common.Encoding.Character
    ( replacementChar
      -- * ASCII Character Ranges
    , asciiWhitespace
    , isAsciiAlpha
    , isAsciiAlphaNum
    , isAsciiWhitespace
    , toAsciiLower
    , toAsciiUpper
    ) where


import qualified Data.Char as C


-- | __Infra:__
--      @[ASCII whitespace]
--      (https://infra.spec.whatwg.org/#ascii-whitespace)@
-- 
-- The ASCII characters defined as whitespace in the HTML standard.  Unlike
-- Haskell's 'Data.Char.isSpace' and anything following that example, does
-- /not/ include @\\x11@ (VT).
asciiWhitespace :: [Char]
asciiWhitespace = "\t\n\f\r "


-- | __Infra:__
--      @[ASCII alpha]
--      (https://infra.spec.whatwg.org/#ascii-alpha)@
-- 
-- Test whether the character is an alphabetic character in the ASCII range
-- (@[A-Za-z]@).
isAsciiAlpha :: Char -> Bool
isAsciiAlpha c = C.isAsciiUpper c || C.isAsciiLower c

-- | __Infra:__
--      @[ASCII alphanumeric]
--      (https://infra.spec.whatwg.org/#ascii-alphanumeric)@
-- 
-- Test whether the character is either an alphabetic character or a digit in
-- the ASCII range (@[A-Za-z0-9]@).
isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum c = isAsciiAlpha c || C.isDigit  c

-- | __Infra:__
--      @[ASCII whitespace]
--      (https://infra.spec.whatwg.org/#ascii-whitespace)@
-- 
-- Test whether the character fits the spec's definition of 'asciiWhitespace'.
isAsciiWhitespace :: Char -> Bool
isAsciiWhitespace = flip elem asciiWhitespace

-- | Convert an uppercase, alphabetic, ASCII character to its lowercase form.
-- This has the same semantics within the ASCII range as 'C.toLower', but
-- leaves any non-ASCII characters unchanged.
-- 
-- >>> toAsciiLower 'A'
-- 'a'
-- 
-- >>> toAsciiLower 'Á'
-- 'Á'
toAsciiLower :: Char -> Char
toAsciiLower c
    | C.isAsciiUpper c = C.toLower c
    | otherwise = c

-- | Convert a lowercase, alphabetic, ASCII character to its uppercase form.
-- This has the same semantics within the ASCII range as 'C.toUpper', but
-- leaves any non-ASCII characters unchanged.
-- 
-- >>> toAsciiUpper 'a'
-- 'A'
-- 
-- >>> toAsciiUpper 'á'
-- 'á'
toAsciiUpper :: Char -> Char
toAsciiUpper c
    | C.isAsciiLower c = C.toUpper c
    | otherwise = c


-- | The Unicode character @\\xFFFD@, safely (but unrecoverably) representing
-- an illegal, invalid, or otherwise unknown character.
replacementChar :: Char
replacementChar = '\xFFFD'