{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.Pandoc.XMLFormat
( decodeAttrName,
encodeAttrName,
atNameAlignment,
atNameApiVersion,
atNameCitationHash,
atNameCitationMode,
atNameCitationNoteNum,
atNameColspan,
atNameColWidth,
atNameFormat,
atNameImageUrl,
atNameLevel,
atNameLinkUrl,
atNameMathType,
atNameMetaBoolValue,
atNameMetaMapEntryKey,
atNameNumberDelim,
atNameNumberStyle,
atNameQuoteType,
atNameRowHeadColumns,
atNameRowspan,
atNameSpaceCount,
atNameStart,
atNameStrContent,
atNameTitle,
tgNameBodyBody,
tgNameBodyHeader,
tgNameCitations,
tgNameCitationPrefix,
tgNameCitationSuffix,
tgNameColspecs,
tgNameDefListDef,
tgNameDefListItem,
tgNameDefListTerm,
tgNameLineItem,
tgNameListItem,
tgNameMetaMapEntry,
tgNameShortCaption,
)
where
import Data.Char (chr, digitToInt, isAsciiLower, isAsciiUpper, isDigit, isHexDigit, ord, toUpper)
import Data.Text (Text)
import qualified Data.Text as T
import Numeric (showHex)
encodeAttrName :: Text -> Text
encodeAttrName :: Text -> Text
encodeAttrName Text
name =
case Text -> String
T.unpack Text
name of
[] -> Text
name
Char
c : String
cs
| Char -> Bool
isNameStartChar Char
c Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isNameChar String
cs Bool -> Bool -> Bool
&& Bool -> Bool
not (Text
"_x" Text -> Text -> Bool
`T.isInfixOf` Text
name) ->
Text
name
| Bool
otherwise ->
String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> String -> [String]
go Char -> Bool
isNameStartChar (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs)
where
go :: (Char -> Bool) -> String -> [String]
go Char -> Bool
_ [] = []
go Char -> Bool
ok (Char
c : String
cs)
| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
&& Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cs String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"x" = Char -> String
encodeChar Char
'_' String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (Char -> Bool) -> String -> [String]
go Char -> Bool
isNameChar String
cs
| Char -> Bool
ok Char
c = [Char
c] String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (Char -> Bool) -> String -> [String]
go Char -> Bool
isNameChar String
cs
| Bool
otherwise = Char -> String
encodeChar Char
c String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (Char -> Bool) -> String -> [String]
go Char -> Bool
isNameChar String
cs
encodeChar :: Char -> String
encodeChar Char
c = String
"_x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
h) Char
'0' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
h String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_"
where
h :: String
h = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String -> String
forall a. Integral a => a -> String -> String
showHex (Char -> Int
ord Char
c) String
""
decodeAttrName :: Text -> Text
decodeAttrName :: Text -> Text
decodeAttrName Text
name
| Text
"_x" Text -> Text -> Bool
`T.isInfixOf` Text
name = [Text] -> Text
T.concat ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ Text -> [Text]
go Text
name
| Bool
otherwise = Text
name
where
go :: Text -> [Text]
go Text
t =
case HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
"_x" Text
t of
(Text
pre, Text
rest)
| Text -> Bool
T.null Text
rest -> [Text
pre]
| Bool
otherwise ->
let body :: Text
body = Int -> Text -> Text
T.drop Int
2 Text
rest
digits :: Text
digits = (Char -> Bool) -> Text -> Text
T.takeWhile Char -> Bool
isHexDigit Text
body
n :: Int
n = Text -> Int
T.length Text
digits
code :: Int
code = (Int -> Char -> Int) -> Int -> Text -> Int
forall a. (a -> Char -> a) -> a -> Text -> a
T.foldl' (\Int
acc Char
d -> Int
16 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
digitToInt Char
d) Int
0 Text
digits
in if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
4
Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
6
Bool -> Bool -> Bool
&& Text
"_" Text -> Text -> Bool
`T.isPrefixOf` Int -> Text -> Text
T.drop Int
n Text
body
Bool -> Bool -> Bool
&& Int -> Bool
forall {a}. (Ord a, Num a) => a -> Bool
validChar Int
code
then Text
pre Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Char -> Text
T.singleton (Int -> Char
chr Int
code) Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Text -> [Text]
go (Int -> Text -> Text
T.drop (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Text
body)
else Text
pre Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Text
"_x" Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: Text -> [Text]
go Text
body
validChar :: a -> Bool
validChar a
code = a
code a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0x10FFFF Bool -> Bool -> Bool
&& Bool -> Bool
not (a
code a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
0xD800 Bool -> Bool -> Bool
&& a
code a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
0xDFFF)
isNameStartChar :: Char -> Bool
isNameStartChar :: Char -> Bool
isNameStartChar Char
c =
Char -> Bool
isAsciiUpper Char
c
Bool -> Bool -> Bool
|| Char -> Bool
isAsciiLower Char
c
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_'
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xC0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xD6')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xD8' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xF6')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xF8' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2FF')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x370' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x37D')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x37F' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x1FFF')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x200C' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x200D')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x2070' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x218F')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x2C00' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2FEF')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x3001' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xD7FF')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xF900' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xFDCF')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xFDF0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xFFFD')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x10000' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xEFFFF')
isNameChar :: Char -> Bool
isNameChar :: Char -> Bool
isNameChar Char
c =
Char -> Bool
isNameStartChar Char
c
Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.'
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\xB7'
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x300' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x36F')
Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x203F' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2040')
atNameApiVersion :: Text
atNameApiVersion :: Text
atNameApiVersion = Text
"api-version"
tgNameMetaMapEntry :: Text
tgNameMetaMapEntry :: Text
tgNameMetaMapEntry = Text
"entry"
atNameMetaMapEntryKey :: Text
atNameMetaMapEntryKey :: Text
atNameMetaMapEntryKey = Text
"key"
atNameMetaBoolValue :: Text
atNameMetaBoolValue :: Text
atNameMetaBoolValue = Text
"value"
atNameLevel :: Text
atNameLevel :: Text
atNameLevel = Text
"level"
atNameStart :: Text
atNameStart :: Text
atNameStart = Text
"start"
atNameNumberDelim :: Text
= Text
"number-delim"
atNameNumberStyle :: Text
= Text
"number-style"
atNameTitle :: Text
atNameTitle :: Text
atNameTitle = Text
"title"
atNameImageUrl :: Text
atNameImageUrl :: Text
atNameImageUrl = Text
"src"
atNameLinkUrl :: Text
atNameLinkUrl :: Text
atNameLinkUrl = Text
"href"
atNameQuoteType :: Text
atNameQuoteType :: Text
atNameQuoteType = Text
"quote-type"
atNameMathType :: Text
atNameMathType :: Text
atNameMathType = Text
"math-type"
atNameFormat :: Text
atNameFormat :: Text
atNameFormat = Text
"format"
atNameAlignment :: Text
atNameAlignment :: Text
atNameAlignment = Text
"alignment"
atNameColWidth :: Text
atNameColWidth :: Text
atNameColWidth = Text
"col-width"
atNameRowHeadColumns :: Text
atNameRowHeadColumns :: Text
atNameRowHeadColumns = Text
"row-head-columns"
atNameRowspan :: Text
atNameRowspan :: Text
atNameRowspan = Text
"row-span"
atNameColspan :: Text
atNameColspan :: Text
atNameColspan = Text
"col-span"
atNameCitationMode :: Text
atNameCitationMode :: Text
atNameCitationMode = Text
"mode"
atNameCitationHash :: Text
atNameCitationHash :: Text
atNameCitationHash = Text
"hash"
atNameCitationNoteNum :: Text
atNameCitationNoteNum :: Text
atNameCitationNoteNum = Text
"note-num"
atNameSpaceCount :: Text
atNameSpaceCount :: Text
atNameSpaceCount = Text
"count"
atNameStrContent :: Text
atNameStrContent :: Text
atNameStrContent = Text
"content"
tgNameCitations :: Text
tgNameCitations :: Text
tgNameCitations = Text
"citations"
tgNameCitationPrefix :: Text
tgNameCitationPrefix :: Text
tgNameCitationPrefix = Text
"prefix"
tgNameCitationSuffix :: Text
tgNameCitationSuffix :: Text
tgNameCitationSuffix = Text
"suffix"
tgNameListItem :: Text
tgNameListItem :: Text
tgNameListItem = Text
"item"
tgNameDefListItem :: Text
tgNameDefListItem :: Text
tgNameDefListItem = Text
"item"
tgNameDefListTerm :: Text
tgNameDefListTerm :: Text
tgNameDefListTerm = Text
"term"
tgNameDefListDef :: Text
tgNameDefListDef :: Text
tgNameDefListDef = Text
"def"
tgNameShortCaption :: Text
tgNameShortCaption :: Text
tgNameShortCaption = Text
"ShortCaption"
tgNameColspecs :: Text
tgNameColspecs :: Text
tgNameColspecs = Text
"colspecs"
tgNameBodyHeader :: Text
tgNameBodyHeader :: Text
tgNameBodyHeader = Text
"header"
tgNameBodyBody :: Text
tgNameBodyBody :: Text
tgNameBodyBody = Text
"body"
tgNameLineItem :: Text
tgNameLineItem :: Text
tgNameLineItem = Text
"line"