Skip to content

Commit 449f37e

Browse files
committed
Fixes after PR review:
* remove `code` from HtmlCodeBlockRenderer.isApplicable * add documentation for extension * add test for multiline code with linebreaks * revert default rendering to original implementation
1 parent 38b3c7e commit 449f37e

File tree

5 files changed

+91
-29
lines changed

5 files changed

+91
-29
lines changed

dokka-subprojects/plugin-base/api/plugin-base.api

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ public final class org/jetbrains/dokka/base/renderers/html/CustomResourceInstall
300300

301301
public abstract interface class org/jetbrains/dokka/base/renderers/html/HtmlCodeBlockRenderer {
302302
public abstract fun buildCodeBlock (Lkotlinx/html/FlowContent;Ljava/lang/String;Ljava/lang/String;)V
303-
public abstract fun isApplicable (Ljava/lang/String;Ljava/lang/String;)Z
303+
public abstract fun isApplicable (Ljava/lang/String;)Z
304304
}
305305

306306
public final class org/jetbrains/dokka/base/renderers/html/HtmlFormatingUtilsKt {

dokka-subprojects/plugin-base/src/main/kotlin/org/jetbrains/dokka/base/DokkaBase.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ public class DokkaBase : DokkaPlugin() {
4848
public val externalLocationProviderFactory: ExtensionPoint<ExternalLocationProviderFactory> by extensionPoint()
4949
public val outputWriter: ExtensionPoint<OutputWriter> by extensionPoint()
5050
public val htmlPreprocessors: ExtensionPoint<PageTransformer> by extensionPoint()
51+
52+
/**
53+
* Extension point for providing custom HTML code block renderers.
54+
*
55+
* This extension point allows overriding the rendering of code blocks in different programming languages.
56+
* Multiple renderers can be installed to support different languages independently.
57+
*/
5158
public val htmlCodeBlockRenderers: ExtensionPoint<HtmlCodeBlockRenderer> by extensionPoint()
5259

5360
@Deprecated("It is not used anymore")

dokka-subprojects/plugin-base/src/main/kotlin/org/jetbrains/dokka/base/renderers/html/HtmlCodeBlockRenderer.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ import kotlinx.html.FlowContent
1414
public interface HtmlCodeBlockRenderer {
1515

1616
/**
17-
* Whether this renderer supports given [language].
18-
*
19-
* [code] can be useful to determine applicability if [language] is not provided (empty string)
17+
* Whether this renderer supports given [language]
2018
*/
21-
public fun isApplicable(language: String, code: String): Boolean
19+
public fun isApplicable(language: String): Boolean
2220

2321
/**
2422
* Defines how to render [code] for specified [language] via HTML tags

dokka-subprojects/plugin-base/src/main/kotlin/org/jetbrains/dokka/base/renderers/html/HtmlRenderer.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -817,33 +817,32 @@ public open class HtmlRenderer(
817817
code: ContentCodeBlock,
818818
pageContext: ContentPage
819819
) {
820-
val codeText = buildString {
821-
code.children.forEach {
822-
when (it) {
823-
is ContentText -> append(it.text)
824-
is ContentBreakLine -> appendLine()
825-
}
826-
}
827-
}
828-
829820
customCodeBlockRenderers.forEach { renderer ->
830-
if (renderer.isApplicable(code.language, codeText)) {
821+
if (renderer.isApplicable(code.language)) {
831822
// we use first applicable renderer to override rendering
823+
val codeText = buildString {
824+
code.children.forEach {
825+
when (it) {
826+
is ContentText -> append(it.text)
827+
is ContentBreakLine -> appendLine()
828+
}
829+
}
830+
}
832831
return with(renderer) {
833-
buildCodeBlock(code.language,codeText)
832+
buildCodeBlock(code.language, codeText)
834833
}
835834
}
836835
}
837836

838-
// if there are no custom renderers - fall back to default
837+
// if there are no applicable custom renderers - fall back to default
839838

840839
div("sample-container") {
841840
val codeLang = "lang-" + code.language.ifEmpty { "kotlin" }
842841
val stylesWithBlock = code.style + TextStyle.Block + codeLang
843842
pre {
844843
code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) {
845844
attributes["theme"] = "idea"
846-
text(codeText)
845+
code.children.forEach { buildContentNode(it, pageContext) }
847846
}
848847
}
849848
/*

dokka-subprojects/plugin-base/src/test/kotlin/renderers/html/CodeBlocksTest.kt

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ class CodeBlocksTest : BaseAbstractTest() {
5959
// where XXX=language of code block
6060
assertEquals(
6161
"""test("hello kotlin")""",
62-
content.getElementsByClass("lang-kotlin").singleOrNull()?.text()
62+
content.getElementsByClass("lang-kotlin").singleOrNull()?.wholeText()
6363
)
6464
assertEquals(
6565
"""test("hello custom")""",
66-
content.getElementsByClass("lang-custom").singleOrNull()?.text()
66+
content.getElementsByClass("lang-custom").singleOrNull()?.wholeText()
6767
)
6868
assertEquals(
6969
"""test("hello other")""",
70-
content.getElementsByClass("lang-other").singleOrNull()?.text()
70+
content.getElementsByClass("lang-other").singleOrNull()?.wholeText()
7171
)
7272
}
7373

@@ -99,15 +99,15 @@ class CodeBlocksTest : BaseAbstractTest() {
9999
val content = renderedContent("root/test/test.html")
100100
assertEquals(
101101
"""test("hello kotlin")""",
102-
content.getElementsByClass("lang-kotlin").singleOrNull()?.text()
102+
content.getElementsByClass("lang-kotlin").singleOrNull()?.wholeText()
103103
)
104104
assertEquals(
105105
"""test("hello custom")""",
106-
content.getElementsByClass("custom-language-block").singleOrNull()?.text()
106+
content.getElementsByClass("custom-language-block").singleOrNull()?.wholeText()
107107
)
108108
assertEquals(
109109
"""test("hello other")""",
110-
content.getElementsByClass("lang-other").singleOrNull()?.text()
110+
content.getElementsByClass("lang-other").singleOrNull()?.wholeText()
111111
)
112112
}
113113

@@ -139,15 +139,73 @@ class CodeBlocksTest : BaseAbstractTest() {
139139
val content = renderedContent("root/test/test.html")
140140
assertEquals(
141141
"""test("hello kotlin")""",
142-
content.getElementsByClass("lang-kotlin").singleOrNull()?.text()
142+
content.getElementsByClass("lang-kotlin").singleOrNull()?.wholeText()
143143
)
144144
assertEquals(
145145
"""test("hello custom")""",
146-
content.getElementsByClass("custom-language-block").singleOrNull()?.text()
146+
content.getElementsByClass("custom-language-block").singleOrNull()?.wholeText()
147147
)
148148
assertEquals(
149149
"""test("hello other")""",
150-
content.getElementsByClass("other-language-block").singleOrNull()?.text()
150+
content.getElementsByClass("other-language-block").singleOrNull()?.wholeText()
151+
)
152+
}
153+
154+
@Test
155+
fun `multiline code block rendering with linebreaks`() = testCode(
156+
"""
157+
/src/test.kt
158+
package test
159+
160+
/**
161+
* Hello, world!
162+
*
163+
* ```kotlin
164+
* // something before linebreak
165+
*
166+
* test("hello kotlin")
167+
* ```
168+
*
169+
* ```custom
170+
* // something before linebreak
171+
*
172+
* test("hello custom")
173+
* ```
174+
*
175+
* ```other
176+
* // something before linebreak
177+
*
178+
* test("hello other")
179+
* ```
180+
*/
181+
fun test(string: String) {}
182+
""".trimIndent(),
183+
listOf(CustomPlugin(applyOtherRenderer = false)) // we add only one custom renderer
184+
) {
185+
val content = renderedContent("root/test/test.html")
186+
assertEquals(
187+
"""
188+
// something before linebreak
189+
190+
test("hello kotlin")
191+
""".trimIndent(),
192+
content.getElementsByClass("lang-kotlin").singleOrNull()?.wholeText()
193+
)
194+
assertEquals(
195+
"""
196+
// something before linebreak
197+
198+
test("hello custom")
199+
""".trimIndent(),
200+
content.getElementsByClass("custom-language-block").singleOrNull()?.wholeText()
201+
)
202+
assertEquals(
203+
"""
204+
// something before linebreak
205+
206+
test("hello other")
207+
""".trimIndent(),
208+
content.getElementsByClass("lang-other").singleOrNull()?.wholeText()
151209
)
152210
}
153211

@@ -165,7 +223,7 @@ class CodeBlocksTest : BaseAbstractTest() {
165223
}
166224

167225
private object CustomHtmlBlockRenderer : HtmlCodeBlockRenderer {
168-
override fun isApplicable(language: String, code: String): Boolean = language == "custom"
226+
override fun isApplicable(language: String): Boolean = language == "custom"
169227

170228
override fun FlowContent.buildCodeBlock(language: String, code: String) {
171229
div("custom-language-block") {
@@ -175,7 +233,7 @@ class CodeBlocksTest : BaseAbstractTest() {
175233
}
176234

177235
private object CustomOtherHtmlBlockRenderer : HtmlCodeBlockRenderer {
178-
override fun isApplicable(language: String, code: String): Boolean = language == "other"
236+
override fun isApplicable(language: String): Boolean = language == "other"
179237

180238
override fun FlowContent.buildCodeBlock(language: String, code: String) {
181239
div("other-language-block") {

0 commit comments

Comments
 (0)