aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-07-07 14:21:15 +0200
committerGitHub <noreply@github.com>2023-07-07 14:21:15 +0200
commit14cd0f3e42e13927f9852d2cb74cc0098c1a429c (patch)
tree7da6ca0fbae833ab58d5d9ee2f353fa96eb0fe27
parentf23a4a9e72b372e94f28fa95d3ca595e9945857a (diff)
downloaddokka-14cd0f3e42e13927f9852d2cb74cc0098c1a429c.tar.gz
dokka-14cd0f3e42e13927f9852d2cb74cc0098c1a429c.tar.bz2
dokka-14cd0f3e42e13927f9852d2cb74cc0098c1a429c.zip
Do not leak unknown asset paths into HTML (#3061)
Fixes #3040
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt8
-rw-r--r--plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt89
-rw-r--r--plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt34
3 files changed, 95 insertions, 36 deletions
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt
index 4fee280e..aae2f65d 100644
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt
+++ b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt
@@ -92,7 +92,7 @@ class DefaultTemplateModelFactory(val context: DokkaContext) : TemplateModelFact
private fun Appendable.resourcesForPage(pathToRoot: String, resources: List<String>): Unit =
resources.forEach {
- append(with(createHTML()) {
+ val resourceHtml = with(createHTML()) {
when {
it.URIExtension == "css" ->
link(
@@ -112,7 +112,11 @@ class DefaultTemplateModelFactory(val context: DokkaContext) : TemplateModelFact
it.isImage() -> link(href = if (it.isAbsolute) it else "$pathToRoot$it")
else -> null
}
- } ?: it)
+ }
+
+ if (resourceHtml != null) {
+ append(resourceHtml)
+ }
}
}
diff --git a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
index a751f071..0bbd35d1 100644
--- a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
+++ b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
@@ -13,13 +13,16 @@ import org.jetbrains.dokka.plugability.DokkaPluginApiPreview
import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement
import org.jetbrains.dokka.transformers.pages.PageTransformer
import org.jsoup.Jsoup
+import org.jsoup.nodes.TextNode
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import utils.TestOutputWriterPlugin
+import utils.assertContains
import java.io.File
import kotlin.test.assertNotNull
import kotlin.test.assertNull
+import kotlin.test.assertTrue
class ResourceLinksTest : BaseAbstractTest() {
class TestResourcesAppenderPlugin(val resources: List<String>) : DokkaPlugin() {
@@ -205,4 +208,90 @@ class ResourceLinksTest : BaseAbstractTest() {
}
}
}
+
+ @Test // see #3040; plain text added to <head> can be rendered by engines inside <body> as well
+ fun `should not add unknown resources as text to the head or body section`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+
+ pluginsConfigurations = mutableListOf(
+ PluginConfigurationImpl(
+ DokkaBase::class.java.canonicalName,
+ DokkaConfiguration.SerializationFormat.JSON,
+ toJsonString(
+ DokkaBaseConfiguration(
+ customAssets = listOf(File("test/unknown-file.ext"))
+ )
+ )
+ )
+ )
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/main/kotlin/test/Test.kt
+ |package test
+ |
+ |class Test
+ """.trimMargin(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val testClassPage = writerPlugin.writer.contents
+ .getValue("root/test/-test/-test.html")
+ .let { Jsoup.parse(it) }
+
+ val headChildNodes = testClassPage.head().childNodes()
+ assertTrue("<head> section should not contain non-blank text nodes") {
+ headChildNodes.all { it !is TextNode || it.isBlank }
+ }
+
+ val bodyChildNodes = testClassPage.body().childNodes()
+ assertTrue("<body> section should not contain non-blank text nodes. Something leaked from head?") {
+ bodyChildNodes.all { it !is TextNode || it.isBlank }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `should load script as defer if name ending in _deferred`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ """
+ |/src/main/kotlin/test/Test.kt
+ |package test
+ |
+ |class Test
+ """.trimMargin(),
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val generatedFiles = writerPlugin.writer.contents
+
+ assertContains(generatedFiles.keys, "scripts/symbol-parameters-wrapper_deferred.js")
+
+ val scripts = generatedFiles.getValue("root/test/-test/-test.html").let { Jsoup.parse(it) }.select("script")
+ val deferredScriptSources = scripts.filter { element -> element.hasAttr("defer") }.map { it.attr("src") }
+
+ // important to check symbol-parameters-wrapper_deferred specifically since it might break some features
+ assertContains(deferredScriptSources, "../../../scripts/symbol-parameters-wrapper_deferred.js")
+ }
+ }
+ }
}
diff --git a/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt b/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt
index 30fc127f..b2b590d3 100644
--- a/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt
+++ b/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt
@@ -177,40 +177,6 @@ class PageTransformerBuilderTest : BaseAbstractTest() {
}
}
- @Test
- fun `should load script as defer if name ending in _deferred`() {
- val configuration = dokkaConfiguration {
- sourceSets {
- sourceSet {
- sourceRoots = listOf("src/main/kotlin")
- }
- }
- }
- val writerPlugin = TestOutputWriterPlugin()
- testInline(
- """
- |/src/main/kotlin/test/Test.kt
- |package test
- |
- |class Test
- """.trimMargin(),
- configuration,
- pluginOverrides = listOf(writerPlugin)
- ) {
- renderingStage = { _, _ ->
- val generatedFiles = writerPlugin.writer.contents
-
- assertContains(generatedFiles.keys, "scripts/symbol-parameters-wrapper_deferred.js")
-
- val scripts = generatedFiles.getValue("root/test/-test/-test.html").let { Jsoup.parse(it) }.select("script")
- val deferredScriptSources = scripts.filter { element -> element.hasAttr("defer") }.map { it.attr("src") }
-
- // important to check symbol-parameters-wrapper_deferred specifically since it might break some features
- assertContains(deferredScriptSources, "../../../scripts/symbol-parameters-wrapper_deferred.js")
- }
- }
- }
-
private fun <T> Collection<T>.assertCount(n: Int, prefix: String = "") =
assert(count() == n) { "${prefix}Expected $n, got ${count()}" }