aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2022-02-22 12:56:41 +0300
committerGitHub <noreply@github.com>2022-02-22 12:56:41 +0300
commitb9b1b588fad604c0cfc3e481f48338437dcaba5f (patch)
tree7c6a04d95f0f9b0c931b25dca91f1cf411f01105
parentc44bf5487bd32f90a4576859548f1db0e9355a07 (diff)
downloaddokka-b9b1b588fad604c0cfc3e481f48338437dcaba5f.tar.gz
dokka-b9b1b588fad604c0cfc3e481f48338437dcaba5f.tar.bz2
dokka-b9b1b588fad604c0cfc3e481f48338437dcaba5f.zip
Fix HTML head and favicon in multi-module projects (#2365)
-rw-r--r--plugins/all-modules-page/api/all-modules-page.api2
-rw-r--r--plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt10
-rw-r--r--plugins/base/api/base.api5
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt22
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/Tags.kt12
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt2
-rw-r--r--plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt7
-rw-r--r--plugins/templating/api/templating.api24
-rw-r--r--plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt4
-rw-r--r--plugins/templating/src/main/kotlin/templates/CommandHandler.kt12
-rw-r--r--plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt60
-rw-r--r--plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt8
-rw-r--r--plugins/templating/src/main/kotlin/templates/SubstitutionCommandHandler.kt29
-rw-r--r--plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt4
-rw-r--r--plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt1
-rw-r--r--plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt62
-rw-r--r--plugins/versioning/api/versioning.api2
-rw-r--r--plugins/versioning/src/main/kotlin/versioning/ReplaceVersionsCommand.kt2
18 files changed, 208 insertions, 60 deletions
diff --git a/plugins/all-modules-page/api/all-modules-page.api b/plugins/all-modules-page/api/all-modules-page.api
index 9d8bca9b..0763d75a 100644
--- a/plugins/all-modules-page/api/all-modules-page.api
+++ b/plugins/all-modules-page/api/all-modules-page.api
@@ -83,5 +83,7 @@ public final class org/jetbrains/dokka/allModulesPage/ResolveLinkCommandHandler
public fun canHandle (Lorg/jetbrains/dokka/base/templating/Command;)Z
public fun finish (Ljava/io/File;)V
public fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
diff --git a/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt b/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt
index e881a5ab..7976ba5a 100644
--- a/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt
+++ b/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt
@@ -16,29 +16,29 @@ class ResolveLinkCommandHandler(context: DokkaContext) : CommandHandler {
private val externalModuleLinkResolver =
context.plugin<AllModulesPagePlugin>().querySingle { externalModuleLinkResolver }
- override fun handleCommand(element: Element, command: Command, input: File, output: File) {
+ override fun handleCommandAsTag(command: Command, body: Element, input: File, output: File) {
command as ResolveLinkCommand
val link = externalModuleLinkResolver.resolve(command.dri, output)
if (link == null) {
- val children = element.childNodes().toList()
+ val children = body.childNodes().toList()
val attributes = Attributes().apply {
put("data-unresolved-link", command.dri.toString())
}
val el = Element(Tag.valueOf("span"), "", attributes).apply {
children.forEach { ch -> appendChild(ch) }
}
- element.replaceWith(el)
+ body.replaceWith(el)
return
}
val attributes = Attributes().apply {
put("href", link)
}
- val children = element.childNodes().toList()
+ val children = body.childNodes().toList()
val el = Element(Tag.valueOf("a"), "", attributes).apply {
children.forEach { ch -> appendChild(ch) }
}
- element.replaceWith(el)
+ body.replaceWith(el)
}
override fun canHandle(command: Command): Boolean = command is ResolveLinkCommand
diff --git a/plugins/base/api/base.api b/plugins/base/api/base.api
index 40ee6813..a38c2cfd 100644
--- a/plugins/base/api/base.api
+++ b/plugins/base/api/base.api
@@ -516,6 +516,9 @@ public final class org/jetbrains/dokka/base/renderers/html/StylesInstaller : org
}
public final class org/jetbrains/dokka/base/renderers/html/TagsKt {
+ public static final field TEMPLATE_COMMAND_BEGIN_BORDER Ljava/lang/String;
+ public static final field TEMPLATE_COMMAND_END_BORDER Ljava/lang/String;
+ public static final field TEMPLATE_COMMAND_SEPARATOR Ljava/lang/String;
public static final fun buildAsInnerHtml (Lkotlin/jvm/functions/Function1;)Ljava/lang/String;
public static final fun strike (Lkotlinx/html/FlowOrPhrasingContent;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun strike$default (Lkotlinx/html/FlowOrPhrasingContent;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
@@ -523,6 +526,8 @@ public final class org/jetbrains/dokka/base/renderers/html/TagsKt {
public static final fun templateCommand (Lkotlinx/html/TagConsumer;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static synthetic fun templateCommand$default (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun templateCommand$default (Lkotlinx/html/TagConsumer;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
+ public static final fun templateCommandAsHtmlComment (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;)V
+ public static synthetic fun templateCommandAsHtmlComment$default (Lkotlinx/html/FlowOrMetaDataContent;Lorg/jetbrains/dokka/base/templating/Command;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static final fun templateCommandFor (Lorg/jetbrains/dokka/base/templating/Command;Lkotlinx/html/TagConsumer;)Lorg/jetbrains/dokka/base/renderers/html/TemplateCommand;
public static final fun wbr (Lkotlinx/html/FlowOrPhrasingContent;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
public static synthetic fun wbr$default (Lkotlinx/html/FlowOrPhrasingContent;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
index 4dd020ce..0ba085cd 100644
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
@@ -23,6 +23,8 @@ import org.jetbrains.dokka.utilities.htmlEscape
import org.jetbrains.kotlin.utils.addIfNotNull
import java.net.URI
+internal const val TEMPLATE_REPLACEMENT: String = "###"
+
open class HtmlRenderer(
context: DokkaContext
) : DefaultRenderer<FlowContent>(context) {
@@ -779,11 +781,11 @@ open class HtmlRenderer(
head {
meta(name = "viewport", content = "width=device-width, initial-scale=1", charset = "UTF-8")
title(page.name)
- templateCommand(PathToRootSubstitutionCommand("###", default = pathToRoot)) {
- link(href = "###images/logo-icon.svg", rel = "icon", type = "image/svg")
+ templateCommandAsHtmlComment(PathToRootSubstitutionCommand(TEMPLATE_REPLACEMENT, default = pathToRoot)) {
+ link(href = "${TEMPLATE_REPLACEMENT}images/logo-icon.svg", rel = "icon", type = "image/svg")
}
- templateCommand(PathToRootSubstitutionCommand("###", default = pathToRoot)) {
- script { unsafe { +"""var pathToRoot = "###";""" } }
+ templateCommandAsHtmlComment(PathToRootSubstitutionCommand(TEMPLATE_REPLACEMENT, default = pathToRoot)) {
+ script { unsafe { +"""var pathToRoot = "$TEMPLATE_REPLACEMENT";""" } }
}
// This script doesn't need to be there but it is nice to have since app in dark mode doesn't 'blink' (class is added before it is rendered)
script {
@@ -804,10 +806,10 @@ open class HtmlRenderer(
rel = LinkRel.stylesheet,
href = it
)
- else templateCommand(PathToRootSubstitutionCommand("###", default = pathToRoot)) {
+ else templateCommandAsHtmlComment(PathToRootSubstitutionCommand(TEMPLATE_REPLACEMENT, default = pathToRoot)) {
link(
rel = LinkRel.stylesheet,
- href = "###$it"
+ href = TEMPLATE_REPLACEMENT + it
)
}
it.substringBefore('?').substringAfterLast('.') == "js" ->
@@ -816,10 +818,10 @@ open class HtmlRenderer(
src = it
) {
async = true
- } else templateCommand(PathToRootSubstitutionCommand("###", default = pathToRoot)) {
+ } else templateCommandAsHtmlComment(PathToRootSubstitutionCommand(TEMPLATE_REPLACEMENT, default = pathToRoot)) {
script(
type = ScriptType.textJavaScript,
- src = "###$it"
+ src = TEMPLATE_REPLACEMENT + it
) {
if (it == "scripts/main.js")
defer = true
@@ -828,8 +830,8 @@ open class HtmlRenderer(
}
}
it.isImage() -> if (it.isAbsolute) link(href = it)
- else templateCommand(PathToRootSubstitutionCommand("###", default = pathToRoot)) {
- link(href = "###$it")
+ else templateCommandAsHtmlComment(PathToRootSubstitutionCommand(TEMPLATE_REPLACEMENT, default = pathToRoot)) {
+ link(href = TEMPLATE_REPLACEMENT + it)
}
else -> unsafe { +it }
}
diff --git a/plugins/base/src/main/kotlin/renderers/html/Tags.kt b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
index a23c7bf1..94a53c27 100644
--- a/plugins/base/src/main/kotlin/renderers/html/Tags.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
@@ -26,6 +26,18 @@ inline fun FlowOrPhrasingContent.strike(classes : String? = null, crossinline bl
open class STRIKE(initialAttributes: Map<String, String>, override val consumer: TagConsumer<*>) :
HTMLTag("strike", consumer, initialAttributes, null, false, false), HtmlBlockInlineTag
+const val TEMPLATE_COMMAND_SEPARATOR = ":"
+const val TEMPLATE_COMMAND_BEGIN_BORDER = "[+]cmd"
+const val TEMPLATE_COMMAND_END_BORDER = "[-]cmd"
+
+fun FlowOrMetaDataContent.templateCommandAsHtmlComment(data: Command, block: FlowOrMetaDataContent.() -> Unit = {}): Unit =
+ (consumer as? ImmediateResolutionTagConsumer)?.processCommand(data, block)
+ ?: let{
+ comment( "$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR${toJsonString(data)}")
+ block()
+ comment(TEMPLATE_COMMAND_END_BORDER)
+ }
+
fun FlowOrMetaDataContent.templateCommand(data: Command, block: TemplateBlock = {}): Unit =
(consumer as? ImmediateResolutionTagConsumer)?.processCommand(data, block)
?: TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer).visit(block)
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt
index ea8cde0f..bbc33164 100644
--- a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt
@@ -19,7 +19,7 @@ class ReplaceVersionsConsumer(private val context: DokkaContext) : ImmediateHtml
}
override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
- PathToRootConsumer.processCommand(command, block, tagConsumer)
+ processCommand(command, block, tagConsumer)
return tagConsumer.finalize()
}
} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
index 9b010b56..fb9ec10e 100644
--- a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
+++ b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
@@ -4,10 +4,11 @@ import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.PluginConfigurationImpl
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration
+import org.jetbrains.dokka.base.renderers.html.TEMPLATE_REPLACEMENT
import org.jetbrains.dokka.base.templating.toJsonString
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import org.jetbrains.dokka.pages.RootPageNode
import org.jetbrains.dokka.plugability.DokkaPlugin
-import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import org.jetbrains.dokka.transformers.pages.PageTransformer
import org.jsoup.Jsoup
import org.junit.jupiter.api.Test
@@ -125,11 +126,11 @@ class ResourceLinksTest : BaseAbstractTest() {
if (isMultiModule) {
Jsoup
.parse(writerPlugin.writer.contents["example.html"])
- .body()
+ .head()
.select("link, script")
.let {
listOf("styles/customStyle.css").forEach { r ->
- assert(it.`is`("[href=###$r]"))
+ assert(it.`is`("[href=$TEMPLATE_REPLACEMENT$r]"))
}
}
} else {
diff --git a/plugins/templating/api/templating.api b/plugins/templating/api/templating.api
index a0fb5122..aedd8ef3 100644
--- a/plugins/templating/api/templating.api
+++ b/plugins/templating/api/templating.api
@@ -28,16 +28,23 @@ public final class org/jetbrains/dokka/templates/AddToNavigationCommandHandler :
public fun finish (Ljava/io/File;)V
public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
public fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public abstract interface class org/jetbrains/dokka/templates/CommandHandler {
public abstract fun canHandle (Lorg/jetbrains/dokka/base/templating/Command;)Z
public abstract fun finish (Ljava/io/File;)V
public abstract fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public abstract fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public abstract fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public final class org/jetbrains/dokka/templates/CommandHandler$DefaultImpls {
public static fun finish (Lorg/jetbrains/dokka/templates/CommandHandler;Ljava/io/File;)V
+ public static fun handleCommand (Lorg/jetbrains/dokka/templates/CommandHandler;Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public static fun handleCommandAsComment (Lorg/jetbrains/dokka/templates/CommandHandler;Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public static fun handleCommandAsTag (Lorg/jetbrains/dokka/templates/CommandHandler;Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public final class org/jetbrains/dokka/templates/DefaultMultiModuleTemplateProcessor : org/jetbrains/dokka/templates/MultiModuleTemplateProcessor {
@@ -54,7 +61,8 @@ public final class org/jetbrains/dokka/templates/DefaultSubmoduleTemplateProcess
public final class org/jetbrains/dokka/templates/DirectiveBasedHtmlTemplateProcessingStrategy : org/jetbrains/dokka/templates/TemplateProcessingStrategy {
public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
public fun finish (Ljava/io/File;)V
- public final fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public final fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public final fun handleCommandAsTag (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
public fun process (Ljava/io/File;Ljava/io/File;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaModuleDescription;)Z
}
@@ -82,6 +90,8 @@ public final class org/jetbrains/dokka/templates/SubstitutionCommandHandler : or
public fun canHandle (Lorg/jetbrains/dokka/base/templating/Command;)Z
public fun finish (Ljava/io/File;)V
public fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public abstract interface class org/jetbrains/dokka/templates/Substitutor {
@@ -101,16 +111,16 @@ public abstract interface class org/jetbrains/dokka/templates/TemplateProcessor
}
public final class org/jetbrains/dokka/templates/TemplatingContext {
- public fun <init> (Ljava/io/File;Ljava/io/File;Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;)V
+ public fun <init> (Ljava/io/File;Ljava/io/File;Ljava/util/List;Lorg/jetbrains/dokka/base/templating/Command;)V
public final fun component1 ()Ljava/io/File;
public final fun component2 ()Ljava/io/File;
- public final fun component3 ()Lorg/jsoup/nodes/Element;
+ public final fun component3 ()Ljava/util/List;
public final fun component4 ()Lorg/jetbrains/dokka/base/templating/Command;
- public final fun copy (Ljava/io/File;Ljava/io/File;Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;)Lorg/jetbrains/dokka/templates/TemplatingContext;
- public static synthetic fun copy$default (Lorg/jetbrains/dokka/templates/TemplatingContext;Ljava/io/File;Ljava/io/File;Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;ILjava/lang/Object;)Lorg/jetbrains/dokka/templates/TemplatingContext;
+ public final fun copy (Ljava/io/File;Ljava/io/File;Ljava/util/List;Lorg/jetbrains/dokka/base/templating/Command;)Lorg/jetbrains/dokka/templates/TemplatingContext;
+ public static synthetic fun copy$default (Lorg/jetbrains/dokka/templates/TemplatingContext;Ljava/io/File;Ljava/io/File;Ljava/util/List;Lorg/jetbrains/dokka/base/templating/Command;ILjava/lang/Object;)Lorg/jetbrains/dokka/templates/TemplatingContext;
public fun equals (Ljava/lang/Object;)Z
+ public final fun getBody ()Ljava/util/List;
public final fun getCommand ()Lorg/jetbrains/dokka/base/templating/Command;
- public final fun getElement ()Lorg/jsoup/nodes/Element;
public final fun getInput ()Ljava/io/File;
public final fun getOutput ()Ljava/io/File;
public fun hashCode ()I
@@ -162,6 +172,8 @@ public final class templates/ReplaceVersionCommandHandler : org/jetbrains/dokka/
public fun canHandle (Lorg/jetbrains/dokka/base/templating/Command;)Z
public fun finish (Ljava/io/File;)V
public fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public final class templates/SourcesetDependencyProcessingStrategy : org/jetbrains/dokka/templates/TemplateProcessingStrategy {
diff --git a/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt b/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt
index 3e7e1290..9531c279 100644
--- a/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt
+++ b/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt
@@ -13,12 +13,12 @@ import java.util.concurrent.ConcurrentHashMap
class AddToNavigationCommandHandler(val context: DokkaContext) : CommandHandler {
private val navigationFragments = ConcurrentHashMap<String, Element>()
- override fun handleCommand(element: Element, command: Command, input: File, output: File) {
+ override fun handleCommandAsTag(command: Command, body: Element, input: File, output: File) {
command as AddToNavigationCommand
context.configuration.modules.find { it.name == command.moduleName }
?.relativePathToOutputDirectory
?.relativeToOrSelf(context.configuration.outputDir)
- ?.let { key -> navigationFragments[key.toString()] = element }
+ ?.let { key -> navigationFragments[key.toString()] = body }
}
override fun canHandle(command: Command) = command is AddToNavigationCommand
diff --git a/plugins/templating/src/main/kotlin/templates/CommandHandler.kt b/plugins/templating/src/main/kotlin/templates/CommandHandler.kt
index d72092a1..1956310b 100644
--- a/plugins/templating/src/main/kotlin/templates/CommandHandler.kt
+++ b/plugins/templating/src/main/kotlin/templates/CommandHandler.kt
@@ -2,10 +2,18 @@ package org.jetbrains.dokka.templates
import org.jetbrains.dokka.base.templating.Command
import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
import java.io.File
-interface CommandHandler {
- fun handleCommand(element: Element, command: Command, input: File, output: File)
+
+interface CommandHandler {
+ @Deprecated("This was renamed to handleCommandAsTag", ReplaceWith("handleCommandAsTag(command, element, input, output)"))
+ fun handleCommand(element: Element, command: Command, input: File, output: File) { }
+
+ @Suppress("DEPRECATION")
+ fun handleCommandAsTag(command: Command, body: Element, input: File, output: File) =
+ handleCommand(body, command, input, output)
+ fun handleCommandAsComment(command: Command, body: List<Node>, input: File, output: File) { }
fun canHandle(command: Command): Boolean
fun finish(output: File) {}
} \ No newline at end of file
diff --git a/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt b/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt
index 2b4951a1..7ef4cb10 100644
--- a/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt
+++ b/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt
@@ -1,13 +1,19 @@
package org.jetbrains.dokka.templates
import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.renderers.html.TEMPLATE_COMMAND_BEGIN_BORDER
+import org.jetbrains.dokka.base.renderers.html.TEMPLATE_COMMAND_END_BORDER
+import org.jetbrains.dokka.base.renderers.html.TEMPLATE_COMMAND_SEPARATOR
import org.jetbrains.dokka.base.templating.Command
import org.jetbrains.dokka.base.templating.parseJson
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
import org.jetbrains.dokka.plugability.query
import org.jsoup.Jsoup
+import org.jsoup.nodes.Comment
import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
+import org.jsoup.nodes.TextNode
import java.io.File
import java.nio.file.Files
@@ -20,20 +26,68 @@ class DirectiveBasedHtmlTemplateProcessingStrategy(private val context: DokkaCon
if (input.isFile && input.extension == "html") {
val document = Jsoup.parse(input, "UTF-8")
document.outputSettings().indentAmount(0).prettyPrint(false)
+
document.select("dokka-template-command").forEach {
- handleCommand(it, parseJson(it.attr("data")), input, output)
+ handleCommandAsTag(it, parseJson(it.attr("data")), input, output)
+ }
+ extractCommandsFromComments(document) { command, body ->
+ val bodyTrimed =
+ body.dropWhile { node -> (node is TextNode && node.isBlank).also { if (it) node.remove() } }
+ .dropLastWhile { node -> (node is TextNode && node.isBlank).also { if (it) node.remove() } }
+ handleCommandAsComment(command, bodyTrimed, input, output)
}
+
Files.write(output.toPath(), listOf(document.outerHtml()))
true
} else false
- fun handleCommand(element: Element, command: Command, input: File, output: File) {
+ fun handleCommandAsTag(element: Element, command: Command, input: File, output: File) {
+ traverseHandlers(command) { handleCommandAsTag(command, element, input, output) }
+ }
+
+ fun handleCommandAsComment(command: Command, body: List<Node>, input: File, output: File) {
+ traverseHandlers(command) { handleCommandAsComment(command, body, input, output) }
+ }
+
+ private fun traverseHandlers(command: Command, action: CommandHandler.() -> Unit) {
val handlers = directiveBasedCommandHandlers.filter { it.canHandle(command) }
if (handlers.isEmpty())
context.logger.warn("Unknown templating command $command")
else
- handlers.forEach { it.handleCommand(element, command, input, output) }
+ handlers.forEach(action)
+ }
+ private fun extractCommandsFromComments(
+ node: Node,
+ startFrom: Int = 0,
+ handler: (command: Command, body: List<Node>) -> Unit
+ ) {
+ val nodes: MutableList<Node> = mutableListOf()
+ var lastStartBorder: Comment? = null
+ var firstStartBorder: Comment? = null
+ for (index in startFrom until node.childNodeSize()) {
+ when (val currentChild = node.childNode(index)) {
+ is Comment -> if (currentChild.data?.startsWith(TEMPLATE_COMMAND_BEGIN_BORDER) == true) {
+ lastStartBorder = currentChild
+ firstStartBorder = firstStartBorder ?: currentChild
+ nodes.clear()
+ } else if (lastStartBorder != null && currentChild.data?.startsWith(TEMPLATE_COMMAND_END_BORDER) == true) {
+ lastStartBorder.remove()
+ val cmd: Command? =
+ lastStartBorder.data?.removePrefix("$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR")?.let { parseJson(it) }
+ cmd?.let { handler(it, nodes) }
+ currentChild.remove()
+ extractCommandsFromComments(node, firstStartBorder?.siblingIndex() ?: 0, handler)
+ return
+ } else {
+ if (lastStartBorder != null) nodes.add(currentChild)
+ }
+ else -> {
+ extractCommandsFromComments(currentChild, handler = handler)
+ if (lastStartBorder != null) nodes.add(currentChild)
+ }
+ }
+ }
}
override fun finish(output: File) {
diff --git a/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt b/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt
index 8035fc83..02570849 100644
--- a/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt
+++ b/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt
@@ -12,10 +12,10 @@ class ReplaceVersionCommandHandler(private val context: DokkaContext) : CommandH
override fun canHandle(command: Command): Boolean = command is ReplaceVersionsCommand
- override fun handleCommand(element: Element, command: Command, input: File, output: File) {
- val position = element.elementSiblingIndex()
- val parent = element.parent()
- element.remove()
+ override fun handleCommandAsTag(command: Command, body: Element, input: File, output: File) {
+ val position = body.elementSiblingIndex()
+ val parent = body.parent()
+ body.remove()
context.configuration.moduleVersion?.takeIf { it.isNotEmpty() }
?.let { parent.insertChildren(position, TextNode(it)) }
}
diff --git a/plugins/templating/src/main/kotlin/templates/SubstitutionCommandHandler.kt b/plugins/templating/src/main/kotlin/templates/SubstitutionCommandHandler.kt
index c7b15137..178f52dc 100644
--- a/plugins/templating/src/main/kotlin/templates/SubstitutionCommandHandler.kt
+++ b/plugins/templating/src/main/kotlin/templates/SubstitutionCommandHandler.kt
@@ -13,28 +13,35 @@ import java.io.File
class SubstitutionCommandHandler(context: DokkaContext) : CommandHandler {
- override fun handleCommand(element: Element, command: Command, input: File, output: File) {
+ override fun handleCommandAsTag(command: Command, body: Element, input: File, output: File) {
command as SubstitutionCommand
- substitute(element, TemplatingContext(input, output, element, command))
+ val childrenCopy = body.children().toList()
+ substitute(childrenCopy, TemplatingContext(input, output, childrenCopy, command))
+
+ val position = body.elementSiblingIndex()
+ val parent = body.parent()
+ body.remove()
+
+ parent?.insertChildren(position, childrenCopy)
+ }
+
+ override fun handleCommandAsComment(command: Command, body: List<Node>, input: File, output: File) {
+ command as SubstitutionCommand
+ substitute(body, TemplatingContext(input, output, body, command))
}
override fun canHandle(command: Command): Boolean = command is SubstitutionCommand
+ override fun finish(output: File) { }
+
private val substitutors = context.plugin<TemplatingPlugin>().query { substitutor }
private fun findSubstitution(commandContext: TemplatingContext<SubstitutionCommand>, match: MatchResult): String =
substitutors.asSequence().mapNotNull { it.trySubstitute(commandContext, match) }.firstOrNull() ?: match.value
- private fun substitute(element: Element, commandContext: TemplatingContext<SubstitutionCommand>) {
+ private fun substitute(elements: List<Node>, commandContext: TemplatingContext<SubstitutionCommand>) {
val regex = commandContext.command.pattern.toRegex()
- element.children().forEach { it.traverseToSubstitute(regex, commandContext) }
-
- val childrenCopy = element.children().toList()
- val position = element.elementSiblingIndex()
- val parent = element.parent()
- element.remove()
-
- parent.insertChildren(position, childrenCopy)
+ elements.forEach { it.traverseToSubstitute(regex, commandContext) }
}
private fun Node.traverseToSubstitute(regex: Regex, commandContext: TemplatingContext<SubstitutionCommand>) {
diff --git a/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt b/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt
index 5f36530b..01c10067 100644
--- a/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt
+++ b/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt
@@ -12,7 +12,7 @@ import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
import org.jetbrains.dokka.plugability.query
import org.jetbrains.dokka.plugability.querySingle
-import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
import java.io.File
interface TemplateProcessor
@@ -88,7 +88,7 @@ class DefaultMultiModuleTemplateProcessor(
data class TemplatingContext<out T : Command>(
val input: File,
val output: File,
- val element: Element,
+ val body: List<Node>,
val command: T,
)
diff --git a/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt b/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt
index 7001b1ba..aea01970 100644
--- a/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt
+++ b/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt
@@ -7,6 +7,7 @@ import templates.ProjectNameSubstitutor
import templates.ReplaceVersionCommandHandler
import templates.SourcesetDependencyProcessingStrategy
+@Suppress("unused")
class TemplatingPlugin : DokkaPlugin() {
val submoduleTemplateProcessor by extensionPoint<SubmoduleTemplateProcessor>()
diff --git a/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt b/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt
index ce2a8afd..44acf340 100644
--- a/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt
+++ b/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt
@@ -3,13 +3,15 @@ package org.jetbrains.dokka.templates
import kotlinx.html.a
import kotlinx.html.div
import kotlinx.html.id
+import kotlinx.html.span
import kotlinx.html.stream.createHTML
import org.jetbrains.dokka.DokkaModuleDescriptionImpl
import org.jetbrains.dokka.base.renderers.html.templateCommand
+import org.jetbrains.dokka.base.renderers.html.templateCommandAsHtmlComment
import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand
import org.junit.Rule
-import org.junit.rules.TemporaryFolder
import org.junit.jupiter.api.Test
+import org.junit.rules.TemporaryFolder
import utils.assertHtmlEqualsIgnoringWhitespace
import java.io.File
@@ -36,7 +38,56 @@ class SubstitutionCommandResolutionTest : TemplatingAbstractTest() {
id = "logo"
}
}
+ checkSubstitutedResult(template, expected)
+ }
+
+ @Test
+ fun `should handle PathToRootCommand as HTML comment`() {
+ val template = createHTML().span {
+ templateCommandAsHtmlComment(PathToRootSubstitutionCommand(pattern = "###", default = "default")) {
+ this@span.a {
+ href = "###index.html"
+ div {
+ id = "logo"
+ }
+ }
+ templateCommandAsHtmlComment(PathToRootSubstitutionCommand(pattern = "####", default = "default")) {
+ this@span.a {
+ href = "####index.html"
+ div {
+ id = "logo"
+ }
+ }
+ }
+ }
+ }
+
+ val expected = createHTML().span {
+ a {
+ href = "../index.html"
+ div {
+ id = "logo"
+ }
+ }
+ a {
+ href = "../index.html"
+ div {
+ id = "logo"
+ }
+ }
+ }
+ checkSubstitutedResult(template, expected)
+ }
+
+ private fun createDirectoriesAndWriteContent(content: String): File {
+ folder.create()
+ val module1 = folder.newFolder("module1")
+ val module1Content = module1.resolve("index.html")
+ module1Content.writeText(content)
+ return module1Content
+ }
+ private fun checkSubstitutedResult(template: String, expected:String) {
val testedFile = createDirectoriesAndWriteContent(template)
val configuration = dokkaConfiguration {
@@ -57,13 +108,4 @@ class SubstitutionCommandResolutionTest : TemplatingAbstractTest() {
}
}
}
-
- private fun createDirectoriesAndWriteContent(content: String): File {
- folder.create()
- val module1 = folder.newFolder("module1")
- val module1Content = module1.resolve("index.html")
- module1Content.writeText(content)
- return module1Content
- }
-
}
diff --git a/plugins/versioning/api/versioning.api b/plugins/versioning/api/versioning.api
index 15ebe7be..b163fd4a 100644
--- a/plugins/versioning/api/versioning.api
+++ b/plugins/versioning/api/versioning.api
@@ -59,6 +59,8 @@ public final class org/jetbrains/dokka/versioning/ReplaceVersionCommandHandler :
public fun finish (Ljava/io/File;)V
public final fun getVersionsNavigationCreator ()Lorg/jetbrains/dokka/versioning/VersionsNavigationCreator;
public fun handleCommand (Lorg/jsoup/nodes/Element;Lorg/jetbrains/dokka/base/templating/Command;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsComment (Lorg/jetbrains/dokka/base/templating/Command;Ljava/util/List;Ljava/io/File;Ljava/io/File;)V
+ public fun handleCommandAsTag (Lorg/jetbrains/dokka/base/templating/Command;Lorg/jsoup/nodes/Element;Ljava/io/File;Ljava/io/File;)V
}
public final class org/jetbrains/dokka/versioning/SemVerVersionOrdering : org/jetbrains/dokka/versioning/VersionsOrdering {
diff --git a/plugins/versioning/src/main/kotlin/versioning/ReplaceVersionsCommand.kt b/plugins/versioning/src/main/kotlin/versioning/ReplaceVersionsCommand.kt
index 728eac09..ad1edd2b 100644
--- a/plugins/versioning/src/main/kotlin/versioning/ReplaceVersionsCommand.kt
+++ b/plugins/versioning/src/main/kotlin/versioning/ReplaceVersionsCommand.kt
@@ -18,7 +18,7 @@ class ReplaceVersionCommandHandler(context: DokkaContext) : CommandHandler {
override fun canHandle(command: Command): Boolean = command is ReplaceVersionsCommand
- override fun handleCommand(element: Element, command: Command, input: File, output: File) {
+ override fun handleCommandAsTag(command: Command, element: Element, input: File, output: File) {
element.empty()
element.append(versionsNavigationCreator(output))
}