-- | 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