packages feed

mangrove-0.1.0.0: src/Web/Mangrove/Parse/Tree/AfterHead.hs

{-|
Description:    Token processing rules between the @\</head\>@ and @\<body\>@ tags.

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

Stability:      stable
Portability:    portable
-}
module Web.Mangrove.Parse.Tree.AfterHead
    ( treeAfterHead
    ) where


import qualified Data.Text as T

import Web.Mangrove.Parse.Common.Error
import Web.Mangrove.Parse.Tokenize.Common
import Web.Mangrove.Parse.Tree.Common
import Web.Mangrove.Parse.Tree.InBody
import Web.Mangrove.Parse.Tree.InHead
import Web.Mangrove.Parse.Tree.Patch
import Web.Willow.Common.Parser
import Web.Willow.Common.Parser.Switch


-- | __HTML:__
--      @[the "after head" insertion mode]
--      (https://html.spec.whatwg.org/multipage/parsing.html#the-after-head-insertion-mode)@
-- 
-- The parsing instructions corresponding to the 'AfterHead' section of the
-- state machine.
treeAfterHead :: TreeBuilder TreeOutput
treeAfterHead = next >>= switch
    [ If isWhitespace insertCharacter
    , If isComment insertComment
    , If isDoctype $ \t' ->
        packTreeErrors [UnexpectedDoctype $ tokenDocumentType t'] t'
    , If (isStartTag ["html"]) $ \t' -> do
        push t'
        treeInBody
    , If (isStartTag ["body"]) $ \t' -> do
        switchMode InBody
        setFramesetNotOk
        close <- closeCurrentNode_
        insert <- insertElement t'
        return $ close ++| insert
    , If (isStartTag ["frameset"]) $ \t' -> do
        switchMode InFrameset
        close <- closeCurrentNode_
        insert <- insertElement t'
        return $ close ++| insert
    , If (isStartTag
        [ "base"
        , "basefont"
        , "bgsound"
        , "link"
        , "meta"
        , "noframes"
        , "script"
        , "style"
        , "template"
        , "title"
        ]) $ \t' -> do
            push t'
            consTreeError UnexpectedMetadataOutsideOfHead <$> treeInHead
    , If (isEndTag ["template"]) $ \t' -> do
        push t'
        treeInHead
    , If (isEndTag ["body", "html", "br"]) anythingElse
    , If (isStartTag ["head"]) $ \t' ->
        packTreeErrors [DuplicateSingletonElement $ tokenElement t'] t'
    , If isAnyEndTag $ \t' ->
        packTreeErrors [UnmatchedEndTag $ tokenElement t'] t'
    , Else anythingElse
    ]
  where anythingElse t' = do
            push t'
            switchMode InBody
            close <- closeCurrentNode_
            insert <- insertElement_ $ emptyTagParams
                { tagName = T.pack "body"
                }
            packTree_ $ close ++ insert