blob: a490df679ebe3563d2423c4efe27407c5363d835 [file] [log] [blame]
Ilya Ryzhenkov62cb5092014-07-15 15:54:05 +04001package org.jetbrains.dokka
2
3import java.util.LinkedHashMap
4import org.jetbrains.dokka.DocumentationNode.Kind
5
6public data class FormatLink(val text: String, val location: Location)
7
8public abstract class StructuredFormatService(val locationService: LocationService,
9 val signatureGenerator: SignatureGenerator) : FormatService {
10
11 abstract public fun appendBlockCode(to: StringBuilder, line: String)
12 abstract public fun appendBlockCode(to: StringBuilder, lines: Iterable<String>)
13 abstract public fun appendHeader(to: StringBuilder, text: String, level: Int = 1)
14 abstract public fun appendText(to: StringBuilder, text: String)
15 abstract public fun appendLine(to: StringBuilder, text: String)
16 public abstract fun appendLine(to: StringBuilder)
17 public abstract fun formatLink(link: FormatLink): String
18 public abstract fun formatBold(text: String): String
19 public abstract fun formatCode(code: String): String
20 public abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String
21
22 open public fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension)
23
24 open public fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink {
25 return FormatLink(to.name, locationService.relativeLocation(from, to, extension))
26 }
27
28 open public fun appendDescription(to: StringBuilder, nodes: Iterable<DocumentationNode>) {
29 val described = nodes.filter { it.doc.hasDescription }
30 if (described.any()) {
31 appendHeader(to, "Description")
32 for (node in described) {
33 appendBlockCode(to, signatureGenerator.render(node))
34 appendLine(to, node.doc.description)
35 appendLine(to)
36 for (section in node.doc.sections) {
37 appendLine(to, formatBold(section.label))
38 appendLine(to, section.text)
39 appendLine(to)
40 }
41 }
42 }
43 }
44
45 open public fun appendSummary(to: StringBuilder, nodes: Iterable<DocumentationNode>) {
46 val breakdownBySummary = nodes.groupByTo(LinkedHashMap()) { node ->
47 node.doc.summary
48 }
49
50 for ((summary, items) in breakdownBySummary) {
51 appendLine(to, summary)
52 appendBlockCode(to, items.map { signatureGenerator.render(it) })
53 }
54 }
55
56 open public fun appendLocation(to: StringBuilder, nodes: Iterable<DocumentationNode>) {
57 val breakdownByName = nodes.groupByTo(LinkedHashMap()) { node -> node.name }
58 for ((name, items) in breakdownByName) {
59 appendHeader(to, "${name}")
60 appendSummary(to, items)
61 appendDescription(to, items)
62 }
63 }
64
65 override fun appendNodes(to: StringBuilder, nodes: Iterable<DocumentationNode>) {
66 val breakdownByLocation = nodes.groupByTo(LinkedHashMap()) { node ->
67 formatBreadcrumbs(node.path.map { link(node, it) })
68 }
69
70 for ((breadcrumbs, items) in breakdownByLocation) {
71 appendLine(to, breadcrumbs)
72 appendLine(to)
73 appendLocation(to, items)
74 }
75
76 for (node in nodes) {
77 if (node.members.any()) {
78 appendHeader(to, "Members")
79
80 appendLine(to, "| Name | Summary |")
81 appendLine(to, "|------|---------|")
82 val children = node.members.sortBy { it.name }
83 val membersMap = children.groupByTo(LinkedHashMap()) { link(node, it) }
84
85 for ((location, members) in membersMap) {
86 val mainMember = members.first()
87 val displayName = when (mainMember.kind) {
88 Kind.Constructor -> "*.init*"
89 else -> signatureGenerator.renderName(mainMember).htmlEscape()
90 }
91
92 appendText(to, "|${formatLink(location)}|")
93
94 val breakdownBySummary = members.groupByTo(LinkedHashMap()) { it.doc.summary }
95 for ((summary, items) in breakdownBySummary) {
96 appendLine(to, summary)
97 appendBlockCode(to, items.map { formatBold("${signatureGenerator.render(it)}") })
98 }
99
100 appendLine(to, "|")
101 }
102 }
103
104 }
105 }
106
107}