aboutsummaryrefslogtreecommitdiff
path: root/src/Model/Content.kt
blob: 8491fd88dee673207c8ef76a9cb83f13446c2dce (plain)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package org.jetbrains.dokka

import kotlin.properties.Delegates

public abstract class ContentNode {
    val children = arrayListOf<ContentNode>()

    class object {
        val empty = ContentEmpty
    }

    fun append(node : ContentNode)  {
        children.add(node)
    }

    fun isEmpty() = children.isEmpty()
}

public object ContentEmpty : ContentNode()
public open class ContentBlock() : ContentNode()

public class ContentText(val text: String) : ContentNode()
public class ContentKeyword(val text: String) : ContentNode()
public class ContentIdentifier(val text: String) : ContentNode()
public class ContentSymbol(val text: String) : ContentNode()

public class ContentParagraph() : ContentBlock()
public class ContentEmphasis() : ContentBlock()
public class ContentStrong() : ContentBlock()
public class ContentStrikethrough() : ContentBlock()
public class ContentCode() : ContentBlock()
public class ContentBlockCode() : ContentBlock()
public class ContentNodeLink(val node : DocumentationNode) : ContentBlock()
public class ContentExternalLink(val href : String) : ContentBlock()
public class ContentList() : ContentBlock()
public class ContentListItem() : ContentBlock()
public class ContentSection(public val label: String) : ContentBlock()

fun content(body: ContentNode.() -> Unit): ContentNode {
    val block = ContentBlock()
    block.body()
    return block
}

fun ContentNode.text(value: String) = append(ContentText(value))
fun ContentNode.keyword(value: String) = append(ContentKeyword(value))
fun ContentNode.symbol(value: String) = append(ContentSymbol(value))
fun ContentNode.identifier(value: String) = append(ContentIdentifier(value))

fun ContentNode.link(to: DocumentationNode, body: ContentNode.() -> Unit) {
    val block = ContentNodeLink(to)
    block.body()
    append(block)
}

public class Content() : ContentNode() {
    public val sections: Map<String, ContentSection> by Delegates.lazy {
        val map = linkedMapOf<String, ContentSection>()
        for (child in children) {
            if (child is ContentSection)
                map.put(child.label, child)
        }

        if ("\$summary" !in map && "\$description" !in map) {
            // no explicit summary and description, convert anonymous section
            val anonymous = map[""]
            if (anonymous != null) {
                map.remove("")
                val summary = ContentSection("\$summary")
                val description = ContentSection("\$description")

                val summaryNodes = anonymous.children.take(1)
                val descriptionNodes = anonymous.children.drop(1)

                if (summaryNodes.any()) {
                    summary.children.addAll(summaryNodes)
                    map.put("\$summary", summary)
                }

                if (descriptionNodes.any()) {
                    description.children.addAll(descriptionNodes)
                    map.put("\$description", description)
                }
            }
        }
        map
    }

    public val summary: ContentNode get()  {
        return sections["\$summary"] ?: ContentNode.empty
    }
    public val description: ContentNode get() = sections["\$description"] ?: ContentNode.empty

    override fun equals(other: Any?): Boolean {
        if (other !is Content)
            return false
        if (sections.size != other.sections.size)
            return false
        for (keys in sections.keySet())
            if (sections[keys] != other.sections[keys])
                return false

        return true
    }

    override fun hashCode(): Int {
        return sections.map { it.hashCode() }.sum()
    }

    override fun toString(): String {
        if (sections.isEmpty())
            return "<empty>"
        return sections.values().joinToString()
    }

    val isEmpty: Boolean
        get() = sections.none()

    class object {
        val Empty = Content()
    }
}