~jaro/balkon

ref: f85c0d0a66dab74200d62fd2579ecf44b8422890 balkon/src/Data/Text/ParagraphLayout/Internal/TreeOfTexts.hs -rw-r--r-- 2.8 KiB
f85c0d0aJaro Test Rich pagination. 1 year, 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
-- | 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