aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin/renderers
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin/renderers')
-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
5 files changed, 115 insertions, 13 deletions
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