diff options
author | Paweł Marks <pmarks@virtuslab.com> | 2020-02-17 09:32:35 +0100 |
---|---|---|
committer | Paweł Marks <Kordyjan@users.noreply.github.com> | 2020-02-18 13:28:23 +0100 |
commit | f625cef495d625d81ee22e950083f57cc4fab875 (patch) | |
tree | d4587be659154a3000ee58fe2297e55604e418e8 /core/src/main/kotlin/renderers | |
parent | 3b200cf10e0c50c2eee4b9da3f7039d678fa4aad (diff) | |
download | dokka-f625cef495d625d81ee22e950083f57cc4fab875.tar.gz dokka-f625cef495d625d81ee22e950083f57cc4fab875.tar.bz2 dokka-f625cef495d625d81ee22e950083f57cc4fab875.zip |
Moves PsiToDocumentablesTranslator to the base plugin
Diffstat (limited to 'core/src/main/kotlin/renderers')
-rw-r--r-- | core/src/main/kotlin/renderers/DefaultRenderer.kt | 124 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/html/HtmlRenderer.kt | 217 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/html/NavigationPage.kt | 50 | ||||
-rw-r--r-- | core/src/main/kotlin/renderers/html/htmlPreprocessors.kt | 68 |
4 files changed, 0 insertions, 459 deletions
diff --git a/core/src/main/kotlin/renderers/DefaultRenderer.kt b/core/src/main/kotlin/renderers/DefaultRenderer.kt deleted file mode 100644 index d09d9ded..00000000 --- a/core/src/main/kotlin/renderers/DefaultRenderer.kt +++ /dev/null @@ -1,124 +0,0 @@ -package org.jetbrains.dokka.renderers - -import org.jetbrains.dokka.CoreExtensions -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.resolvers.LocationProvider -import org.jetbrains.dokka.transformers.pages.PageNodeTransformer - -abstract class DefaultRenderer<T>( - protected val outputWriter: OutputWriter, - protected val context: DokkaContext -) : Renderer { - - 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 diff --git a/core/src/main/kotlin/renderers/html/HtmlRenderer.kt b/core/src/main/kotlin/renderers/html/HtmlRenderer.kt deleted file mode 100644 index 376ce5c8..00000000 --- a/core/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ /dev/null @@ -1,217 +0,0 @@ -package org.jetbrains.dokka.renderers.html - -import kotlinx.html.* -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Function -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.renderers.DefaultRenderer -import org.jetbrains.dokka.renderers.OutputWriter -import java.io.File - -open class HtmlRenderer( - outputWriter: OutputWriter, - context: DokkaContext -) : DefaultRenderer<FlowContent>(outputWriter, context) { - - private val pageList = mutableListOf<String>() - - override val preprocessors = listOf( - RootCreator, - SearchPageInstaller, - ResourceInstaller, - NavigationPageInstaller, - StyleAndScriptsAppender - ) - - override fun FlowContent.buildList(node: ContentList, pageContext: ContentPage) = - if (node.ordered) ol { - buildListItems(node.children, pageContext) - } - else ul { - buildListItems(node.children, pageContext) - } - - open fun OL.buildListItems(items: List<ContentNode>, pageContext: ContentPage) { - items.forEach { - if (it is ContentList) - buildList(it, pageContext) - else - li { it.build(this, pageContext) } - } - } - - open fun UL.buildListItems(items: List<ContentNode>, pageContext: ContentPage) { - items.forEach { - if (it is ContentList) - buildList(it, pageContext) - else - li { it.build(this, pageContext) } - } - } - - override fun FlowContent.buildResource( - node: ContentEmbeddedResource, - pageContext: ContentPage - ) { // TODO: extension point there - val imageExtensions = setOf("png", "jpg", "jpeg", "gif", "bmp", "tif", "webp", "svg") - return if (File(node.address).extension.toLowerCase() in imageExtensions) { - //TODO: add imgAttrs parsing - val imgAttrs = node.extras.filterIsInstance<HTMLSimpleAttr>().joinAttr() - img(src = node.address, alt = node.altText) - } else { - println("Unrecognized resource type: $node") - } - } - - override fun FlowContent.buildTable(node: ContentTable, pageContext: ContentPage) { - table { - thead { - node.header.forEach { - tr { - it.children.forEach { - th { - it.build(this@table, pageContext) - } - } - } - } - } - tbody { - node.children.forEach { - tr { - it.children.forEach { - td { - it.build(this, pageContext) - } - } - } - } - } - } - } - - override fun FlowContent.buildHeader(level: Int, content: FlowContent.() -> Unit) { - when (level) { - 1 -> h1(block = content) - 2 -> h2(block = content) - 3 -> h3(block = content) - 4 -> h4(block = content) - 5 -> h5(block = content) - else -> h6(block = content) - } - } - - override fun FlowContent.buildNavigation(page: PageNode) = - locationProvider.ancestors(page).asReversed().forEach { node -> - text("/") - if (node.isNavigable) buildLink(node, page) - else text(node.name) - } - - private fun FlowContent.buildLink(to: PageNode, from: PageNode) = - buildLink(locationProvider.resolve(to, from)) { - text(to.name) - } - - fun FlowContent.buildLink( - to: DRI, - platforms: List<PlatformData>, - from: PageNode? = null, - block: FlowContent.() -> Unit - ) = buildLink(locationProvider.resolve(to, platforms, from), block) - - override fun buildError(node: ContentNode) { - context.logger.error("Unknown ContentNode type: $node") - } - - override fun FlowContent.buildNewLine() { - br() - } - - override fun FlowContent.buildLink(address: String, content: FlowContent.() -> Unit) = - a(href = address, block = content) - - override fun FlowContent.buildCode(code: List<ContentNode>, language: String, pageContext: ContentPage) { - buildNewLine() - code.forEach { - +((it as? ContentText)?.text ?: run { context.logger.error("Cannot cast $it as ContentText!"); "" }) - buildNewLine() - } - } - - override fun renderPage(page: PageNode) { - super.renderPage(page) - if (page is ContentPage) { - pageList.add( - """{ "name": "${page.name}", ${if (page is ClasslikePageNode) "\"class\": \"${page.name}\"," else ""} "location": "${locationProvider.resolve( - page - )}" }""" - ) - } - } - - override fun FlowContent.buildText(textNode: ContentText) { - text(textNode.text) - } - - override fun render(root: RootPageNode) { - super.render(root) - outputWriter.write("scripts/pages", "var pages = [\n${pageList.joinToString(",\n")}\n]", ".js") - } - - private fun PageNode.root(path: String) = locationProvider.resolveRoot(this) + path - - override fun buildPage(page: ContentPage, content: (FlowContent, ContentPage) -> Unit): String = - buildHtml(page, page.embeddedResources) { content(this, page) } - - open fun buildHtml(page: PageNode, resources: List<String>, content: FlowContent.() -> Unit) = - createHTML().html { - head { - title(page.name) - with(resources) { - filter { it.substringBefore('?').substringAfterLast('.') == "css" } - .forEach { link(rel = LinkRel.stylesheet, href = page.root(it)) } - filter { it.substringBefore('?').substringAfterLast('.') == "js" } - .forEach { script(type = ScriptType.textJavaScript, src = page.root(it)) { async = true } } - } - script { unsafe { +"""var pathToRoot = "${locationProvider.resolveRoot(page)}";""" } } - } - body { - div { - id = "navigation" - div { - id = "searchBar" - form(action = page.root("-search.html"), method = FormMethod.get) { - id = "searchForm" - input(type = InputType.search, name = "query") - input(type = InputType.submit) { value = "Search" } - } - } - div { - id = "sideMenu" - } - } - div { - id = "content" - content() - } - } - } -} - -fun List<HTMLMetadata>.joinAttr() = joinToString(" ") { it.key + "=" + it.value } - -private fun PageNode.pageKind() = when (this) { - is PackagePageNode -> "package" - is ClasslikePageNode -> "class" - is MemberPageNode -> when (this.documentable) { - is Function -> "function" - else -> "other" - } - else -> "other" -} - -private val PageNode.isNavigable: Boolean - get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
\ No newline at end of file diff --git a/core/src/main/kotlin/renderers/html/NavigationPage.kt b/core/src/main/kotlin/renderers/html/NavigationPage.kt deleted file mode 100644 index 4a2fb40d..00000000 --- a/core/src/main/kotlin/renderers/html/NavigationPage.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.jetbrains.dokka.renderers.html - -import kotlinx.html.* -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.pages.PageNode -import org.jetbrains.dokka.pages.PlatformData -import org.jetbrains.dokka.pages.RendererSpecificPage -import org.jetbrains.dokka.pages.RenderingStrategy - -class NavigationPage(val root: NavigationNode) : RendererSpecificPage { - override val name = "navigation" - - override val children = emptyList<PageNode>() - - override fun modified(name: String, children: List<PageNode>) = this - - override val strategy = RenderingStrategy<HtmlRenderer> { - createHTML().visit(root, "nav-submenu", this) - } - - private fun <R> TagConsumer<R>.visit(node: NavigationNode, navId: String, renderer: HtmlRenderer): R = - with(renderer) { - div("sideMenuPart") { - id = navId - div("overview") { - buildLink(node.dri, node.platforms) { +node.name } - if (node.children.isNotEmpty()) { - span("navButton") { - onClick = """document.getElementById("$navId").classList.toggle("hidden");""" - span("navButtonContent") - } - } - } - node.children.withIndex().forEach { (n, p) -> visit(p, "$navId-$n", renderer) } - } - } -} - -class NavigationNode( - val name: String, - val dri: DRI, - val platforms: List<PlatformData>, - val children: List<NavigationNode> -) - -fun NavigationPage.transform(block: (NavigationNode) -> NavigationNode) = NavigationPage(root.transform(block)) - -fun NavigationNode.transform(block: (NavigationNode) -> NavigationNode) = - run(block).let { NavigationNode(it.name, it.dri, it.platforms, it.children.map(block)) } diff --git a/core/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/core/src/main/kotlin/renderers/html/htmlPreprocessors.kt deleted file mode 100644 index 4ee67448..00000000 --- a/core/src/main/kotlin/renderers/html/htmlPreprocessors.kt +++ /dev/null @@ -1,68 +0,0 @@ -package org.jetbrains.dokka.renderers.html - -import kotlinx.html.h1 -import kotlinx.html.id -import kotlinx.html.table -import kotlinx.html.tbody -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.renderers.platforms -import org.jetbrains.dokka.transformers.pages.PageNodeTransformer - -object RootCreator : PageNodeTransformer { - override fun invoke(input: RootPageNode) = - RendererSpecificRootPage("", listOf(input), RenderingStrategy.DoNothing) -} - -object SearchPageInstaller : PageNodeTransformer { - override fun invoke(input: RootPageNode) = input.modified(children = input.children + searchPage) - - private val searchPage = RendererSpecificResourcePage( - name = "Search", - children = emptyList(), - strategy = RenderingStrategy<HtmlRenderer> { - buildHtml(it, listOf("styles/style.css", "scripts/pages.js")) { - h1 { - id = "searchTitle" - text("Search results for ") - } - table { - tbody { - id = "searchTable" - } - } - } - }) -} - -object NavigationPageInstaller : PageNodeTransformer { - override fun invoke(input: RootPageNode) = input.modified( - children = input.children + NavigationPage( - input.children.filterIsInstance<ContentPage>().single().let(::visit) - ) - ) - - private fun visit(page: ContentPage): NavigationNode = NavigationNode( - page.name, - page.dri.first(), - page.platforms(), - page.children.filterIsInstance<ContentPage>().map { visit(it) }) -} - -object ResourceInstaller : PageNodeTransformer { - override fun invoke(input: RootPageNode) = input.modified(children = input.children + resourcePages) - - private val resourcePages = listOf("styles", "scripts", "images").map { - RendererSpecificResourcePage(it, emptyList(), RenderingStrategy.Copy("/dokka/$it")) - } -} - -object StyleAndScriptsAppender : PageNodeTransformer { - override fun invoke(input: RootPageNode) = input.transformContentPagesTree { - it.modified( - embeddedResources = it.embeddedResources + listOf( - "styles/style.css", - "scripts/navigationLoader.js" - ) - ) - } -} |