aboutsummaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2017-03-09 17:47:09 +0300
committerSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2017-03-20 18:20:19 +0300
commit2eb805e47505388c0e47102e9257f6f79681e699 (patch)
treeb50cc77717f4c9565579419ad197f21ec7938d24 /core/src
parent8eff2cf33d1ba671191d6e2873f005e6b5f7057e (diff)
downloaddokka-2eb805e47505388c0e47102e9257f6f79681e699.tar.gz
dokka-2eb805e47505388c0e47102e9257f6f79681e699.tar.bz2
dokka-2eb805e47505388c0e47102e9257f6f79681e699.zip
Create HTML based format for kotlin-website
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt193
-rw-r--r--core/src/main/kotlin/Formats/StandardFormats.kt6
-rw-r--r--core/src/main/kotlin/Formats/StructuredFormatService.kt2
-rw-r--r--core/src/main/resources/dokka/format/kotlin-website-html.properties2
-rw-r--r--core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt74
5 files changed, 276 insertions, 1 deletions
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
new file mode 100644
index 00000000..d2962911
--- /dev/null
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
@@ -0,0 +1,193 @@
+package org.jetbrains.dokka
+
+import com.google.inject.Inject
+import com.google.inject.name.Named
+import org.jetbrains.dokka.Utilities.impliedPlatformsName
+import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
+import java.nio.file.Path
+
+
+private object EmptyHtmlTemplateServie : HtmlTemplateService {
+ override fun appendFooter(to: StringBuilder) {
+
+ }
+
+ override fun appendHeader(to: StringBuilder, title: String?, basePath: Path) {
+
+ }
+}
+
+
+open class KotlinWebsiteHtmlOutputBuilder(to: StringBuilder,
+ location: Location,
+ locationService: LocationService,
+ languageService: LanguageService,
+ extension: String,
+ impliedPlatforms: List<String>)
+ : HtmlOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms, EmptyHtmlTemplateServie) {
+ private var needHardLineBreaks = false
+ private var insideDiv = 0
+
+ override fun appendLine() {
+
+ }
+
+ override fun appendBreadcrumbs(path: Iterable<FormatLink>) {
+ if (path.count() > 1) {
+ to.append("<div class='api-docs-breadcrumbs'>")
+ super.appendBreadcrumbs(path)
+ to.append("</div>")
+ }
+ }
+
+ override fun appendCode(body: () -> Unit) = wrapIfNotEmpty("<code>", "</code>", body)
+
+ override fun appendStrikethrough(body: () -> Unit) = wrapInTag("s", body)
+
+ protected fun div(to: StringBuilder, cssClass: String, otherAttributes: String = "", block: () -> Unit) {
+ to.append("<div class=\"$cssClass\"$otherAttributes")
+ to.append(">")
+ insideDiv++
+ block()
+ insideDiv--
+ to.append("</div>\n")
+ }
+
+ override fun appendAsSignature(node: ContentNode, block: () -> Unit) {
+ val contentLength = node.textLength
+ if (contentLength == 0) return
+ div(to, "signature") {
+ needHardLineBreaks = contentLength >= 62
+ try {
+ block()
+ } finally {
+ needHardLineBreaks = false
+ }
+ }
+ }
+
+ override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
+ div(to, "overload-group", calculateDataAttributes(platforms)) {
+ ensureParagraph()
+ block()
+ ensureParagraph()
+ }
+ }
+
+ override fun appendLink(href: String, body: () -> Unit) = wrap("<a href=\"$href\">", "</a>", body)
+
+ override fun appendHeader(level: Int, body: () -> Unit) {
+ if (insideDiv > 0) {
+ wrapInTag("p", body, newlineAfterClose = true)
+ } else {
+ super.appendHeader(level, body)
+ }
+ }
+
+ override fun appendTable(vararg columns: String, body: () -> Unit) {
+ to.appendln("<table class=\"api-docs-table\">")
+ body()
+ to.appendln("</table>")
+ }
+
+ override fun appendTableBody(body: () -> Unit) {
+ to.appendln("<tbody>")
+ body()
+ to.appendln("</tbody>")
+ }
+
+ override fun appendTableRow(body: () -> Unit) {
+ to.appendln("<tr>")
+ body()
+ to.appendln("</tr>")
+ }
+
+ override fun appendTableCell(body: () -> Unit) {
+ to.appendln("<td>")
+ body()
+ to.appendln("\n</td>")
+ }
+
+ override fun appendSymbol(text: String) {
+ to.append("<span class=\"symbol\">${text.htmlEscape()}</span>")
+ }
+
+ override fun appendKeyword(text: String) {
+ to.append("<span class=\"keyword\">${text.htmlEscape()}</span>")
+ }
+
+ override fun appendIdentifier(text: String, kind: IdentifierKind, signature: String?) {
+ val id = signature?.let { " id=\"$it\"" }.orEmpty()
+ to.append("<span class=\"${identifierClassName(kind)}\"$id>${text.htmlEscape()}</span>")
+ }
+
+ override fun appendSoftLineBreak() {
+ if (needHardLineBreaks)
+ to.append("<br/>")
+ }
+
+ override fun appendIndentedSoftLineBreak() {
+ if (needHardLineBreaks) {
+ to.append("<br/>&nbsp;&nbsp;&nbsp;&nbsp;")
+ }
+ }
+
+ private fun identifierClassName(kind: IdentifierKind) = when (kind) {
+ IdentifierKind.ParameterName -> "parameterName"
+ IdentifierKind.SummarizedTypeName -> "summarizedTypeName"
+ else -> "identifier"
+ }
+
+ fun calculateDataAttributes(platforms: Set<String>): String {
+ fun String.isKotlinVersion() = this.startsWith("Kotlin")
+ fun String.isJREVersion() = this.startsWith("JRE")
+ val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)
+ val jreVersion = platforms.singleOrNull(String::isJREVersion)
+ val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() }
+
+ val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: ""
+ val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: ""
+ val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: ""
+ return "$platformsAttr$kotlinVersionAttr$jreVersionAttr"
+ }
+
+ override fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
+ if (platforms.isNotEmpty())
+ wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
+ else
+ appendTableRow(block)
+ }
+
+ override fun appendPlatforms(platforms: Set<String>) {
+
+ }
+
+ override fun appendBreadcrumbSeparator() {
+ to.append(" / ")
+ }
+
+ override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) {
+ div(to, "sample") {
+ appendBlockCode(language) {
+ imports()
+ wrap("\n\nfun main(args: Array<String>) {", "}") {
+ wrap("\n//sampleStart\n", "\n//sampleEnd\n", body)
+ }
+ }
+ }
+ }
+}
+
+class KotlinWebsiteHtmlFormatService @Inject constructor(locationService: LocationService,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>)
+ : HtmlFormatService(locationService, signatureGenerator, EmptyHtmlTemplateServie, impliedPlatforms) {
+
+ override fun enumerateSupportFiles(callback: (String, String) -> Unit) {
+
+ }
+
+ override fun createOutputBuilder(to: StringBuilder, location: Location) =
+ KotlinWebsiteHtmlOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+}
+
diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt
index 6b077444..c67386af 100644
--- a/core/src/main/kotlin/Formats/StandardFormats.kt
+++ b/core/src/main/kotlin/Formats/StandardFormats.kt
@@ -40,6 +40,12 @@ class KotlinWebsiteFormatRunnableSamplesDescriptor : KotlinFormatDescriptorBase(
override val outlineServiceClass = YamlOutlineService::class
}
+class KotlinWebsiteHtmlFormatDescriptor : KotlinFormatDescriptorBase() {
+ override val formatServiceClass = KotlinWebsiteHtmlFormatService::class
+ override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class
+ override val outlineServiceClass = YamlOutlineService::class
+}
+
class JekyllFormatDescriptor : KotlinFormatDescriptorBase() {
override val formatServiceClass = JekyllFormatService::class
}
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 84f91d9c..743a6ac8 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -253,7 +253,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
for ((path, nodes) in breakdownByLocation) {
- if (!noHeader) {
+ if (!noHeader && path.isNotEmpty()) {
appendBreadcrumbs(path)
appendLine()
appendLine()
diff --git a/core/src/main/resources/dokka/format/kotlin-website-html.properties b/core/src/main/resources/dokka/format/kotlin-website-html.properties
new file mode 100644
index 00000000..f4c320b9
--- /dev/null
+++ b/core/src/main/resources/dokka/format/kotlin-website-html.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.KotlinWebsiteHtmlFormatDescriptor
+description=Generates Kotlin website documentation \ No newline at end of file
diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt
new file mode 100644
index 00000000..5c2fbe75
--- /dev/null
+++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt
@@ -0,0 +1,74 @@
+package org.jetbrains.dokka.tests
+
+import org.jetbrains.dokka.*
+import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
+import org.junit.Test
+
+class KotlinWebSiteHtmlFormatTest {
+ private val kwsService = KotlinWebsiteHtmlFormatService(InMemoryLocationService, KotlinLanguageService(), listOf())
+
+
+ @Test fun dropImport() {
+ verifyKWSNodeByName("dropImport", "foo")
+ }
+
+ @Test fun sample() {
+ verifyKWSNodeByName("sample", "foo")
+ }
+
+ @Test fun sampleWithAsserts() {
+ verifyKWSNodeByName("sampleWithAsserts", "a")
+ }
+
+ @Test fun newLinesInSamples() {
+ verifyKWSNodeByName("newLinesInSamples", "foo")
+ }
+
+ @Test fun newLinesInImportList() {
+ verifyKWSNodeByName("newLinesInImportList", "foo")
+ }
+
+ @Test fun returnTag() {
+ verifyKWSNodeByName("returnTag", "indexOf")
+ }
+
+ @Test fun overloadGroup() {
+ verifyKWSNodeByName("overloadGroup", "magic")
+ }
+
+ @Test fun dataTags() {
+ val module = buildMultiplePlatforms("dataTags")
+ verifyMultiplatformPackage(module, "dataTags")
+ }
+
+ @Test fun dataTagsInGroupNode() {
+ val path = "dataTagsInGroupNode"
+ val module = buildMultiplePlatforms(path)
+ verifyModelOutput(module, ".html", "testdata/format/website-html/$path/multiplatform.kt") { model, output ->
+ kwsService.createOutputBuilder(output, tempLocation).appendNodes(model.members.single().members.find { it.kind == NodeKind.GroupNode }.singletonOrEmptyList())
+ }
+ verifyMultiplatformPackage(module, path)
+ }
+
+ private fun verifyKWSNodeByName(fileName: String, name: String) {
+ verifyOutput("testdata/format/website-html/$fileName.kt", ".html", format = "kotlin-website-html") { model, output ->
+ kwsService.createOutputBuilder(output, tempLocation).appendNodes(model.members.single().members.filter { it.name == name })
+ }
+ }
+
+ private fun buildMultiplePlatforms(path: String): DocumentationModule {
+ val module = DocumentationModule("test")
+ val options = DocumentationOptions("", "html", generateIndexPages = false)
+ appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options)
+ appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jre7.kt"), defaultPlatforms = listOf("JVM", "JRE7"), options = options)
+ appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options)
+ return module
+ }
+
+ private fun verifyMultiplatformPackage(module: DocumentationModule, path: String) {
+ verifyModelOutput(module, ".package.html", "testdata/format/website-html/$path/multiplatform.kt") { model, output ->
+ kwsService.createOutputBuilder(output, tempLocation).appendNodes(model.members)
+ }
+ }
+
+}