aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin')
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt12
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt23
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/Tags.kt22
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt31
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt22
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt30
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt12
-rw-r--r--plugins/base/src/main/kotlin/templating/Command.kt6
-rw-r--r--plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt14
-rw-r--r--plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt2
10 files changed, 152 insertions, 22 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index 8289447c..fce5c399 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -6,6 +6,8 @@ import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.base.renderers.*
import org.jetbrains.dokka.base.renderers.html.*
+import org.jetbrains.dokka.base.renderers.html.command.consumers.PathToRootConsumer
+import org.jetbrains.dokka.base.renderers.html.command.consumers.ResolveLinkConsumer
import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactory
import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProviderFactory
import org.jetbrains.dokka.base.resolvers.external.javadoc.JavadocExternalLocationProviderFactory
@@ -15,6 +17,7 @@ import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat
import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
import org.jetbrains.dokka.base.signatures.SignatureProvider
import org.jetbrains.dokka.base.templating.Command
+import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
import org.jetbrains.dokka.base.transformers.documentables.*
import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer
import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
@@ -38,7 +41,7 @@ class DokkaBase : DokkaPlugin() {
val htmlPreprocessors by extensionPoint<PageTransformer>()
val kotlinAnalysis by extensionPoint<KotlinAnalysis>()
val tabSortingStrategy by extensionPoint<TabSortingStrategy>()
- val templatingCommand by extensionPoint<Class<out Command>>()
+ val immediateHtmlCommandConsumer by extensionPoint<ImmediateHtmlCommandConsumer>()
val descriptorToDocumentableTranslator by extending {
CoreExtensions.sourceToDocumentableTranslator providing ::DefaultDescriptorToDocumentableTranslator
@@ -206,6 +209,13 @@ class DokkaBase : DokkaPlugin() {
htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator) }
}
+ val resolveLinkConsumer by extending {
+ immediateHtmlCommandConsumer with ResolveLinkConsumer
+ }
+
+ val pathToRootConsumer by extending {
+ immediateHtmlCommandConsumer with PathToRootConsumer
+ }
val baseSearchbarDataInstaller by extending {
htmlPreprocessors providing ::SearchbarDataInstaller order { after(sourceLinksTransformer) }
}
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
index d344dafe..ba5329bf 100644
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
@@ -9,6 +9,7 @@ import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.renderers.DefaultRenderer
import org.jetbrains.dokka.base.renderers.TabSortingStrategy
+import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
import org.jetbrains.dokka.base.renderers.isImage
import org.jetbrains.dokka.base.renderers.pageId
import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
@@ -45,6 +46,10 @@ open class HtmlRenderer(
private val tabSortingStrategy = context.plugin<DokkaBase>().querySingle { tabSortingStrategy }
+ private fun <R> TagConsumer<R>.prepareForTemplates() =
+ if (context.configuration.delayTemplateSubstitution || this is ImmediateResolutionTagConsumer) this
+ else ImmediateResolutionTagConsumer(this, context)
+
private fun <T : ContentNode> sortTabs(strategy: TabSortingStrategy, tabs: Collection<T>): List<T> {
val sorted = strategy.sort(tabs)
if (sorted.size != tabs.size)
@@ -208,7 +213,7 @@ open class HtmlRenderer(
): List<Pair<DisplaySourceSet, String>> {
var counter = 0
return nodes.toList().map { (sourceSet, elements) ->
- sourceSet to createHTML(prettyPrint = false).div {
+ sourceSet to createHTML(prettyPrint = false).prepareForTemplates().div {
elements.forEach {
buildContentNode(it, pageContext, sourceSet.toSet())
}
@@ -221,7 +226,7 @@ open class HtmlRenderer(
sourceSet.sourceSetIDs.all.flatMap { sourceSetDependencyMap[it].orEmpty() }
.any { sourceSetId -> sourceSetId in sourceSets.sourceSetIDs }
}.map {
- it to createHTML(prettyPrint = false).div(classes = "content sourceset-depenent-content") {
+ it to createHTML(prettyPrint = false).prepareForTemplates().div(classes = "content sourceset-depenent-content") {
if (counter++ == 0) attributes["data-active"] = ""
attributes["data-togglable"] = it.sourceSetIDs.merged.toString()
unsafe {
@@ -236,13 +241,13 @@ open class HtmlRenderer(
val distinct =
node.groupDivergentInstances(pageContext, { instance, contentPage, sourceSet ->
- createHTML(prettyPrint = false).div {
+ createHTML(prettyPrint = false).prepareForTemplates().div {
instance.before?.let { before ->
buildContentNode(before, pageContext, sourceSet)
}
}.stripDiv()
}, { instance, contentPage, sourceSet ->
- createHTML(prettyPrint = false).div {
+ createHTML(prettyPrint = false).prepareForTemplates().div {
instance.after?.let { after ->
buildContentNode(after, pageContext, sourceSet)
}
@@ -253,7 +258,7 @@ open class HtmlRenderer(
val groupedDivergent = it.value.groupBy { it.second }
consumer.onTagContentUnsafe {
- +createHTML().div("divergent-group") {
+ +createHTML().prepareForTemplates().div("divergent-group") {
attributes["data-filterable-current"] = groupedDivergent.keys.joinToString(" ") {
it.sourceSetIDs.merged.toString()
}
@@ -268,11 +273,11 @@ open class HtmlRenderer(
val content = contentsForSourceSetDependent(divergentForPlatformDependent, pageContext)
consumer.onTagContentUnsafe {
- +createHTML().div("with-platform-tags") {
+ +createHTML().prepareForTemplates().div("with-platform-tags") {
consumer.onTagContentUnsafe { +it.key.first }
consumer.onTagContentUnsafe {
- +createHTML().span("pull-right") {
+ +createHTML().prepareForTemplates().span("pull-right") {
if ((distinct.size > 1 && groupedDivergent.size == 1) || groupedDivergent.size == 1 || content.size == 1) {
if (node.sourceSets.size != 1) {
createPlatformTags(node, setOf(content.first().first))
@@ -716,7 +721,7 @@ open class HtmlRenderer(
private fun resolveLink(link: String, page: PageNode): String = if (URI(link).isAbsolute) link else page.root(link)
open fun buildHtml(page: PageNode, resources: List<String>, content: FlowContent.() -> Unit) =
- createHTML().html {
+ createHTML().prepareForTemplates().html {
head {
meta(name = "viewport", content = "width=device-width, initial-scale=1", charset = "UTF-8")
title(page.name)
@@ -737,7 +742,7 @@ open class HtmlRenderer(
else -> unsafe { +it }
}
}
- templateCommand(PathToRootSubstitutionCommand("###")) {
+ templateCommand(PathToRootSubstitutionCommand("###", default = locationProvider.pathToRoot(page))) {
script { unsafe { +"""var pathToRoot = "###";""" } }
}
}
diff --git a/plugins/base/src/main/kotlin/renderers/html/Tags.kt b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
index 59d711e9..0da16a1a 100644
--- a/plugins/base/src/main/kotlin/renderers/html/Tags.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
@@ -1,9 +1,13 @@
package org.jetbrains.dokka.base.renderers.html
import kotlinx.html.*
+import kotlinx.html.stream.createHTML
+import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
import org.jetbrains.dokka.base.templating.Command
import org.jetbrains.dokka.base.templating.toJsonString
+typealias TemplateBlock = TemplateCommand.() -> Unit
+
@HtmlTagMarker
fun FlowOrPhrasingContent.wbr(classes: String? = null, block: WBR.() -> Unit = {}): Unit =
WBR(attributesMapOf("class", classes), consumer).visit(block)
@@ -13,11 +17,16 @@ open class WBR(initialAttributes: Map<String, String>, consumer: TagConsumer<*>)
HTMLTag("wbr", consumer, initialAttributes, namespace = null, inlineTag = true, emptyTag = false),
HtmlBlockInlineTag
-fun FlowOrPhrasingOrMetaDataContent.templateCommand(data: Command, block: TemplateCommand.() -> Unit = {}): Unit =
- TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer).visit(block)
+fun FlowOrPhrasingOrMetaDataContent.templateCommand(data: Command, block: TemplateBlock = {}): Unit =
+ (consumer as? ImmediateResolutionTagConsumer)?.processCommand(data, block)
+ ?: TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer).visit(block)
+
+fun <T> TagConsumer<T>.templateCommand(data: Command, block: TemplateBlock = {}): T =
+ (this as? ImmediateResolutionTagConsumer)?.processCommandAndFinalize(data, block)
+ ?: TemplateCommand(attributesMapOf("data", toJsonString(data)), this).visitAndFinalize(this, block)
-fun <T> TagConsumer<T>.templateCommand(data: Command, block: TemplateCommand.() -> Unit = {}): T =
- TemplateCommand(attributesMapOf("data", toJsonString(data)), this).visitAndFinalize(this, block)
+fun templateCommandFor(data: Command, consumer: TagConsumer<*>) =
+ TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer)
class TemplateCommand(initialAttributes: Map<String, String>, consumer: TagConsumer<*>) :
HTMLTag(
@@ -29,3 +38,8 @@ class TemplateCommand(initialAttributes: Map<String, String>, consumer: TagConsu
emptyTag = false
),
CommonAttributeGroupFacadeFlowInteractivePhrasingContent
+
+// This hack is outrageous. I hate it but I cannot find any other way around `kotlinx.html` type system.
+fun TemplateBlock.buildAsInnerHtml(): String = createHTML(prettyPrint = false).run {
+ TemplateCommand(emptyMap, this).visitAndFinalize(this, this@buildAsInnerHtml).substringAfter(">").substringBeforeLast("<")
+}
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt
new file mode 100644
index 00000000..68f6dc81
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt
@@ -0,0 +1,31 @@
+package org.jetbrains.dokka.base.renderers.html.command.consumers
+
+import kotlinx.html.TagConsumer
+import kotlinx.html.visit
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.renderers.html.TemplateBlock
+import org.jetbrains.dokka.base.renderers.html.templateCommand
+import org.jetbrains.dokka.base.renderers.html.templateCommandFor
+import org.jetbrains.dokka.base.templating.Command
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.query
+
+class ImmediateResolutionTagConsumer<out R>(
+ private val downstream: TagConsumer<R>,
+ private val context: DokkaContext
+): TagConsumer<R> by downstream {
+ fun processCommand(command: Command, block: TemplateBlock) {
+ context.plugin<DokkaBase>().query { immediateHtmlCommandConsumer }
+ .find { it.canProcess(command) }
+ ?.processCommand(command, block, this)
+ ?: run { templateCommandFor(command, downstream).visit(block) }
+ }
+
+ fun processCommandAndFinalize(command: Command, block: TemplateBlock): R =
+ context.plugin<DokkaBase>().query { immediateHtmlCommandConsumer }
+ .find { it.canProcess(command) }
+ ?.processCommandAndFinalize(command, block, this)
+ ?: downstream.templateCommand(command, block)
+}
+
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt
new file mode 100644
index 00000000..b4649af6
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.dokka.base.renderers.html.command.consumers
+
+import org.jetbrains.dokka.base.renderers.html.TemplateBlock
+import org.jetbrains.dokka.base.renderers.html.buildAsInnerHtml
+import org.jetbrains.dokka.base.templating.Command
+import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
+import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand
+
+object PathToRootConsumer: ImmediateHtmlCommandConsumer {
+ override fun canProcess(command: Command) = command is PathToRootSubstitutionCommand
+
+ override fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>) {
+ command as PathToRootSubstitutionCommand
+ tagConsumer.onTagContentUnsafe { +block.buildAsInnerHtml().replace(command.pattern, command.default) }
+ }
+
+ override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
+ processCommand(command, block, tagConsumer)
+ return tagConsumer.finalize()
+ }
+
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt
new file mode 100644
index 00000000..1c42c3d5
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka.base.renderers.html.command.consumers
+
+import kotlinx.html.SPAN
+import kotlinx.html.span
+import kotlinx.html.unsafe
+import kotlinx.html.visit
+import org.jetbrains.dokka.base.renderers.html.TemplateBlock
+import org.jetbrains.dokka.base.renderers.html.buildAsInnerHtml
+import org.jetbrains.dokka.base.templating.Command
+import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
+import org.jetbrains.dokka.base.templating.ResolveLinkCommand
+import org.jetbrains.dokka.utilities.htmlEscape
+
+object ResolveLinkConsumer: ImmediateHtmlCommandConsumer {
+ override fun canProcess(command: Command) = command is ResolveLinkCommand
+
+ override fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>) {
+ command as ResolveLinkCommand
+ SPAN(mapOf("data-unresolved-link" to command.dri.toString().htmlEscape()), tagConsumer).visit {
+ unsafe { block.buildAsInnerHtml() }
+ }
+ }
+
+ override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
+ command as ResolveLinkCommand
+ return tagConsumer.span {
+ attributes["data-unresolved-link"] = command.dri.toString().htmlEscape()
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
index 030197a5..437a1c58 100644
--- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
@@ -20,9 +20,15 @@ open class DokkaLocationProvider(
protected open val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
fun registerPath(page: PageNode, prefix: List<String>) {
- val newPrefix = prefix + page.pathName
- put(page, newPrefix)
- page.children.forEach { registerPath(it, newPrefix) }
+ if (page is RootPageNode && page.forceTopLevelName) {
+ put(page, prefix + PAGE_WITH_CHILDREN_SUFFIX)
+ page.children.forEach { registerPath(it, prefix) }
+ } else {
+ val newPrefix = prefix + page.pathName
+ put(page, newPrefix)
+ page.children.forEach { registerPath(it, newPrefix) }
+ }
+
}
put(pageGraphRoot, emptyList())
pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
diff --git a/plugins/base/src/main/kotlin/templating/Command.kt b/plugins/base/src/main/kotlin/templating/Command.kt
index 0b998dee..5a81144c 100644
--- a/plugins/base/src/main/kotlin/templating/Command.kt
+++ b/plugins/base/src/main/kotlin/templating/Command.kt
@@ -1,13 +1,11 @@
package org.jetbrains.dokka.base.templating
-import com.fasterxml.jackson.annotation.JsonSubTypes
-import com.fasterxml.jackson.annotation.JsonSubTypes.Type
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.CLASS
-@JsonTypeInfo(use= CLASS)
+@JsonTypeInfo(use = CLASS)
interface Command
-abstract class SubstitutionCommand: Command {
+abstract class SubstitutionCommand : Command {
abstract val pattern: String
}
diff --git a/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt b/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt
new file mode 100644
index 00000000..a2a3b31e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt
@@ -0,0 +1,14 @@
+package org.jetbrains.dokka.base.templating
+
+import org.jetbrains.dokka.base.renderers.html.TemplateBlock
+import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
+import org.jetbrains.dokka.plugability.DokkaContext
+
+interface ImmediateHtmlCommandConsumer {
+ fun canProcess(command:Command): Boolean
+
+ fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>)
+
+ fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R
+}
+
diff --git a/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt b/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt
index 03f091c3..f307db86 100644
--- a/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt
+++ b/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt
@@ -1,3 +1,3 @@
package org.jetbrains.dokka.base.templating
-data class PathToRootSubstitutionCommand(override val pattern: String): SubstitutionCommand() \ No newline at end of file
+data class PathToRootSubstitutionCommand(override val pattern: String, val default: String): SubstitutionCommand() \ No newline at end of file