{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | Defines types for zipping and iterating over HTML trees.
module Zenacy.HTML.Internal.Zip
  ( HTMLZipper
  , HTMLZipAction
  , HTMLIter
  , HTMLZipPath(..)
  , htmlZip
  , htmlZipM
  , htmlUnzip
  , htmlUnzipM
  , htmlZipNode
  , htmlZipNodeM
  , htmlZipRoot
  , htmlZipRootM
  , htmlZipUp
  , htmlZipParent
  , htmlZipFirst
  , htmlZipLast
  , htmlZipFind
  , htmlZipNext
  , htmlZipPrev
  , htmlZipGet
  , htmlZipTest
  , htmlZipTestNode
  , htmlZipTestName
  , htmlZipTestFirst
  , htmlZipTestLast
  , htmlZipModify
  , htmlZipModifyM
  , htmlZipDelete
  , htmlZipCollapse
  , htmlZipInsertBefore
  , htmlZipInsertAfter
  , htmlZipContentBefore
  , htmlZipContentAfter
  , htmlZipContentLeft
  , htmlZipContentRight
  , htmlZipDropBefore
  , htmlZipDropAfter
  , htmlZipDropLeft
  , htmlZipDropRight
  , htmlZipPruneBefore
  , htmlZipPruneAfter
  , htmlZipPruneLeft
  , htmlZipPruneRight
  , htmlZipRepeat
  , htmlZipStepNext
  , htmlZipStepBack
  , htmlZipSearch
  , htmlZipIndex
  , htmlIter
  , htmlIterZipper
  , htmlIterSearch
  , htmlIterModify
  , htmlIterNext
  , htmlIterBack
  , htmlZipPath
  , htmlZipPathEmpty
  , htmlZipPathFind
  ) where

import Zenacy.HTML.Internal.Core
import Zenacy.HTML.Internal.HTML
import Zenacy.HTML.Internal.Oper
import Control.Monad
  ( (>=>)
  )
import Data.Bool
  ( bool
  )
import Data.Default
  ( Default(..)
  )
import Data.Maybe
  ( fromMaybe
  , isNothing
  )
import Data.Monoid
  ( (<>)
  )
import Data.Text
  ( Text
  )
import qualified Data.Text as T
  ( unpack
  )

-- | The zipper crumb definition.
data HTMLCrumb = HTMLCrumb HTMLNode [HTMLNode] [HTMLNode]

-- | The zipper type.
data HTMLZipper = HTMLZipper HTMLNode [HTMLCrumb]

-- | Defines an action on a zipper.
type HTMLZipAction = HTMLZipper -> Maybe HTMLZipper

-- | Defines a zip direction.
data Direction = Down | Across | Up

-- | The zipper iterator type.
data HTMLIter = HTMLIter Direction HTMLZipper

-- | Defines the type for a path.
newtype HTMLZipPath = HTMLZipPath [Int] deriving (Int -> HTMLZipPath -> ShowS
[HTMLZipPath] -> ShowS
HTMLZipPath -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HTMLZipPath] -> ShowS
$cshowList :: [HTMLZipPath] -> ShowS
show :: HTMLZipPath -> String
$cshow :: HTMLZipPath -> String
showsPrec :: Int -> HTMLZipPath -> ShowS
$cshowsPrec :: Int -> HTMLZipPath -> ShowS
Show, HTMLZipPath -> HTMLZipPath -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HTMLZipPath -> HTMLZipPath -> Bool
$c/= :: HTMLZipPath -> HTMLZipPath -> Bool
== :: HTMLZipPath -> HTMLZipPath -> Bool
$c== :: HTMLZipPath -> HTMLZipPath -> Bool
Eq, Eq HTMLZipPath
HTMLZipPath -> HTMLZipPath -> Bool
HTMLZipPath -> HTMLZipPath -> Ordering
HTMLZipPath -> HTMLZipPath -> HTMLZipPath
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: HTMLZipPath -> HTMLZipPath -> HTMLZipPath
$cmin :: HTMLZipPath -> HTMLZipPath -> HTMLZipPath
max :: HTMLZipPath -> HTMLZipPath -> HTMLZipPath
$cmax :: HTMLZipPath -> HTMLZipPath -> HTMLZipPath
>= :: HTMLZipPath -> HTMLZipPath -> Bool
$c>= :: HTMLZipPath -> HTMLZipPath -> Bool
> :: HTMLZipPath -> HTMLZipPath -> Bool
$c> :: HTMLZipPath -> HTMLZipPath -> Bool
<= :: HTMLZipPath -> HTMLZipPath -> Bool
$c<= :: HTMLZipPath -> HTMLZipPath -> Bool
< :: HTMLZipPath -> HTMLZipPath -> Bool
$c< :: HTMLZipPath -> HTMLZipPath -> Bool
compare :: HTMLZipPath -> HTMLZipPath -> Ordering
$ccompare :: HTMLZipPath -> HTMLZipPath -> Ordering
Ord)

-- | Defaults for zip path.
instance Default HTMLZipPath where
  def :: HTMLZipPath
def = HTMLZipPath
htmlZipPathEmpty

-- | Creates a zipper for a HTML node.
htmlZip :: HTMLNode -> HTMLZipper
htmlZip :: HTMLNode -> HTMLZipper
htmlZip HTMLNode
x = HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
x []

-- | Creates a zipper for a HTML node in a Monad.
htmlZipM :: Monad m => HTMLNode -> m HTMLZipper
htmlZipM :: forall (m :: * -> *). Monad m => HTMLNode -> m HTMLZipper
htmlZipM = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLNode -> HTMLZipper
htmlZip

-- | Extracts the HTML node from a zipper.
htmlUnzip :: HTMLZipper -> HTMLNode
htmlUnzip :: HTMLZipper -> HTMLNode
htmlUnzip = HTMLZipper -> HTMLNode
htmlZipNode forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLZipper
htmlZipRoot

-- | Extracts the HTML node from a zipper in a Monad.
htmlUnzipM :: Monad m => HTMLZipper -> m HTMLNode
htmlUnzipM :: forall (m :: * -> *). Monad m => HTMLZipper -> m HTMLNode
htmlUnzipM = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLNode
htmlUnzip

-- | Gets the current HTML node.
htmlZipNode :: HTMLZipper -> HTMLNode
htmlZipNode :: HTMLZipper -> HTMLNode
htmlZipNode (HTMLZipper HTMLNode
x [HTMLCrumb]
_) = HTMLNode
x

-- | Gets the current HTML node in a Monad.
htmlZipNodeM :: Monad m => HTMLZipper -> m HTMLNode
htmlZipNodeM :: forall (m :: * -> *). Monad m => HTMLZipper -> m HTMLNode
htmlZipNodeM = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLNode
htmlZipNode

-- | Moves the zipper to the root HTML node.
htmlZipRoot :: HTMLZipper -> HTMLZipper
htmlZipRoot :: HTMLZipper -> HTMLZipper
htmlZipRoot HTMLZipper
x = forall b a. b -> (a -> b) -> Maybe a -> b
maybe HTMLZipper
x HTMLZipper -> HTMLZipper
htmlZipRoot forall a b. (a -> b) -> a -> b
$ HTMLZipper -> Maybe HTMLZipper
htmlZipParent HTMLZipper
x

-- | Moves the zipper to the root HTML node in a Monad.
htmlZipRootM :: Monad m => HTMLZipper -> m HTMLZipper
htmlZipRootM :: forall (m :: * -> *). Monad m => HTMLZipper -> m HTMLZipper
htmlZipRootM = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLZipper
htmlZipRoot

-- | Moves the zipper to the parent node.
htmlZipUp :: HTMLZipper -> Maybe HTMLZipper
htmlZipUp :: HTMLZipper -> Maybe HTMLZipper
htmlZipUp = HTMLZipper -> Maybe HTMLZipper
htmlZipParent

-- | Moves the zipper to the parent node.
htmlZipParent :: HTMLZipper -> Maybe HTMLZipper
htmlZipParent :: HTMLZipper -> Maybe HTMLZipper
htmlZipParent = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
ls [HTMLNode]
rs):[HTMLCrumb]
cs) ->
    let c :: [HTMLNode]
c = forall a. [a] -> [a]
reverse [HTMLNode]
ls forall a. Semigroup a => a -> a -> a
<> [HTMLNode
x] forall a. Semigroup a => a -> a -> a
<> [HTMLNode]
rs
    in case HTMLNode
n of
      HTMLDocument Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLDoctype Text
n Maybe Text
p Maybe Text
s ->
        forall a. Maybe a
Nothing
      HTMLFragment Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLTemplate HTMLNamespace
s [HTMLAttr]
a HTMLNode
c ->
        forall a. Maybe a
Nothing
      HTMLText Text
t ->
        forall a. Maybe a
Nothing
      HTMLComment Text
c ->
        forall a. Maybe a
Nothing

-- | Moves the zipper to the first child node.
htmlZipFirst :: HTMLZipper -> Maybe HTMLZipper
htmlZipFirst :: HTMLZipper -> Maybe HTMLZipper
htmlZipFirst (HTMLZipper HTMLNode
y [HTMLCrumb]
z) = case HTMLNode
y of
  HTMLDocument Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n []
  HTMLFragment Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n []
  HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a []
  HTMLNode
_ -> forall a. Maybe a
Nothing
  where
    f :: [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [] HTMLNode
n = forall a. Maybe a
Nothing
    f (HTMLNode
h:[HTMLNode]
rs) HTMLNode
n = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
h ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [] [HTMLNode]
rs)forall a. a -> [a] -> [a]
:[HTMLCrumb]
z)

-- | Moves the zipper to the last child node.
htmlZipLast :: HTMLZipper -> Maybe HTMLZipper
htmlZipLast :: HTMLZipper -> Maybe HTMLZipper
htmlZipLast (HTMLZipper HTMLNode
y [HTMLCrumb]
z) = case HTMLNode
y of
  HTMLDocument Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n []
  HTMLFragment Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n []
  HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a []
  HTMLNode
_ -> forall a. Maybe a
Nothing
  where
    f :: [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
xs HTMLNode
n =
      case forall a. [a] -> [a]
reverse [HTMLNode]
xs of
        (HTMLNode
h:[HTMLNode]
ls) ->
          forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
h ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [HTMLNode]
ls [])forall a. a -> [a] -> [a]
:[HTMLCrumb]
z)
        [] ->
          forall a. Maybe a
Nothing

-- | Moves the zipper to a named child element.
htmlZipFind :: (HTMLNode -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipFind :: (HTMLNode -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipFind HTMLNode -> Bool
p (HTMLZipper HTMLNode
y [HTMLCrumb]
z) = case HTMLNode
y of
  HTMLDocument Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n []
  HTMLFragment Text
n [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n []
  HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c ->
    [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c forall a b. (a -> b) -> a -> b
$ Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a []
  HTMLNode
_ -> forall a. Maybe a
Nothing
  where
    f :: [HTMLNode] -> HTMLNode -> Maybe HTMLZipper
f [HTMLNode]
c HTMLNode
n = case forall a. (a -> Bool) -> [a] -> ([a], [a])
break HTMLNode -> Bool
p [HTMLNode]
c of
      ([HTMLNode]
ls, []) -> forall a. Maybe a
Nothing
      ([HTMLNode]
ls, HTMLNode
h:[HTMLNode]
rs) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$
        HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
h ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n (forall a. [a] -> [a]
reverse [HTMLNode]
ls) [HTMLNode]
rs)forall a. a -> [a] -> [a]
:[HTMLCrumb]
z)

-- | Moves to the next sibling.
htmlZipNext :: HTMLZipper -> Maybe HTMLZipper
htmlZipNext :: HTMLZipper -> Maybe HTMLZipper
htmlZipNext = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
ls []):[HTMLCrumb]
cs) -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
ls (HTMLNode
h:[HTMLNode]
rs)):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
h ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n (HTMLNode
xforall a. a -> [a] -> [a]
:[HTMLNode]
ls) [HTMLNode]
rs)forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Moves to the previous sibling.
htmlZipPrev :: HTMLZipper -> Maybe HTMLZipper
htmlZipPrev :: HTMLZipper -> Maybe HTMLZipper
htmlZipPrev = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [] [HTMLNode]
rs):[HTMLCrumb]
cs) -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n (HTMLNode
h:[HTMLNode]
ls) [HTMLNode]
rs):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
h ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [HTMLNode]
ls (HTMLNode
xforall a. a -> [a] -> [a]
:[HTMLNode]
rs))forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Gets the child specified by an index.
htmlZipGet :: Int -> HTMLZipper -> Maybe HTMLZipper
htmlZipGet :: Int -> HTMLZipper -> Maybe HTMLZipper
htmlZipGet Int
n HTMLZipper
z
  | Int
n forall a. Ord a => a -> a -> Bool
< Int
0 = forall a. Maybe a
Nothing
  | Int
n forall a. Eq a => a -> a -> Bool
== Int
0 = HTMLZipper -> Maybe HTMLZipper
htmlZipFirst HTMLZipper
z
  | Bool
otherwise = HTMLZipper -> Maybe HTMLZipper
htmlZipFirst HTMLZipper
z forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall {t}. (Eq t, Num t) => t -> HTMLZipper -> Maybe HTMLZipper
f Int
n
  where
    f :: t -> HTMLZipper -> Maybe HTMLZipper
f t
0 = forall a. a -> Maybe a
Just
    f t
n = HTMLZipper -> Maybe HTMLZipper
htmlZipNext forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> t -> HTMLZipper -> Maybe HTMLZipper
f (t
n forall a. Num a => a -> a -> a
- t
1)

-- | Continues a zipper if a test is passed.
htmlZipTest :: (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest :: (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest HTMLZipper -> Bool
f HTMLZipper
z = forall a. a -> a -> Bool -> a
bool forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just HTMLZipper
z) forall a b. (a -> b) -> a -> b
$ HTMLZipper -> Bool
f HTMLZipper
z

-- | Continues a zipper if a node test is passed.
htmlZipTestNode :: (HTMLNode -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTestNode :: (HTMLNode -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTestNode HTMLNode -> Bool
f = (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest forall a b. (a -> b) -> a -> b
$ HTMLNode -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLNode
htmlZipNode

-- | Tests the current node for an element name.
htmlZipTestName :: Text -> HTMLZipper -> Maybe HTMLZipper
htmlZipTestName :: Text -> HTMLZipper -> Maybe HTMLZipper
htmlZipTestName Text
x = (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest (Text -> HTMLNode -> Bool
htmlElemHasName Text
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> HTMLNode
htmlZipNode)

-- | Test whether the zipper is at the first child node.
htmlZipTestFirst :: HTMLZipper -> Maybe HTMLZipper
htmlZipTestFirst :: HTMLZipper -> Maybe HTMLZipper
htmlZipTestFirst = (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest (forall a. Maybe a -> Bool
isNothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> Maybe HTMLZipper
htmlZipPrev)

-- | Test whether the zipper is at the last child node.
htmlZipTestLast :: HTMLZipper -> Maybe HTMLZipper
htmlZipTestLast :: HTMLZipper -> Maybe HTMLZipper
htmlZipTestLast = (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipTest (forall a. Maybe a -> Bool
isNothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipper -> Maybe HTMLZipper
htmlZipNext)

-- | Modifies the currently focused node.
htmlZipModify :: (HTMLNode -> HTMLNode) -> HTMLZipper -> HTMLZipper
htmlZipModify :: (HTMLNode -> HTMLNode) -> HTMLZipper -> HTMLZipper
htmlZipModify HTMLNode -> HTMLNode
f (HTMLZipper HTMLNode
y [HTMLCrumb]
z) = HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (HTMLNode -> HTMLNode
f HTMLNode
y) [HTMLCrumb]
z

-- | Modifies the currently focused node in a Monad.
htmlZipModifyM :: Monad m => (HTMLNode -> HTMLNode) -> HTMLZipper -> m HTMLZipper
htmlZipModifyM :: forall (m :: * -> *).
Monad m =>
(HTMLNode -> HTMLNode) -> HTMLZipper -> m HTMLZipper
htmlZipModifyM HTMLNode -> HTMLNode
f = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HTMLNode -> HTMLNode) -> HTMLZipper -> HTMLZipper
htmlZipModify HTMLNode -> HTMLNode
f

-- | Deletes the current node.
htmlZipDelete :: HTMLZipper -> Maybe HTMLZipper
htmlZipDelete :: HTMLZipper -> Maybe HTMLZipper
htmlZipDelete = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) ->
    let c :: [HTMLNode]
c = forall a. [a] -> [a]
reverse [HTMLNode]
l forall a. Semigroup a => a -> a -> a
<> [HTMLNode]
r
    in case HTMLNode
n of
      HTMLDocument Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLFragment Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLNode
_ -> forall a. Maybe a
Nothing

-- | Collapses the current node.
htmlZipCollapse :: HTMLZipper -> Maybe HTMLZipper
htmlZipCollapse :: HTMLZipper -> Maybe HTMLZipper
htmlZipCollapse = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) ->
    let c :: [HTMLNode]
c = forall a. [a] -> [a]
reverse [HTMLNode]
l forall a. Semigroup a => a -> a -> a
<> HTMLNode -> [HTMLNode]
htmlNodeContent HTMLNode
x forall a. Semigroup a => a -> a -> a
<> [HTMLNode]
r
    in case HTMLNode
n of
      HTMLDocument Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLDocument Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLFragment Text
n [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> [HTMLNode] -> HTMLNode
HTMLFragment Text
n [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [] ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper (Text -> HTMLNamespace -> [HTMLAttr] -> [HTMLNode] -> HTMLNode
HTMLElement Text
n HTMLNamespace
s [HTMLAttr]
a [HTMLNode]
c) [HTMLCrumb]
cs
      HTMLNode
_ -> forall a. Maybe a
Nothing

-- | Inserts a node before the current node.
htmlZipInsertBefore :: HTMLNode -> HTMLZipper -> Maybe HTMLZipper
htmlZipInsertBefore :: HTMLNode -> HTMLZipper -> Maybe HTMLZipper
htmlZipInsertBefore HTMLNode
y = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
x ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n (HTMLNode
yforall a. a -> [a] -> [a]
:[HTMLNode]
l) [HTMLNode]
r)forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Inserts a node after the current node.
htmlZipInsertAfter :: HTMLNode -> HTMLZipper -> Maybe HTMLZipper
htmlZipInsertAfter :: HTMLNode -> HTMLZipper -> Maybe HTMLZipper
htmlZipInsertAfter HTMLNode
y = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
x ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [HTMLNode]
l (HTMLNode
yforall a. a -> [a] -> [a]
:[HTMLNode]
r))forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Gets the siblings to the left of the current node.
htmlZipContentBefore :: HTMLZipper -> [HTMLNode]
htmlZipContentBefore :: HTMLZipper -> [HTMLNode]
htmlZipContentBefore = \case
  HTMLZipper HTMLNode
x [] -> []
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) -> forall a. [a] -> [a]
reverse [HTMLNode]
l

-- | Gets the siblings to the right of the current node.
htmlZipContentAfter :: HTMLZipper -> [HTMLNode]
htmlZipContentAfter :: HTMLZipper -> [HTMLNode]
htmlZipContentAfter = \case
  HTMLZipper HTMLNode
x [] -> []
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
r):[HTMLCrumb]
cs) -> [HTMLNode]
r

-- | Synonym for htmlZipContentBefore.
htmlZipContentLeft :: HTMLZipper -> [HTMLNode]
htmlZipContentLeft :: HTMLZipper -> [HTMLNode]
htmlZipContentLeft = HTMLZipper -> [HTMLNode]
htmlZipContentBefore

-- | Synonym for htmlZipContentAfter.
htmlZipContentRight :: HTMLZipper -> [HTMLNode]
htmlZipContentRight :: HTMLZipper -> [HTMLNode]
htmlZipContentRight = HTMLZipper -> [HTMLNode]
htmlZipContentAfter

-- | Drops the siblings to the left of the current node.
htmlZipDropBefore :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropBefore :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropBefore = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
_ [HTMLNode]
r):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
x ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [] [HTMLNode]
r)forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Drops the siblings to the right of the current node.
htmlZipDropAfter :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropAfter :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropAfter = \case
  HTMLZipper HTMLNode
x [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
x ((HTMLCrumb HTMLNode
n [HTMLNode]
l [HTMLNode]
_):[HTMLCrumb]
cs) ->
    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ HTMLNode -> [HTMLCrumb] -> HTMLZipper
HTMLZipper HTMLNode
x ((HTMLNode -> [HTMLNode] -> [HTMLNode] -> HTMLCrumb
HTMLCrumb HTMLNode
n [HTMLNode]
l [])forall a. a -> [a] -> [a]
:[HTMLCrumb]
cs)

-- | Synonym for htmlZipDropBefore.
htmlZipDropLeft :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropLeft :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropLeft = HTMLZipper -> Maybe HTMLZipper
htmlZipDropBefore

-- | Synonym for htmlZipDropAfter.
htmlZipDropRight :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropRight :: HTMLZipper -> Maybe HTMLZipper
htmlZipDropRight = HTMLZipper -> Maybe HTMLZipper
htmlZipDropAfter

-- | Drops all of the branches to the left of the current node
--   while moving up to and ending at the root.
htmlZipPruneBefore :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneBefore :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneBefore = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipRepeat HTMLZipper -> Maybe HTMLZipper
safeDrop HTMLZipper -> Maybe HTMLZipper
htmlZipParent
  where
    safeDrop :: HTMLZipper -> Maybe HTMLZipper
safeDrop HTMLZipper
z = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe HTMLZipper
z forall a b. (a -> b) -> a -> b
$ HTMLZipper -> Maybe HTMLZipper
htmlZipDropBefore HTMLZipper
z

-- | Drops all of the branches to the right of the current node
--   while moving up to and ending at the root.
htmlZipPruneAfter :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneAfter :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneAfter = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipRepeat HTMLZipper -> Maybe HTMLZipper
safeDrop HTMLZipper -> Maybe HTMLZipper
htmlZipParent
  where
    safeDrop :: HTMLZipper -> Maybe HTMLZipper
safeDrop HTMLZipper
z = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe HTMLZipper
z forall a b. (a -> b) -> a -> b
$ HTMLZipper -> Maybe HTMLZipper
htmlZipDropAfter HTMLZipper
z

-- | Synonym for htmlZipPruneBefore.
htmlZipPruneLeft :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneLeft :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneLeft = HTMLZipper -> Maybe HTMLZipper
htmlZipPruneBefore

-- | Synonym for htmlZipPruneAfter.
htmlZipPruneRight :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneRight :: HTMLZipper -> Maybe HTMLZipper
htmlZipPruneRight = HTMLZipper -> Maybe HTMLZipper
htmlZipPruneAfter

-- | Repeats a zipper action until another zipper returns Nothing.
htmlZipRepeat :: HTMLZipAction -> HTMLZipAction -> HTMLZipAction
htmlZipRepeat :: (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipRepeat HTMLZipper -> Maybe HTMLZipper
f HTMLZipper -> Maybe HTMLZipper
g HTMLZipper
z =
  case HTMLZipper -> Maybe HTMLZipper
f HTMLZipper
z of
    Maybe HTMLZipper
Nothing -> forall a. Maybe a
Nothing
    Just HTMLZipper
z1 -> case HTMLZipper -> Maybe HTMLZipper
g HTMLZipper
z1 of
      Maybe HTMLZipper
Nothing -> forall a. a -> Maybe a
Just HTMLZipper
z1
      Just HTMLZipper
z2 -> (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipRepeat HTMLZipper -> Maybe HTMLZipper
f HTMLZipper -> Maybe HTMLZipper
g HTMLZipper
z2

-- | Step a zipper forward one node.
htmlZipStepNext :: HTMLZipper -> Maybe HTMLZipper
htmlZipStepNext :: HTMLZipper -> Maybe HTMLZipper
htmlZipStepNext = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipStep HTMLZipper -> Maybe HTMLZipper
htmlZipFirst HTMLZipper -> Maybe HTMLZipper
htmlZipNext

-- | Step a zipper back one node.
htmlZipStepBack :: HTMLZipper -> Maybe HTMLZipper
htmlZipStepBack :: HTMLZipper -> Maybe HTMLZipper
htmlZipStepBack = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipStep HTMLZipper -> Maybe HTMLZipper
htmlZipLast HTMLZipper -> Maybe HTMLZipper
htmlZipPrev

-- | Step a zipper.
htmlZipStep :: HTMLZipAction -> HTMLZipAction -> HTMLZipAction
htmlZipStep :: (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper)
-> HTMLZipper
-> Maybe HTMLZipper
htmlZipStep HTMLZipper -> Maybe HTMLZipper
first HTMLZipper -> Maybe HTMLZipper
next HTMLZipper
z =
  case HTMLZipper -> Maybe HTMLZipper
first HTMLZipper
z of
    Just HTMLZipper
x -> forall a. a -> Maybe a
Just HTMLZipper
x
    Maybe HTMLZipper
Nothing -> HTMLZipper -> Maybe HTMLZipper
f HTMLZipper
z
  where
    f :: HTMLZipper -> Maybe HTMLZipper
f HTMLZipper
x = case HTMLZipper -> Maybe HTMLZipper
next HTMLZipper
x of
      Just HTMLZipper
a -> forall a. a -> Maybe a
Just HTMLZipper
a
      Maybe HTMLZipper
Nothing -> case HTMLZipper -> Maybe HTMLZipper
htmlZipParent HTMLZipper
x of
        Just HTMLZipper
b -> HTMLZipper -> Maybe HTMLZipper
f HTMLZipper
b
        Maybe HTMLZipper
Nothing -> forall a. Maybe a
Nothing

-- | Searches a zipper until a predicate is true.
htmlZipSearch
  :: (HTMLZipper -> Maybe HTMLZipper)
  -> (HTMLZipper -> Bool)
  -> HTMLZipper
  -> Maybe HTMLZipper
htmlZipSearch :: (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipSearch HTMLZipper -> Maybe HTMLZipper
step HTMLZipper -> Bool
test HTMLZipper
x
  | HTMLZipper -> Bool
test HTMLZipper
x = forall a. a -> Maybe a
Just HTMLZipper
x
  | Bool
otherwise = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Maybe a
Nothing ((HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Bool) -> HTMLZipper -> Maybe HTMLZipper
htmlZipSearch HTMLZipper -> Maybe HTMLZipper
step HTMLZipper -> Bool
test) forall a b. (a -> b) -> a -> b
$ HTMLZipper -> Maybe HTMLZipper
step HTMLZipper
x

-- | Gets the index for a node.
htmlZipIndex :: HTMLZipper -> Maybe Int
htmlZipIndex :: HTMLZipper -> Maybe Int
htmlZipIndex = \case
  HTMLZipper HTMLNode
_ [] -> forall a. Maybe a
Nothing
  HTMLZipper HTMLNode
_ ((HTMLCrumb HTMLNode
_ [HTMLNode]
ls [HTMLNode]
_):[HTMLCrumb]
_) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [HTMLNode]
ls

-- | Dumps a zipper to a string.
htmlZipDump :: HTMLZipper -> String
htmlZipDump :: HTMLZipper -> String
htmlZipDump (HTMLZipper HTMLNode
n [HTMLCrumb]
cs) =
  HTMLNode -> String
name HTMLNode
n forall a. Semigroup a => a -> a -> a
<> String
"\n" forall a. Semigroup a => a -> a -> a
<> [HTMLCrumb] -> String
go [HTMLCrumb]
cs
  where
    go :: [HTMLCrumb] -> String
    go :: [HTMLCrumb] -> String
go [] = String
""
    go ((HTMLCrumb HTMLNode
n [HTMLNode]
ls [HTMLNode]
rs):[HTMLCrumb]
cs) =
      HTMLNode -> String
name HTMLNode
n forall a. Semigroup a => a -> a -> a
<> String
"\n"
      forall a. Semigroup a => a -> a -> a
<> String
" ls: " forall a. Semigroup a => a -> a -> a
<> [HTMLNode] -> String
names [HTMLNode]
ls forall a. Semigroup a => a -> a -> a
<> String
"\n"
      forall a. Semigroup a => a -> a -> a
<> String
" rs: " forall a. Semigroup a => a -> a -> a
<> [HTMLNode] -> String
names [HTMLNode]
rs forall a. Semigroup a => a -> a -> a
<> String
"\n"
      forall a. Semigroup a => a -> a -> a
<> [HTMLCrumb] -> String
go [HTMLCrumb]
cs
    name :: HTMLNode -> String
name = Text -> String
T.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLNode -> Text
htmlElemName
    names :: [HTMLNode] -> String
names = forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map HTMLNode -> String
name

-- | Returns an iterator for a zipper.
htmlIter :: HTMLZipper -> HTMLIter
htmlIter :: HTMLZipper -> HTMLIter
htmlIter = Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Down

-- | Gets the iterator for a zipper.
htmlIterZipper :: HTMLIter -> HTMLZipper
htmlIterZipper :: HTMLIter -> HTMLZipper
htmlIterZipper (HTMLIter Direction
_ HTMLZipper
z) = HTMLZipper
z

-- | Modifies the zipper for an interator.
htmlIterModify :: (HTMLZipper -> HTMLZipper) -> HTMLIter -> HTMLIter
htmlIterModify :: (HTMLZipper -> HTMLZipper) -> HTMLIter -> HTMLIter
htmlIterModify HTMLZipper -> HTMLZipper
f (HTMLIter Direction
d HTMLZipper
z) = (Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
d forall a b. (a -> b) -> a -> b
$ HTMLZipper -> HTMLZipper
f HTMLZipper
z)

-- | Advances an iterator to the next element.
htmlIterNext :: HTMLIter -> Maybe HTMLIter
htmlIterNext :: HTMLIter -> Maybe HTMLIter
htmlIterNext = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper) -> HTMLIter -> Maybe HTMLIter
iterStep HTMLZipper -> Maybe HTMLZipper
htmlZipFirst HTMLZipper -> Maybe HTMLZipper
htmlZipNext

-- | Advances an iterator to the previous element.
htmlIterBack :: HTMLIter -> Maybe HTMLIter
htmlIterBack :: HTMLIter -> Maybe HTMLIter
htmlIterBack = (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper) -> HTMLIter -> Maybe HTMLIter
iterStep HTMLZipper -> Maybe HTMLZipper
htmlZipLast HTMLZipper -> Maybe HTMLZipper
htmlZipPrev

-- | Steps an iterator.
iterStep
  :: (HTMLZipper -> Maybe HTMLZipper)
  -> (HTMLZipper -> Maybe HTMLZipper)
  -> HTMLIter
  -> Maybe HTMLIter
iterStep :: (HTMLZipper -> Maybe HTMLZipper)
-> (HTMLZipper -> Maybe HTMLZipper) -> HTMLIter -> Maybe HTMLIter
iterStep HTMLZipper -> Maybe HTMLZipper
first HTMLZipper -> Maybe HTMLZipper
next = HTMLIter -> Maybe HTMLIter
go
  where
    go :: HTMLIter -> Maybe HTMLIter
go (HTMLIter Direction
d HTMLZipper
z) =
      case Direction
d of
        Direction
Down ->
          case HTMLZipper -> Maybe HTMLZipper
first HTMLZipper
z of
            Just HTMLZipper
x -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Down HTMLZipper
x
            Maybe HTMLZipper
Nothing -> HTMLIter -> Maybe HTMLIter
go forall a b. (a -> b) -> a -> b
$ Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Across HTMLZipper
z
        Direction
Across ->
          case HTMLZipper -> Maybe HTMLZipper
next HTMLZipper
z of
            Just HTMLZipper
x -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Down HTMLZipper
x
            Maybe HTMLZipper
Nothing -> HTMLIter -> Maybe HTMLIter
go forall a b. (a -> b) -> a -> b
$ Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Up HTMLZipper
z
        Direction
Up ->
          case HTMLZipper -> Maybe HTMLZipper
htmlZipParent HTMLZipper
z of
            Just HTMLZipper
x -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Direction -> HTMLZipper -> HTMLIter
HTMLIter Direction
Across HTMLZipper
x
            Maybe HTMLZipper
Nothing -> forall a. Maybe a
Nothing

-- | Searches an iterator until a predicate is true.
htmlIterSearch
  :: (HTMLIter -> Maybe HTMLIter)
  -> (HTMLZipper -> Bool)
  -> HTMLIter
  -> Maybe HTMLIter
htmlIterSearch :: (HTMLIter -> Maybe HTMLIter)
-> (HTMLZipper -> Bool) -> HTMLIter -> Maybe HTMLIter
htmlIterSearch HTMLIter -> Maybe HTMLIter
step HTMLZipper -> Bool
test x :: HTMLIter
x@(HTMLIter Direction
_ HTMLZipper
z)
  | HTMLZipper -> Bool
test HTMLZipper
z = forall a. a -> Maybe a
Just HTMLIter
x
  | Bool
otherwise = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Maybe a
Nothing ((HTMLIter -> Maybe HTMLIter)
-> (HTMLZipper -> Bool) -> HTMLIter -> Maybe HTMLIter
htmlIterSearch HTMLIter -> Maybe HTMLIter
step HTMLZipper -> Bool
test) forall a b. (a -> b) -> a -> b
$ HTMLIter -> Maybe HTMLIter
step HTMLIter
x

-- | Defines an empty path.
htmlZipPathEmpty :: HTMLZipPath
htmlZipPathEmpty :: HTMLZipPath
htmlZipPathEmpty = [Int] -> HTMLZipPath
HTMLZipPath []

-- | Gets the path for a node.
htmlZipPath :: HTMLZipper -> HTMLZipPath
htmlZipPath :: HTMLZipper -> HTMLZipPath
htmlZipPath = forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Int] -> HTMLZipPath
HTMLZipPath []) forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. HTMLZipPath -> HTMLZipper -> Maybe HTMLZipPath
go HTMLZipPath
htmlZipPathEmpty
  where
    go :: HTMLZipPath -> HTMLZipper -> Maybe HTMLZipPath
    go :: HTMLZipPath -> HTMLZipper -> Maybe HTMLZipPath
go (HTMLZipPath [Int]
p) HTMLZipper
z =
      case HTMLZipper -> Maybe Int
htmlZipIndex HTMLZipper
z of
        Maybe Int
Nothing ->
          forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [Int] -> HTMLZipPath
HTMLZipPath [Int]
p
        Just Int
x ->
          case HTMLZipper -> Maybe HTMLZipper
htmlZipParent HTMLZipper
z of
            Maybe HTMLZipper
Nothing -> forall a. Maybe a
Nothing
            Just HTMLZipper
y -> HTMLZipPath -> HTMLZipper -> Maybe HTMLZipPath
go ([Int] -> HTMLZipPath
HTMLZipPath forall a b. (a -> b) -> a -> b
$ Int
x forall a. a -> [a] -> [a]
: [Int]
p) HTMLZipper
y

-- | Finds the zipper for a path starting from the current node.
htmlZipPathFind :: HTMLZipPath -> HTMLZipper -> Maybe HTMLZipper
htmlZipPathFind :: HTMLZipPath -> HTMLZipper -> Maybe HTMLZipper
htmlZipPathFind (HTMLZipPath [Int]
p) = [Int] -> HTMLZipper -> Maybe HTMLZipper
f [Int]
p
  where
    f :: [Int] -> HTMLZipper -> Maybe HTMLZipper
f [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure
    f (Int
x:[Int]
xs) = Int -> HTMLZipper -> Maybe HTMLZipper
htmlZipGet Int
x forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> [Int] -> HTMLZipper -> Maybe HTMLZipper
f [Int]
xs