aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt')
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt127
1 files changed, 127 insertions, 0 deletions
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
new file mode 100644
index 00000000..c6183cf3
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -0,0 +1,127 @@
+package org.jetbrains.dokka.base.renderers
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.renderers.OutputWriter
+import org.jetbrains.dokka.renderers.Renderer
+import org.jetbrains.dokka.resolvers.LocationProvider
+import org.jetbrains.dokka.transformers.pages.PageNodeTransformer
+
+abstract class DefaultRenderer<T>(
+ protected val context: DokkaContext
+) : Renderer {
+
+ protected val outputWriter = context.single(CoreExtensions.outputWriter)
+
+ protected lateinit var locationProvider: LocationProvider
+ private set
+
+ protected open val preprocessors: Iterable<PageNodeTransformer> = emptyList()
+
+ abstract fun T.buildHeader(level: Int, content: T.() -> Unit)
+ abstract fun T.buildLink(address: String, content: T.() -> Unit)
+ abstract fun T.buildList(node: ContentList, pageContext: ContentPage)
+ abstract fun T.buildNewLine()
+ abstract fun T.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage)
+ abstract fun T.buildTable(node: ContentTable, pageContext: ContentPage)
+ abstract fun T.buildText(textNode: ContentText)
+ abstract fun T.buildNavigation(page: PageNode)
+
+ abstract fun buildPage(page: ContentPage, content: (T, ContentPage) -> Unit): String
+ abstract fun buildError(node: ContentNode)
+
+ open fun T.buildGroup(node: ContentGroup, pageContext: ContentPage) {
+ node.children.forEach { it.build(this, pageContext) }
+ }
+
+ open fun T.buildLinkText(nodes: List<ContentNode>, pageContext: ContentPage) {
+ nodes.forEach { it.build(this, pageContext) }
+ }
+
+ open fun T.buildCode(code: List<ContentNode>, language: String, pageContext: ContentPage) {
+ code.forEach { it.build(this, pageContext) }
+ }
+
+ open fun T.buildHeader(node: ContentHeader, pageContext: ContentPage) {
+ buildHeader(node.level) { node.children.forEach { it.build(this, pageContext) } }
+ }
+
+ open fun ContentNode.build(builder: T, pageContext: ContentPage) =
+ builder.buildContentNode(this, pageContext)
+
+ open fun T.buildContentNode(node: ContentNode, pageContext: ContentPage) {
+ when (node) {
+ is ContentText -> buildText(node)
+ is ContentHeader -> buildHeader(node, pageContext)
+ is ContentCode -> buildCode(node.children, node.language, pageContext)
+ is ContentDRILink -> buildLink(
+ locationProvider.resolve(node.address, node.platforms.toList(), pageContext)
+ ) {
+ buildLinkText(node.children, pageContext)
+ }
+ is ContentResolvedLink -> buildLink(node.address) { buildLinkText(node.children, pageContext) }
+ is ContentEmbeddedResource -> buildResource(node, pageContext)
+ is ContentList -> buildList(node, pageContext)
+ is ContentTable -> buildTable(node, pageContext)
+ is ContentGroup -> buildGroup(node, pageContext)
+ else -> buildError(node)
+ }
+ }
+
+ open fun buildPageContent(context: T, page: ContentPage) {
+ context.buildNavigation(page)
+ page.content.build(context, page)
+ }
+
+ open fun renderPage(page: PageNode) {
+ val path by lazy { locationProvider.resolve(page, skipExtension = true) }
+ when (page) {
+ is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".html")
+ is RendererSpecificPage -> when (val strategy = page.strategy) {
+ is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path)
+ is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "")
+ is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".html")
+ RenderingStrategy.DoNothing -> Unit
+ }
+ else -> throw AssertionError(
+ "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content"
+ )
+ }
+ }
+
+ open fun renderPages(root: PageNode) {
+ renderPage(root)
+ root.children.forEach { renderPages(it) }
+ }
+
+ // reimplement this as preprocessor
+ open fun renderPackageList(root: ContentPage) =
+ getPackageNamesAndPlatforms(root)
+ .keys
+ .joinToString("\n")
+ .also { outputWriter.write("${root.name}/package-list", it, "") }
+
+ open fun getPackageNamesAndPlatforms(root: PageNode): Map<String, List<PlatformData>> =
+ root.children
+ .map(::getPackageNamesAndPlatforms)
+ .fold(emptyMap<String, List<PlatformData>>()) { e, acc -> acc + e } +
+ if (root is PackagePageNode) {
+ mapOf(root.name to root.platforms())
+ } else {
+ emptyMap()
+ }
+
+ override fun render(root: RootPageNode) {
+ val newRoot = preprocessors.fold(root) { acc, t -> t(acc) }
+
+ locationProvider =
+ context.single(CoreExtensions.locationProviderFactory).getLocationProvider(newRoot)
+
+ root.children<ModulePageNode>().forEach { renderPackageList(it) }
+
+ renderPages(newRoot)
+ }
+}
+
+fun ContentPage.platforms() = this.content.platforms.toList() \ No newline at end of file