1 {-# LANGUAGE OverloadedLists #-}
2 {-# LANGUAGE UndecidableInstances #-}
3 {-# OPTIONS_GHC -Wno-orphans #-}
5 module Literate.Document.HTML (
6 module Literate.Document.HTML,
7 module Text.Blaze.Html5,
8 module Text.Blaze.Renderer.Utf8,
12 import Data.Char qualified as Char
13 import Data.List qualified as List
14 import Data.Map.Strict qualified as Map
15 import Data.Text qualified as Text
16 import Data.Text.Short qualified as ShortText
17 import Literate.Document.Table
18 import Literate.Document.Type
19 import Literate.Prelude
21 import Text.Blaze.Html5
22 import Text.Blaze.Html5.Attributes qualified as HA
23 import Text.Blaze.Renderer.Utf8
24 import Prelude qualified
26 instance IsString AttributeValue
27 instance IsString Html
29 classes :: [String] -> Attribute
33 & List.filter (not . null)
35 & List.intersperse " "
38 className :: Show a => a -> String
40 x & show & List.map \c ->
45 type CSSBlock = Map String String
47 styles :: CSSBlock -> Attribute
50 [ toValue k <> ":" <> toValue v <> ";"
51 | (k, v) <- kvs & Map.toList
56 type CSS = Map [String] CSSBlock
57 styleCSS :: CSS -> Markup
61 $ [ mconcat [n <> " {" | n <- ns]
64 [ k <> ":" <> v <> ";"
65 | (k, v) <- kvs & Map.toList
68 <> mconcat [" }" | _n <- ns]
70 | (ns, kvs) <- m & Map.toList
79 instance ToMarkup ShortText where
80 toMarkup = ShortText.toText >>> toMarkup
81 preEscapedToMarkup = ShortText.toText >>> preEscapedToMarkup
83 instance ToCSS Text where
86 instance ToCSS Length where
88 LengthAbsolute x -> x & toCSS
89 LengthRelative x -> x & toCSS
90 instance ToCSS LengthAbsolute where
92 LengthAbsoluteMillimeters x -> show x <> "mm"
93 instance ToCSS LengthRelative where
95 LengthRelativeFractionalRatio x -> show x <> "fr"
96 LengthRelativeMaxContent -> "max-content"
97 LengthRelativeMinContent -> "min-content"
100 PageOrientationLandscape -> 29.7 & cm
101 PageOrientationPortrait -> 21.0 & cm
102 cssPageHeight = \case
103 PageOrientationLandscape -> 21.0 & cm
104 PageOrientationPortrait -> 29.7 & cm
108 PageSizeA4Plus -> "A4plus"
110 cssPageOrientation = \case
111 PageOrientationPortrait -> "portrait"
112 PageOrientationLandscape -> "landscape"
114 cssPrintPage :: PageOrientation -> PageSize -> CSS
115 cssPrintPage pageOrient pageSize =
120 [ cssPageSize pageSize
121 , cssPageOrientation pageOrient
128 cssBlockObjectFitCover :: CSSBlock
129 cssBlockObjectFitCover = ["object-fit" := "cover"]
131 instance ToMarkup Blocks where
132 toMarkup = foldMap toMarkup . unBlocks
133 instance ToMarkup Block where
135 BlockDiv x -> div $ x & toMarkup
136 BlockFlex x -> x & toMarkup
137 BlockPara (Inlines x) -> p $ x & foldMap toMarkup
138 BlockTable x -> x & toMarkup
139 instance ToMarkup Inline where
141 InlineText x -> x & toMarkup
142 instance ToMarkup FlexItem where
144 forM_ (itm & flexItemContent) toMarkup
145 instance ToMarkup Flex where
149 [ "display" := "flex"
150 , "flex-direction" := flx & flexDirection & toCSS
151 , "gap" := flx & flexGap & toCSS
154 forM_ (flx & flexItems) toMarkup
156 instance ToMarkup Table where
160 ! styles ["grid-template-columns" := tbl & tableTemplateFinal <&> toCSS & List.unwords]
162 forM_ (tbl & tableHeads) \hd -> do
163 div ! classes ["table-head"] $ do
164 forM_ (hd & tableHeadColumns) \cel -> do
165 div ! classes ["table-cell"] $ do
167 cel & tableCellContent & toMarkup
168 forM_ (tbl & tableRows & ol1) \(rowCount, row) -> do
169 div ! classes ["table-body", if even rowCount then "even" else "odd"] $ do
170 forM_ (row & tableRowColumns) \cel -> do
172 ! classes ["table-cell"]
173 ! styles ["justify-items" := cel & tableCellJustify & toCSS]
175 cel & tableCellContent & toMarkup
176 instance ToMarkup Dict where
181 forM_ (dic & dictEntries) \(key, val) ->
182 div ! classes ["dict-entry"] $ do
183 div ! classes ["dict-key"] $ do
185 div ! classes ["dict-value"] $ do
187 instance ToCSS Justification where
189 JustificationLeft -> "left"
190 JustificationBegin -> "begin"
191 JustificationCenter -> "center"
192 JustificationEnd -> "end"
193 JustificationRight -> "right"
194 instance ToCSS FlexDirection where
196 FlexDirectionColumn -> "column"
197 FlexDirectionRow -> "row"