packages feed

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

{-|
Description:    Token processing rules for content misnested within a @\<table\>@.
Copyright:      (c) 2020-2021 Sam May
License:        MPL-2.0
Maintainer:     ag.eitilt@gmail.com

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


import qualified Data.Foldable as D
import qualified Data.List as L
import qualified Data.Tuple.HT as U.HT

import Web.Mangrove.Parse.Common.Error
import Web.Mangrove.Parse.Tokenize.Common
import Web.Mangrove.Parse.Tree.Common
import Web.Mangrove.Parse.Tree.InTable
import Web.Mangrove.Parse.Tree.Patch
import Web.Willow.Common.Encoding.Character
import Web.Willow.Common.Parser
import Web.Willow.Common.Parser.Switch

import {-# SOURCE #-} Web.Mangrove.Parse.Tree.Dispatcher


-- | __HTML:__
--      @[the "in table text" insertion mode]
--      (https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-intabletext)@
-- 
-- The parsing instructions corresponding to the 'InTableText' section of the
-- state machine.
treeInTableText :: TreeBuilder TreeOutput
treeInTableText = do
    resetMode
    pending <- treeInTableText'
    let processF = if not $ all (maybe True isAsciiWhitespace . U.HT.snd3) pending
            then anythingElse
            else insertCharacter
    ps <- D.foldrM (repack processF) [] pending
    start <- packTree_ []
    return $ L.foldr foldOut start ps
  where repack _ ([], Nothing, _) [] = return []
        repack _ (errs, Nothing, _) [] = pure . consTreeErrors errs <$> dispatchHtml
        repack _ (errs, Nothing, _) (t:ts) = return $ consTreeErrors errs t : ts
        repack f (errs, Just c, state) ts = (: ts) <$> f (dummyStateToken errs (Character c) state)
        foldOut ps ps' = ps' { treePatches = treePatches ps ++ treePatches ps' }
        consTreeErrors = flip $ foldr consTreeError

-- | __HTML:__
--      @[the "in table" insertion mode]
--      (https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-intable)@
-- 
-- The parsing instructions corresponding to the 'InTableText' section of the
-- state machine.  Specifically, this consumes all following 'Character' tokens
-- to construct the list of [pending table character tokens]
-- (https://html.spec.whatwg.org/multipage/parsing.html#concept-pending-table-char-tokens),
-- while the surrounding 'treeInTableText' is what actually sends them to the
-- 'InTable' state for insertion.
treeInTableText' :: TreeBuilder [([ParseError], Maybe Char, TokenizerOutputState)]
treeInTableText' = next >>= switch
    [ If isNull $ \t' -> do
        cs <- treeInTableText'
        return $ (UnexpectedNullCharacter : tokenErrs t', Nothing, tokenState t') : cs
    , If isCharacter $ \t' -> do
        cs <- treeInTableText'
        return $ (tokenErrs t', tokenCharacter t', tokenState t') : cs
    , Else $ \t' -> do
        push t'
        return []
    ]