1 {-# LANGUAGE DataKinds #-}
2 {-# LANGUAGE DuplicateRecordFields #-}
3 {-# LANGUAGE ExistentialQuantification #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE FlexibleContexts #-}
6 {-# LANGUAGE MultiParamTypeClasses #-}
7 {-# LANGUAGE OverloadedStrings #-}
8 {-# LANGUAGE ScopedTypeVariables #-}
9 {-# LANGUAGE TypeApplications #-}
10 {-# OPTIONS_GHC -fno-warn-orphans #-}
11 module Hdoc.DTC.Write.HTML5.Base where
13 import Control.Monad (Monad(..))
15 import Data.Char (Char)
16 import Data.Default.Class (Default(..))
17 import Data.Either (Either(..))
18 import Data.Foldable (Foldable(..))
19 import Data.Function (($), (.), id)
20 import Data.Functor ((<$>))
21 import Data.Functor.Compose (Compose(..))
23 import Data.Locale hiding (Index)
24 import Data.Maybe (Maybe(..), maybe)
25 import Data.Monoid (Monoid(..))
26 import Data.Semigroup (Semigroup(..))
27 import Data.Sequence (Seq)
28 import Data.String (String, IsString(..))
29 import Data.Text (Text)
31 import Text.Show (Show(..))
32 import qualified Control.Monad.Trans.RWS.Strict as RWS
33 import qualified Data.HashMap.Strict as HM
34 import qualified Data.HashSet as HS
35 import qualified Data.Text.Lazy as TL
36 import qualified Data.TreeMap.Strict as TM
37 import qualified Majority.Judgment as MJ
38 import qualified Text.Blaze.Html5 as H
39 import qualified Text.Blaze.Internal as H
41 import Control.Monad.Utils
43 import Hdoc.DTC.Document as DTC
44 import Hdoc.DTC.Write.XML ()
45 import qualified Hdoc.DTC.Analyze.Check as Analyze
46 import qualified Hdoc.DTC.Analyze.Collect as Analyze
47 -- import qualified Hdoc.DTC.Analyze.Index as Analyze
48 import qualified Hdoc.DTC.Write.Plain as Plain
49 import qualified Text.Blaze.Internal as B
52 type HTML5 = ComposeRWS Reader Writer State B.MarkupM ()
53 instance IsString HTML5 where
60 , Loqualize locales (L10n HTML5)
61 , Loqualize locales (Plain.L10n Plain.Plain)
64 { config_css :: Either FilePath TL.Text
65 , config_js :: Either FilePath TL.Text
66 , config_locale :: LocaleIn locales
67 , config_generator :: TL.Text
69 instance Default Config where
71 { config_css = Right "style/dtc-html5.css"
72 , config_js = Right "" -- "style/dtc-html5.js"
73 , config_locale = LocaleIn @'[EN] en_US
74 , config_generator = "https://hackage.haskell.org/package/hdoc"
79 { reader_l10n :: Loqualization (L10n HTML5)
80 , reader_plainify :: Plain.Reader
81 , reader_italic :: Bool
82 , reader_all :: Analyze.All
84 , reader_section :: [Section]
86 instance Default Reader where
88 { reader_l10n = Loqualization EN_US
89 , reader_plainify = def
90 , reader_italic = False
93 , reader_section = def
98 { writer_scripts :: HS.HashSet FilePath
99 , writer_styles :: HS.HashSet (Either FilePath TL.Text)
101 instance Default Writer where
103 { writer_scripts = def
104 , writer_styles = def
106 instance Semigroup Writer where
108 { writer_scripts = HS.union (writer_scripts x) (writer_scripts y)
109 , writer_styles = HS.union (writer_styles x) (writer_styles y)
111 instance Monoid Writer where
117 { state_errors :: !(Analyze.Errors Nat1)
118 , state_ref :: !(HM.HashMap Ident Nat1)
119 , state_at :: !(HM.HashMap Ident Nat1)
120 , state_tag :: !(HM.HashMap Ident Nat1)
121 , state_irefs :: !(TM.TreeMap Word Nat1)
122 , state_indices :: ![(Terms, Index)]
123 , state_notes :: ![Seq [Para]]
124 , state_note_num_ref :: !Nat1
125 , state_note_num_content :: !Nat1
126 , state_judgments :: !(HM.HashMap JudgmentKey [MJ.OpinionsByChoice Choice Name (MJ.Ranked Grade)])
128 instance Default State where
135 , state_indices = def
137 , state_note_num_ref = def
138 , state_note_num_content = def
139 , state_judgments = def
142 -- * Class 'Html5ify'
143 class Html5ify a where
144 html5ify :: a -> HTML5
145 instance Html5ify H.Markup where
146 html5ify = Compose . return
147 instance Html5ify Char where
148 html5ify = html5ify . H.toMarkup
149 instance Html5ify Text where
150 html5ify = html5ify . H.toMarkup
151 instance Html5ify TL.Text where
152 html5ify = html5ify . H.toMarkup
153 instance Html5ify String where
154 html5ify = html5ify . H.toMarkup
155 instance Html5ify Ident where
156 html5ify (Ident i) = html5ify i
157 instance Html5ify Int where
158 html5ify = html5ify . show
159 instance Html5ify Name where
160 html5ify (Name i) = html5ify i
161 instance Html5ify Nat where
162 html5ify (Nat n) = html5ify n
163 instance Html5ify Nat1 where
164 html5ify (Nat1 n) = html5ify n
165 instance Html5ify a => Html5ify (Maybe a) where
166 html5ify = foldMap html5ify
168 html5AttrClass :: [TL.Text] -> HTML5 -> HTML5
169 html5AttrClass = \case
173 (H.AddCustomAttribute "class"
174 (H.String $ TL.unpack $ TL.unwords cls) <$>) .
177 html5AttrId :: Ident -> HTML5 -> HTML5
178 html5AttrId (Ident id_) =
180 (H.AddCustomAttribute "id"
181 (H.String $ TL.unpack id_) <$>) .
184 html5CommonAttrs :: CommonAttrs -> HTML5 -> HTML5
185 html5CommonAttrs CommonAttrs{..} =
186 html5AttrClass attrs_classes .
187 maybe id html5AttrId attrs_id
191 ( Plain.L10n msg lang
192 , Plain.L10n TL.Text lang
193 ) => L10n msg lang where
194 l10n_Header_Address :: FullLocale lang -> msg
195 l10n_Header_Date :: FullLocale lang -> msg
196 l10n_Header_Version :: FullLocale lang -> msg
197 l10n_Header_Origin :: FullLocale lang -> msg
198 l10n_Header_Source :: FullLocale lang -> msg
199 l10n_Errors_All :: FullLocale lang -> Nat -> msg
200 l10n_Error_At_unknown :: FullLocale lang -> msg
201 l10n_Error_At_ambiguous :: FullLocale lang -> msg
202 l10n_Error_Rref_unknown :: FullLocale lang -> msg
203 l10n_Error_Reference_ambiguous :: FullLocale lang -> msg
204 l10n_Error_Judgment_Judges_unknown :: FullLocale lang -> msg
205 l10n_Error_Judgment_Judge_unknown :: FullLocale lang -> msg
206 l10n_Error_Judgment_Judge_duplicated :: FullLocale lang -> msg
207 l10n_Error_Judgment_Grades_unknown :: FullLocale lang -> msg
208 l10n_Error_Judgment_Grades_duplicated :: FullLocale lang -> msg
209 l10n_Error_Judgment_Grade_unknown :: FullLocale lang -> msg
210 l10n_Error_Judgment_Choice_duplicated :: FullLocale lang -> msg
211 instance L10n HTML5 EN where
212 l10n_Header_Address _l10n = "Address"
213 l10n_Header_Date _l10n = "Date"
214 l10n_Header_Origin _l10n = "Origin"
215 l10n_Header_Source _l10n = "Source"
216 l10n_Header_Version _l10n = "Version"
217 l10n_Errors_All _l10n n = "All errors ("<>html5ify n<>")"
218 l10n_Error_At_unknown _l10n = "Unknown anchor"
219 l10n_Error_At_ambiguous _l10n = "Ambiguous anchor"
220 l10n_Error_Rref_unknown _l10n = "Unknown reference"
221 l10n_Error_Reference_ambiguous _l10n = "Ambiguous reference"
222 l10n_Error_Judgment_Judges_unknown _l10n = "Unknown judges"
223 l10n_Error_Judgment_Judge_unknown _l10n = "Unknown judge"
224 l10n_Error_Judgment_Judge_duplicated _l10n = "Duplicated judge"
225 l10n_Error_Judgment_Grades_unknown _l10n = "Unknown grades"
226 l10n_Error_Judgment_Grades_duplicated _l10n = "Duplicated grades"
227 l10n_Error_Judgment_Grade_unknown _l10n = "Unknown grade"
228 l10n_Error_Judgment_Choice_duplicated _l10n = "Duplicated choice"
229 instance L10n HTML5 FR where
230 l10n_Header_Address _l10n = "Adresse"
231 l10n_Header_Date _l10n = "Date"
232 l10n_Header_Origin _l10n = "Origine"
233 l10n_Header_Source _l10n = "Source"
234 l10n_Header_Version _l10n = "Version"
235 l10n_Errors_All _l10n n = "Toutes les erreurs ("<>html5ify n<>")"
236 l10n_Error_At_unknown _l10n = "Ancre inconnue"
237 l10n_Error_At_ambiguous _l10n = "Ancre ambiguë"
238 l10n_Error_Rref_unknown _l10n = "Référence inconnue"
239 l10n_Error_Reference_ambiguous _l10n = "Référence ambiguë"
240 l10n_Error_Judgment_Judges_unknown _l10n = "Juges inconnu·es"
241 l10n_Error_Judgment_Judge_unknown _l10n = "Juge unconnu·e"
242 l10n_Error_Judgment_Judge_duplicated _l10n = "Juge en double"
243 l10n_Error_Judgment_Grades_unknown _l10n = "Mentions inconnues"
244 l10n_Error_Judgment_Grades_duplicated _l10n = "Mentions en double"
245 l10n_Error_Judgment_Grade_unknown _l10n = "Mention inconnue"
246 l10n_Error_Judgment_Choice_duplicated _l10n = "Choix en double"
248 instance Plain.L10n HTML5 EN where
249 l10n_Colon l10n = html5ify (Plain.l10n_Colon l10n :: TL.Text)
250 l10n_Table_of_Contents l10n = html5ify (Plain.l10n_Table_of_Contents l10n :: TL.Text)
251 l10n_Date date l10n = html5ify (Plain.l10n_Date date l10n :: TL.Text)
252 l10n_Quote msg _l10n = do
253 depth <- composeLift $ RWS.asks $ Plain.reader_quote . reader_plainify
254 let (o,c) :: (HTML5, HTML5) =
255 case unNat depth `mod` 3 of
260 localComposeRWS (\ro -> ro
261 {reader_plainify = (reader_plainify ro)
262 {Plain.reader_quote = succNat depth}}) $
265 instance Plain.L10n HTML5 FR where
266 l10n_Colon l10n = html5ify (Plain.l10n_Colon l10n :: TL.Text)
267 l10n_Table_of_Contents l10n = html5ify (Plain.l10n_Table_of_Contents l10n :: TL.Text)
268 l10n_Date date l10n = html5ify (Plain.l10n_Date date l10n :: TL.Text)
269 l10n_Quote msg _l10n = do
270 depth <- composeLift $ RWS.asks $ Plain.reader_quote . reader_plainify
271 let (o,c) :: (HTML5, HTML5) =
272 case unNat depth `mod` 3 of
277 localComposeRWS (\ro -> ro
278 {reader_plainify = (reader_plainify ro)
279 {Plain.reader_quote = succNat depth}}) $