diff options
author | Ilya Ryzhenkov <orangy@jetbrains.com> | 2014-07-15 15:54:05 +0400 |
---|---|---|
committer | Ilya Ryzhenkov <orangy@jetbrains.com> | 2014-07-15 15:54:05 +0400 |
commit | 62cb509a1a5adf0e5f9ba8d8e7545a93eb8516b2 (patch) | |
tree | 52e0ad3452a198ee279df8ed3e93c9c0a39a5f6b | |
parent | ad884a9ce79f191f3a7b7aed115080e341265ef3 (diff) | |
download | dokka-62cb509a1a5adf0e5f9ba8d8e7545a93eb8516b2.tar.gz dokka-62cb509a1a5adf0e5f9ba8d8e7545a93eb8516b2.tar.bz2 dokka-62cb509a1a5adf0e5f9ba8d8e7545a93eb8516b2.zip |
Refactor formatting service to detach grouping logic from markup
-rw-r--r-- | src/Formats/FormatService.kt | 5 | ||||
-rw-r--r-- | src/Formats/HtmlFormatService.kt | 94 | ||||
-rw-r--r-- | src/Formats/JekyllFormatService.kt | 11 | ||||
-rw-r--r-- | src/Formats/MarkdownFormatService.kt | 123 | ||||
-rw-r--r-- | src/Formats/StructuredFormatService.kt | 107 | ||||
-rw-r--r-- | src/Formats/TextFormatService.kt | 3 | ||||
-rw-r--r-- | src/Locations/LocationService.kt | 9 | ||||
-rw-r--r-- | src/main.kt | 4 |
8 files changed, 207 insertions, 149 deletions
diff --git a/src/Formats/FormatService.kt b/src/Formats/FormatService.kt index 3708e9a7..b106692a 100644 --- a/src/Formats/FormatService.kt +++ b/src/Formats/FormatService.kt @@ -2,7 +2,8 @@ package org.jetbrains.dokka public trait FormatService { val extension: String - fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) + fun appendNodes(to: StringBuilder, + nodes: Iterable<DocumentationNode>) } -fun FormatService.format(node: Iterable<DocumentationNode>): String = StringBuilder { format(node, this) }.toString()
\ No newline at end of file +fun FormatService.format(nodes: Iterable<DocumentationNode>): String = StringBuilder { appendNodes(this, nodes) }.toString()
\ No newline at end of file diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt index f3d71215..6c004509 100644 --- a/src/Formats/HtmlFormatService.kt +++ b/src/Formats/HtmlFormatService.kt @@ -1,64 +1,50 @@ package org.jetbrains.dokka -public class HtmlFormatService(val locationService: LocationService, - val signatureGenerator: SignatureGenerator) : FormatService { +public open class HtmlFormatService(locationService: LocationService, signatureGenerator: SignatureGenerator) +: StructuredFormatService(locationService, signatureGenerator) { override val extension: String = "html" - override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) { - for (node in nodes) { - with (to) { - appendln("<h2>") - appendln("Summary for ${node.name}") - appendln("</h2>") - appendln("<code>") - appendln(signatureGenerator.render(node)) - appendln("</code>") - appendln() - appendln("<p>") - appendln(node.doc.summary) - appendln("</p>") - appendln("<hr/>") - for (section in node.doc.sections) { - appendln("<h3>") - appendln(section.label) - appendln("</h3>") - appendln("<p>") - appendln(section.text) - appendln("</p>") - } + override fun appendBlockCode(to: StringBuilder, line: String) { + to.appendln("<code>") + to.appendln(line) + to.appendln("</code>") + } + + override fun appendBlockCode(to: StringBuilder, lines: Iterable<String>) { + to.appendln("<code>") + to.appendln(lines.join("\n")) + to.appendln("</code>") + } + + override fun appendHeader(to: StringBuilder, text: String, level: Int) { + to.appendln("<h$level>$text</h$level>") + } + + override fun appendText(to: StringBuilder, text: String) { + to.appendln("<p>$text</p>") + } - appendln("<h3>") - appendln("Members") - appendln("</h3>") - appendln("<table>") + override fun appendLine(to: StringBuilder, text: String) { + to.appendln("$text<br/>") + } + + override fun appendLine(to: StringBuilder) { + to.appendln("<br/>") + } - appendln("<thead>") - appendln("<tr>") - appendln("<td>Member</td>") - appendln("<td>Signature</td>") - appendln("<td>Summary</td>") - appendln("</tr>") - appendln("</thead>") + override fun formatLink(link: FormatLink): String { + return "<a href=\"${link.location.path}\">${link.text}</a>" + } - appendln("<tbody>") - for (member in node.members.sortBy { it.name }) { - val relativePath = locationService.relativeLocation(node, member, extension) - appendln("<tr>") - appendln("<td>") - append("<a href=\"${relativePath}\">${member.name}</a>") - appendln("</td>") - appendln("<td>") - append("${signatureGenerator.render(member)}") - appendln("</td>") - appendln("<td>") - append("${member.doc.summary}") - appendln("</td>") - appendln("</tr>") - } - appendln("</tbody>") - appendln("</table>") + override fun formatBold(text: String): String { + return "<b>$text</b>" + } + + override fun formatCode(code: String): String { + return "<code>$code</code>" + } - } - } + override fun formatBreadcrumbs(items: Iterable<FormatLink>): String { + return items.map { formatLink(it) }.joinToString(" / ") } }
\ No newline at end of file diff --git a/src/Formats/JekyllFormatService.kt b/src/Formats/JekyllFormatService.kt index 1b855b01..ff53827c 100644 --- a/src/Formats/JekyllFormatService.kt +++ b/src/Formats/JekyllFormatService.kt @@ -2,12 +2,15 @@ package org.jetbrains.dokka public class JekyllFormatService(locationService: LocationService, signatureGenerator: SignatureGenerator) : MarkdownFormatService(locationService, signatureGenerator) { - override val extension: String = "md" - override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) { + + override fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, "html") + + override fun appendNodes(to: StringBuilder, + nodes: Iterable<DocumentationNode>) { to.appendln("---") - to.appendln("layout: post") + to.appendln("layout: api") to.appendln("title: ${nodes.first().name}") to.appendln("---") - super<MarkdownFormatService>.format(nodes, to) + super<MarkdownFormatService>.appendNodes(to, nodes) } }
\ No newline at end of file diff --git a/src/Formats/MarkdownFormatService.kt b/src/Formats/MarkdownFormatService.kt index 0fcfa444..2a91a4a3 100644 --- a/src/Formats/MarkdownFormatService.kt +++ b/src/Formats/MarkdownFormatService.kt @@ -1,98 +1,55 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.DocumentationNode.Kind -import java.util.LinkedHashMap -public open class MarkdownFormatService(val locationService: LocationService, - val signatureGenerator: SignatureGenerator) : FormatService { +public open class MarkdownFormatService(locationService: LocationService, signatureGenerator: SignatureGenerator) +: StructuredFormatService(locationService, signatureGenerator) { + override val extension: String = "md" - override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) { - with (to) { - val breakdown = nodes.groupByTo(LinkedHashMap()) { node -> - node.path.map { "[${it.name}](${locationService.relativeLocation(node, it, extension)})" }.joinToString(" / ") - } - for ((path, items) in breakdown) { - appendln(path) - appendln() - formatLocation(items) - } - for (node in nodes) { - if (node.members.any()) { - appendln("## Members") - appendln("| Name | Summary |") - appendln("|------|---------|") - val children = node.members.sortBy { it.name } - val membersMap = children.groupByTo(LinkedHashMap()) { locationService.relativeLocation(node, it, extension) } - for ((location, members) in membersMap) { - val mainMember = members.first() - val displayName = when (mainMember.kind) { - Kind.Constructor -> "*.init*" - else -> signatureGenerator.renderName(mainMember).htmlEscape() - } - append("|[${displayName}](${location})|") - append(members.groupByTo(LinkedHashMap()) { it.doc.summary }.map { group -> - val (summary, items) = group - StringBuilder { - if (!summary.isEmpty()) { - append("${summary}<br>") - } - for (item in items) { - append(" `${signatureGenerator.render(item)}`<br>") - } - }.toString() - }.joinToString("<br>")) - appendln("|") - } - } + override public fun formatBreadcrumbs(items: Iterable<FormatLink>): String { + return items.map { formatLink(it) }.joinToString(" / ") + } + + override public fun formatCode(code: String): String { + return "`$code`" + } - } - } + override public fun formatBold(text: String): String { + return "**$text**" } + override public fun formatLink(link: FormatLink): String { + return "[${link.text}](${link.location.path})" + } - private fun StringBuilder.formatLocation(nodes: Iterable<DocumentationNode>) { - val breakdown = nodes.groupByTo(LinkedHashMap()) { node -> - node.name - } - for ((name, items) in breakdown) { - appendln("# ${name}") - formatSummary(items) - } + override public fun appendLine(to: StringBuilder) { + to.appendln() } - private fun StringBuilder.formatSummary(nodes: Iterable<DocumentationNode>) { - val breakdown = nodes.groupByTo(LinkedHashMap()) { node -> - node.doc.summary - } - for ((summary, items) in breakdown) { - appendln(summary) - appendln("```") - for (item in items) - appendln(signatureGenerator.render(item)) - appendln("```") - } + override public fun appendLine(to: StringBuilder, text: String) { + to.appendln(text) + } - val described = nodes.filter { it.doc.hasDescription } - if (described.any()) { - appendln("## Description") - for (node in described) { - appendln("```") - appendln(signatureGenerator.render(node)) - appendln("```") - appendln(node.doc.description) - appendln() - for (section in node.doc.sections) { - append("**") - append(section.label) - append("**") - appendln() - append(section.text) - appendln() - appendln() - } - } - } + override public fun appendText(to: StringBuilder, text: String) { + to.append(text) } + override public fun appendHeader(to: StringBuilder, text: String, level: Int) { + appendLine(to) + appendLine(to, "${"#".repeat(level)} $text") + appendLine(to) + } + + override public fun appendBlockCode(to: StringBuilder, lines: Iterable<String>) { + appendLine(to, "```") + for (line in lines) + appendLine(to, line) + appendLine(to, "```") + } + + override public fun appendBlockCode(to: StringBuilder, line: String) { + appendLine(to, "```") + appendLine(to, line) + appendLine(to, "```") + } } diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt new file mode 100644 index 00000000..a490df67 --- /dev/null +++ b/src/Formats/StructuredFormatService.kt @@ -0,0 +1,107 @@ +package org.jetbrains.dokka + +import java.util.LinkedHashMap +import org.jetbrains.dokka.DocumentationNode.Kind + +public data class FormatLink(val text: String, val location: Location) + +public abstract class StructuredFormatService(val locationService: LocationService, + val signatureGenerator: SignatureGenerator) : FormatService { + + abstract public fun appendBlockCode(to: StringBuilder, line: String) + abstract public fun appendBlockCode(to: StringBuilder, lines: Iterable<String>) + abstract public fun appendHeader(to: StringBuilder, text: String, level: Int = 1) + abstract public fun appendText(to: StringBuilder, text: String) + abstract public fun appendLine(to: StringBuilder, text: String) + public abstract fun appendLine(to: StringBuilder) + public abstract fun formatLink(link: FormatLink): String + public abstract fun formatBold(text: String): String + public abstract fun formatCode(code: String): String + public abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String + + open public fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension) + + open public fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink { + return FormatLink(to.name, locationService.relativeLocation(from, to, extension)) + } + + open public fun appendDescription(to: StringBuilder, nodes: Iterable<DocumentationNode>) { + val described = nodes.filter { it.doc.hasDescription } + if (described.any()) { + appendHeader(to, "Description") + for (node in described) { + appendBlockCode(to, signatureGenerator.render(node)) + appendLine(to, node.doc.description) + appendLine(to) + for (section in node.doc.sections) { + appendLine(to, formatBold(section.label)) + appendLine(to, section.text) + appendLine(to) + } + } + } + } + + open public fun appendSummary(to: StringBuilder, nodes: Iterable<DocumentationNode>) { + val breakdownBySummary = nodes.groupByTo(LinkedHashMap()) { node -> + node.doc.summary + } + + for ((summary, items) in breakdownBySummary) { + appendLine(to, summary) + appendBlockCode(to, items.map { signatureGenerator.render(it) }) + } + } + + open public fun appendLocation(to: StringBuilder, nodes: Iterable<DocumentationNode>) { + val breakdownByName = nodes.groupByTo(LinkedHashMap()) { node -> node.name } + for ((name, items) in breakdownByName) { + appendHeader(to, "${name}") + appendSummary(to, items) + appendDescription(to, items) + } + } + + override fun appendNodes(to: StringBuilder, nodes: Iterable<DocumentationNode>) { + val breakdownByLocation = nodes.groupByTo(LinkedHashMap()) { node -> + formatBreadcrumbs(node.path.map { link(node, it) }) + } + + for ((breadcrumbs, items) in breakdownByLocation) { + appendLine(to, breadcrumbs) + appendLine(to) + appendLocation(to, items) + } + + for (node in nodes) { + if (node.members.any()) { + appendHeader(to, "Members") + + appendLine(to, "| Name | Summary |") + appendLine(to, "|------|---------|") + val children = node.members.sortBy { it.name } + val membersMap = children.groupByTo(LinkedHashMap()) { link(node, it) } + + for ((location, members) in membersMap) { + val mainMember = members.first() + val displayName = when (mainMember.kind) { + Kind.Constructor -> "*.init*" + else -> signatureGenerator.renderName(mainMember).htmlEscape() + } + + appendText(to, "|${formatLink(location)}|") + + val breakdownBySummary = members.groupByTo(LinkedHashMap()) { it.doc.summary } + for ((summary, items) in breakdownBySummary) { + appendLine(to, summary) + appendBlockCode(to, items.map { formatBold("${signatureGenerator.render(it)}") }) + } + + appendLine(to, "|") + } + } + + } + } + +}
\ No newline at end of file diff --git a/src/Formats/TextFormatService.kt b/src/Formats/TextFormatService.kt index 2fb2a0a3..f309ad96 100644 --- a/src/Formats/TextFormatService.kt +++ b/src/Formats/TextFormatService.kt @@ -2,7 +2,8 @@ package org.jetbrains.dokka public class TextFormatService(val signatureGenerator: SignatureGenerator) : FormatService { override val extension: String = "txt" - override fun format(nodes: Iterable<DocumentationNode>, to: StringBuilder) { + override fun appendNodes(to: StringBuilder, + nodes: Iterable<DocumentationNode>) { for (node in nodes) { with (to) { appendln(signatureGenerator.render(node)) diff --git a/src/Locations/LocationService.kt b/src/Locations/LocationService.kt index 03f22d08..6472e906 100644 --- a/src/Locations/LocationService.kt +++ b/src/Locations/LocationService.kt @@ -2,7 +2,10 @@ package org.jetbrains.dokka import java.io.File -data class Location(val file: File) +public data class Location(val file: File) { + public val path : String + get() = file.path +} public trait LocationService { fun location(node: DocumentationNode): Location @@ -11,8 +14,8 @@ public trait LocationService { public fun escapeUri(path: String): String = path.replace('<', '_').replace('>', '_') -fun LocationService.relativeLocation(node: DocumentationNode, link: DocumentationNode, extension: String): File { +fun LocationService.relativeLocation(node: DocumentationNode, link: DocumentationNode, extension: String): Location { val ownerFolder = location(node).file.getParentFile()!! val memberPath = location(link).file.appendExtension(extension) - return ownerFolder.getRelativePath(memberPath) + return Location(ownerFolder.getRelativePath(memberPath)) } diff --git a/src/main.kt b/src/main.kt index 9da545d7..f9b734a3 100644 --- a/src/main.kt +++ b/src/main.kt @@ -57,8 +57,8 @@ public fun main(args: Array<String>) { val signatureGenerator = KotlinSignatureGenerator() val locationService = FoldersLocationService(arguments.outputDir) - val markdown = JekyllFormatService(locationService, signatureGenerator) - val generator = FileGenerator(signatureGenerator, locationService, markdown) + val formatter = HtmlFormatService(locationService, signatureGenerator) + val generator = FileGenerator(signatureGenerator, locationService, formatter) generator.generate(documentation) Disposer.dispose(environment) }
\ No newline at end of file |