~jaro/balkon

ref: ab656a2899d3cade7899b8ef905e5caafc085ee4 balkon/src/Data/Text/ParagraphLayout/Internal/Tree.hs -rw-r--r-- 2.7 KiB
ab656a28Jaro Deprecate the Plain interface. 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.
--
-- The tree is a hierarchy of boxes, with one box always present as the root.
-- Each box may contain any combination of text sequences and other boxes.
module Data.Text.ParagraphLayout.Internal.Tree
    ( RootNode (..)
    , InnerNode (..)
    , Box (..)
    , Leaf (..)
    , flatten
    )
where

import Data.Text.ParagraphLayout.Internal.BoxOptions
import Data.Text.ParagraphLayout.Internal.TextOptions

-- | Root of the paragraph tree.
data RootNode d

    = RootBox
    -- ^ The root inline box. Always present in a paragraph.
    --
    -- Cannot be styled directly, but can still set options for formatting
    -- text sequences directly descending from this box.
        (Box d)
        -- ^ Contents of the 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.
        Int
        -- ^ Byte offset to the next text node or the end of the paragraph text.

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

-- TODO: we need a way to test box equality, maybe add indexes?
type BoxPath d = [(d, BoxOptions)]

-- | Representation of a leaf node of the tree after flattening.
data Leaf d = TextLeaf

    d
    -- ^ User-defined data associated with the text node.

    Int
    -- ^ Byte offset to the next text node or the end of the paragraph text.

    TextOptions
    -- ^ Style options to apply to this text sequence.

    (BoxPath d)
    -- ^ Inline boxes found on the path from this text sequence to the root
    -- of the original tree.

-- | Convert the tree to a flat list of its leaf nodes (text sequences).
flatten :: RootNode d -> [Leaf d]
flatten (RootBox (Box ns textOpts)) = flattenNodes [] textOpts ns

flattenNodes :: BoxPath d -> TextOptions -> [InnerNode d] -> [Leaf d]
flattenNodes _ _ [] = []
flattenNodes path textOpts (n : ns) =
    flattenNode path textOpts n ++ flattenNodes path textOpts ns

flattenNode :: BoxPath d -> TextOptions -> InnerNode d -> [Leaf d]
flattenNode path textOpts (TextSequence d len) = [TextLeaf d len textOpts path]
flattenNode path _ (InlineBox d (Box ns textOpts) boxOpts) =
    flattenNodes ((d, boxOpts) : path) textOpts ns