diff options
Diffstat (limited to 'plugins/all-modules-page')
20 files changed, 99 insertions, 681 deletions
diff --git a/plugins/all-modules-page/build.gradle.kts b/plugins/all-modules-page/build.gradle.kts index c6e88574..9c5fe1c3 100644 --- a/plugins/all-modules-page/build.gradle.kts +++ b/plugins/all-modules-page/build.gradle.kts @@ -6,6 +6,8 @@ registerDokkaArtifactPublication("dokkaAllModulesPage") { dependencies { implementation(project(":plugins:base")) + implementation(project(":plugins:templating")) + implementation(project(":plugins:versioning")) testImplementation(project(":plugins:base")) testImplementation(project(":plugins:base:base-test-utils")) testImplementation(project(":plugins:gfm")) @@ -13,10 +15,9 @@ dependencies { val coroutines_version: String by project implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") - - implementation("org.jsoup:jsoup:1.12.1") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.1") - val kotlinx_html_version: String by project - testImplementation("org.jetbrains.kotlinx:kotlinx-html-jvm:$kotlinx_html_version") + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:$kotlinx_html_version") + + implementation("org.jsoup:jsoup:1.12.1") }
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt b/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt index 5ac854b4..0013feed 100644 --- a/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt +++ b/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt @@ -8,15 +8,23 @@ import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.query import org.jetbrains.dokka.plugability.querySingle +import org.jetbrains.dokka.templates.TemplatingPlugin +import org.jetbrains.dokka.versioning.VersioningPlugin class AllModulesPageGeneration(private val context: DokkaContext) : Generation { private val allModulesPagePlugin by lazy { context.plugin<AllModulesPagePlugin>() } + private val templatingPlugin by lazy { context.plugin<TemplatingPlugin>() } + private val versioningPlugin by lazy { context.plugin<VersioningPlugin>() } override fun Timer.generate() { + report("Creating all modules page") val pages = createAllModulesPage() + report("Copy previous documentation") + handlePreviousDocs() + report("Transforming pages") val transformedPages = transformAllModulesPage(pages) @@ -29,6 +37,8 @@ class AllModulesPageGeneration(private val context: DokkaContext) : Generation { override val generationName = "index page for project" + fun handlePreviousDocs() = versioningPlugin.querySingle { versioningHandler }.invoke() + fun createAllModulesPage() = allModulesPagePlugin.querySingle { allModulesPageCreator }.invoke() fun transformAllModulesPage(pages: RootPageNode) = @@ -39,5 +49,5 @@ class AllModulesPageGeneration(private val context: DokkaContext) : Generation { } fun processSubmodules() = - allModulesPagePlugin.querySingle { templateProcessor }.process() + templatingPlugin.querySingle { templateProcessor }.process() }
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt b/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt index c99293ef..9f4b62ee 100644 --- a/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt +++ b/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt @@ -1,31 +1,29 @@ package org.jetbrains.dokka.allModulesPage import org.jetbrains.dokka.CoreExtensions -import org.jetbrains.dokka.allModulesPage.templates.* import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProviderFactory import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory import org.jetbrains.dokka.plugability.DokkaPlugin +import org.jetbrains.dokka.templates.TemplatingPlugin import org.jetbrains.dokka.transformers.pages.PageCreator import org.jetbrains.dokka.transformers.pages.PageTransformer class AllModulesPagePlugin : DokkaPlugin() { - val templateProcessor by extensionPoint<TemplateProcessor>() - val templateProcessingStrategy by extensionPoint<TemplateProcessingStrategy>() val partialLocationProviderFactory by extensionPoint<LocationProviderFactory>() val allModulesPageCreator by extensionPoint<PageCreator>() val allModulesPageTransformer by extensionPoint<PageTransformer>() val externalModuleLinkResolver by extensionPoint<ExternalModuleLinkResolver>() - val substitutor by extensionPoint<Substitutor>() - val allModulesPageCreators by extending { allModulesPageCreator providing ::MultimodulePageCreator } + val dokkaBase by lazy { plugin<DokkaBase>() } + val multimoduleLocationProvider by extending { - (plugin<DokkaBase>().locationProviderFactory + (dokkaBase.locationProviderFactory providing MultimoduleLocationProvider::Factory override plugin<DokkaBase>().locationProvider) } @@ -37,37 +35,11 @@ class AllModulesPagePlugin : DokkaPlugin() { val allModulesPageGeneration by extending { (CoreExtensions.generation providing ::AllModulesPageGeneration - override plugin<DokkaBase>().singleGeneration) - } - - val defaultTemplateProcessor by extending { - templateProcessor providing ::DefaultTemplateProcessor - } - - val directiveBasedHtmlTemplateProcessingStrategy by extending { - templateProcessingStrategy providing ::DirectiveBasedHtmlTemplateProcessingStrategy order { - before(fallbackProcessingStrategy) - } - } - - val fallbackProcessingStrategy by extending { - templateProcessingStrategy providing ::FallbackTemplateProcessingStrategy - } - - val navigationSearchTemplateStrategy by extending { - templateProcessingStrategy providing ::NavigationSearchTemplateStrategy order { - before(fallbackProcessingStrategy) - } - } - - val pagesSearchTemplateStrategy by extending { - templateProcessingStrategy providing ::PagesSearchTemplateStrategy order { - before(fallbackProcessingStrategy) - } + override dokkaBase.singleGeneration) } - val pathToRootSubstitutor by extending { - substitutor providing ::PathToRootSubstitutor + val resolveLinkCommandHandler by extending { + plugin<TemplatingPlugin>().directiveBasedCommandHandlers providing ::ResolveLinkCommandHandler } val multiModuleLinkResolver by extending { diff --git a/plugins/all-modules-page/src/main/kotlin/templates/ExternalModuleLinkResolver.kt b/plugins/all-modules-page/src/main/kotlin/ExternalModuleLinkResolver.kt index d0e787b6..74513957 100644 --- a/plugins/all-modules-page/src/main/kotlin/templates/ExternalModuleLinkResolver.kt +++ b/plugins/all-modules-page/src/main/kotlin/ExternalModuleLinkResolver.kt @@ -1,4 +1,4 @@ -package org.jetbrains.dokka.allModulesPage.templates +package org.jetbrains.dokka.allModulesPage import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.base.DokkaBase @@ -30,14 +30,22 @@ class DefaultExternalModuleLinkResolver(val context: DokkaContext) : ExternalMod context.configuration.modules.map(::loadPackageListForModule).toMap() return packageLists.mapNotNull { (module, packageList) -> packageList?.let { - ExternalDocumentation( - URL("file:/${module.name}/${module.name}"), - packageList - ) + context.configuration.modules.find { it.name == module.name }?.let { m -> + ExternalDocumentation( + URL("file:/${m.relativePathToOutputDirectory.toRelativeOutputDir()}"), + packageList + ) + } } } } + private fun File.toRelativeOutputDir(): File = if(isAbsolute) { + relativeToOrSelf(context.configuration.outputDir) + } else { + this + } + private fun loadPackageListForModule(module: DokkaConfiguration.DokkaModuleDescription) = module.sourceOutputDirectory.resolve(File(identifierToFilename(module.name))).let { it to PackageList.load( @@ -71,7 +79,7 @@ class DefaultExternalModuleLinkResolver(val context: DokkaContext) : ExternalMod RecognizedLinkFormat.DokkaJekyll -> ".md" else -> "" } - "${module.relativePathToOutputDirectory}/${identifierToFilename(moduleName)}/index$extension" + "${module.relativePathToOutputDirectory}/index$extension" } } diff --git a/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt b/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt index 1dbbd386..c7c32d55 100644 --- a/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt +++ b/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt @@ -1,7 +1,6 @@ package org.jetbrains.dokka.allModulesPage import org.jetbrains.dokka.allModulesPage.MultimodulePageCreator.Companion.MULTIMODULE_PACKAGE_PLACEHOLDER -import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.resolvers.local.DokkaBaseLocationProvider import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory import org.jetbrains.dokka.links.DRI diff --git a/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt b/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt index a333d7c4..458cf4c1 100644 --- a/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt +++ b/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt @@ -8,6 +8,7 @@ import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumen import org.jetbrains.dokka.base.parsers.moduleAndPackage.parseModuleAndPackageDocumentation import org.jetbrains.dokka.base.parsers.moduleAndPackage.parseModuleAndPackageDocumentationFragments import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint +import org.jetbrains.dokka.base.templating.InsertTemplateExtra import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder import org.jetbrains.dokka.links.DRI @@ -17,10 +18,14 @@ import org.jetbrains.dokka.model.doc.P import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.plugability.configuration import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle import org.jetbrains.dokka.transformers.pages.PageCreator import org.jetbrains.dokka.utilities.DokkaLogger +import org.jetbrains.dokka.versioning.ReplaceVersionsCommand +import org.jetbrains.dokka.versioning.VersioningConfiguration +import org.jetbrains.dokka.versioning.VersioningPlugin class MultimodulePageCreator( private val context: DokkaContext, @@ -39,6 +44,11 @@ class MultimodulePageCreator( kind = ContentKind.Cover, sourceSets = sourceSetData ) { + /* The line below checks if there is a provided configuration for versioning. + If not, we are skipping the template for inserting versions navigation */ + configuration<VersioningPlugin, VersioningConfiguration>(context)?.let { + group(extra = PropertyContainer.withAll(InsertTemplateExtra(ReplaceVersionsCommand))) { } + } header(2, "All modules:") table(styles = setOf(MultimoduleTable)) { modules.forEach { module -> diff --git a/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt b/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt new file mode 100644 index 00000000..e881a5ab --- /dev/null +++ b/plugins/all-modules-page/src/main/kotlin/ResolveLinkCommandHandler.kt @@ -0,0 +1,45 @@ +package org.jetbrains.dokka.allModulesPage + +import org.jetbrains.dokka.base.templating.Command +import org.jetbrains.dokka.base.templating.ResolveLinkCommand +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.plugability.plugin +import org.jetbrains.dokka.plugability.querySingle +import org.jetbrains.dokka.templates.CommandHandler +import org.jsoup.nodes.Attributes +import org.jsoup.nodes.Element +import org.jsoup.parser.Tag +import java.io.File + +class ResolveLinkCommandHandler(context: DokkaContext) : CommandHandler { + + private val externalModuleLinkResolver = + context.plugin<AllModulesPagePlugin>().querySingle { externalModuleLinkResolver } + + override fun handleCommand(element: Element, command: Command, input: File, output: File) { + command as ResolveLinkCommand + val link = externalModuleLinkResolver.resolve(command.dri, output) + if (link == null) { + val children = element.childNodes().toList() + val attributes = Attributes().apply { + put("data-unresolved-link", command.dri.toString()) + } + val el = Element(Tag.valueOf("span"), "", attributes).apply { + children.forEach { ch -> appendChild(ch) } + } + element.replaceWith(el) + return + } + + val attributes = Attributes().apply { + put("href", link) + } + val children = element.childNodes().toList() + val el = Element(Tag.valueOf("a"), "", attributes).apply { + children.forEach { ch -> appendChild(ch) } + } + element.replaceWith(el) + } + + override fun canHandle(command: Command): Boolean = command is ResolveLinkCommand +}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt b/plugins/all-modules-page/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt deleted file mode 100644 index 2b065731..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/DirectiveBasedTemplateProcessing.kt +++ /dev/null @@ -1,141 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.jetbrains.dokka.allModulesPage.AllModulesPagePlugin -import org.jetbrains.dokka.base.templating.* -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.query -import org.jetbrains.dokka.plugability.querySingle -import org.jsoup.Jsoup -import org.jsoup.nodes.* -import org.jsoup.parser.Tag -import java.io.File -import java.nio.file.Files -import java.util.concurrent.ConcurrentHashMap - -class DirectiveBasedHtmlTemplateProcessingStrategy(private val context: DokkaContext) : TemplateProcessingStrategy { - private val navigationFragments = ConcurrentHashMap<String, Element>() - - private val substitutors = context.plugin<AllModulesPagePlugin>().query { substitutor } - private val externalModuleLinkResolver = context.plugin<AllModulesPagePlugin>().querySingle { externalModuleLinkResolver } - - override suspend fun process(input: File, output: File): Boolean = coroutineScope { - if (input.extension == "html") { - launch { - val document = withContext(IO) { Jsoup.parse(input, "UTF-8") } - document.outputSettings().indentAmount(0).prettyPrint(false) - document.select("dokka-template-command").forEach { - when (val command = parseJson<Command>(it.attr("data"))) { - is ResolveLinkCommand -> resolveLink(it, command, output) - is AddToNavigationCommand -> navigationFragments[command.moduleName] = it - is SubstitutionCommand -> substitute(it, TemplatingContext(input, output, it, command)) - else -> context.logger.warn("Unknown templating command $command") - } - } - withContext(IO) { Files.write(output.toPath(), listOf(document.outerHtml())) } - } - true - } else false - } - - private fun substitute(element: Element, commandContext: TemplatingContext<SubstitutionCommand>) { - val regex = commandContext.command.pattern.toRegex() - element.children().forEach { it.traverseToSubstitute(regex, commandContext) } - - val childrenCopy = element.children().toList() - val position = element.elementSiblingIndex() - val parent = element.parent() - element.remove() - - parent.insertChildren(position, childrenCopy) - } - - private fun Node.traverseToSubstitute(regex: Regex, commandContext: TemplatingContext<SubstitutionCommand>) { - when (this) { - is TextNode -> replaceWith(TextNode(wholeText.substitute(regex, commandContext))) - is DataNode -> replaceWith(DataNode(wholeData.substitute(regex, commandContext))) - is Element -> { - attributes().forEach { attr(it.key, it.value.substitute(regex, commandContext)) } - childNodes().forEach { it.traverseToSubstitute(regex, commandContext) } - } - } - } - - private fun String.substitute(regex: Regex, commandContext: TemplatingContext<SubstitutionCommand>) = buildString { - var lastOffset = 0 - regex.findAll(this@substitute).forEach { match -> - append(this@substitute, lastOffset, match.range.first) - append(findSubstitution(commandContext, match)) - lastOffset = match.range.last + 1 - } - append(this@substitute, lastOffset, this@substitute.length) - } - - private fun findSubstitution(commandContext: TemplatingContext<SubstitutionCommand>, match: MatchResult): String = - substitutors.asSequence().mapNotNull { it.trySubstitute(commandContext, match) }.firstOrNull() ?: match.value - - override suspend fun finish(output: File) { - if (navigationFragments.isNotEmpty()) { - val attributes = Attributes().apply { - put("class", "sideMenu") - } - 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}") } - } - command.childNodes().toList().forEachIndexed { index, child -> - if (index == 0) { - child.attr("id", "$moduleName-nav-submenu") - } - node.appendChild(child) - } - } - - withContext(IO) { - Files.write(output.resolve("navigation.html").toPath(), listOf(node.outerHtml())) - } - - node.select("a").forEach { a -> - a.attr("href")?.also { a.attr("href", "../${it}") } - } - navigationFragments.keys.forEach { - withContext(IO) { - Files.write( - output.resolve(it).resolve("navigation.html").toPath(), - listOf(node.outerHtml()) - ) - } - } - } - } - - private fun resolveLink(it: Element, command: ResolveLinkCommand, fileContext: File) { - - val link = externalModuleLinkResolver.resolve(command.dri, fileContext) - if (link == null) { - val children = it.childNodes().toList() - val attributes = Attributes().apply { - put("data-unresolved-link", command.dri.toString()) - } - val element = Element(Tag.valueOf("span"), "", attributes).apply { - children.forEach { ch -> appendChild(ch) } - } - it.replaceWith(element) - return - } - - val attributes = Attributes().apply { - put("href", link) - } - val children = it.childNodes().toList() - val element = Element(Tag.valueOf("a"), "", attributes).apply { - children.forEach { ch -> appendChild(ch) } - } - it.replaceWith(element) - } -} diff --git a/plugins/all-modules-page/src/main/kotlin/templates/FallbackTemplateProcessingStrategy.kt b/plugins/all-modules-page/src/main/kotlin/templates/FallbackTemplateProcessingStrategy.kt deleted file mode 100644 index 9b5251ac..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/FallbackTemplateProcessingStrategy.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import org.jetbrains.dokka.plugability.DokkaContext -import java.io.File -import java.nio.file.Files - -class FallbackTemplateProcessingStrategy(dokkaContext: DokkaContext) : TemplateProcessingStrategy { - - override suspend fun process(input: File, output: File): Boolean = coroutineScope { - launch(IO) { - Files.copy(input.toPath(), output.toPath()) - } - true - } -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt b/plugins/all-modules-page/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt deleted file mode 100644 index c6c67752..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt +++ /dev/null @@ -1,74 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import java.io.File -import java.nio.file.Files -import com.fasterxml.jackson.module.kotlin.treeToValue -import org.jetbrains.dokka.base.renderers.html.SearchRecord -import org.jetbrains.dokka.base.templating.* -import org.jetbrains.dokka.plugability.DokkaContext -import java.util.concurrent.ConcurrentHashMap - -abstract class BaseJsonNavigationTemplateProcessingStrategy(val context: DokkaContext) : TemplateProcessingStrategy { - abstract val navigationFileNameWithoutExtension: String - abstract val path: String - - private val fragments = ConcurrentHashMap<String, List<SearchRecord>>() - - open fun canProcess(file: File): Boolean = - file.extension == "json" && file.nameWithoutExtension == navigationFileNameWithoutExtension - - override suspend fun process(input: File, output: File): Boolean = coroutineScope { - val canProcess = canProcess(input) - if (canProcess) { - launch { - withContext(Dispatchers.IO) { - runCatching { parseJson<AddToSearch>(input.readText()) }.getOrNull() - }?.let { command -> - fragments[command.moduleName] = command.elements - } ?: fallbackToCopy(input, output) - } - } - canProcess - } - - override suspend fun finish(output: File) { - if (fragments.isNotEmpty()) { - val content = toJsonString(fragments.entries.flatMap { (moduleName, navigation) -> - navigation.map { it.withResolvedLocation(moduleName) } - }) - withContext(Dispatchers.IO) { - output.resolve("$path/$navigationFileNameWithoutExtension.json").writeText(content) - - fragments.keys.forEach { - output.resolve(it).resolve("$path/$navigationFileNameWithoutExtension.json").writeText(content) - } - } - } - } - - private suspend fun fallbackToCopy(input: File, output: File) { - context.logger.warn("Falling back to just copying file for ${input.name} even thought it should process it") - withContext(Dispatchers.IO) { input.copyTo(output) } - } - - private fun SearchRecord.withResolvedLocation(moduleName: String): SearchRecord = - copy(location = "$moduleName/$location") - -} - -class NavigationSearchTemplateStrategy(val dokkaContext: DokkaContext) : - BaseJsonNavigationTemplateProcessingStrategy(dokkaContext) { - override val navigationFileNameWithoutExtension: String = "navigation-pane" - override val path: String = "scripts" -} - -class PagesSearchTemplateStrategy(val dokkaContext: DokkaContext) : - BaseJsonNavigationTemplateProcessingStrategy(dokkaContext) { - override val navigationFileNameWithoutExtension: String = "pages" - override val path: String = "scripts" -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/templates/PathToRootSubstitutor.kt b/plugins/all-modules-page/src/main/kotlin/templates/PathToRootSubstitutor.kt deleted file mode 100644 index 5056b724..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/PathToRootSubstitutor.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand -import org.jetbrains.dokka.base.templating.SubstitutionCommand -import org.jetbrains.dokka.plugability.DokkaContext -import java.io.File - -class PathToRootSubstitutor(private val dokkaContext: DokkaContext) : Substitutor { - override fun trySubstitute(context: TemplatingContext<SubstitutionCommand>, match: MatchResult): String? = - if (context.command is PathToRootSubstitutionCommand) { - context.output.toPath().parent.relativize(dokkaContext.configuration.outputDir.toPath()).toString().split(File.separator).joinToString(separator = "/", postfix = "/") { it } - } else null - -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/templates/Substitutor.kt b/plugins/all-modules-page/src/main/kotlin/templates/Substitutor.kt deleted file mode 100644 index 98f1d88e..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/Substitutor.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import org.jetbrains.dokka.base.templating.SubstitutionCommand - -fun interface Substitutor { - fun trySubstitute(context: TemplatingContext<SubstitutionCommand>, match: MatchResult): String? -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/templates/TemplateProcessor.kt b/plugins/all-modules-page/src/main/kotlin/templates/TemplateProcessor.kt deleted file mode 100644 index 18d63df0..00000000 --- a/plugins/all-modules-page/src/main/kotlin/templates/TemplateProcessor.kt +++ /dev/null @@ -1,60 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.coroutines.* -import org.jetbrains.dokka.allModulesPage.AllModulesPagePlugin -import org.jetbrains.dokka.base.templating.Command -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.query -import org.jsoup.nodes.Element -import java.io.File -import java.nio.file.Files -import java.nio.file.Path -import kotlin.coroutines.coroutineContext - -interface TemplateProcessor { - fun process() -} - -interface TemplateProcessingStrategy { - suspend fun process(input: File, output: File): Boolean - suspend fun finish(output: File) {} -} - -class DefaultTemplateProcessor( - private val context: DokkaContext, -): TemplateProcessor { - - private val strategies: List<TemplateProcessingStrategy> = context.plugin<AllModulesPagePlugin>().query { templateProcessingStrategy } - - override fun process() = runBlocking(Dispatchers.Default) { - coroutineScope { - context.configuration.modules.forEach { - launch { - it.sourceOutputDirectory.visit(context.configuration.outputDir.resolve(it.relativePathToOutputDirectory)) - } - } - } - strategies.map { it.finish(context.configuration.outputDir) } - Unit - } - - private suspend fun File.visit(target: File): Unit = coroutineScope { - val source = this@visit - if (source.isDirectory) { - target.mkdir() - source.list()?.forEach { - launch { source.resolve(it).visit(target.resolve(it)) } - } - } else { - strategies.asSequence().first { it.process(source, target) } - } - } -} - -data class TemplatingContext<out T: Command>( - val input: File, - val output: File, - val element: Element, - val command: T, -)
\ No newline at end of file diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToNavigationCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToNavigationCommandResolutionTest.kt deleted file mode 100644 index f917916a..00000000 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToNavigationCommandResolutionTest.kt +++ /dev/null @@ -1,137 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.html.a -import kotlinx.html.div -import kotlinx.html.id -import kotlinx.html.span -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.DokkaModuleDescriptionImpl -import org.jetbrains.dokka.allModulesPage.MultiModuleAbstractTest -import org.jetbrains.dokka.base.renderers.html.templateCommand -import org.jetbrains.dokka.base.templating.AddToNavigationCommand -import org.jetbrains.dokka.plugability.DokkaContext -import org.junit.Rule -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -import org.junit.rules.TemporaryFolder - -class AddToNavigationCommandResolutionTest : MultiModuleAbstractTest() { - @get:Rule - val folder: TemporaryFolder = TemporaryFolder() - - @Test - fun `should substitute AddToNavigationCommand in root directory`() = - addToNavigationTest { - val output = folder.root.resolve("navigation.html").readText() - val expected = expectedOutput( - ModuleWithPrefix("module1"), - ModuleWithPrefix("module2") - ) - assertHtmlEqualsIgnoringWhitespace(expected, output) - } - - @ParameterizedTest - @ValueSource(strings = ["module1", "module2"]) - fun `should substitute AddToNavigationCommand in modules directory`(moduleName: String) = - addToNavigationTest { - val output = folder.root.resolve(moduleName).resolve("navigation.html").readText() - val expected = expectedOutput( - ModuleWithPrefix("module1", ".."), - ModuleWithPrefix("module2", "..") - ) - assertHtmlEqualsIgnoringWhitespace(expected, output) - } - - private fun expectedOutput(vararg modulesWithPrefix: ModuleWithPrefix) = createHTML(prettyPrint = true) - .div("sideMenu") { - modulesWithPrefix.forEach { (moduleName, prefix) -> - val relativePrefix = prefix?.let { "$it/" } ?: "" - div("sideMenuPart") { - id = "$moduleName-nav-submenu" - div("overview") { - a { - href = "$relativePrefix$moduleName/module-page.html" - span { - +"module-$moduleName" - } - } - } - div("sideMenuPart") { - id = "$moduleName-nav-submenu-0" - div("overview") { - a { - href = "$relativePrefix$moduleName/$moduleName/package-page.html" - span { - +"package-$moduleName" - } - } - } - } - } - } - } - - private fun inputForModule(moduleName: String) = createHTML() - .templateCommand(AddToNavigationCommand(moduleName)) { - div("sideMenuPart") { - id = "$moduleName-nav-submenu" - div("overview") { - a { - href = "module-page.html" - span { - +"module-$moduleName" - } - } - } - div("sideMenuPart") { - id = "$moduleName-nav-submenu-0" - div("overview") { - a { - href = "$moduleName/package-page.html" - span { - +"package-$moduleName" - } - } - } - } - } - } - - private fun addToNavigationTest(test: (DokkaContext) -> Unit) { - folder.create() - val module1 = folder.newFolder("module1") - val module2 = folder.newFolder("module2") - - val configuration = dokkaConfiguration { - modules = listOf( - DokkaModuleDescriptionImpl( - name = "module1", - relativePathToOutputDirectory = module1, - includes = emptySet(), - sourceOutputDirectory = module1, - ), - DokkaModuleDescriptionImpl( - name = "module2", - relativePathToOutputDirectory = module2, - includes = emptySet(), - sourceOutputDirectory = module2, - ), - ) - this.outputDir = folder.root - } - - val module1Navigation = module1.resolve("navigation.html") - module1Navigation.writeText(inputForModule("module1")) - val module2Navigation = module2.resolve("navigation.html") - module2Navigation.writeText(inputForModule("module2")) - - testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { ctx -> - test(ctx) - } - } - } - - private data class ModuleWithPrefix(val moduleName: String, val prefix: String? = null) -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToSearchCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToSearchCommandResolutionTest.kt deleted file mode 100644 index 238134c7..00000000 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/AddToSearchCommandResolutionTest.kt +++ /dev/null @@ -1,90 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import org.jetbrains.dokka.DokkaModuleDescriptionImpl -import org.jetbrains.dokka.allModulesPage.MultiModuleAbstractTest -import org.jetbrains.dokka.base.renderers.html.SearchRecord -import org.jetbrains.dokka.base.templating.AddToSearch -import org.jetbrains.dokka.base.templating.parseJson -import org.jetbrains.dokka.base.templating.toJsonString -import org.junit.Rule -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -import org.junit.rules.TemporaryFolder -import java.io.File -import kotlin.test.assertEquals - -class AddToSearchCommandResolutionTest : MultiModuleAbstractTest() { - companion object { - val elements = listOf( - SearchRecord(name = "name1", location = "location1"), - SearchRecord(name = "name2", location = "location2") - ) - val fromModule1 = AddToSearch( - moduleName = "module1", - elements = elements - ) - val fromModule2 = AddToSearch( - moduleName = "module2", - elements = elements - ) - } - - @get:Rule - val folder: TemporaryFolder = TemporaryFolder() - - @ParameterizedTest - @ValueSource(strings = ["navigation-pane.json", "pages.json"]) - fun `should merge navigation templates`(fileName: String) { - val (module1Navigation, module2Navigation) = setupTestDirectoriesWithContent(fileName) - - val outputDir = folder.root - val configuration = dokkaConfiguration { - modules = listOf( - DokkaModuleDescriptionImpl( - name = "module1", - relativePathToOutputDirectory = folder.root.resolve("module1"), - includes = emptySet(), - sourceOutputDirectory = folder.root.resolve("module1"), - ), - DokkaModuleDescriptionImpl( - name = "module2", - relativePathToOutputDirectory = folder.root.resolve("module2"), - includes = emptySet(), - sourceOutputDirectory = folder.root.resolve("module2"), - ), - ) - this.outputDir = outputDir - } - - testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { _ -> - val expected = elements.map { it.copy(location = "module1/${it.location}") } + - elements.map { it.copy(location = "module2/${it.location}") } - - val output = - parseJson<List<SearchRecord>>(outputDir.resolve("scripts/${fileName}").readText()) - assertEquals(expected, output.sortedBy { it.location }) - - val outputFromModule1 = parseJson<List<SearchRecord>>(module1Navigation.readText()) - assertEquals(expected, outputFromModule1.sortedBy { it.location }) - - val outputFromModule2 = parseJson<List<SearchRecord>>(module2Navigation.readText()) - assertEquals(expected, outputFromModule2.sortedBy { it.location }) - } - } - } - - private fun setupTestDirectoriesWithContent(fileName: String): List<File> { - folder.create() - val scriptsForModule1 = folder.newFolder("module1", "scripts") - val scriptsForModule2 = folder.newFolder("module2", "scripts") - folder.newFolder("scripts") - - val module1Navigation = scriptsForModule1.resolve(fileName) - module1Navigation.writeText(toJsonString(fromModule1)) - val module2Navigation = scriptsForModule2.resolve(fileName) - module2Navigation.writeText(toJsonString(fromModule2)) - - return listOf(module1Navigation, module2Navigation) - } -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/SubstitutionCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/SubstitutionCommandResolutionTest.kt deleted file mode 100644 index 89984b46..00000000 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/SubstitutionCommandResolutionTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import kotlinx.html.a -import kotlinx.html.div -import kotlinx.html.id -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.DokkaModuleDescriptionImpl -import org.jetbrains.dokka.allModulesPage.MultiModuleAbstractTest -import org.jetbrains.dokka.base.renderers.html.templateCommand -import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand -import org.junit.Rule -import org.junit.rules.TemporaryFolder -import org.junit.jupiter.api.Test -import java.io.File - -class SubstitutionCommandResolutionTest : MultiModuleAbstractTest() { - - @get:Rule - val folder: TemporaryFolder = TemporaryFolder() - - @Test - fun `should handle PathToRootCommand`() { - val template = createHTML() - .templateCommand(PathToRootSubstitutionCommand(pattern = "###", default = "default")) { - a { - href = "###index.html" - div { - id = "logo" - } - } - } - - val expected = createHTML().a { - href = "../index.html" - div { - id = "logo" - } - } - - val testedFile = createDirectoriesAndWriteContent(template) - - val configuration = dokkaConfiguration { - modules = listOf( - DokkaModuleDescriptionImpl( - name = "module1", - relativePathToOutputDirectory = folder.root.resolve("module1"), - includes = emptySet(), - sourceOutputDirectory = folder.root.resolve("module1"), - ) - ) - this.outputDir = folder.root - } - - testFromData(configuration, preserveOutputLocation = true){ - submoduleProcessingStage = { - assertHtmlEqualsIgnoringWhitespace(expected, testedFile.readText()) - } - } - } - - private fun createDirectoriesAndWriteContent(content: String): File { - folder.create() - val module1 = folder.newFolder("module1") - val module1Content = module1.resolve("index.html") - module1Content.writeText(content) - return module1Content - } - -}
\ No newline at end of file diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/assertHtmlEqualsIgnoringWhitespace.kt b/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/assertHtmlEqualsIgnoringWhitespace.kt deleted file mode 100644 index 5a9ff531..00000000 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/assertHtmlEqualsIgnoringWhitespace.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.jetbrains.dokka.allModulesPage.templates - -import junit.framework.Assert.assertEquals -import org.jsoup.Jsoup - -/** - * Parses it using JSOUP, trims whitespace at the end of the line and asserts if they are equal - * parsing is required to unify the formatting - */ -fun assertHtmlEqualsIgnoringWhitespace(expected: String, actual: String) { - assertEquals( - Jsoup.parse(expected).outerHtml().trimSpacesAtTheEndOfLine(), - Jsoup.parse(actual).outerHtml().trimSpacesAtTheEndOfLine() - ) -} - -private fun String.trimSpacesAtTheEndOfLine(): String = - replace(" \n", "\n")
\ No newline at end of file diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/ResolveLinkCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt index 1b4e8638..cbf254a0 100644 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/ResolveLinkCommandResolutionTest.kt +++ b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt @@ -12,13 +12,14 @@ import org.jetbrains.dokka.links.DRI import org.junit.Rule import org.junit.jupiter.api.Test import org.junit.rules.TemporaryFolder +import utils.assertHtmlEqualsIgnoringWhitespace import java.io.File class ResolveLinkCommandResolutionTest : MultiModuleAbstractTest() { @get:Rule val folder: TemporaryFolder = TemporaryFolder() - fun configuration() = dokkaConfiguration { + private fun configuration() = dokkaConfiguration { modules = listOf( DokkaModuleDescriptionImpl( name = "module1", @@ -49,7 +50,7 @@ class ResolveLinkCommandResolutionTest : MultiModuleAbstractTest() { } val expected = createHTML().a { - href = "../../module2/module2/package2/-sample/index.html" + href = "../../module2/package2/-sample/index.html" span { +"Sample" } diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/ResolveLinkGfmCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt index 62aa9338..75576727 100644 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/ResolveLinkGfmCommandResolutionTest.kt +++ b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt @@ -18,7 +18,7 @@ class ResolveLinkGfmCommandResolutionTest : MultiModuleAbstractTest() { @get:Rule val folder: TemporaryFolder = TemporaryFolder() - fun configuration() = dokkaConfiguration { + private fun configuration() = dokkaConfiguration { modules = listOf( DokkaModuleDescriptionImpl( name = "module1", @@ -49,7 +49,7 @@ class ResolveLinkGfmCommandResolutionTest : MultiModuleAbstractTest() { } }.toString() - val expected = "[Sample text inside](../../module2/module2/package2/-sample/index.md)" + val expected = "[Sample text inside](../../module2/package2/-sample/index.md)" val content = setup(link) val configuration = configuration() @@ -61,7 +61,7 @@ class ResolveLinkGfmCommandResolutionTest : MultiModuleAbstractTest() { } } - fun setup(content: String): File { + private fun setup(content: String): File { folder.create() val innerModule1 = folder.newFolder("module1", "module1") val innerModule2 = folder.newFolder("module2", "module2") @@ -71,4 +71,4 @@ class ResolveLinkGfmCommandResolutionTest : MultiModuleAbstractTest() { contentFile.writeText(content) return contentFile } -}
\ No newline at end of file +} diff --git a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/mockedPackageListFactory.kt b/plugins/all-modules-page/src/test/kotlin/templates/mockedPackageListFactory.kt index 7a10041b..7a10041b 100644 --- a/plugins/all-modules-page/src/test/kotlin/org/jetbrains/dokka/allModulesPage/templates/mockedPackageListFactory.kt +++ b/plugins/all-modules-page/src/test/kotlin/templates/mockedPackageListFactory.kt |