aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Ryzhenkov <orangy@jetbrains.com>2014-07-15 15:54:05 +0400
committerIlya Ryzhenkov <orangy@jetbrains.com>2014-07-15 15:54:05 +0400
commit62cb509a1a5adf0e5f9ba8d8e7545a93eb8516b2 (patch)
tree52e0ad3452a198ee279df8ed3e93c9c0a39a5f6b
parentad884a9ce79f191f3a7b7aed115080e341265ef3 (diff)
downloaddokka-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.kt5
-rw-r--r--src/Formats/HtmlFormatService.kt94
-rw-r--r--src/Formats/JekyllFormatService.kt11
-rw-r--r--src/Formats/MarkdownFormatService.kt123
-rw-r--r--src/Formats/StructuredFormatService.kt107
-rw-r--r--src/Formats/TextFormatService.kt3
-rw-r--r--src/Locations/LocationService.kt9
-rw-r--r--src/main.kt4
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("&nbsp;/&nbsp;")
}
} \ 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("&nbsp;&nbsp;`${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