blob: 0fcfa444fe7ee9ae4bc17d9f812f83b234589a0b [file] [log] [blame]
Ilya Ryzhenkova0bfdbd2014-07-14 15:00:33 +04001package org.jetbrains.dokka
2
Ilya Ryzhenkov68d3bc82014-07-14 19:34:52 +04003import org.jetbrains.dokka.DocumentationNode.Kind
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +04004import java.util.LinkedHashMap
Ilya Ryzhenkov68d3bc82014-07-14 19:34:52 +04005
Ilya Ryzhenkoveeb42e92014-07-14 22:29:34 +04006public open class MarkdownFormatService(val locationService: LocationService,
7 val signatureGenerator: SignatureGenerator) : FormatService {
Ilya Ryzhenkova0bfdbd2014-07-14 15:00:33 +04008 override val extension: String = "md"
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +04009 override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
Ilya Ryzhenkova0bfdbd2014-07-14 15:00:33 +040010 with (to) {
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +040011 val breakdown = nodes.groupByTo(LinkedHashMap()) { node ->
12 node.path.map { "[${it.name}](${locationService.relativeLocation(node, it, extension)})" }.joinToString(" / ")
13 }
14 for ((path, items) in breakdown) {
15 appendln(path)
Ilya Ryzhenkov68d3bc82014-07-14 19:34:52 +040016 appendln()
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +040017 formatLocation(items)
Ilya Ryzhenkova0bfdbd2014-07-14 15:00:33 +040018 }
19
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +040020 for (node in nodes) {
21 if (node.members.any()) {
22 appendln("## Members")
23 appendln("| Name | Summary |")
24 appendln("|------|---------|")
25 val children = node.members.sortBy { it.name }
26 val membersMap = children.groupByTo(LinkedHashMap()) { locationService.relativeLocation(node, it, extension) }
27 for ((location, members) in membersMap) {
28 val mainMember = members.first()
29 val displayName = when (mainMember.kind) {
30 Kind.Constructor -> "*.init*"
31 else -> signatureGenerator.renderName(mainMember).htmlEscape()
32 }
33 append("|[${displayName}](${location})|")
34 append(members.groupByTo(LinkedHashMap()) { it.doc.summary }.map { group ->
35 val (summary, items) = group
36 StringBuilder {
37 if (!summary.isEmpty()) {
38 append("${summary}<br>")
39 }
40 for (item in items) {
41 append("&nbsp;&nbsp;`${signatureGenerator.render(item)}`<br>")
42 }
43 }.toString()
44 }.joinToString("<br>"))
45 appendln("|")
Ilya Ryzhenkov68d3bc82014-07-14 19:34:52 +040046 }
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +040047 }
48
49 }
50 }
51 }
52
53
54 private fun StringBuilder.formatLocation(nodes: Iterable<DocumentationNode>) {
55 val breakdown = nodes.groupByTo(LinkedHashMap()) { node ->
56 node.name
57 }
58 for ((name, items) in breakdown) {
59 appendln("# ${name}")
60 formatSummary(items)
61 }
62 }
63
64 private fun StringBuilder.formatSummary(nodes: Iterable<DocumentationNode>) {
65 val breakdown = nodes.groupByTo(LinkedHashMap()) { node ->
66 node.doc.summary
67 }
68 for ((summary, items) in breakdown) {
69 appendln(summary)
70 appendln("```")
71 for (item in items)
72 appendln(signatureGenerator.render(item))
73 appendln("```")
74 }
75
76 val described = nodes.filter { it.doc.hasDescription }
77 if (described.any()) {
78 appendln("## Description")
79 for (node in described) {
80 appendln("```")
81 appendln(signatureGenerator.render(node))
82 appendln("```")
83 appendln(node.doc.description)
84 appendln()
85 for (section in node.doc.sections) {
86 append("**")
87 append(section.label)
88 append("**")
89 appendln()
90 append(section.text)
91 appendln()
92 appendln()
Ilya Ryzhenkov69abe982014-07-14 18:38:22 +040093 }
Ilya Ryzhenkova0bfdbd2014-07-14 15:00:33 +040094 }
95 }
96 }
Ilya Ryzhenkovcd7084d2014-07-14 21:15:04 +040097
Ilya Ryzhenkov68d3bc82014-07-14 19:34:52 +040098}