-- | Represents the contents of a paragraph as a tree of boxes and texts.
--
-- This is intended for easier construction of paragraphs, at the cost of lower
-- performance. All texts will be concatenated together by layout functions.
module Data.Text.ParagraphLayout.Internal.TreeOfTexts
( RootNode (..)
, InnerNode (..)
, Box (..)
, toStrict
)
where
import Data.Text (Text)
import Data.Text.Foreign (lengthWord8)
import qualified Data.Text.Lazy as Lazy (toStrict)
import qualified Data.Text.Internal.Lazy as Lazy (Text, chunk, empty)
import Data.Text.ParagraphLayout.Internal.BoxOptions
import Data.Text.ParagraphLayout.Internal.TextOptions
import qualified Data.Text.ParagraphLayout.Internal.Tree as Strict
-- | Root of the paragraph tree.
data RootNode d
= RootBox (Box d)
-- ^ The root box.
-- | Non-root node of the paragraph tree.
data InnerNode d
= InlineBox
-- ^ An inline box, nested in another box.
d
-- ^ User-defined data associated with the box.
(Box d)
-- ^ Contents of the box.
BoxOptions
-- ^ Style options to apply to the inline box.
| TextSequence
-- ^ A leaf node containing text.
d
-- ^ User-defined data associated with the text node.
Text
-- ^ Text contents of the node.
-- | A box with content and a defined format. Corresponds to a DOM element.
data Box d = Box
[InnerNode d]
-- ^ Text nodes and other boxes contained by this box.
TextOptions
-- ^ Style options to apply to text sequences directly contained
-- by this box.
toStrict :: Text -> RootNode d -> Text -> (Text, Int, Strict.RootNode d)
toStrict prefix root suffix = (txt, initialOffset, root')
where
txt = Lazy.toStrict $ Lazy.chunk prefix txtTail
initialOffset = lengthWord8 prefix
(txtTail, root') = strictRoot (Lazy.chunk suffix Lazy.empty) root
strictRoot :: Lazy.Text -> RootNode d -> (Lazy.Text, Strict.RootNode d)
strictRoot t (RootBox b) = (t', Strict.RootBox b')
where
(t', b') = strictBox t b
strictBox :: Lazy.Text -> Box d -> (Lazy.Text, Strict.Box d)
strictBox t (Box nodes opts) = (t', Strict.Box nodes' opts)
where
(t', nodes') = strictNodes t nodes
strictNodes :: Lazy.Text -> [InnerNode d] -> (Lazy.Text, [Strict.InnerNode d])
strictNodes t [] = (t, [])
strictNodes t (node : nodes) = (t'', node' : nodes')
where
(t'', node') = strictNode t' node
(t', nodes') = strictNodes t nodes
strictNode :: Lazy.Text -> InnerNode d -> (Lazy.Text, Strict.InnerNode d)
strictNode suffix (TextSequence d txt) = (combinedText, node)
where
combinedText = Lazy.chunk txt suffix
node = Strict.TextSequence d (lengthWord8 txt)
strictNode suffix (InlineBox d b o) = (combinedText, Strict.InlineBox d node o)
where
(combinedText, node) = strictBox suffix b