From 68eaffc19a20ddefbc9ed15aa7e1eeeb71e44f64 Mon Sep 17 00:00:00 2001 From: Ignat Beresnev Date: Tue, 19 Apr 2022 13:11:38 +0300 Subject: [PATCH] Update Jsoup to 1.14.3 (#2448) * Update Jsoup to 1.14.3 * Fix Jsoup API breaking changes after the update * Fix new Qodana inspections * Replace IllegalStateException with more appropriate NoSuchElementException (cherry picked from commit 3d573827230e7a750c002cf416cf9231161dd9b3) --- gradle.properties | 2 +- .../dokka/it/AbstractIntegrationTest.kt | 2 +- .../base-test-utils/api/base-test-utils.api | 1 + .../main/kotlin/renderers/SignatureUtils.kt | 3 +- .../kotlin/linking/EnumValuesLinkingTest.kt | 32 +++++++++++++++---- .../kotlin/renderers/html/TextStylesTest.kt | 3 +- .../kotlin/resourceLinks/ResourceLinksTest.kt | 8 ++--- ...FunctionalTypeConstructorsSignatureTest.kt | 4 +-- .../test/kotlin/signatures/SignatureTest.kt | 10 +++--- .../javadoc/JavadocAccessorNamingTest.kt | 2 +- .../src/test/kotlin/KotlinAsJavaPluginTest.kt | 15 ++++----- .../src/test/kotlin/MathjaxPluginTest.kt | 4 +-- .../AddToNavigationCommandHandler.kt | 4 +-- .../DirectiveBasedTemplateProcessing.kt | 12 ++++--- .../templates/ReplaceVersionCommandHandler.kt | 11 ++++--- 15 files changed, 69 insertions(+), 44 deletions(-) diff --git a/gradle.properties b/gradle.properties index 292abc2756..921e1a25e0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ kotlin_version=1.6.20 coroutines_version=1.6.0 kotlinx_html_version=0.7.3 kotlin_plugin_version=211-1.6.20-release-275-IJ7442.40 -jsoup_version=1.13.1 +jsoup_version=1.14.3 idea_version=211.7442.40 language_version=1.4 jackson_version=2.12.4 diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt index c5ea0093c1..adc75f436e 100644 --- a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt +++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt @@ -61,7 +61,7 @@ abstract class AbstractIntegrationTest { val fileText = file.readText() val html = Jsoup.parse(fileText) html.allElements.toList().forEach { element -> - val href = (element.attr("href") ?: return@forEach) + val href = element.attr("href") if (href.startsWith("https")) return@forEach if (href.startsWith("http")) return@forEach diff --git a/plugins/base/base-test-utils/api/base-test-utils.api b/plugins/base/base-test-utils/api/base-test-utils.api index a0b535f2f7..6a31e4681e 100644 --- a/plugins/base/base-test-utils/api/base-test-utils.api +++ b/plugins/base/base-test-utils/api/base-test-utils.api @@ -95,6 +95,7 @@ public final class signatures/Parameters : utils/Tag { public final class signatures/SignatureUtilsKt { public static final fun firstSignature (Lorg/jsoup/nodes/Element;)Lorg/jsoup/nodes/Element; + public static final fun lastSignature (Lorg/jsoup/nodes/Element;)Lorg/jsoup/nodes/Element; public static final fun renderedContent (Lutils/TestOutputWriter;Ljava/lang/String;)Lorg/jsoup/nodes/Element; public static synthetic fun renderedContent$default (Lutils/TestOutputWriter;Ljava/lang/String;ILjava/lang/Object;)Lorg/jsoup/nodes/Element; public static final fun signature (Lorg/jsoup/nodes/Element;)Lorg/jsoup/select/Elements; diff --git a/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt b/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt index 1d7253985b..3397b2b4b3 100644 --- a/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt +++ b/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt @@ -11,7 +11,8 @@ fun TestOutputWriter.renderedContent(path: String = "root/example.html"): Elemen .single() fun Element.signature(): Elements = select("div.symbol.monospace") -fun Element.firstSignature(): Element = signature().first() +fun Element.firstSignature(): Element = signature().first() ?: throw NoSuchElementException("No signature found") +fun Element.lastSignature(): Element = signature().last() ?: throw NoSuchElementException("No signature found") class Parameters(vararg matchers: Any) : Tag("span", *matchers, expectedClasses = listOf("parameters")) class Parameter(vararg matchers: Any) : Tag("span", *matchers, expectedClasses = listOf("parameter")) \ No newline at end of file diff --git a/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt b/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt index 29e705fdd6..f95d9860ed 100644 --- a/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt +++ b/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt @@ -13,7 +13,7 @@ import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import java.nio.file.Paths import utils.TestOutputWriterPlugin -import java.lang.AssertionError +import kotlin.AssertionError class EnumValuesLinkingTest : BaseAbstractTest() { @@ -106,12 +106,32 @@ class EnumValuesLinkingTest : BaseAbstractTest() { assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "JavaEnum.ON_DECEIT" }) } - // single method will throw an exception if there is no single element (0 or 2+) - Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-java-linker/index.html"]).select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]").single() - Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-java-linker/index.html"]).select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]").single() - Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-kotlin-linker/index.html"]).select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]").single() - Jsoup.parse(writerPlugin.writer.contents["root/linking.source/-kotlin-linker/index.html"]).select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]").single() + Jsoup + .parse(writerPlugin.writer.contents.getValue("root/linking.source/-java-linker/index.html")) + .select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]") + .assertOnlyOneElement() + + Jsoup + .parse(writerPlugin.writer.contents.getValue("root/linking.source/-java-linker/index.html")) + .select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]") + .assertOnlyOneElement() + + Jsoup + .parse(writerPlugin.writer.contents.getValue("root/linking.source/-kotlin-linker/index.html")) + .select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]") + .assertOnlyOneElement() + + Jsoup + .parse(writerPlugin.writer.contents.getValue("root/linking.source/-kotlin-linker/index.html")) + .select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]") + .assertOnlyOneElement() } } } + + private fun List.assertOnlyOneElement() { + if (isEmpty() || size > 1) { + throw AssertionError("Single element expected in list: $this") + } + } } diff --git a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt b/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt index d65a4f6e24..fd2f7860f7 100644 --- a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt +++ b/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt @@ -45,7 +45,8 @@ class TextStylesTest : HtmlRenderingOnlyTestBase() { } HtmlRenderer(context).render(page) renderedContent.match(Span("keyword")) - assertEquals(renderedContent.children().last().attr("class"), "token keyword") + val lastChild = renderedContent.children().last() ?: throw IllegalStateException("No element found") + assertEquals(lastChild.attr("class"), "token keyword") } @Test diff --git a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt index fb9ec10eac..8a8586eece 100644 --- a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt +++ b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt @@ -65,7 +65,7 @@ class ResourceLinksTest : BaseAbstractTest() { ) { renderingStage = { root, context -> Jsoup - .parse(writerPlugin.writer.contents["root/example.html"]) + .parse(writerPlugin.writer.contents.getValue("root/example.html")) .head() .select("link, script") .let { @@ -125,7 +125,7 @@ class ResourceLinksTest : BaseAbstractTest() { } if (isMultiModule) { Jsoup - .parse(writerPlugin.writer.contents["example.html"]) + .parse(writerPlugin.writer.contents.getValue("example.html")) .head() .select("link, script") .let { @@ -135,7 +135,7 @@ class ResourceLinksTest : BaseAbstractTest() { } } else { Jsoup - .parse(writerPlugin.writer.contents["root/example.html"]) + .parse(writerPlugin.writer.contents.getValue("root/example.html")) .head() .select("link, script") .let { @@ -184,7 +184,7 @@ class ResourceLinksTest : BaseAbstractTest() { assertNull(writerPlugin.writer.contents["scripts/relativePath.js"]) assertNull(writerPlugin.writer.contents["styles/relativePath.js"]) Jsoup - .parse(writerPlugin.writer.contents["root/example.html"]) + .parse(writerPlugin.writer.contents.getValue("root/example.html")) .head() .select("link, script") .let { diff --git a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt index e631117f82..cd55a001a4 100644 --- a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt @@ -235,7 +235,7 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-java-class/index.html").signature().last().match( + writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match( "open val ", A("javaFunction"), ": (", A("Integer"), ") -> ", A("String"), Span(), ignoreSpanWithTokenStyle = true ) @@ -261,7 +261,7 @@ class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-java-class/index.html").signature().last().match( + writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match( "open val ", A("kotlinFunction"), ": (", A("Integer"), ") -> ", A("String"), Span(), ignoreSpanWithTokenStyle = true ) diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt index ddf1c89294..6f4de32baa 100644 --- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt @@ -547,7 +547,7 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example.html").signature().first().match( + writerPlugin.writer.renderedContent("root/example.html").firstSignature().match( "typealias ", A("PlainTypealias"), " = ", A("Int"), Span(), ignoreSpanWithTokenStyle = true ) @@ -577,7 +577,7 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").signature().first().match( + writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( Div( Div( "@", A("SomeAnnotation") @@ -607,7 +607,7 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example.html").signature().first().match( + writerPlugin.writer.renderedContent("root/example.html").firstSignature().match( "typealias ", A("PlainTypealias"), " = ", A("Comparable"), "<", A("Int"), ">", Span(), ignoreSpanWithTokenStyle = true @@ -634,7 +634,7 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example.html").signature().first().match( + writerPlugin.writer.renderedContent("root/example.html").firstSignature().match( "typealias ", A("GenericTypealias"), "<", A("T"), "> = ", A("Comparable"), "<", A("T"), ">", Span(), ignoreSpanWithTokenStyle = true @@ -663,7 +663,7 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first() + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").firstSignature() .match( "fun ", A("someFun"), "(", Parameters( Parameter("xd: ", A("XD"), "<", A("Int"), ", ", A("String"), ">"), diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt index edb0bd6b8f..907b032ba7 100644 --- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt +++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt @@ -43,7 +43,7 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() { pluginOverrides = listOf(writerPlugin, JavadocPlugin()) ) { renderingStage = { _, _ -> - val html = writerPlugin.writer.contents["sample/TestCase.html"].let { Jsoup.parse(it) } + val html = writerPlugin.writer.contents.getValue("sample/TestCase.html").let { Jsoup.parse(it) } val props = html .select("#memberSummary_tabpanel") .select("th[scope=row].colSecond") diff --git a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt index b9627f9b29..0c9bd708ed 100644 --- a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt +++ b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt @@ -9,10 +9,7 @@ import org.jetbrains.dokka.pages.* import org.jetbrains.kotlin.utils.addToStdlib.cast import org.junit.Assert import org.junit.jupiter.api.Test -import signatures.Parameter -import signatures.Parameters -import signatures.renderedContent -import signatures.signature +import signatures.* import utils.* import kotlin.test.assertEquals @@ -329,7 +326,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { cleanupOutput = true ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").firstSignature().match( "final ", A("Integer"), A("someFun"), "(", Parameters( Parameter(A("Integer"), "xd") ), ")", Span(), ignoreSpanWithTokenStyle = true @@ -368,7 +365,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { cleanupOutput = true ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").firstSignature().match( "final ", A("Integer"), A("someFun"), "(", Parameters( Parameter(A("Map"), "<", A("String"), ", ", A("Integer"), "> xd"), ), ")", Span(), ignoreSpanWithTokenStyle = true @@ -434,7 +431,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { cleanupOutput = true ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test-kt/sample.html").signature().first().match( + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test-kt/sample.html").firstSignature().match( "final static ", A("String"), A("sample"), "(", Parameters( Parameter(A("Integer"), "a"), ), ")", Span(), ignoreSpanWithTokenStyle = true @@ -479,7 +476,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { assertEquals("Constructors", text.text) } renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test/-test.html").signature().first().match( + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test/-test.html").firstSignature().match( A("Test"), A("Test"), "(", Parameters( Parameter(A("Integer"), "xd") ), ")", Span(), ignoreSpanWithTokenStyle = true @@ -524,7 +521,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { assertEquals("Constructors", text.text) } renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-wrapped/-wrapped.html").signature().first().match( + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-wrapped/-wrapped.html").firstSignature().match( A("Wrapped"), A("Wrapped"), "(", Parameters( Parameter(A("Integer"), "xd,").withClasses("indented"), Parameter(A("Long"), "l,").withClasses("indented"), diff --git a/plugins/mathjax/src/test/kotlin/MathjaxPluginTest.kt b/plugins/mathjax/src/test/kotlin/MathjaxPluginTest.kt index a354365bad..0f713708be 100644 --- a/plugins/mathjax/src/test/kotlin/MathjaxPluginTest.kt +++ b/plugins/mathjax/src/test/kotlin/MathjaxPluginTest.kt @@ -34,7 +34,7 @@ class MathjaxPluginTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> Jsoup - .parse(writerPlugin.writer.contents["root/example/test.html"]) + .parse(writerPlugin.writer.contents.getValue("root/example/test.html")) .head() .select("link, script") .let { @@ -72,7 +72,7 @@ class MathjaxPluginTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin, MathjaxPlugin()) ) { renderingStage = { _, _ -> - val parsed = Jsoup.parse(writerPlugin.writer.contents["root/example/test.html"]) + val parsed = Jsoup.parse(writerPlugin.writer.contents.getValue("root/example/test.html")) // Ensure the MathJax CDN is loaded assert(parsed.select("link, script").`is`("[href=$LIB_PATH], [src=$LIB_PATH]")) diff --git a/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt b/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt index 9531c27968..fa58ecbad4 100644 --- a/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt +++ b/plugins/templating/src/main/kotlin/templates/AddToNavigationCommandHandler.kt @@ -31,7 +31,7 @@ class AddToNavigationCommandHandler(val context: DokkaContext) : CommandHandler val node = Element(Tag.valueOf("div"), "", attributes) navigationFragments.entries.sortedBy { it.key }.forEach { (moduleName, command) -> command.select("a").forEach { a -> - a.attr("href")?.also { a.attr("href", "${moduleName}/${it}") } + a.attr("href").also { a.attr("href", "${moduleName}/${it}") } } command.childNodes().toList().forEachIndexed { index, child -> if (index == 0) { @@ -43,7 +43,7 @@ class AddToNavigationCommandHandler(val context: DokkaContext) : CommandHandler Files.write(output.resolve("navigation.html").toPath(), listOf(node.outerHtml())) node.select("a").forEach { a -> - a.attr("href")?.also { a.attr("href", "../${it}") } + a.attr("href").also { a.attr("href", "../${it}") } } navigationFragments.keys.forEach { Files.write( diff --git a/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt b/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt index 7ef4cb10eb..07f808832a 100644 --- a/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt +++ b/plugins/templating/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt @@ -67,15 +67,17 @@ class DirectiveBasedHtmlTemplateProcessingStrategy(private val context: DokkaCon 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) { + is Comment -> if (currentChild.data.startsWith(TEMPLATE_COMMAND_BEGIN_BORDER)) { lastStartBorder = currentChild firstStartBorder = firstStartBorder ?: currentChild nodes.clear() - } else if (lastStartBorder != null && currentChild.data?.startsWith(TEMPLATE_COMMAND_END_BORDER) == true) { + } else if (lastStartBorder != null && currentChild.data.startsWith(TEMPLATE_COMMAND_END_BORDER)) { lastStartBorder.remove() - val cmd: Command? = - lastStartBorder.data?.removePrefix("$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR")?.let { parseJson(it) } - cmd?.let { handler(it, nodes) } + val cmd = lastStartBorder.data + .removePrefix("$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR") + .let { parseJson(it) } + + handler(cmd, nodes) currentChild.remove() extractCommandsFromComments(node, firstStartBorder?.siblingIndex() ?: 0, handler) return diff --git a/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt b/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt index 0257084926..8173f83999 100644 --- a/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt +++ b/plugins/templating/src/main/kotlin/templates/ReplaceVersionCommandHandler.kt @@ -13,10 +13,13 @@ class ReplaceVersionCommandHandler(private val context: DokkaContext) : CommandH override fun canHandle(command: Command): Boolean = command is ReplaceVersionsCommand 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)) } + if (parent != null) { + val position = body.elementSiblingIndex() + body.remove() + + context.configuration.moduleVersion?.takeIf { it.isNotEmpty() } + ?.let { parent.insertChildren(position, TextNode(it)) } + } } } \ No newline at end of file