{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE GADTs #-} module Html.Type.Internal where import GHC.TypeLits import GHC.Exts import Data.Proxy import Data.Type.Bool {-# DEPRECATED Acronym , Applet , Basefont , Big , Blink , Center , Command , Content , Dir , Font , Frame , Frameset , Isindex , Keygen , Listing , Marquee , Multicol , Noembed , Plaintext , Shadow , Spacer , Strike , Tt , Xmp , Nextid "This is an obsolete html element and should not be used." #-} -- | The data type of all html elements and the kind of elements. data Element = DOCTYPE | A | Abbr | Acronym | Address | Applet | Area | Article | Aside | Audio | B | Base | Basefont | Bdi | Bdo | Bgsound | Big | Blink | Blockquote | Body | Br | Button | Canvas | Caption | Center | Cite | Code | Col | Colgroup | Command | Content | Data | Datalist | Dd | Del | Details | Dfn | Dialog | Dir | Div | Dl | Dt | Element | Em | Embed | Fieldset | Figcaption | Figure | Font | Footer | Form | Frame | Frameset | H1 | H2 | H3 | H4 | H5 | H6 | Head | Header | Hgroup | Hr | Html | I | Iframe | Image | Img | Input | Ins | Isindex | Kbd | Keygen | Label | Legend | Li | Link | Listing | Main | Map | Mark | Marquee | Math | Menu | Menuitem | Meta | Meter | Multicol | Nav | Nextid | Nobr | Noembed | Noframes | Noscript | Object | Ol | Optgroup | Option | Output | P | Param | Picture | Plaintext | Pre | Progress | Q | Rp | Rt | Rtc | Ruby | S | Samp | Script | Section | Select | Shadow | Slot | Small | Source | Spacer | Span | Strike | Strong | Style | Sub | Summary | Sup | Svg | Table | Tbody | Td | Template | Textarea | Tfoot | Th | Thead | Time | Title | Tr | Track | Tt | U | Ul | Var | Video | Wbr | Xmp data Attribute = AcceptA | AcceptCharsetA | AccesskeyA | ActionA | AlignA | AltA | AsyncA | AutocompleteA | AutofocusA | AutoplayA | AutosaveA | BgcolorA | BorderA | BufferedA | ChallengeA | CharsetA | CheckedA | CiteA | ClassA | CodeA | CodebaseA | ColorA | ColsA | ColspanA | ContentA | ContenteditableA | ContextmenuA | ControlsA | CoordsA | CrossoriginA | DataA | DatetimeA | DefaultA | DeferA | DirA | DirnameA | DisabledA | DownloadA | DraggableA | DropzoneA | EnctypeA | ForA | FormA | FormactionA | HeadersA | HeightA | HiddenA | HighA | HrefA | HreflangA | HttpEquivA | IconA | IdA | IntegrityA | IsmapA | ItempropA | KeytypeA | KindA | LabelA | LangA | LanguageA | ListA | LoopA | LowA | ManifestA | MaxA | MaxlengthA | MinlengthA | MediaA | MethodA | MinA | MultipleA | MutedA | NameA | NovalidateA | OpenA | OptimumA | PatternA | PingA | PlaceholderA | PosterA | PreloadA | RadiogroupA | ReadonlyA | RelA | RequiredA | ReversedA | RowsA | RowspanA | SandboxA | ScopeA | ScopedA | SeamlessA | SelectedA | ShapeA | SizeA | SizesA | SlotA | SpanA | SpellcheckA | SrcA | SrcdocA | SrclangA | SrcsetA | StartA | StepA | StyleA | SummaryA | TabindexA | TargetA | TitleA | TypeA | UsemapA | ValueA | WidthA | WrapA newtype (:=) (a :: Attribute) b = AT b -- | Check whether `b` is a valid child of `a`. You'll propably never -- need to call this directly. Through a GADT, it is enforced that -- every child is lawful. type family (a :: Element) ?> b :: Constraint where a ?> (b # c) = (a ?> b, a ?> c) a ?> (b :@: _) _ = MaybeTypeError a b (TestPaternity (SingleElement b) (GetInfo a) (GetInfo b)) a ?> Maybe b = a ?> b a ?> Either b c = (a ?> b, a ?> c) a ?> f ((b :@: c) d) = a ?> (b :@: c) d a ?> f (b # c) = a ?> (b # c) a ?> () = () a ?> (b -> c) = TypeError (Text "Html elements can't contain functions") a ?> b = CheckString a b type family (a :: Element) ??> b :: Constraint where a ??> () = () a ??> (b # c) = (a ??> b, a ??> c) a ??> (b := _) = If (Elem a (GetAttributeInfo b) || Null (GetAttributeInfo b)) (() :: Constraint) (TypeError (ShowType b :<>: Text " is not a valid attribute of " :<>: ShowType a)) a ??> b = TypeError (ShowType b :<>: Text " is not an attribute.") -- | Combine two elements or attributes sequentially. -- -- >>> i_ () # div_ () --
-- -- >>> i_A (A.id_ "a" # A.class_ "b") "c" -- c data (#) a b = (:#:) a b {-# INLINE (#) #-} (#) :: a -> b -> a # b (#) = (:#:) infixr 5 # -- | Type synonym for elements without attributes. type (>) a b = (:@:) a () b -- | Decorate an element with attributes and descend to a valid child. -- It is recommended to use the predefined elements. -- -- >>> WithAttributes (A.class_ "bar") "a" :: ('Div :@: ('ClassA := String)) String -- -- -- >>> div_A (A.class_ "bar") "a" -- -- -- >>> div_ "a" --