packages feed

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

{-|
Description:    Token processing rules within non-HTML content.

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

Stability:      stable
Portability:    portable
-}
module Web.Mangrove.Parse.Tree.Dispatcher
    ( dispatcher
    , dispatchHtml
    ) where


import qualified Control.Monad.Trans.State as N.S

import qualified Data.Text as T

import Web.Willow.DOM

import Web.Mangrove.Parse.Tree.Common
import Web.Mangrove.Parse.Tree.Patch
import Web.Willow.Common.Parser
import Web.Willow.Common.Parser.Switch

import Web.Mangrove.Parse.Tree.Initial
import Web.Mangrove.Parse.Tree.AfterAfterBody
import Web.Mangrove.Parse.Tree.AfterAfterFrameset
import Web.Mangrove.Parse.Tree.AfterBody
import Web.Mangrove.Parse.Tree.AfterFrameset
import Web.Mangrove.Parse.Tree.AfterHead
import Web.Mangrove.Parse.Tree.BeforeHead
import Web.Mangrove.Parse.Tree.BeforeHtml
import Web.Mangrove.Parse.Tree.Foreign
import Web.Mangrove.Parse.Tree.InBody
import Web.Mangrove.Parse.Tree.InCaption
import Web.Mangrove.Parse.Tree.InCell
import Web.Mangrove.Parse.Tree.InColumnGroup
import Web.Mangrove.Parse.Tree.InFrameset
import Web.Mangrove.Parse.Tree.InHead
import Web.Mangrove.Parse.Tree.InHeadNoscript
import Web.Mangrove.Parse.Tree.InRow
import Web.Mangrove.Parse.Tree.InSelect
import Web.Mangrove.Parse.Tree.InSelectInTable
import Web.Mangrove.Parse.Tree.InTable
import Web.Mangrove.Parse.Tree.InTableBody
import Web.Mangrove.Parse.Tree.InTableText
import Web.Mangrove.Parse.Tree.InTemplate
import Web.Mangrove.Parse.Tree.InText


-- | __HTML:__
--      @[tree construction dispatcher]
--      (https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher)@
-- 
-- Delegate parsing the binary stream to the appropriate content class: lenient
-- HTML (via insertion mode) or embedded, more-structured MathML/SVG content.
dispatcher :: TreeBuilder TreeOutput
dispatcher = dispatchToken
  where dispatchToken = do
            state <- N.S.get
            adjusted <- adjustedCurrentNode
            flip switch adjusted
                [ If_ (const $ null (openElements state)) dispatchHtml
                , If_ (\n -> (n >>= elementNamespace) == Just htmlNamespace) dispatchHtml
                , If_ (maybe False atMathMLIntegration) $ lookAhead next >>= switch
                    [ If_ (hasStartTagName $ T.pack "mglyph") treeForeign
                    , If_ (hasStartTagName $ T.pack "malignmark") treeForeign
                    , If_ isAnyStartTag dispatchHtml
                    , If_ isCharacter dispatchHtml
                    , Else_ treeForeign
                    ]
                , If_ (maybe False atHtmlIntegration) $ lookAhead next >>= switch
                    [ If_ isAnyStartTag dispatchHtml
                    , If_ isCharacter dispatchHtml
                    , Else_ treeForeign
                    ]
                -- 'isMathMLAnnotationXml' is less specific than
                -- 'atHtmlIntegration' and so needs to appear after it.
                , If_ (maybe False isMathMLAnnotationXml) $ lookAhead next >>= switch
                    [ If_ (hasStartTagName $ T.pack "svg") dispatchHtml
                    , Else_ treeForeign
                    ]
                , Else_ treeForeign
                ]
        hasStartTagName name t' = case tokenOut t' of
            StartTag d -> tagName d == name
            _ -> False


-- | __HTML:__
--      @[the rules for parsing tokens in HTML content]
--      (https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhtml)@
-- 
-- Defer processing of the current token to the instructions defined by the
-- active 'insertionMode'.
dispatchHtml :: TreeBuilder TreeOutput
dispatchHtml = N.S.get >>= \state -> case insertionMode state of
    Initial -> treeInitial
    BeforeHtml -> treeBeforeHtml
    BeforeHead -> treeBeforeHead
    InHead -> treeInHead
    InHeadNoscript -> treeInHeadNoscript
    AfterHead -> treeAfterHead
    InBody -> treeInBody
    InText -> treeInText
    InTable -> treeInTable
    InTableText -> treeInTableText
    InCaption -> treeInCaption
    InColumnGroup -> treeInColumnGroup
    InTableBody -> treeInTableBody
    InRow -> treeInRow
    InCell -> treeInCell
    InSelect -> treeInSelect
    InSelectInTable -> treeInSelectInTable
    InTemplate -> treeInTemplate
    AfterBody -> treeAfterBody
    InFrameset -> treeInFrameset
    AfterFrameset -> treeAfterFrameset
    AfterAfterBody -> treeAfterAfterBody
    AfterAfterFrameset -> treeAfterAfterFrameset