mirror of
https://github.com/apple/pkl.git
synced 2026-03-24 18:11:27 +01:00
Initial commit
This commit is contained in:
134
pkl-doc/src/main/kotlin/org/pkl/doc/ClassPageGenerator.kt
Normal file
134
pkl-doc/src/main/kotlin/org/pkl/doc/ClassPageGenerator.kt
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlinx.html.*
|
||||
import org.pkl.core.PClass
|
||||
|
||||
internal class ClassPageGenerator(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
docPackage: DocPackage,
|
||||
docModule: DocModule,
|
||||
clazz: PClass,
|
||||
pageScope: ClassScope,
|
||||
isTestMode: Boolean
|
||||
) : ModuleOrClassPageGenerator<ClassScope>(docsiteInfo, docModule, clazz, pageScope, isTestMode) {
|
||||
override val html: HTML.() -> Unit = {
|
||||
renderHtmlHead()
|
||||
|
||||
body {
|
||||
onLoad = "onLoad()"
|
||||
|
||||
renderPageHeader(docPackage.name, docPackage.version, clazz.moduleName, clazz.simpleName)
|
||||
|
||||
main {
|
||||
renderParentLinks()
|
||||
|
||||
renderAnchors(clazz)
|
||||
|
||||
h1 {
|
||||
id = "declaration-title"
|
||||
+clazz.simpleName
|
||||
|
||||
span {
|
||||
id = "declaration-version"
|
||||
+docPackage.version
|
||||
}
|
||||
}
|
||||
|
||||
val memberDocs =
|
||||
MemberDocs(
|
||||
clazz.docComment,
|
||||
pageScope,
|
||||
clazz.annotations,
|
||||
isDeclaration = true,
|
||||
mapOf(
|
||||
MemberInfoKey("Known subtypes", runtimeDataClasses) to
|
||||
{
|
||||
id = HtmlConstants.KNOWN_SUBTYPES
|
||||
classes = runtimeDataClasses
|
||||
},
|
||||
MemberInfoKey("Known usages", runtimeDataClasses) to
|
||||
{
|
||||
id = HtmlConstants.KNOWN_USAGES
|
||||
classes = runtimeDataClasses
|
||||
},
|
||||
MemberInfoKey("All versions", runtimeDataClasses) to
|
||||
{
|
||||
id = HtmlConstants.KNOWN_VERSIONS
|
||||
classes = runtimeDataClasses
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
renderMemberGroupLinks(
|
||||
Triple("Overview", "#_overview", memberDocs.isExpandable),
|
||||
Triple("Properties", "#_properties", clazz.hasListedProperty),
|
||||
Triple("Methods", "#_methods", clazz.hasListedMethod)
|
||||
)
|
||||
|
||||
renderAnchor("_overview")
|
||||
div {
|
||||
id = "_declaration"
|
||||
classes = setOf("member")
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-signature", "member-deprecated")
|
||||
} else setOf("member-signature")
|
||||
|
||||
renderModifiers(clazz.modifiers, "class")
|
||||
|
||||
span {
|
||||
classes = setOf("name-decl")
|
||||
|
||||
+clazz.simpleName
|
||||
}
|
||||
|
||||
renderTypeParameters(clazz.typeParameters)
|
||||
|
||||
renderClassExtendsClause(clazz, pageScope)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
|
||||
renderProperties()
|
||||
renderMethods()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// example output:
|
||||
// class HostAlias (io.k8s/api/core/v1/PodSpec:befa7c51) • Pkl Hub
|
||||
override fun HTMLTag.renderPageTitle() {
|
||||
val classScope = pageScope
|
||||
val moduleScope = classScope.parent!!
|
||||
val packageScope = moduleScope.parent!!
|
||||
|
||||
+classScope.clazz.simpleName
|
||||
+" ("
|
||||
+packageScope.name
|
||||
+moduleScope.name.drop(packageScope.name.length).replace('.', '/')
|
||||
+":"
|
||||
+packageScope.version
|
||||
+") • "
|
||||
+(docsiteInfo.title ?: "Pkldoc")
|
||||
}
|
||||
}
|
||||
277
pkl-doc/src/main/kotlin/org/pkl/doc/CliDocGenerator.kt
Normal file
277
pkl-doc/src/main/kotlin/org/pkl/doc/CliDocGenerator.kt
Normal file
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import java.nio.file.Path
|
||||
import kotlin.Pair
|
||||
import org.pkl.commons.cli.CliBaseOptions.Companion.getProjectFile
|
||||
import org.pkl.commons.cli.CliCommand
|
||||
import org.pkl.commons.cli.CliException
|
||||
import org.pkl.core.*
|
||||
import org.pkl.core.module.ModuleKeyFactories
|
||||
import org.pkl.core.packages.*
|
||||
|
||||
/**
|
||||
* Entry point for the high-level Pkldoc API.
|
||||
*
|
||||
* The high-level API offers the same configuration options as the Pkldoc CLI.
|
||||
*
|
||||
* For the low-level Pkldoc API, see [DocGenerator].
|
||||
*/
|
||||
class CliDocGenerator(private val options: CliDocGeneratorOptions) : CliCommand(options.base) {
|
||||
|
||||
private val packageResolver = PackageResolver.getInstance(securityManager, moduleCacheDir)
|
||||
|
||||
private val stdlibDependency =
|
||||
DocPackageInfo.PackageDependency(
|
||||
name = "pkl",
|
||||
uri = null,
|
||||
version = if (options.isTestMode) "0.24.0" else Release.current().version().toString(),
|
||||
sourceCode =
|
||||
if (options.isTestMode) URI("https://github.com/apple/pkl/blob/dev/stdlib/")
|
||||
else URI(Release.current().sourceCode().homepage()),
|
||||
sourceCodeUrlScheme =
|
||||
if (options.isTestMode)
|
||||
"https://github.com/apple/pkl/blob/0.24.0/stdlib%{path}#L%{line}-L%{endLine}"
|
||||
else Release.current().sourceCode().sourceCodeUrlScheme,
|
||||
documentation =
|
||||
if (options.isTestMode) URI("https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/")
|
||||
else
|
||||
URI(
|
||||
PklInfo.current()
|
||||
.packageIndex
|
||||
.getPackagePage("pkl", Release.current().version().toString())
|
||||
)
|
||||
)
|
||||
|
||||
private fun DependencyMetadata.getPackageDependencies(): List<DocPackageInfo.PackageDependency> {
|
||||
return buildList {
|
||||
for ((_, dependency) in dependencies) {
|
||||
val metadata =
|
||||
try {
|
||||
packageResolver.getDependencyMetadata(dependency.packageUri, dependency.checksums)
|
||||
} catch (e: Exception) {
|
||||
throw CliException(
|
||||
"Failed to fetch dependency metadata for ${dependency.packageUri}: ${e.message}"
|
||||
)
|
||||
}
|
||||
val packageDependency =
|
||||
DocPackageInfo.PackageDependency(
|
||||
name = metadata.name,
|
||||
uri = dependency.packageUri.uri,
|
||||
version = metadata.version.toString(),
|
||||
sourceCode = metadata.sourceCode,
|
||||
sourceCodeUrlScheme = metadata.sourceCodeUrlScheme,
|
||||
documentation = metadata.documentation
|
||||
)
|
||||
add(packageDependency)
|
||||
}
|
||||
add(stdlibDependency)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PackageUri.toDocPackageInfo(): DocPackageInfo {
|
||||
val metadataAndChecksum =
|
||||
try {
|
||||
packageResolver.getDependencyMetadataAndComputeChecksum(this)
|
||||
} catch (e: PackageLoadError) {
|
||||
throw CliException("Failed to package metadata for $this: ${e.message}")
|
||||
}
|
||||
val metadata = metadataAndChecksum.first
|
||||
val checksum = metadataAndChecksum.second
|
||||
return DocPackageInfo(
|
||||
name = "${uri.authority}${uri.path.substringBeforeLast('@')}",
|
||||
moduleNamePrefix = "${metadata.name}.",
|
||||
version = metadata.version.toString(),
|
||||
importUri = toPackageAssetUri("/").toString(),
|
||||
uri = uri,
|
||||
authors = metadata.authors,
|
||||
issueTracker = metadata.issueTracker,
|
||||
dependencies = metadata.getPackageDependencies(),
|
||||
overview = metadata.description,
|
||||
extraAttributes = mapOf("Checksum" to checksum.sha256),
|
||||
sourceCode = metadata.sourceCode,
|
||||
sourceCodeUrlScheme = metadata.sourceCodeUrlScheme
|
||||
)
|
||||
}
|
||||
|
||||
private fun PackageUri.gatherAllModules(): List<PackageAssetUri> {
|
||||
fun PackageAssetUri.gatherModulesRecursively(): List<PackageAssetUri> {
|
||||
val self = this
|
||||
return buildList {
|
||||
for (element in packageResolver.listElements(self, null)) {
|
||||
val elementAssetUri = self.resolve(element.name)
|
||||
if (element.isDirectory) {
|
||||
addAll(elementAssetUri.gatherModulesRecursively())
|
||||
} else if (element.name.endsWith(".pkl")) {
|
||||
add(elementAssetUri)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return toPackageAssetUri("/").gatherModulesRecursively()
|
||||
}
|
||||
|
||||
override fun doRun() {
|
||||
val docsiteInfoModuleUris = mutableListOf<URI>()
|
||||
val packageInfoModuleUris = mutableListOf<URI>()
|
||||
val regularModuleUris = mutableListOf<URI>()
|
||||
val pklProjectPaths = mutableSetOf<Path>()
|
||||
val packageUris = mutableListOf<PackageUri>()
|
||||
for (moduleUri in options.base.normalizedSourceModules) {
|
||||
if (moduleUri.scheme == "file") {
|
||||
val dir = Path.of(moduleUri).parent
|
||||
val projectFile = dir.getProjectFile(options.base.normalizedRootDir)
|
||||
if (projectFile != null) {
|
||||
pklProjectPaths.add(projectFile)
|
||||
}
|
||||
}
|
||||
when {
|
||||
moduleUri.path?.endsWith("/docsite-info.pkl", ignoreCase = true) ?: false ->
|
||||
docsiteInfoModuleUris.add(moduleUri)
|
||||
moduleUri.path?.endsWith("/doc-package-info.pkl", ignoreCase = true) ?: false ->
|
||||
packageInfoModuleUris.add(moduleUri)
|
||||
moduleUri.scheme == "package" -> {
|
||||
if (moduleUri.fragment != null) {
|
||||
throw CliException("Cannot generate documentation for just one module within a package")
|
||||
}
|
||||
try {
|
||||
packageUris.add(PackageUri(moduleUri))
|
||||
} catch (e: URISyntaxException) {
|
||||
throw CliException(e.message!!)
|
||||
}
|
||||
}
|
||||
else -> regularModuleUris.add(moduleUri)
|
||||
}
|
||||
}
|
||||
|
||||
if (docsiteInfoModuleUris.size > 1) {
|
||||
throw CliException(
|
||||
"`sourceModules` contains multiple modules named `docsite-info.pkl`:\n" +
|
||||
docsiteInfoModuleUris.joinToString("\n")
|
||||
)
|
||||
}
|
||||
|
||||
if (packageInfoModuleUris.isEmpty() && packageUris.isEmpty()) {
|
||||
throw CliException(
|
||||
"`sourceModules` must contain at least one module named `doc-package-info.pkl`, or an argument must be a package URI."
|
||||
)
|
||||
}
|
||||
|
||||
if (regularModuleUris.isEmpty() && packageUris.isEmpty()) {
|
||||
throw CliException(
|
||||
"`sourceModules` must contain at least one module to generate documentation for."
|
||||
)
|
||||
}
|
||||
|
||||
val builder = evaluatorBuilder()
|
||||
var docsiteInfo: DocsiteInfo
|
||||
val schemasByDocPackageInfoAndPath =
|
||||
mutableMapOf<Pair<DocPackageInfo, Path>, MutableSet<ModuleSchema>>()
|
||||
val schemasByDocPackageInfo = mutableMapOf<DocPackageInfo, Set<ModuleSchema>>()
|
||||
// Evaluate module imports eagerly, which is cheap if docs are also generated for most imported
|
||||
// modules.
|
||||
// Alternatively, imports could be evaluated lazily,
|
||||
// at the expense of interleaving schema/module evaluation and Pkldoc generation.
|
||||
val importedModules: MutableMap<URI, ModuleSchema> = mutableMapOf()
|
||||
|
||||
try {
|
||||
fun Evaluator.collectImportedModules(imports: Map<String, URI>) {
|
||||
for ((_, uri) in imports) {
|
||||
importedModules.computeIfAbsent(uri) { evaluateSchema(ModuleSource.uri(uri)) }
|
||||
}
|
||||
}
|
||||
|
||||
builder.build().use { evaluator ->
|
||||
for (packageUri in packageUris) {
|
||||
val docPackageInfo = packageUri.toDocPackageInfo()
|
||||
val pklModules = packageUri.gatherAllModules()
|
||||
val pklModuleSchemas =
|
||||
pklModules
|
||||
.map { evaluator.evaluateSchema(ModuleSource.uri(it.uri)) }
|
||||
.filter { !it.isAmend }
|
||||
.onEach { evaluator.collectImportedModules(it.imports) }
|
||||
.toSet()
|
||||
|
||||
schemasByDocPackageInfo[docPackageInfo] = pklModuleSchemas
|
||||
}
|
||||
|
||||
docsiteInfo =
|
||||
when {
|
||||
docsiteInfoModuleUris.isEmpty() -> DocsiteInfo(null, null, mapOf())
|
||||
else -> {
|
||||
val module = evaluator.evaluate(ModuleSource.uri(docsiteInfoModuleUris.single()))
|
||||
DocsiteInfo.fromPkl(module).apply {
|
||||
evaluator.collectImportedModules(overviewImports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uri in packageInfoModuleUris) {
|
||||
val module = evaluator.evaluate(ModuleSource.uri(uri))
|
||||
val docPackageInfo =
|
||||
DocPackageInfo.fromPkl(module).apply {
|
||||
evaluator.collectImportedModules(overviewImports)
|
||||
}
|
||||
schemasByDocPackageInfoAndPath[docPackageInfo to Path.of(uri.path).parent] =
|
||||
mutableSetOf()
|
||||
}
|
||||
|
||||
for (uri in regularModuleUris) {
|
||||
val entry =
|
||||
schemasByDocPackageInfoAndPath.keys.find { uri.path.startsWith(it.second.toString()) }
|
||||
?: throw CliException("Could not find a doc-package-info.pkl for module $uri")
|
||||
val schema =
|
||||
evaluator.evaluateSchema(ModuleSource.uri(uri)).apply {
|
||||
evaluator.collectImportedModules(imports)
|
||||
}
|
||||
schemasByDocPackageInfoAndPath[entry]!!.add(schema)
|
||||
}
|
||||
|
||||
// doc generator resolves `pkl.base` even if not imported explicitly
|
||||
val pklBaseUri = URI("pkl:base")
|
||||
importedModules[pklBaseUri] = evaluator.evaluateSchema(ModuleSource.uri(pklBaseUri))
|
||||
}
|
||||
} finally {
|
||||
ModuleKeyFactories.closeQuietly(builder.moduleKeyFactories)
|
||||
}
|
||||
|
||||
val versions = mutableMapOf<String, Version>()
|
||||
val versionComparator =
|
||||
Comparator<String> { v1, v2 ->
|
||||
versions
|
||||
.getOrPut(v1) { Version.parse(v1) }
|
||||
.compareTo(versions.getOrPut(v2) { Version.parse(v2) })
|
||||
}
|
||||
schemasByDocPackageInfo.putAll(schemasByDocPackageInfoAndPath.mapKeys { it.key.first })
|
||||
|
||||
try {
|
||||
DocGenerator(
|
||||
docsiteInfo,
|
||||
schemasByDocPackageInfo,
|
||||
importedModules::getValue,
|
||||
versionComparator,
|
||||
options.normalizedOutputDir,
|
||||
options.isTestMode
|
||||
)
|
||||
.run()
|
||||
} catch (e: DocGeneratorException) {
|
||||
throw CliException(e.message!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.nio.file.Path
|
||||
import org.pkl.commons.cli.CliBaseOptions
|
||||
import org.pkl.commons.resolveSafely
|
||||
|
||||
/** Configuration options for [CliDocGenerator]. */
|
||||
data class CliDocGeneratorOptions
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
/** Base options shared between CLI commands. */
|
||||
val base: CliBaseOptions,
|
||||
|
||||
/** The directory where generated documentation is placed. */
|
||||
val outputDir: Path,
|
||||
|
||||
/**
|
||||
* Internal option only used for testing.
|
||||
*
|
||||
* Generates source URLs with fixed line numbers `#L123-L456` to avoid churn in expected output
|
||||
* files (e.g., when stdlib line numbers change).
|
||||
*/
|
||||
val isTestMode: Boolean = false
|
||||
) {
|
||||
/** [outputDir] after undergoing normalization. */
|
||||
val normalizedOutputDir: Path = base.normalizedWorkingDir.resolveSafely(outputDir)
|
||||
}
|
||||
32
pkl-doc/src/main/kotlin/org/pkl/doc/Constants.kt
Normal file
32
pkl-doc/src/main/kotlin/org/pkl/doc/Constants.kt
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
internal object HtmlConstants {
|
||||
/** The `known-versions` element ID. */
|
||||
const val KNOWN_VERSIONS: String = "known-versions"
|
||||
|
||||
/** The `known-subtypes` element ID. */
|
||||
const val KNOWN_SUBTYPES: String = "known-subtypes"
|
||||
|
||||
/** The `known-usages` element ID. */
|
||||
const val KNOWN_USAGES: String = "known-usages"
|
||||
}
|
||||
|
||||
internal object CssConstants {
|
||||
/** The `current-version` CSS class. */
|
||||
const val CURRENT_VERSION: String = "current-version"
|
||||
}
|
||||
218
pkl-doc/src/main/kotlin/org/pkl/doc/DocGenerator.kt
Normal file
218
pkl-doc/src/main/kotlin/org/pkl/doc/DocGenerator.kt
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.createSymbolicLinkPointingTo
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.isSameFileAs
|
||||
import org.pkl.commons.deleteRecursively
|
||||
import org.pkl.commons.toUri
|
||||
import org.pkl.core.ModuleSchema
|
||||
import org.pkl.core.PClassInfo
|
||||
import org.pkl.core.Version
|
||||
|
||||
/**
|
||||
* Entry point for the low-level Pkldoc API.
|
||||
*
|
||||
* For the high-level Pkldoc API, see [CliDocGenerator].
|
||||
*/
|
||||
class DocGenerator(
|
||||
/**
|
||||
* The documentation website to generate.
|
||||
*
|
||||
* API equivalent of `pkl:DocsiteInfo`.
|
||||
*/
|
||||
private val docsiteInfo: DocsiteInfo,
|
||||
|
||||
/** The modules to generate documentation for, grouped by package. */
|
||||
modules: Map<DocPackageInfo, Collection<ModuleSchema>>,
|
||||
|
||||
/**
|
||||
* A function to resolve imports in [modules], [packageInfos], and [docsiteInfo].
|
||||
*
|
||||
* Module `pkl.base` is resolved with this function even if not explicitly imported.
|
||||
*/
|
||||
private val importResolver: (URI) -> ModuleSchema,
|
||||
|
||||
/** A comparator for package versions. */
|
||||
versionComparator: Comparator<String>,
|
||||
/** The directory where generated documentation is placed. */
|
||||
private val outputDir: Path,
|
||||
|
||||
/**
|
||||
* Internal option used only for testing.
|
||||
*
|
||||
* Generates source URLs with fixed line numbers `#L123-L456` to avoid churn in expected output
|
||||
* files (e.g., when stdlib line numbers change).
|
||||
*/
|
||||
private val isTestMode: Boolean = false
|
||||
) {
|
||||
companion object {
|
||||
internal fun List<PackageData>.current(
|
||||
versionComparator: Comparator<String>
|
||||
): List<PackageData> {
|
||||
val comparator =
|
||||
compareBy<PackageData> { it.ref.pkg }.thenBy(versionComparator) { it.ref.version }
|
||||
return asSequence()
|
||||
// If matching a semver pattern, remove any version that has a prerelease
|
||||
// version (e.g. SNAPSHOT in 1.2.3-SNAPSHOT)
|
||||
.filter { Version.parseOrNull(it.ref.version)?.preRelease == null }
|
||||
.sortedWith(comparator)
|
||||
.distinctBy { it.ref.pkg }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
private val descendingVersionComparator: Comparator<String> = versionComparator.reversed()
|
||||
|
||||
private val docPackages: List<DocPackage> = modules.map { DocPackage(it.key, it.value.toList()) }
|
||||
|
||||
/** Runs this documentation generator. */
|
||||
fun run() {
|
||||
try {
|
||||
val htmlGenerator =
|
||||
HtmlGenerator(docsiteInfo, docPackages, importResolver, outputDir, isTestMode)
|
||||
val searchIndexGenerator = SearchIndexGenerator(outputDir)
|
||||
val packageDataGenerator = PackageDataGenerator(outputDir)
|
||||
val runtimeDataGenerator = RuntimeDataGenerator(descendingVersionComparator, outputDir)
|
||||
|
||||
for (docPackage in docPackages) {
|
||||
if (docPackage.isUnlisted) continue
|
||||
|
||||
docPackage.deletePackageDir()
|
||||
htmlGenerator.generate(docPackage)
|
||||
searchIndexGenerator.generate(docPackage)
|
||||
packageDataGenerator.generate(docPackage)
|
||||
}
|
||||
|
||||
val packagesData = packageDataGenerator.readAll()
|
||||
val currentPackagesData = packagesData.current(descendingVersionComparator)
|
||||
|
||||
createSymlinks(currentPackagesData)
|
||||
|
||||
htmlGenerator.generateSite(currentPackagesData)
|
||||
searchIndexGenerator.generateSiteIndex(currentPackagesData)
|
||||
runtimeDataGenerator.deleteDataDir()
|
||||
runtimeDataGenerator.generate(packagesData)
|
||||
} catch (e: IOException) {
|
||||
throw DocGeneratorException("I/O error generating documentation.", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DocPackage.deletePackageDir() {
|
||||
outputDir.resolve("$name/$version").deleteRecursively()
|
||||
}
|
||||
|
||||
private fun createSymlinks(currentPackagesData: List<PackageData>) {
|
||||
for (packageData in currentPackagesData) {
|
||||
val basePath = outputDir.resolve(packageData.ref.pkg)
|
||||
val src = basePath.resolve(packageData.ref.version)
|
||||
val dest = basePath.resolve("current")
|
||||
if (dest.exists() && dest.isSameFileAs(src)) continue
|
||||
dest.deleteIfExists()
|
||||
dest.createSymbolicLinkPointingTo(basePath.relativize(src))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class DocPackage(val docPackageInfo: DocPackageInfo, val modules: List<ModuleSchema>) {
|
||||
val name: String
|
||||
get() = docPackageInfo.name
|
||||
|
||||
val version: String
|
||||
get() = docPackageInfo.version
|
||||
|
||||
val uri: URI?
|
||||
get() = docPackageInfo.uri
|
||||
|
||||
val overview: String?
|
||||
get() = docPackageInfo.overview
|
||||
|
||||
val minPklVersion: Version? by lazy { docModules.mapNotNull { it.minPklVersion }.maxOrNull() }
|
||||
|
||||
val deprecation: String? = docPackageInfo.annotations.deprecation
|
||||
|
||||
val isUnlisted: Boolean = docPackageInfo.annotations.isUnlisted
|
||||
|
||||
val hasListedModule: Boolean by lazy { docModules.any { !it.isUnlisted } }
|
||||
|
||||
private val exampleModulesBySubject: Map<String, List<ModuleSchema>> by lazy {
|
||||
val result = mutableMapOf<String, MutableList<ModuleSchema>>()
|
||||
for (mod in modules) {
|
||||
val ann = mod.annotations.find { it.classInfo == PClassInfo.DocExample } ?: continue
|
||||
|
||||
@Suppress("UNCHECKED_CAST") val subjects = ann["subjects"] as List<String>
|
||||
for (subject in subjects) {
|
||||
val examples = result[subject]
|
||||
if (examples == null) {
|
||||
result[subject] = mutableListOf(mod)
|
||||
} else {
|
||||
examples.add(mod)
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
val docModules: List<DocModule> by lazy {
|
||||
val regularModules =
|
||||
modules.filter { mod -> !mod.annotations.any { it.classInfo == PClassInfo.DocExample } }
|
||||
regularModules.map { mod ->
|
||||
DocModule(
|
||||
this,
|
||||
mod,
|
||||
docPackageInfo.version,
|
||||
docPackageInfo.getModuleImportUri(mod.moduleName),
|
||||
docPackageInfo.getModuleSourceCode(mod.moduleName)?.toUri(),
|
||||
exampleModulesBySubject[mod.moduleName] ?: listOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class DocModule(
|
||||
val parent: DocPackage,
|
||||
val schema: ModuleSchema,
|
||||
val version: String,
|
||||
val importUri: URI,
|
||||
val sourceUrl: URI?,
|
||||
val examples: List<ModuleSchema>
|
||||
) {
|
||||
val name: String
|
||||
get() = schema.moduleName
|
||||
|
||||
val path: String by lazy {
|
||||
name.substring(parent.docPackageInfo.moduleNamePrefix.length).replace('.', '/')
|
||||
}
|
||||
|
||||
val overview: String?
|
||||
get() = schema.docComment
|
||||
|
||||
val minPklVersion: Version? by lazy {
|
||||
val version =
|
||||
schema.annotations.find { it.classInfo == PClassInfo.ModuleInfo }?.get("minPklVersion")
|
||||
as String?
|
||||
version?.let { Version.parse(it) }
|
||||
}
|
||||
|
||||
val deprecation: String? = schema.annotations.deprecation
|
||||
|
||||
val isUnlisted: Boolean = schema.annotations.isUnlisted
|
||||
}
|
||||
19
pkl-doc/src/main/kotlin/org/pkl/doc/DocGeneratorException.kt
Normal file
19
pkl-doc/src/main/kotlin/org/pkl/doc/DocGeneratorException.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
class DocGeneratorException(message: String, cause: Throwable? = null) :
|
||||
RuntimeException(message, cause)
|
||||
238
pkl-doc/src/main/kotlin/org/pkl/doc/DocPackageInfo.kt
Normal file
238
pkl-doc/src/main/kotlin/org/pkl/doc/DocPackageInfo.kt
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import kotlinx.serialization.Contextual
|
||||
import org.pkl.commons.toUri
|
||||
import org.pkl.core.Member
|
||||
import org.pkl.core.Member.SourceLocation
|
||||
import org.pkl.core.PModule
|
||||
import org.pkl.core.PObject
|
||||
import org.pkl.core.TypeAlias
|
||||
|
||||
/** API equivalent of standard library module `pkl.DocPackageInfo`. */
|
||||
data class DocPackageInfo(
|
||||
/** The name of this doc package. */
|
||||
val name: String,
|
||||
|
||||
/** The prefix for all modules within this doc package. */
|
||||
val moduleNamePrefix: String = "$name.",
|
||||
|
||||
/** The URI of the package, if it is a `package://` URI. */
|
||||
val uri: URI?,
|
||||
|
||||
/**
|
||||
* The version of this package.
|
||||
*
|
||||
* Use `"0.0.0"` for unversioned packages.
|
||||
*/
|
||||
val version: String,
|
||||
|
||||
/** The import base URI for modules in this package. */
|
||||
val importUri: String,
|
||||
|
||||
/** The maintainers' emails for this package. */
|
||||
val authors: List<String>?,
|
||||
|
||||
/** The web URL of the source code for this package. */
|
||||
val sourceCode: URI?,
|
||||
|
||||
/** The source code scheme for this package. */
|
||||
val sourceCodeUrlScheme: String?,
|
||||
|
||||
/** The web URL of the issue tracker for this package. */
|
||||
val issueTracker: URI?,
|
||||
|
||||
/**
|
||||
* The packages depended-on by this package.
|
||||
*
|
||||
* Used to display package dependencies and to create documentation links.
|
||||
*/
|
||||
val dependencies: List<PackageDependency> = listOf(),
|
||||
|
||||
/**
|
||||
* The overview documentation for this package.
|
||||
*
|
||||
* Supports the same Morkdown syntax as Pkldoc comments. By default, only the first paragraph is
|
||||
* displayed.
|
||||
*/
|
||||
val overview: String?,
|
||||
|
||||
/** Imports used to resolve Pkldoc links in [overview]. */
|
||||
val overviewImports: Map<String, URI> = mapOf(),
|
||||
|
||||
/** Annotations for this package, such as `@Deprecated`. */
|
||||
val annotations: List<PObject> = listOf(),
|
||||
|
||||
/** Extra attributes to add to the documentation of the package. */
|
||||
val extraAttributes: Map<String, String> = mapOf(),
|
||||
) {
|
||||
companion object {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun fromPkl(module: PModule): DocPackageInfo =
|
||||
DocPackageInfo(
|
||||
name = module["name"] as String,
|
||||
version = module["version"] as String,
|
||||
importUri = module["importUri"] as String,
|
||||
uri = (module["uri"] as String?)?.toUri(),
|
||||
authors = module["authors"] as List<String>,
|
||||
sourceCode = (module["sourceCode"] as String?)?.toUri(),
|
||||
sourceCodeUrlScheme = module["sourceCodeUrlScheme"] as String?,
|
||||
issueTracker = (module["issueTracker"] as String?)?.toUri(),
|
||||
dependencies =
|
||||
(module["dependencies"] as List<PObject>).map { dependency ->
|
||||
PackageDependency(
|
||||
name = dependency["name"] as String,
|
||||
uri = null, // dependencies declared in a doc-package-info file do not have URIs
|
||||
version = dependency["version"] as String,
|
||||
sourceCode = (dependency["sourceCode"] as String?)?.toUri(),
|
||||
sourceCodeUrlScheme = dependency["sourceCodeUrlScheme"] as String?,
|
||||
documentation = (dependency["documentation"] as String?)?.toUri()
|
||||
)
|
||||
},
|
||||
overview = module["overview"] as String,
|
||||
overviewImports =
|
||||
(module["overviewImports"] as Map<String, String>).mapValues { it.value.toUri() },
|
||||
annotations = module["annotations"] as List<PObject>,
|
||||
extraAttributes = module["extraAttributes"] as Map<String, String>
|
||||
)
|
||||
}
|
||||
|
||||
internal fun getModuleRef(moduleName: String): ModuleRef? {
|
||||
if (moduleName.startsWith(moduleNamePrefix)) {
|
||||
return ModuleRef(name, uri, version, getModulePath(moduleName, moduleNamePrefix))
|
||||
}
|
||||
for (dependency in dependencies) {
|
||||
if (moduleName.startsWith(dependency.prefix)) {
|
||||
return ModuleRef(
|
||||
dependency.name,
|
||||
dependency.uri,
|
||||
dependency.version,
|
||||
getModulePath(moduleName, dependency.prefix)
|
||||
)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun getTypeRef(type: Member /* PClass|TypeAlias */): TypeRef? {
|
||||
val moduleName = type.moduleName
|
||||
if (moduleName.startsWith(moduleNamePrefix)) {
|
||||
return TypeRef(
|
||||
name,
|
||||
uri,
|
||||
version,
|
||||
getModulePath(moduleName, moduleNamePrefix),
|
||||
type.simpleName,
|
||||
isTypeAlias = type is TypeAlias
|
||||
)
|
||||
}
|
||||
for (dependency in dependencies) {
|
||||
if (moduleName.startsWith(dependency.prefix)) {
|
||||
return TypeRef(
|
||||
dependency.name,
|
||||
dependency.uri,
|
||||
dependency.version,
|
||||
getModulePath(moduleName, dependency.prefix),
|
||||
type.simpleName,
|
||||
isTypeAlias = type is TypeAlias
|
||||
)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun getModuleImportUri(moduleName: String): URI =
|
||||
when (importUri) {
|
||||
"pkl:/" -> "pkl:${moduleName.substring(4)}".toUri()
|
||||
else -> "$importUri${getModulePath(moduleName, moduleNamePrefix)}.pkl".toUri()
|
||||
}
|
||||
|
||||
internal fun getModuleSourceCode(moduleName: String): String? {
|
||||
val path = "/" + getModulePath(moduleName, moduleNamePrefix) + ".pkl"
|
||||
// assumption: the fragment is only used for line numbers
|
||||
return sourceCodeUrlScheme?.replace("%{path}", path)?.substringBefore('#')
|
||||
}
|
||||
|
||||
private fun getModulePath(moduleName: String, packagePrefix: String): String =
|
||||
moduleName.substring(packagePrefix.length).replace('.', '/')
|
||||
|
||||
/** Information about a depended-on package. */
|
||||
data class PackageDependency(
|
||||
/** The name of the depended-on package. */
|
||||
val name: String,
|
||||
|
||||
/** The URI of the dependend-upon package, if any. */
|
||||
val uri: @Contextual URI?,
|
||||
|
||||
/** The version of the depended-on package. */
|
||||
val version: String,
|
||||
|
||||
/**
|
||||
* The web URL of the source code for the depended-on package *version*. Must end with a slash.
|
||||
*/
|
||||
val sourceCode: @Contextual URI?,
|
||||
|
||||
/** The source URL scheme of the depended-upon package _version_, with placeholders. */
|
||||
val sourceCodeUrlScheme: String?,
|
||||
|
||||
/**
|
||||
* The web URL of the Pkldoc page for the depended-on package *version*. Must end with a slash.
|
||||
* Only needs to be set if the depended-on package belongs to a different Pkldoc website.
|
||||
*/
|
||||
val documentation: @Contextual URI?,
|
||||
) {
|
||||
internal val prefix = "$name."
|
||||
|
||||
/** Note: Returns an absolute URI, or an URI relative to the current site. */
|
||||
internal fun getModuleDocUrl(moduleName: String): URI? =
|
||||
when {
|
||||
!moduleName.startsWith(prefix) -> null
|
||||
else -> {
|
||||
val modulePath = moduleName.substring(prefix.length).replace('.', '/')
|
||||
if (documentation == null) {
|
||||
"$name/$version/$modulePath/index.html".toUri()
|
||||
} else {
|
||||
documentation.resolve("$modulePath/index.html")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getModuleSourceCode(moduleName: String): URI? =
|
||||
when {
|
||||
!moduleName.startsWith(prefix) -> null
|
||||
else -> {
|
||||
val modulePath = moduleName.substring(prefix.length).replace('.', '/')
|
||||
sourceCode?.resolve("$modulePath.pkl")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getModuleSourceCodeWithSourceLocation(
|
||||
moduleName: String,
|
||||
sourceLocation: SourceLocation
|
||||
): URI? {
|
||||
return when {
|
||||
!moduleName.startsWith(prefix) -> null
|
||||
else -> {
|
||||
val modulePath = moduleName.substring(prefix.length).replace('.', '/')
|
||||
val path = "/$modulePath.pkl"
|
||||
sourceCodeUrlScheme?.replaceSourceCodePlaceholders(path, sourceLocation)?.toUri()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
539
pkl-doc/src/main/kotlin/org/pkl/doc/DocScope.kt
Normal file
539
pkl-doc/src/main/kotlin/org/pkl/doc/DocScope.kt
Normal file
@@ -0,0 +1,539 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import org.pkl.commons.toUri
|
||||
import org.pkl.core.*
|
||||
import org.pkl.core.Member.SourceLocation
|
||||
import org.pkl.core.util.IoUtils
|
||||
|
||||
/**
|
||||
* A lexical scope that can be the source or target of a doc link (that is, a link to a Pkl member
|
||||
* embedded in a doc comment). Used to resolve doc links as well as class names in type signatures.
|
||||
* Scoping rules conform to the Pkl language as much as possible.
|
||||
*
|
||||
* Implementation note: equals and hashCode implementations are based on identity comparisons of
|
||||
* underlying [ModuleSchema] types.
|
||||
*/
|
||||
internal sealed class DocScope {
|
||||
abstract val url: URI
|
||||
|
||||
abstract val parent: DocScope?
|
||||
|
||||
private val siteScope: SiteScope? by lazy {
|
||||
var scope = this
|
||||
while (scope !is SiteScope) {
|
||||
scope = scope.parent ?: return@lazy null
|
||||
}
|
||||
scope
|
||||
}
|
||||
|
||||
private val packageScope: PackageScope? by lazy {
|
||||
var scope = this
|
||||
while (scope !is PackageScope) {
|
||||
scope = scope.parent ?: return@lazy null
|
||||
}
|
||||
scope
|
||||
}
|
||||
|
||||
val relativeSiteUrl: URI by lazy { siteScope!!.urlRelativeTo(this) }
|
||||
|
||||
val relativePackageUrl: URI by lazy { packageScope!!.urlRelativeTo(this) }
|
||||
|
||||
fun urlRelativeTo(other: DocScope): URI = IoUtils.relativize(url, other.url)
|
||||
|
||||
/** Looks up the method with the given name in the program element associated with this scope. */
|
||||
abstract fun getMethod(name: String): MethodScope?
|
||||
|
||||
/**
|
||||
* Looks up the property or class with the given name in the program element associated with this
|
||||
* scope.
|
||||
*/
|
||||
abstract fun getProperty(name: String): DocScope?
|
||||
|
||||
abstract fun resolveModuleNameToDocUrl(name: String): URI?
|
||||
|
||||
fun resolveModuleNameToRelativeDocUrl(name: String): URI? =
|
||||
resolveModuleNameToDocUrl(name)?.let { IoUtils.relativize(it, url) }
|
||||
|
||||
abstract fun resolveModuleNameToSourceUrl(
|
||||
name: String,
|
||||
sourceLocation: Member.SourceLocation
|
||||
): URI?
|
||||
|
||||
/** Resolves the given method name relative to this scope. */
|
||||
abstract fun resolveMethod(name: String): MethodScope?
|
||||
|
||||
/**
|
||||
* Resolves the given property name, class name, type alias name, method parameter name, or type
|
||||
* parameter name relative to this scope.
|
||||
*/
|
||||
abstract fun resolveVariable(name: String): DocScope?
|
||||
|
||||
/**
|
||||
* Resolves a doc link such as `someImport.SomeClass` or `SomeClass.someMethod()` originating in
|
||||
* this scope.
|
||||
*/
|
||||
fun resolveDocLink(text: String): DocScope? {
|
||||
var currScope: DocScope = this
|
||||
|
||||
val parts = text.split('.')
|
||||
if (parts.isEmpty()) return null
|
||||
|
||||
val first = parts[0]
|
||||
currScope =
|
||||
when {
|
||||
first.endsWith("()") -> currScope.resolveMethod(first.dropLast(2)) ?: return null
|
||||
else -> currScope.resolveVariable(first) ?: return null
|
||||
}
|
||||
|
||||
for (i in 1..parts.lastIndex) {
|
||||
val part = parts[i]
|
||||
currScope =
|
||||
when {
|
||||
part.endsWith("()") -> currScope.getMethod(part.dropLast(2)) ?: return null
|
||||
else -> currScope.getProperty(part) ?: return null
|
||||
}
|
||||
}
|
||||
|
||||
return currScope
|
||||
}
|
||||
|
||||
override fun toString() = "${this::class.java.simpleName} { url=$url }"
|
||||
}
|
||||
|
||||
/** A scope that corresponds to an entire Pkldoc page. */
|
||||
internal abstract class PageScope : DocScope() {
|
||||
/** The location of the runtime data file for this page. */
|
||||
abstract val dataUrl: URI
|
||||
}
|
||||
|
||||
// equality is identity
|
||||
internal class SiteScope(
|
||||
docPackages: List<DocPackage>,
|
||||
private val overviewImports: Map<String, URI>,
|
||||
private val importResolver: (URI) -> ModuleSchema,
|
||||
outputDir: Path
|
||||
) : PageScope() {
|
||||
private val pklVersion = Release.current().version().withBuild(null).toString()
|
||||
|
||||
private val pklBaseModule: ModuleSchema by lazy { importResolver("pkl:base".toUri()) }
|
||||
|
||||
val packageScopes: Map<String, PackageScope> by lazy {
|
||||
docPackages.associate { docPackage ->
|
||||
docPackage.name to
|
||||
PackageScope(
|
||||
docPackage.docPackageInfo,
|
||||
docPackage.docModules.map { it.schema },
|
||||
pklBaseModule,
|
||||
docPackage.docPackageInfo.overviewImports,
|
||||
this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val pklBaseScope: ModuleScope by lazy {
|
||||
ModuleScope(pklBaseModule, resolveModuleNameToDocUrl("pkl.base")!!, null)
|
||||
}
|
||||
|
||||
override val parent: DocScope?
|
||||
get() = null
|
||||
|
||||
override val url: URI by lazy {
|
||||
IoUtils.ensurePathEndsWithSlash(outputDir.toUri()).resolve("index.html")
|
||||
}
|
||||
|
||||
override val dataUrl: URI
|
||||
get() = throw UnsupportedOperationException("perVersionDataUrl")
|
||||
|
||||
fun createEmptyPackageScope(
|
||||
name: String,
|
||||
version: String,
|
||||
sourceCodeUrlScheme: String?,
|
||||
sourceCode: URI?
|
||||
): PackageScope =
|
||||
PackageScope(
|
||||
DocPackageInfo(
|
||||
name = name,
|
||||
version = version,
|
||||
sourceCode = sourceCode,
|
||||
sourceCodeUrlScheme = sourceCodeUrlScheme,
|
||||
authors = emptyList(),
|
||||
extraAttributes = emptyMap(),
|
||||
importUri = "",
|
||||
issueTracker = null,
|
||||
overview = null,
|
||||
uri = null
|
||||
),
|
||||
emptyList(),
|
||||
pklBaseModule,
|
||||
emptyMap(),
|
||||
this
|
||||
)
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = null
|
||||
|
||||
override fun getProperty(name: String): DocScope? = null
|
||||
|
||||
fun getPackage(name: String): PackageScope = packageScopes.getValue(name)
|
||||
|
||||
fun resolveImport(uri: URI): ModuleSchema = importResolver(uri)
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String): URI? =
|
||||
when {
|
||||
name.startsWith("pkl.") -> {
|
||||
val packagePage =
|
||||
packageScopes["pkl"]?.url // link to locally generated stdlib docs if available
|
||||
?: PklInfo.current().packageIndex.getPackagePage("pkl", pklVersion).toUri()
|
||||
packagePage.resolve(name.substring(4) + "/")
|
||||
}
|
||||
// doesn't make much sense to search in [packageScopes]
|
||||
// because we don't know the requested module version
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(
|
||||
name: String,
|
||||
sourceLocation: Member.SourceLocation
|
||||
): URI? =
|
||||
when {
|
||||
name.startsWith("pkl.") -> {
|
||||
val path = "/stdlib/${name.substring(4)}.pkl"
|
||||
Release.current()
|
||||
.sourceCode()
|
||||
.sourceCodeUrlScheme
|
||||
.replaceSourceCodePlaceholders(path, sourceLocation)
|
||||
.toUri()
|
||||
}
|
||||
// doesn't make much sense to search in [packageScopes]
|
||||
// because we don't know the requested module version
|
||||
else -> null
|
||||
}
|
||||
|
||||
// used to resolve Pkldoc links in docsite-info.pkl
|
||||
override fun resolveMethod(name: String): MethodScope? = pklBaseScope.getMethod(name)
|
||||
|
||||
// used to resolve Pkldoc links in docsite-info.pkl
|
||||
override fun resolveVariable(name: String): DocScope? =
|
||||
overviewImports[name]?.let { uri ->
|
||||
val mod = resolveImport(uri)
|
||||
resolveModuleNameToDocUrl(mod.moduleName)?.let { url -> ModuleScope(mod, url, null) }
|
||||
}
|
||||
?: pklBaseScope.getProperty(name)
|
||||
}
|
||||
|
||||
internal class PackageScope(
|
||||
val docPackageInfo: DocPackageInfo,
|
||||
modules: List<ModuleSchema>,
|
||||
pklBaseModule: ModuleSchema,
|
||||
private val overviewImports: Map<String, URI>,
|
||||
override val parent: SiteScope
|
||||
) : PageScope() {
|
||||
val name = docPackageInfo.name
|
||||
|
||||
val version = docPackageInfo.version
|
||||
|
||||
private val modulePrefix = docPackageInfo.moduleNamePrefix
|
||||
|
||||
private val moduleScopes: Map<String, ModuleScope> by lazy {
|
||||
modules.associate { module ->
|
||||
val docUrl =
|
||||
url.resolve(
|
||||
"${module.moduleName.substring(modulePrefix.length).replace('.', '/')}/index.html"
|
||||
)
|
||||
module.moduleName to ModuleScope(module, docUrl, this)
|
||||
}
|
||||
}
|
||||
|
||||
private val pklBaseScope: ModuleScope by lazy {
|
||||
ModuleScope(pklBaseModule, resolveModuleNameToDocUrl("pkl.base")!!, null)
|
||||
}
|
||||
|
||||
override val url: URI by lazy { parent.url.resolve("./$name/$version/index.html") }
|
||||
|
||||
override val dataUrl: URI by lazy { parent.url.resolve("./data/$name/$version/index.js") }
|
||||
|
||||
fun getModule(name: String): ModuleScope = moduleScopes.getValue(name)
|
||||
|
||||
fun getPklBaseMethod(name: String): MethodScope? = pklBaseScope.getMethod(name)
|
||||
|
||||
fun getPklBaseProperty(name: String): DocScope? = pklBaseScope.getProperty(name)
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = null
|
||||
|
||||
override fun getProperty(name: String): DocScope? = null
|
||||
|
||||
fun resolveImport(uri: URI): ModuleSchema = parent.resolveImport(uri)
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String): URI? {
|
||||
moduleScopes[name]?.url?.let {
|
||||
return it
|
||||
}
|
||||
for (dependency in docPackageInfo.dependencies) {
|
||||
dependency.getModuleDocUrl(name)?.let {
|
||||
return parent.url.resolve(it)
|
||||
}
|
||||
}
|
||||
return parent.resolveModuleNameToDocUrl(name)
|
||||
}
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: SourceLocation): URI? {
|
||||
for (dependency in docPackageInfo.dependencies) {
|
||||
dependency.getModuleSourceCodeWithSourceLocation(name, sourceLocation)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
return parent.resolveModuleNameToSourceUrl(name, sourceLocation)
|
||||
}
|
||||
|
||||
// used to resolve Pkldoc links in package-info.pkl
|
||||
override fun resolveMethod(name: String): MethodScope? = getPklBaseMethod(name)
|
||||
|
||||
// used to resolve Pkldoc links in package-info.pkl
|
||||
override fun resolveVariable(name: String): DocScope? =
|
||||
overviewImports[name]?.let { uri ->
|
||||
val mod = resolveImport(uri)
|
||||
resolveModuleNameToDocUrl(mod.moduleName)?.let { url -> ModuleScope(mod, url, null) }
|
||||
}
|
||||
?: getPklBaseProperty(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is PackageScope && docPackageInfo.name == other.docPackageInfo.name
|
||||
|
||||
override fun hashCode(): Int =
|
||||
PackageScope::class.hashCode() * 31 + docPackageInfo.name.hashCode()
|
||||
}
|
||||
|
||||
internal class ModuleScope(
|
||||
val module: ModuleSchema,
|
||||
override val url: URI,
|
||||
override val parent: PackageScope?
|
||||
) : PageScope() {
|
||||
val name: String
|
||||
get() = module.moduleName
|
||||
|
||||
val path: String by lazy {
|
||||
name.substring(parent!!.docPackageInfo.moduleNamePrefix.length).replace('.', '/')
|
||||
}
|
||||
|
||||
override val dataUrl: URI by lazy { parent!!.dataUrl.resolve("./$path/index.js") }
|
||||
|
||||
override fun getMethod(name: String): MethodScope? =
|
||||
module.moduleClass.allMethods[name]?.let { MethodScope(it, this) }
|
||||
|
||||
override fun getProperty(name: String): DocScope? =
|
||||
module.moduleClass.allProperties[name]?.let { PropertyScope(it, this) }
|
||||
?: module.allClasses[name]?.let { ClassScope(it, url, this) }
|
||||
?: module.allTypeAliases[name]?.let { TypeAliasScope(it, url, this) }
|
||||
|
||||
private fun resolveImport(uri: URI): ModuleSchema = parent!!.resolveImport(uri)
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String): URI? =
|
||||
when (name) {
|
||||
module.moduleName -> url
|
||||
else -> parent!!.resolveModuleNameToDocUrl(name)
|
||||
}
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: SourceLocation): URI? =
|
||||
when (name) {
|
||||
module.moduleName ->
|
||||
parent!!
|
||||
.docPackageInfo
|
||||
.sourceCodeUrlScheme
|
||||
?.replaceSourceCodePlaceholders("/$path.pkl", sourceLocation)
|
||||
?.toUri()
|
||||
else -> parent!!.resolveModuleNameToSourceUrl(name, sourceLocation)
|
||||
}
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? =
|
||||
module.moduleClass.methods[name]?.let { MethodScope(it, this) }
|
||||
?: parent!!.getPklBaseMethod(name) ?: getMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? =
|
||||
name.takeIf { it == "module" }?.let { this }
|
||||
?: module.imports[name]?.let { uri ->
|
||||
val mod = resolveImport(uri)
|
||||
resolveModuleNameToDocUrl(mod.moduleName)?.let { url -> ModuleScope(mod, url, null) }
|
||||
}
|
||||
?: module.moduleClass.properties[name]?.let { PropertyScope(it, this) }
|
||||
// inherited classes/type aliases are in scope when resolving types -> search `all`
|
||||
?: module.allClasses[name]?.let { ClassScope(it, url, this) }
|
||||
?: module.allTypeAliases[name]?.let { TypeAliasScope(it, url, this) }
|
||||
?: parent!!.getPklBaseProperty(name) ?: getProperty(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is ModuleScope && module == other.module
|
||||
|
||||
override fun hashCode(): Int = module.hashCode()
|
||||
}
|
||||
|
||||
internal class ClassScope(
|
||||
val clazz: PClass,
|
||||
private val parentUrl: URI,
|
||||
override val parent: ModuleScope?
|
||||
) : PageScope() {
|
||||
override val url: URI by lazy {
|
||||
// `isModuleClass` distinction is relevant when this scope is a link target
|
||||
if (clazz.isModuleClass) parentUrl else parentUrl.resolve("${clazz.simpleName}.html")
|
||||
}
|
||||
|
||||
override val dataUrl: URI by lazy { parent!!.dataUrl.resolve("${clazz.simpleName}.js") }
|
||||
|
||||
override fun getMethod(name: String): MethodScope? =
|
||||
clazz.allMethods[name]?.let { MethodScope(it, this) }
|
||||
|
||||
override fun getProperty(name: String): DocScope? =
|
||||
clazz.allProperties[name]?.let { PropertyScope(it, this) }
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String): URI? =
|
||||
parent!!.resolveModuleNameToDocUrl(name)
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(
|
||||
name: String,
|
||||
sourceLocation: Member.SourceLocation
|
||||
): URI? = parent!!.resolveModuleNameToSourceUrl(name, sourceLocation)
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? =
|
||||
clazz.methods[name]?.let { MethodScope(it, this) }
|
||||
?: parent!!.resolveMethod(name) ?: getMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? =
|
||||
clazz.typeParameters.find { it.name == name }?.let { ParameterScope(name, this) }
|
||||
?: clazz.properties[name]?.let { PropertyScope(it, this) } ?: parent!!.resolveVariable(name)
|
||||
?: clazz.allProperties[name]?.let { PropertyScope(it, this) }
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is ClassScope && clazz == other.clazz
|
||||
|
||||
override fun hashCode(): Int = clazz.hashCode()
|
||||
}
|
||||
|
||||
internal class TypeAliasScope(
|
||||
val typeAlias: TypeAlias,
|
||||
private val parentDocUrl: URI,
|
||||
override val parent: ModuleScope?
|
||||
) : DocScope() {
|
||||
override val url: URI
|
||||
get() = parentDocUrl.resolve("#${typeAlias.simpleName}")
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = parent?.getMethod(name)
|
||||
|
||||
override fun getProperty(name: String): DocScope? = parent?.getProperty(name)
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToDocUrl")
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: Member.SourceLocation) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToSourceUrl")
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? = parent?.resolveMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? = parent?.resolveVariable(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is TypeAliasScope && typeAlias == other.typeAlias
|
||||
|
||||
override fun hashCode(): Int = typeAlias.hashCode()
|
||||
}
|
||||
|
||||
internal class MethodScope(val method: PClass.Method, override val parent: DocScope) : DocScope() {
|
||||
override val url: URI
|
||||
get() = parent.url.resolve("#${method.simpleName}()")
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = null
|
||||
|
||||
override fun getProperty(name: String): DocScope? = null
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToDocUrl")
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: Member.SourceLocation) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToSourceUrl")
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? = parent.resolveMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? =
|
||||
method.typeParameters.find { it.name == name }?.let { ParameterScope(name, this) }
|
||||
?: method.parameters[name]?.let { ParameterScope(name, this) } ?: parent.resolveVariable(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is MethodScope && method == other.method
|
||||
|
||||
override fun hashCode(): Int = method.hashCode()
|
||||
}
|
||||
|
||||
internal class PropertyScope(
|
||||
val property: PClass.Property,
|
||||
override val parent: DocScope // ModuleScope|ClassScope
|
||||
) : DocScope() {
|
||||
override val url: URI
|
||||
get() = parent.url.resolve("#${property.simpleName}")
|
||||
|
||||
override fun getProperty(name: String): DocScope? = null
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = null
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToDocUrl")
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: Member.SourceLocation) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToSourceUrl")
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? = parent.resolveMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? = parent.resolveVariable(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is PropertyScope && property == other.property
|
||||
|
||||
override fun hashCode(): Int = property.hashCode()
|
||||
}
|
||||
|
||||
/** A method parameter or type parameter. */
|
||||
internal class ParameterScope(val name: String, override val parent: DocScope) : DocScope() {
|
||||
override val url: URI
|
||||
get() =
|
||||
if (parent is ClassScope) {
|
||||
parent.url.resolve("#$name")
|
||||
} else {
|
||||
"${parent.url}.$name".toUri()
|
||||
}
|
||||
|
||||
override fun getMethod(name: String): MethodScope? = null
|
||||
|
||||
override fun getProperty(name: String): DocScope? = null
|
||||
|
||||
override fun resolveModuleNameToDocUrl(name: String) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToDocUrl")
|
||||
|
||||
override fun resolveModuleNameToSourceUrl(name: String, sourceLocation: Member.SourceLocation) =
|
||||
// only used for page scopes
|
||||
throw UnsupportedOperationException("resolveModuleNameToSourceUrl")
|
||||
|
||||
override fun resolveMethod(name: String): MethodScope? = parent.resolveMethod(name)
|
||||
|
||||
override fun resolveVariable(name: String): DocScope? = parent.resolveVariable(name)
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is ParameterScope && name == other.name && parent == other.parent
|
||||
|
||||
override fun hashCode(): Int = name.hashCode() * 31 + parent.hashCode()
|
||||
}
|
||||
48
pkl-doc/src/main/kotlin/org/pkl/doc/DocsiteInfo.kt
Normal file
48
pkl-doc/src/main/kotlin/org/pkl/doc/DocsiteInfo.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import org.pkl.commons.toUri
|
||||
import org.pkl.core.PModule
|
||||
|
||||
/** API equivalent of standard library module `pkl.DocsiteInfo`. */
|
||||
data class DocsiteInfo(
|
||||
/** The display title of this Pkldoc website. */
|
||||
val title: String?,
|
||||
|
||||
/**
|
||||
* The overview documentation on the main page of this website.
|
||||
*
|
||||
* Uses the same Morkdown format as Pkldoc comments. Unless expanded, only the first paragraph is
|
||||
* shown.
|
||||
*/
|
||||
val overview: String?,
|
||||
|
||||
/** Imports used to resolve Pkldoc links in [overview]. */
|
||||
val overviewImports: Map<String, URI>
|
||||
) {
|
||||
companion object {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun fromPkl(module: PModule): DocsiteInfo =
|
||||
DocsiteInfo(
|
||||
title = module["title"] as String?,
|
||||
overview = module["overview"] as String?,
|
||||
overviewImports =
|
||||
(module["overviewImports"] as Map<String, String>).mapValues { it.value.toUri() },
|
||||
)
|
||||
}
|
||||
}
|
||||
91
pkl-doc/src/main/kotlin/org/pkl/doc/HtmlGenerator.kt
Normal file
91
pkl-doc/src/main/kotlin/org/pkl/doc/HtmlGenerator.kt
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import org.pkl.core.ModuleSchema
|
||||
|
||||
internal class HtmlGenerator(
|
||||
private val docsiteInfo: DocsiteInfo,
|
||||
docPackages: List<DocPackage>,
|
||||
importResolver: (URI) -> ModuleSchema,
|
||||
private val outputDir: Path,
|
||||
private val isTestMode: Boolean
|
||||
) {
|
||||
private val siteScope =
|
||||
SiteScope(docPackages, docsiteInfo.overviewImports, importResolver, outputDir)
|
||||
|
||||
fun generate(docPackage: DocPackage) {
|
||||
val packageScope = siteScope.getPackage(docPackage.name)
|
||||
|
||||
PackagePageGenerator(docsiteInfo, docPackage, packageScope).run()
|
||||
|
||||
for (docModule in docPackage.docModules) {
|
||||
if (docModule.isUnlisted) continue
|
||||
|
||||
val moduleScope = packageScope.getModule(docModule.name)
|
||||
|
||||
ModulePageGenerator(docsiteInfo, docPackage, docModule, moduleScope, isTestMode).run()
|
||||
|
||||
for ((_, clazz) in docModule.schema.classes) {
|
||||
if (clazz.isUnlisted) continue
|
||||
|
||||
ClassPageGenerator(
|
||||
docsiteInfo,
|
||||
docPackage,
|
||||
docModule,
|
||||
clazz,
|
||||
ClassScope(clazz, moduleScope.url, moduleScope),
|
||||
isTestMode
|
||||
)
|
||||
.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateSite(packagesData: List<PackageData>) {
|
||||
MainPageGenerator(docsiteInfo, packagesData, siteScope).run()
|
||||
|
||||
generateStaticResources()
|
||||
}
|
||||
|
||||
private fun generateStaticResources() {
|
||||
copyResource("fonts/lato-v14-latin_latin-ext-regular.woff2", outputDir)
|
||||
copyResource("fonts/lato-v14-latin_latin-ext-700.woff2", outputDir)
|
||||
|
||||
copyResource("fonts/open-sans-v15-latin_latin-ext-regular.woff2", outputDir)
|
||||
copyResource("fonts/open-sans-v15-latin_latin-ext-italic.woff2", outputDir)
|
||||
copyResource("fonts/open-sans-v15-latin_latin-ext-700.woff2", outputDir)
|
||||
copyResource("fonts/open-sans-v15-latin_latin-ext-700italic.woff2", outputDir)
|
||||
|
||||
copyResource("fonts/source-code-pro-v7-latin_latin-ext-regular.woff2", outputDir)
|
||||
copyResource("fonts/source-code-pro-v7-latin_latin-ext-700.woff2", outputDir)
|
||||
|
||||
copyResource("fonts/MaterialIcons-Regular.woff2", outputDir)
|
||||
|
||||
copyResource("scripts/pkldoc.js", outputDir)
|
||||
copyResource("scripts/search-worker.js", outputDir)
|
||||
copyResource("scripts/scroll-into-view.min.js", outputDir)
|
||||
|
||||
copyResource("styles/pkldoc.css", outputDir)
|
||||
|
||||
copyResource("images/apple-touch-icon.png", outputDir)
|
||||
copyResource("images/favicon.svg", outputDir)
|
||||
copyResource("images/favicon-16x16.png", outputDir)
|
||||
copyResource("images/favicon-32x32.png", outputDir)
|
||||
}
|
||||
}
|
||||
73
pkl-doc/src/main/kotlin/org/pkl/doc/Main.kt
Normal file
73
pkl-doc/src/main/kotlin/org/pkl/doc/Main.kt
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@file:JvmName("Main")
|
||||
|
||||
package org.pkl.doc
|
||||
|
||||
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||
import com.github.ajalt.clikt.parameters.arguments.convert
|
||||
import com.github.ajalt.clikt.parameters.arguments.multiple
|
||||
import com.github.ajalt.clikt.parameters.groups.provideDelegate
|
||||
import com.github.ajalt.clikt.parameters.options.option
|
||||
import com.github.ajalt.clikt.parameters.options.required
|
||||
import com.github.ajalt.clikt.parameters.types.path
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import org.pkl.commons.cli.cliMain
|
||||
import org.pkl.commons.cli.commands.BaseCommand
|
||||
import org.pkl.commons.cli.commands.ProjectOptions
|
||||
import org.pkl.core.Release
|
||||
|
||||
/** Main method for the Pkldoc CLI. */
|
||||
internal fun main(args: Array<String>) {
|
||||
cliMain { DocCommand().main(args) }
|
||||
}
|
||||
|
||||
class DocCommand :
|
||||
BaseCommand(name = "pkldoc", helpLink = Release.current().documentation().homepage(), help = "") {
|
||||
|
||||
private val modules: List<URI> by
|
||||
argument(
|
||||
name = "<modules>",
|
||||
help = "Module paths/uris, or package uris to generate documentation for"
|
||||
)
|
||||
.convert { parseModuleName(it) }
|
||||
.multiple(required = true)
|
||||
|
||||
private val outputDir: Path by
|
||||
option(
|
||||
names = arrayOf("-o", "--output-dir"),
|
||||
metavar = "<directory>",
|
||||
help = "Directory where generated documentation is placed."
|
||||
)
|
||||
.path()
|
||||
.required()
|
||||
|
||||
private val projectOptions by ProjectOptions()
|
||||
|
||||
override fun run() {
|
||||
val options =
|
||||
CliDocGeneratorOptions(
|
||||
baseOptions.baseOptions(
|
||||
modules,
|
||||
projectOptions,
|
||||
),
|
||||
outputDir,
|
||||
true
|
||||
)
|
||||
CliDocGenerator(options).run()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
internal abstract class MainOrPackagePageGenerator<S>(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
pageScope: S,
|
||||
private val siteScope: SiteScope
|
||||
) : PageGenerator<S>(docsiteInfo, pageScope) where S : PageScope {
|
||||
protected fun UL.renderModuleOrPackage(
|
||||
name: String,
|
||||
moduleOrPackageScope: DocScope,
|
||||
memberDocs: MemberDocs
|
||||
) {
|
||||
li {
|
||||
renderAnchor(name)
|
||||
|
||||
div {
|
||||
classes = setOf("member", "with-page-link")
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
renderSelfLink(name)
|
||||
|
||||
div {
|
||||
classes = setOf("member-left")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-modifiers", "member-deprecated")
|
||||
} else setOf("member-modifiers")
|
||||
|
||||
renderModifiers(
|
||||
setOf(),
|
||||
if (moduleOrPackageScope is PackageScope) "package" else "module"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
classes = setOf("member-main")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-signature", "member-deprecated")
|
||||
} else setOf("member-signature")
|
||||
|
||||
a {
|
||||
classes = setOf("name-decl")
|
||||
val link = "./" + moduleOrPackageScope.urlRelativeTo(pageScope).toString()
|
||||
href =
|
||||
if (pageScope is SiteScope) {
|
||||
link.replaceFirst((moduleOrPackageScope as PackageScope).version, "current")
|
||||
} else {
|
||||
link
|
||||
}
|
||||
+name
|
||||
}
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
pkl-doc/src/main/kotlin/org/pkl/doc/MainPageGenerator.kt
Normal file
106
pkl-doc/src/main/kotlin/org/pkl/doc/MainPageGenerator.kt
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
internal class MainPageGenerator(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
private val packagesData: List<PackageData>,
|
||||
pageScope: SiteScope
|
||||
) : MainOrPackagePageGenerator<SiteScope>(docsiteInfo, pageScope, pageScope) {
|
||||
override val html: HTML.() -> Unit = {
|
||||
renderHtmlHead()
|
||||
|
||||
body {
|
||||
onLoad = "onLoad()"
|
||||
|
||||
renderPageHeader(null, null, null, null)
|
||||
|
||||
main {
|
||||
h1 {
|
||||
id = "declaration-title"
|
||||
|
||||
+(docsiteInfo.title ?: "")
|
||||
}
|
||||
|
||||
val memberDocs = MemberDocs(docsiteInfo.overview, pageScope, listOf(), isDeclaration = true)
|
||||
|
||||
renderMemberGroupLinks(
|
||||
Triple("Overview", "#_overview", memberDocs.isExpandable),
|
||||
Triple("Packages", "#_packages", packagesData.isNotEmpty())
|
||||
)
|
||||
|
||||
if (docsiteInfo.overview != null) {
|
||||
renderAnchor("_overview")
|
||||
div {
|
||||
id = "_declaration"
|
||||
classes = setOf("member")
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
|
||||
renderPackages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun HTMLTag.renderPageTitle() {
|
||||
+(docsiteInfo.title ?: "Pkldoc")
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderPackages() {
|
||||
if (packagesData.isEmpty()) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_packages")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Packages"
|
||||
}
|
||||
|
||||
ul {
|
||||
for (pkg in packagesData) {
|
||||
val packageScope =
|
||||
pageScope.packageScopes[pkg.ref.pkg]
|
||||
// create scope for previously generated package
|
||||
?: pageScope.createEmptyPackageScope(
|
||||
pkg.ref.pkg,
|
||||
pkg.ref.version,
|
||||
pkg.sourceCodeUrlScheme,
|
||||
pkg.sourceCode
|
||||
)
|
||||
|
||||
val memberDocs =
|
||||
MemberDocs(
|
||||
pkg.summary,
|
||||
packageScope,
|
||||
listOfNotNull(pkg.deprecation?.let { createDeprecatedAnnotation(it) }),
|
||||
isDeclaration = false
|
||||
)
|
||||
|
||||
renderModuleOrPackage(pkg.ref.pkg, packageScope, memberDocs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
pkl-doc/src/main/kotlin/org/pkl/doc/Markdown.kt
Normal file
112
pkl-doc/src/main/kotlin/org/pkl/doc/Markdown.kt
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import org.commonmark.internal.InlineParserImpl
|
||||
import org.commonmark.node.Code
|
||||
import org.commonmark.node.Link
|
||||
import org.commonmark.node.LinkReferenceDefinition
|
||||
import org.commonmark.node.Text
|
||||
import org.commonmark.parser.InlineParser
|
||||
import org.commonmark.parser.InlineParserContext
|
||||
import org.commonmark.parser.InlineParserFactory
|
||||
import org.commonmark.parser.delimiter.DelimiterProcessor
|
||||
import org.commonmark.renderer.html.CoreHtmlNodeRenderer
|
||||
import org.commonmark.renderer.html.HtmlNodeRendererContext
|
||||
|
||||
internal class MarkdownParserFactory(private val pageScope: DocScope) : InlineParserFactory {
|
||||
// the scope of the doc comment to be parsed next; mutated by [MemberDocs]
|
||||
var docScope: DocScope = pageScope
|
||||
|
||||
override fun create(inlineParserContext: InlineParserContext): InlineParser {
|
||||
return InlineParserImpl(MarkdownParserContext(docScope, pageScope, inlineParserContext))
|
||||
}
|
||||
}
|
||||
|
||||
internal class MarkdownParserContext(
|
||||
private val docScope: DocScope,
|
||||
private val pageScope: DocScope,
|
||||
private val delegate: InlineParserContext
|
||||
) : InlineParserContext {
|
||||
companion object {
|
||||
private val keywords = setOf("null", "true", "false", "this", "unknown", "nothing")
|
||||
}
|
||||
|
||||
private val seenLinkTargets = mutableSetOf<DocScope>()
|
||||
|
||||
override fun getCustomDelimiterProcessors(): List<DelimiterProcessor> {
|
||||
return delegate.customDelimiterProcessors
|
||||
}
|
||||
|
||||
/**
|
||||
* This method communicates with [MarkdownNodeRenderer] through the method's return value:
|
||||
* * `title = "pkldoc:1:$label"` -> replace link with `Code(label)`
|
||||
* * `title = "pkldoc:2:$label"` -> replace link text with `Code(label)`
|
||||
*
|
||||
* We only want to modify *short* reference links as described above. Whereas this method can't
|
||||
* tell whether it's resolving a short or full reference link, PklNodeRenderer can, by comparing
|
||||
* the link text to the passed through label.
|
||||
*/
|
||||
override fun getLinkReferenceDefinition(label: String): LinkReferenceDefinition {
|
||||
if (label in keywords) {
|
||||
return LinkReferenceDefinition(label, label, "pkldoc:1:$label")
|
||||
}
|
||||
|
||||
val destScope = docScope.resolveDocLink(label)
|
||||
val destination = destScope?.urlRelativeTo(pageScope)?.toString() ?: "not_found"
|
||||
val command =
|
||||
when {
|
||||
// dangling link
|
||||
destScope == null -> 2
|
||||
|
||||
// don't link to ourselves
|
||||
destScope == docScope -> 1
|
||||
|
||||
// don't link to our own method parameters
|
||||
destScope is ParameterScope && destScope.parent == docScope -> 1
|
||||
|
||||
// only link to a target once
|
||||
!seenLinkTargets.add(destScope) -> 1
|
||||
else -> 2
|
||||
}
|
||||
|
||||
return LinkReferenceDefinition(label, destination, "pkldoc:$command:$label")
|
||||
}
|
||||
}
|
||||
|
||||
internal class MarkdownNodeRenderer(context: HtmlNodeRendererContext) :
|
||||
CoreHtmlNodeRenderer(context) {
|
||||
override fun visit(link: Link) {
|
||||
val title = link.title
|
||||
if (title == null || !title.startsWith("pkldoc:")) {
|
||||
super.visit(link)
|
||||
return
|
||||
}
|
||||
|
||||
// see [MarkdownParserContext] for contents of `title`
|
||||
val command = title[7]
|
||||
val label = title.substring(9)
|
||||
val isShortReferenceLink =
|
||||
link.firstChild === link.lastChild && (link.firstChild as? Text)?.literal == label
|
||||
|
||||
when {
|
||||
!isShortReferenceLink -> super.visit(link.apply { this.title = null })
|
||||
command == '1' -> visit(Code(label))
|
||||
command == '2' -> visit(Link(link.destination, null).apply { appendChild(Code(label)) })
|
||||
else -> throw AssertionError("Unknown command: $command")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.io.StringWriter
|
||||
import kotlinx.html.*
|
||||
import org.pkl.core.Member
|
||||
import org.pkl.core.PClass
|
||||
import org.pkl.core.PClass.ClassMember
|
||||
import org.pkl.core.PClass.Method
|
||||
import org.pkl.core.TypeParameter
|
||||
import org.pkl.core.TypeParameter.Variance
|
||||
import org.pkl.core.ValueRenderers
|
||||
|
||||
internal abstract class ModuleOrClassPageGenerator<S>(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
private val docModule: DocModule,
|
||||
protected val clazz: PClass,
|
||||
scope: S,
|
||||
private val isTestMode: Boolean
|
||||
) : PageGenerator<S>(docsiteInfo, scope) where S : PageScope {
|
||||
protected fun HtmlBlockTag.renderProperties() {
|
||||
if (!clazz.hasListedProperty) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_properties")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Properties"
|
||||
if (clazz.superclass.hasListedProperty) {
|
||||
renderShowInheritedButton()
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
for ((propertyName, property) in clazz.allProperties) {
|
||||
if (property.isUnlisted) continue
|
||||
|
||||
li {
|
||||
renderAnchor(propertyName)
|
||||
|
||||
div {
|
||||
val isInherited = property.owner.info != clazz.info
|
||||
classes =
|
||||
when {
|
||||
isInherited -> setOf("member", "inherited", "expandable", "hidden", "collapsed")
|
||||
property.isHidden -> setOf("member", "hidden-member")
|
||||
else -> setOf("member")
|
||||
}
|
||||
|
||||
val propertyScope = PropertyScope(property, pageScope)
|
||||
val memberDocs =
|
||||
MemberDocs(property.inheritedDocComment, propertyScope, property.annotations)
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
renderSelfLink(propertyName)
|
||||
|
||||
div {
|
||||
classes = setOf("member-left")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-modifiers", "member-deprecated")
|
||||
} else setOf("member-modifiers")
|
||||
|
||||
renderModifiers(property.modifiers)
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
classes = setOf("member-main")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-signature", "member-deprecated")
|
||||
} else setOf("member-signature")
|
||||
|
||||
if (isInherited) renderClassContext(property)
|
||||
|
||||
span {
|
||||
classes = setOf("name-decl")
|
||||
|
||||
+propertyName
|
||||
}
|
||||
|
||||
+": "
|
||||
renderType(property.type, propertyScope)
|
||||
|
||||
if (isInherited) {
|
||||
renderModuleContext(property)
|
||||
}
|
||||
renderMemberSourceLink(property)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderClassContext(member: ClassMember) {
|
||||
if (pageScope is ClassScope) {
|
||||
span {
|
||||
classes = setOf("context")
|
||||
renderClassName(member.owner)
|
||||
+"."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderModuleContext(member: Member) {
|
||||
span {
|
||||
classes = setOf("context")
|
||||
+" ("
|
||||
renderModuleName(member.moduleName)
|
||||
+")"
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderExportedValue(value: Any): String {
|
||||
val writer = StringWriter()
|
||||
ValueRenderers.pcf(writer, " ", false, false).renderValue(value)
|
||||
return writer.toString()
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderMethods() {
|
||||
if (!clazz.hasListedMethod) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_methods")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Methods"
|
||||
if (clazz.superclass.hasListedMethod) {
|
||||
renderShowInheritedButton()
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
for ((methodName, method) in clazz.allMethods) {
|
||||
if (method.isUnlisted) continue
|
||||
|
||||
li {
|
||||
renderAnchors(method)
|
||||
|
||||
div {
|
||||
val isInherited = method.owner.info != clazz.info
|
||||
classes =
|
||||
if (isInherited) {
|
||||
setOf("member", "inherited", "expandable", "hidden", "collapsed")
|
||||
} else setOf("member")
|
||||
|
||||
val methodScope = MethodScope(method, pageScope)
|
||||
val memberDocs =
|
||||
MemberDocs(method.inheritedDocComment, methodScope, method.annotations)
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
renderSelfLink("$methodName()")
|
||||
|
||||
div {
|
||||
classes = setOf("member-left")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-modifiers", "member-deprecated")
|
||||
} else setOf("member-modifiers")
|
||||
|
||||
renderModifiers(method.modifiers, "function")
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
classes = setOf("member-main")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember)
|
||||
setOf("member-signature", "member-deprecated")
|
||||
else setOf("member-signature")
|
||||
|
||||
if (isInherited) renderClassContext(method)
|
||||
|
||||
span {
|
||||
classes = setOf("name-decl")
|
||||
|
||||
+method.simpleName
|
||||
}
|
||||
|
||||
renderTypeParameters(method.typeParameters)
|
||||
|
||||
renderMethodParameters(method, methodScope)
|
||||
|
||||
+": "
|
||||
renderType(method.returnType, methodScope)
|
||||
|
||||
if (isInherited) {
|
||||
renderModuleContext(method)
|
||||
}
|
||||
renderMemberSourceLink(method)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderTypeParameters(parameters: List<TypeParameter>) {
|
||||
if (parameters.isEmpty()) return
|
||||
|
||||
+"<"
|
||||
var first = true
|
||||
parameters.forEachIndexed { idx, param ->
|
||||
if (first) first = false else +", "
|
||||
when (param.variance) {
|
||||
Variance.CONTRAVARIANT -> +"in "
|
||||
Variance.COVARIANT -> +"out "
|
||||
else -> {}
|
||||
}
|
||||
a {
|
||||
classes = setOf("param${idx + 1}")
|
||||
+param.name
|
||||
}
|
||||
}
|
||||
+">"
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderMethodParameters(method: Method, methodScope: MethodScope) {
|
||||
+"("
|
||||
var first = true
|
||||
val indexOffset = method.typeParameters.size
|
||||
method.parameters.entries.forEachIndexed { idx, (name, type) ->
|
||||
if (first) first = false else +", "
|
||||
span {
|
||||
classes = setOf("param${indexOffset + idx + 1}")
|
||||
+name
|
||||
}
|
||||
+": "
|
||||
renderType(type, methodScope)
|
||||
}
|
||||
+")"
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderMemberSourceLink(member: Member) {
|
||||
// Prevent churn by setting static line numbers.
|
||||
// This is so our doc generator tests don't break if, say, we change sources in the stdlib.
|
||||
val startLine = if (isTestMode) 123 else member.sourceLocation.startLine
|
||||
val endLine = if (isTestMode) 456 else member.sourceLocation.endLine
|
||||
val moduleSourceUrl =
|
||||
pageScope.resolveModuleNameToSourceUrl(
|
||||
member.moduleName,
|
||||
Member.SourceLocation(startLine, endLine)
|
||||
)
|
||||
?: return
|
||||
a {
|
||||
classes = setOf("member-source-link")
|
||||
href = moduleSourceUrl.toString()
|
||||
+"Source"
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderShowInheritedButton() {
|
||||
span {
|
||||
classes = setOf("toggle-inherited-members")
|
||||
+"("
|
||||
span {
|
||||
classes = setOf("toggle-inherited-members-link", "button-link")
|
||||
+"show inherited"
|
||||
}
|
||||
+")"
|
||||
}
|
||||
}
|
||||
}
|
||||
288
pkl-doc/src/main/kotlin/org/pkl/doc/ModulePageGenerator.kt
Normal file
288
pkl-doc/src/main/kotlin/org/pkl/doc/ModulePageGenerator.kt
Normal file
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
internal class ModulePageGenerator(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
docPackage: DocPackage,
|
||||
docModule: DocModule,
|
||||
pageScope: ModuleScope,
|
||||
isTestMode: Boolean
|
||||
) :
|
||||
ModuleOrClassPageGenerator<ModuleScope>(
|
||||
docsiteInfo,
|
||||
docModule,
|
||||
docModule.schema.moduleClass,
|
||||
pageScope,
|
||||
isTestMode
|
||||
) {
|
||||
private val module = docModule.schema
|
||||
|
||||
override val html: HTML.() -> Unit = {
|
||||
renderHtmlHead()
|
||||
|
||||
body {
|
||||
onLoad = "onLoad()"
|
||||
|
||||
renderPageHeader(docPackage.name, docPackage.version, docModule.name, null)
|
||||
|
||||
main {
|
||||
renderParentLinks()
|
||||
|
||||
h1 {
|
||||
id = "declaration-title"
|
||||
|
||||
+docModule.name
|
||||
|
||||
span {
|
||||
id = "declaration-version"
|
||||
+docPackage.version
|
||||
}
|
||||
}
|
||||
|
||||
val memberDocs =
|
||||
MemberDocs(
|
||||
clazz.docComment,
|
||||
pageScope,
|
||||
clazz.annotations,
|
||||
isDeclaration = true,
|
||||
collectMemberInfo(docModule)
|
||||
)
|
||||
|
||||
renderMemberGroupLinks(
|
||||
Triple("Overview", "#_overview", memberDocs.isExpandable),
|
||||
Triple("Properties", "#_properties", clazz.hasListedProperty),
|
||||
Triple("Methods", "#_methods", clazz.hasListedMethod),
|
||||
Triple("Classes", "#_classes", module.hasListedClass),
|
||||
Triple("Type Aliases", "#_type-aliases", module.hasListedTypeAlias)
|
||||
)
|
||||
|
||||
renderAnchor("_overview")
|
||||
div {
|
||||
id = "_declaration"
|
||||
classes = setOf("member")
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
|
||||
div {
|
||||
classes = setOf("member-signature")
|
||||
|
||||
renderModifiers(module.moduleClass.modifiers, "module")
|
||||
|
||||
span {
|
||||
classes = setOf("name-decl")
|
||||
|
||||
+docModule.name
|
||||
}
|
||||
|
||||
renderModuleAmendsOrExtendsClause(module)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
|
||||
renderProperties()
|
||||
renderMethods()
|
||||
renderClasses()
|
||||
renderTypeAliases()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// example output:
|
||||
// module PodSpec (io.k8s/api/core/v1:befa7c51) • Pkl Hub
|
||||
override fun HTMLTag.renderPageTitle() {
|
||||
val moduleScope = pageScope
|
||||
val packageScope = moduleScope.parent!!
|
||||
|
||||
+moduleScope.name.substringAfterLast('.')
|
||||
+" ("
|
||||
+packageScope.name
|
||||
+moduleScope.name.drop(packageScope.name.length).substringBeforeLast('.').replace('.', '/')
|
||||
+":"
|
||||
+packageScope.version
|
||||
+") • "
|
||||
+(docsiteInfo.title ?: "Pkldoc")
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderTypeAliases() {
|
||||
if (!module.hasListedTypeAlias) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_type-aliases")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Type Aliases"
|
||||
if (module.supermodule.hasListedTypeAlias) {
|
||||
renderShowInheritedButton()
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
for ((typeAliasName, typeAlias) in module.allTypeAliases) {
|
||||
if (typeAlias.isUnlisted) continue
|
||||
|
||||
li {
|
||||
renderAnchors(typeAlias)
|
||||
|
||||
div {
|
||||
val isInherited = typeAliasName !in module.typeAliases
|
||||
classes =
|
||||
if (isInherited) {
|
||||
setOf("member", "inherited", "expandable", "hidden", "collapsed")
|
||||
} else setOf("member")
|
||||
|
||||
val typeAliasScope = TypeAliasScope(typeAlias, pageScope.url, pageScope)
|
||||
val memberDocs =
|
||||
MemberDocs(typeAlias.docComment, typeAliasScope, typeAlias.annotations)
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
renderSelfLink(typeAliasName)
|
||||
|
||||
div {
|
||||
classes = setOf("member-left")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-modifiers", "member-deprecated")
|
||||
} else setOf("member-modifiers")
|
||||
|
||||
renderModifiers(typeAlias.modifiers, "typealias")
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
classes = setOf("member-main")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-signature", "member-deprecated")
|
||||
} else setOf("member-signature")
|
||||
|
||||
renderTypeAliasName(typeAlias, "name-decl")
|
||||
renderTypeParameters(typeAlias.typeParameters)
|
||||
+" = "
|
||||
renderType(typeAlias.aliasedType, typeAliasScope)
|
||||
|
||||
if (isInherited) {
|
||||
renderModuleContext(typeAlias)
|
||||
}
|
||||
renderMemberSourceLink(typeAlias)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderClasses() {
|
||||
if (!module.hasListedClass) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_classes")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Classes"
|
||||
if (module.supermodule.hasListedClass) {
|
||||
renderShowInheritedButton()
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
for ((className, clazz) in module.allClasses) {
|
||||
if (clazz.isUnlisted) continue
|
||||
|
||||
li {
|
||||
renderAnchor(className)
|
||||
|
||||
div {
|
||||
val isInherited = className !in module.classes
|
||||
classes =
|
||||
if (isInherited) {
|
||||
setOf(
|
||||
"member",
|
||||
"with-page-link",
|
||||
"inherited",
|
||||
"expandable",
|
||||
"hidden",
|
||||
"collapsed"
|
||||
)
|
||||
} else setOf("member", "with-page-link")
|
||||
|
||||
val classScope = ClassScope(clazz, pageScope.url, pageScope)
|
||||
val memberDocs =
|
||||
MemberDocs(clazz.docComment, classScope, clazz.annotations, isDeclaration = false)
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
renderSelfLink(className)
|
||||
|
||||
div {
|
||||
classes = setOf("member-left")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-modifiers", "member-deprecated")
|
||||
} else setOf("member-modifiers")
|
||||
|
||||
renderModifiers(clazz.modifiers, "class")
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
classes = setOf("member-main")
|
||||
|
||||
div {
|
||||
classes =
|
||||
if (memberDocs.isDeprecatedMember) {
|
||||
setOf("member-signature", "member-deprecated")
|
||||
} else setOf("member-signature")
|
||||
|
||||
renderClassName(clazz, "name-decl")
|
||||
renderTypeParameters(clazz.typeParameters)
|
||||
renderClassExtendsClause(clazz, classScope)
|
||||
|
||||
if (isInherited) {
|
||||
renderModuleContext(clazz)
|
||||
}
|
||||
renderMemberSourceLink(clazz)
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
438
pkl-doc/src/main/kotlin/org/pkl/doc/PackageDataGenerator.kt
Normal file
438
pkl-doc/src/main/kotlin/org/pkl/doc/PackageDataGenerator.kt
Normal file
@@ -0,0 +1,438 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.writer
|
||||
import kotlin.streams.toList
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.commons.readString
|
||||
import org.pkl.commons.toUri
|
||||
import org.pkl.commons.walk
|
||||
import org.pkl.core.*
|
||||
import org.pkl.core.util.IoUtils
|
||||
|
||||
/**
|
||||
* Reads and writes package-data.json, which contains enough information to include a package's
|
||||
* previously generated docs in a newly generated doc website. This is useful if there's a problem
|
||||
* with fetching or evaluating the latest package version.
|
||||
*/
|
||||
internal class PackageDataGenerator(private val outputDir: Path) {
|
||||
fun generate(pkg: DocPackage) {
|
||||
val path =
|
||||
outputDir.resolve(pkg.name).resolve(pkg.version).resolve("package-data.json").apply {
|
||||
createParentDirectories()
|
||||
}
|
||||
PackageData(pkg).write(path)
|
||||
}
|
||||
|
||||
fun readAll(): List<PackageData> {
|
||||
return outputDir.walk().use { paths ->
|
||||
paths
|
||||
.filter { it.fileName?.toString() == "package-data.json" }
|
||||
.map { PackageData.read(it) }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Uniquely identifies a specific version of a package, module, class, or type alias. */
|
||||
internal sealed class ElementRef {
|
||||
/** The package name. */
|
||||
abstract val pkg: String
|
||||
|
||||
/// The URI of the package, if any
|
||||
abstract val pkgUri: URI?
|
||||
|
||||
/** The package version. */
|
||||
abstract val version: String
|
||||
|
||||
/** The Pkldoc page URL of the element relative to its Pkldoc website root. */
|
||||
abstract val pageUrl: URI
|
||||
|
||||
/**
|
||||
* The Pkldoc page URL of the element relative to [other]'s page URL. Assumes that both elements
|
||||
* have the same Pkldoc website root.
|
||||
*/
|
||||
fun pageUrlRelativeTo(other: ElementRef): String {
|
||||
return IoUtils.relativize(pageUrl, other.pageUrl).toString()
|
||||
}
|
||||
}
|
||||
|
||||
/** Uniquely identifies a specific version of a package. */
|
||||
@Serializable
|
||||
internal data class PackageRef(
|
||||
/** The package name. */
|
||||
override val pkg: String,
|
||||
|
||||
/** The package's URI, if any. */
|
||||
override val pkgUri: @Contextual URI?,
|
||||
|
||||
/** The package version. */
|
||||
override val version: String
|
||||
) : ElementRef() {
|
||||
override val pageUrl: URI by lazy { "$pkg/$version/index.html".toUri() }
|
||||
}
|
||||
|
||||
/** Uniquely identifies a specific version of a module. */
|
||||
@Serializable
|
||||
internal data class ModuleRef(
|
||||
/** The package name. */
|
||||
override val pkg: String,
|
||||
|
||||
/** The package's URI, if any. */
|
||||
override val pkgUri: @Contextual URI?,
|
||||
|
||||
/** The package version. */
|
||||
override val version: String,
|
||||
|
||||
/** The module path. */
|
||||
val module: String
|
||||
) : ElementRef() {
|
||||
override val pageUrl: URI by lazy { "$pkg/$version/$module/index.html".toUri() }
|
||||
|
||||
val moduleClassRef: TypeRef by lazy {
|
||||
TypeRef(pkg, pkgUri, version, module, PClassInfo.MODULE_CLASS_NAME)
|
||||
}
|
||||
|
||||
val id: ModuleId by lazy { ModuleId(pkg, module) }
|
||||
|
||||
val fullName: String by lazy { "$pkg.${module.replace('/', '.')}" }
|
||||
}
|
||||
|
||||
/** Uniquely identifies a specific version of a class or type alias. */
|
||||
@Serializable
|
||||
internal data class TypeRef(
|
||||
/** The package name. */
|
||||
override val pkg: String,
|
||||
|
||||
/** The package's URI, if any. */
|
||||
override val pkgUri: @Contextual URI?,
|
||||
|
||||
/** The package version. */
|
||||
override val version: String,
|
||||
|
||||
/** The module path. */
|
||||
val module: String,
|
||||
|
||||
/** The simple type name. */
|
||||
val type: String,
|
||||
|
||||
/** Whether this is a type alias rather than a class. */
|
||||
val isTypeAlias: Boolean = false
|
||||
) : ElementRef() {
|
||||
|
||||
val id: TypeId by lazy { TypeId(pkg, module, type) }
|
||||
|
||||
val displayName: String by lazy { if (isModuleClass) module.substringAfterLast('/') else type }
|
||||
|
||||
override val pageUrl: URI by lazy {
|
||||
when {
|
||||
isTypeAlias -> "$pkg/$version/$module/index.html#$type".toUri()
|
||||
isModuleClass -> "$pkg/$version/$module/index.html".toUri()
|
||||
else -> "$pkg/$version/$module/$type.html".toUri()
|
||||
}
|
||||
}
|
||||
|
||||
private val isModuleClass: Boolean
|
||||
get() = type == PClassInfo.MODULE_CLASS_NAME
|
||||
}
|
||||
|
||||
/** Uniquely identifies a package (modulo its version). */
|
||||
internal typealias PackageId = String
|
||||
|
||||
/** Uniquely identifies a module (modulo its version). */
|
||||
internal data class ModuleId(val pkg: String, val module: String)
|
||||
|
||||
/** Uniquely identifies a class or type alias (modulo its version). */
|
||||
internal data class TypeId(val pkg: String, val module: String, val type: String)
|
||||
|
||||
/**
|
||||
* Persisted data for a package. Used by subsequent Pkldoc runs to generate main page and runtime
|
||||
* data (e.g., package versions and usages).
|
||||
*/
|
||||
@Serializable
|
||||
internal class PackageData(
|
||||
/** The ref of this package. */
|
||||
val ref: PackageRef,
|
||||
|
||||
/** The first paragraph of the overview documentation for this package. */
|
||||
val summary: String? = null,
|
||||
|
||||
/** The deprecation message of this package, or `null` if this package isn't deprecated. */
|
||||
val deprecation: String? = null,
|
||||
|
||||
/** The web URL of the source code for this package. */
|
||||
val sourceCode: @Contextual URI?,
|
||||
|
||||
/** The source code pattern, with placeholders (e.g. `%{path}`) */
|
||||
val sourceCodeUrlScheme: String?,
|
||||
|
||||
/** The dependencies of this package. */
|
||||
val dependencies: List<DependencyData> = listOf(),
|
||||
|
||||
/** The modules in this package. */
|
||||
val modules: List<ModuleData> = listOf()
|
||||
) {
|
||||
companion object {
|
||||
val json = Json { serializersModule = serializers }
|
||||
|
||||
fun read(path: Path): PackageData {
|
||||
val jsonStr: String =
|
||||
try {
|
||||
path.readString()
|
||||
} catch (e: IOException) {
|
||||
throw DocGeneratorException("I/O error reading `$path`.", e)
|
||||
}
|
||||
|
||||
return try {
|
||||
json.decodeFromString(jsonStr)
|
||||
} catch (e: SerializationException) {
|
||||
throw DocGeneratorException("Error deserializing `$path`.", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
pkg: DocPackage
|
||||
) : this(
|
||||
PackageRef(pkg.name, pkg.uri, pkg.version),
|
||||
getDocCommentSummary(pkg.overview),
|
||||
pkg.docPackageInfo.annotations.deprecation,
|
||||
pkg.docPackageInfo.sourceCode,
|
||||
pkg.docPackageInfo.sourceCodeUrlScheme,
|
||||
pkg.docPackageInfo.dependencies.map { DependencyData(PackageRef(it.name, it.uri, it.version)) },
|
||||
pkg.docModules.mapNotNull { if (it.isUnlisted) null else ModuleData(pkg, it) }
|
||||
)
|
||||
|
||||
fun write(path: Path) {
|
||||
val jsonStr =
|
||||
try {
|
||||
json.encodeToString(this)
|
||||
} catch (e: SerializationException) {
|
||||
throw DocGeneratorException("Error serializing `$path`.", e)
|
||||
}
|
||||
|
||||
try {
|
||||
path.createParentDirectories()
|
||||
path.writer().use { it.write(jsonStr) }
|
||||
} catch (e: IOException) {
|
||||
throw DocGeneratorException("I/O error writing `$path`.", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A package depended upon by [PackageData]. */
|
||||
@Serializable
|
||||
internal class DependencyData(
|
||||
/** The ref of the depended-on package. */
|
||||
val ref: PackageRef
|
||||
)
|
||||
|
||||
/** Persisted data for a module. */
|
||||
@Serializable
|
||||
internal class ModuleData(
|
||||
/** The ref of this module. */
|
||||
val ref: ModuleRef,
|
||||
|
||||
/** The first paragraph of the overview documentation for this module. */
|
||||
val summary: String? = null,
|
||||
|
||||
/** The deprecation message, or `null` if this module isn't deprecated. */
|
||||
val deprecation: String? = null,
|
||||
|
||||
/** The supermodules of this module, starting from the direct supermodule. */
|
||||
@Suppress("unused") val supermodules: List<ModuleRef> = listOf(),
|
||||
|
||||
/** The class of this module, or `null` if this module amends another module. */
|
||||
val moduleClass: ClassData? = null,
|
||||
|
||||
/** The classes declared in this module. */
|
||||
val classes: List<ClassData> = listOf(),
|
||||
|
||||
/** The type aliases declared in this module. */
|
||||
val typeAliases: List<TypeAliasData> = listOf()
|
||||
) {
|
||||
constructor(
|
||||
pkg: DocPackage,
|
||||
module: DocModule
|
||||
) : this(
|
||||
ModuleRef(pkg.name, pkg.uri, pkg.version, module.path),
|
||||
getDocCommentSummary(module.overview),
|
||||
module.schema.annotations.deprecation,
|
||||
generateSequence(module.schema.supermodule) { it.supermodule }
|
||||
.map { pkg.docPackageInfo.getModuleRef(module.name) }
|
||||
.filterNotNull()
|
||||
.toList(),
|
||||
if (module.schema.isAmend) null else ClassData(pkg, module, module.schema.moduleClass),
|
||||
module.schema.classes.mapNotNull {
|
||||
if (it.value.isUnlisted) null else ClassData(pkg, module, it.value)
|
||||
},
|
||||
module.schema.typeAliases.mapNotNull {
|
||||
if (it.value.isUnlisted) null else TypeAliasData(pkg, module, it.value)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/** Persisted data for a class or type alias. */
|
||||
@Serializable
|
||||
internal sealed class TypeData {
|
||||
/** The ref of this type. */
|
||||
abstract val ref: TypeRef
|
||||
|
||||
/**
|
||||
* The classes (including module classes) used in the API of this type. Standard library classes
|
||||
* are not included.
|
||||
*/
|
||||
abstract val usedTypes: List<TypeRef>
|
||||
}
|
||||
|
||||
/** Persisted data for a class. */
|
||||
@Serializable
|
||||
internal class ClassData(
|
||||
override val ref: TypeRef,
|
||||
|
||||
/**
|
||||
* The superclasses of this class, starting from the direct superclass. Every class except
|
||||
* `pkl.Any` has a superclass.
|
||||
*/
|
||||
val superclasses: List<TypeRef> = listOf(),
|
||||
override val usedTypes: List<TypeRef> = listOf(),
|
||||
) : TypeData() {
|
||||
constructor(
|
||||
pkg: DocPackage,
|
||||
module: DocModule,
|
||||
clazz: PClass
|
||||
) : this(
|
||||
TypeRef(pkg.name, pkg.uri, pkg.version, module.path, clazz.simpleName),
|
||||
generateSequence(clazz.superclass) { it.superclass }
|
||||
.map { pkg.docPackageInfo.getTypeRef(it) }
|
||||
.filterNotNull()
|
||||
.toList(),
|
||||
findTypesUsedBy(clazz, pkg.docPackageInfo).toList()
|
||||
)
|
||||
}
|
||||
|
||||
/** Persisted data for a type alias. */
|
||||
@Serializable
|
||||
internal class TypeAliasData(
|
||||
/** The ref of this type alias. */
|
||||
override val ref: TypeRef,
|
||||
|
||||
/** The types used by this type alias. */
|
||||
override val usedTypes: List<TypeRef> = listOf()
|
||||
) : TypeData() {
|
||||
constructor(
|
||||
pkg: DocPackage,
|
||||
module: DocModule,
|
||||
alias: TypeAlias
|
||||
) : this(
|
||||
TypeRef(pkg.name, pkg.uri, pkg.version, module.path, alias.simpleName, isTypeAlias = true),
|
||||
findTypesUsedBy(alias, pkg.docPackageInfo).toList()
|
||||
)
|
||||
}
|
||||
|
||||
private fun findTypesUsedBy(clazz: PClass, enclosingPackage: DocPackageInfo): Set<TypeRef> {
|
||||
val result = mutableSetOf<TypeRef>()
|
||||
clazz.supertype?.let { supertype ->
|
||||
for (typeArgument in supertype.typeArguments) {
|
||||
findTypesUsedBy(typeArgument, clazz, enclosingPackage, result)
|
||||
}
|
||||
}
|
||||
for ((_, property) in clazz.properties) {
|
||||
findTypesUsedBy(property.type, clazz, enclosingPackage, result)
|
||||
}
|
||||
for ((_, method) in clazz.methods) {
|
||||
for ((_, type) in method.parameters) {
|
||||
findTypesUsedBy(type, clazz, enclosingPackage, result)
|
||||
}
|
||||
findTypesUsedBy(method.returnType, clazz, enclosingPackage, result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findTypesUsedBy(alias: TypeAlias, enclosingPackage: DocPackageInfo): Set<TypeRef> {
|
||||
val result = mutableSetOf<TypeRef>()
|
||||
findTypesUsedBy(alias.aliasedType, alias, enclosingPackage, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findTypesUsedBy(
|
||||
type: PType,
|
||||
enclosingType: Member /* PClass|TypeAlias */,
|
||||
enclosingPackage: DocPackageInfo,
|
||||
result: MutableSet<TypeRef>
|
||||
) {
|
||||
when (type) {
|
||||
is PType.Class -> {
|
||||
val target = type.pClass
|
||||
if (!target.isStandardLibraryMember && !target.isUnlisted && target != enclosingType) {
|
||||
enclosingPackage.getTypeRef(target)?.let { result.add(it) }
|
||||
}
|
||||
for (typeArgument in type.typeArguments) {
|
||||
findTypesUsedBy(typeArgument, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
}
|
||||
is PType.Alias -> {
|
||||
val target = type.typeAlias
|
||||
if (!target.isStandardLibraryMember && !target.isUnlisted && target != enclosingType) {
|
||||
enclosingPackage.getTypeRef(target)?.let { result.add(it) }
|
||||
}
|
||||
}
|
||||
is PType.Constrained -> {
|
||||
findTypesUsedBy(type.baseType, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
is PType.Function -> {
|
||||
for (parameterType in type.parameterTypes) {
|
||||
findTypesUsedBy(parameterType, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
findTypesUsedBy(type.returnType, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
PType.MODULE -> {
|
||||
if (enclosingType.simpleName != PClassInfo.MODULE_CLASS_NAME) {
|
||||
result.add(
|
||||
TypeRef(
|
||||
enclosingPackage.name,
|
||||
enclosingPackage.uri,
|
||||
enclosingPackage.version,
|
||||
enclosingType.moduleName.substring(enclosingPackage.name.length + 1).replace('.', '/'),
|
||||
PClassInfo.MODULE_CLASS_NAME
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
PType.NOTHING -> {}
|
||||
is PType.Nullable -> {
|
||||
findTypesUsedBy(type.baseType, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
is PType.Union -> {
|
||||
for (elementType in type.elementTypes) {
|
||||
findTypesUsedBy(elementType, enclosingType, enclosingPackage, result)
|
||||
}
|
||||
}
|
||||
is PType.StringLiteral -> {}
|
||||
is PType.TypeVariable -> {}
|
||||
PType.UNKNOWN -> {}
|
||||
else -> {
|
||||
throw AssertionError("Unknown PType: $type")
|
||||
}
|
||||
}
|
||||
}
|
||||
132
pkl-doc/src/main/kotlin/org/pkl/doc/PackagePageGenerator.kt
Normal file
132
pkl-doc/src/main/kotlin/org/pkl/doc/PackagePageGenerator.kt
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlinx.html.*
|
||||
|
||||
internal class PackagePageGenerator(
|
||||
docsiteInfo: DocsiteInfo,
|
||||
private val docPackage: DocPackage,
|
||||
pageScope: PackageScope
|
||||
) : MainOrPackagePageGenerator<PackageScope>(docsiteInfo, pageScope, pageScope.parent) {
|
||||
override val html: HTML.() -> Unit = {
|
||||
renderHtmlHead()
|
||||
|
||||
body {
|
||||
onLoad = "onLoad()"
|
||||
|
||||
renderPageHeader(docPackage.name, docPackage.version, null, null)
|
||||
|
||||
main {
|
||||
renderParentLinks()
|
||||
|
||||
h1 {
|
||||
id = "declaration-title"
|
||||
+docPackage.name
|
||||
|
||||
span {
|
||||
id = "declaration-version"
|
||||
+docPackage.version
|
||||
}
|
||||
}
|
||||
|
||||
val packageInfo = docPackage.docPackageInfo
|
||||
val memberDocs =
|
||||
MemberDocs(
|
||||
packageInfo.overview,
|
||||
pageScope,
|
||||
packageInfo.annotations,
|
||||
isDeclaration = true,
|
||||
collectMemberInfoForPackage(docPackage)
|
||||
)
|
||||
|
||||
renderMemberGroupLinks(
|
||||
Triple("Overview", "#_overview", memberDocs.isExpandable),
|
||||
Triple("Modules", "#_modules", docPackage.hasListedModule)
|
||||
)
|
||||
|
||||
renderAnchor("_overview")
|
||||
div {
|
||||
id = "_declaration"
|
||||
classes = setOf("member")
|
||||
|
||||
memberDocs.renderExpandIcon(this)
|
||||
|
||||
div {
|
||||
classes = setOf("member-signature")
|
||||
|
||||
renderModifiers(setOf(), "package")
|
||||
|
||||
span {
|
||||
classes = setOf("name-decl")
|
||||
|
||||
+docPackage.name
|
||||
}
|
||||
}
|
||||
|
||||
memberDocs.renderDocComment(this)
|
||||
}
|
||||
|
||||
renderModules()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// example output:
|
||||
// package io.k8s (befa7c51) • Pkl Hub
|
||||
override fun HTMLTag.renderPageTitle() {
|
||||
+pageScope.name
|
||||
+" ("
|
||||
+pageScope.version
|
||||
+") • "
|
||||
+(docsiteInfo.title ?: "Pkldoc")
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderModules() {
|
||||
if (!docPackage.hasListedModule) return
|
||||
|
||||
div {
|
||||
classes = setOf("member-group")
|
||||
|
||||
renderAnchor("_modules")
|
||||
|
||||
h2 {
|
||||
classes = setOf("member-group-title")
|
||||
|
||||
+"Modules"
|
||||
}
|
||||
|
||||
ul {
|
||||
for (docModule in docPackage.docModules) {
|
||||
if (docModule.isUnlisted) continue
|
||||
|
||||
val module = docModule.schema
|
||||
val moduleScope = pageScope.getModule(module.moduleName)
|
||||
val memberDocs =
|
||||
MemberDocs(
|
||||
module.docComment,
|
||||
moduleScope,
|
||||
module.annotations,
|
||||
isDeclaration = false,
|
||||
collectMemberInfo(docModule)
|
||||
)
|
||||
|
||||
renderModuleOrPackage(module.moduleName, moduleScope, memberDocs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
770
pkl-doc/src/main/kotlin/org/pkl/doc/PageGenerator.kt
Normal file
770
pkl-doc/src/main/kotlin/org/pkl/doc/PageGenerator.kt
Normal file
@@ -0,0 +1,770 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import kotlin.io.path.bufferedWriter
|
||||
import kotlinx.html.*
|
||||
import kotlinx.html.stream.appendHTML
|
||||
import org.commonmark.ext.gfm.tables.TablesExtension
|
||||
import org.commonmark.parser.Parser
|
||||
import org.commonmark.renderer.html.HtmlRenderer
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.commons.toPath
|
||||
import org.pkl.core.*
|
||||
import org.pkl.core.util.IoUtils
|
||||
|
||||
internal abstract class PageGenerator<out S>(
|
||||
protected val docsiteInfo: DocsiteInfo,
|
||||
protected val pageScope: S
|
||||
) where S : PageScope {
|
||||
private val markdownInlineParserFactory = MarkdownParserFactory(pageScope)
|
||||
|
||||
private val markdownParser =
|
||||
Parser.builder()
|
||||
.extensions(listOf(TablesExtension.create()))
|
||||
.inlineParserFactory(markdownInlineParserFactory)
|
||||
.build()
|
||||
|
||||
private val markdownRenderer =
|
||||
HtmlRenderer.builder()
|
||||
.extensions(listOf(TablesExtension.create()))
|
||||
.nodeRendererFactory { MarkdownNodeRenderer(it) }
|
||||
.build()
|
||||
|
||||
fun run() {
|
||||
val path = pageScope.url.toPath()
|
||||
path.createParentDirectories()
|
||||
path.bufferedWriter().use {
|
||||
it.appendLine("<!DOCTYPE html>")
|
||||
it.appendHTML().html(null, html)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract val html: HTML.() -> Unit
|
||||
|
||||
protected abstract fun HTMLTag.renderPageTitle()
|
||||
|
||||
protected fun HTML.renderHtmlHead() {
|
||||
head {
|
||||
title { renderPageTitle() }
|
||||
script {
|
||||
src = pageScope.relativeSiteUrl.resolve("scripts/pkldoc.js").toString()
|
||||
defer = true
|
||||
}
|
||||
script {
|
||||
src = pageScope.relativeSiteUrl.resolve("scripts/scroll-into-view.min.js").toString()
|
||||
defer = true
|
||||
}
|
||||
if (pageScope !is SiteScope) {
|
||||
script {
|
||||
src = IoUtils.relativize(pageScope.dataUrl, pageScope.url).toString()
|
||||
defer = true
|
||||
}
|
||||
}
|
||||
link {
|
||||
href = pageScope.relativeSiteUrl.resolve("styles/pkldoc.css").toString()
|
||||
media = "screen"
|
||||
type = "text/css"
|
||||
rel = "stylesheet"
|
||||
}
|
||||
link {
|
||||
rel = "icon"
|
||||
type = "image/svg+xml"
|
||||
href = pageScope.relativeSiteUrl.resolve("images/favicon.svg").toString()
|
||||
}
|
||||
link {
|
||||
rel = "apple-touch-icon"
|
||||
sizes = "180x180"
|
||||
href = pageScope.relativeSiteUrl.resolve("images/apple-touch-icon.png").toString()
|
||||
}
|
||||
link {
|
||||
rel = "icon"
|
||||
type = "image/png"
|
||||
sizes = "32x32"
|
||||
href = pageScope.relativeSiteUrl.resolve("images/favicon-32x32.png").toString()
|
||||
}
|
||||
link {
|
||||
rel = "icon"
|
||||
type = "image/png"
|
||||
sizes = "16x16"
|
||||
href = pageScope.relativeSiteUrl.resolve("images/favicon-16x16.png").toString()
|
||||
}
|
||||
meta { charset = "UTF-8" }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderPageHeader(
|
||||
packageName: String?,
|
||||
packageVersion: String?,
|
||||
moduleName: String?,
|
||||
className: String?
|
||||
) {
|
||||
header {
|
||||
if (docsiteInfo.title != null) {
|
||||
div {
|
||||
id = "doc-title"
|
||||
|
||||
a {
|
||||
href = pageScope.relativeSiteUrl.toString()
|
||||
+docsiteInfo.title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
id = "search"
|
||||
|
||||
i {
|
||||
id = "search-icon"
|
||||
classes = setOf("material-icons")
|
||||
+"search"
|
||||
}
|
||||
|
||||
input {
|
||||
id = "search-input"
|
||||
type = InputType.search
|
||||
placeholder =
|
||||
if (packageName == null) {
|
||||
"Click or press 'S' to search"
|
||||
} else {
|
||||
"Click or press 'S' to search this package"
|
||||
}
|
||||
autoComplete = false
|
||||
if (packageName != null) {
|
||||
require(packageVersion != null)
|
||||
attributes["data-package-name"] = packageName
|
||||
attributes["data-package-version"] = packageVersion
|
||||
attributes["data-package-url-prefix"] =
|
||||
"../".repeat(pageScope.relativePackageUrl.path.count { it == '/' })
|
||||
}
|
||||
if (moduleName != null) {
|
||||
attributes["data-module-name"] = moduleName
|
||||
}
|
||||
if (className != null) {
|
||||
attributes["data-class-name"] = className
|
||||
}
|
||||
attributes["data-root-url-prefix"] =
|
||||
"../".repeat(pageScope.relativeSiteUrl.path.count { it == '/' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderParentLinks() {
|
||||
a {
|
||||
classes = setOf("declaration-parent-link")
|
||||
href = pageScope.relativeSiteUrl.toString()
|
||||
|
||||
+(docsiteInfo.title ?: "Pkldoc")
|
||||
}
|
||||
|
||||
val packageScope =
|
||||
when (pageScope) {
|
||||
is ClassScope -> pageScope.parent!!.parent
|
||||
is ModuleScope -> pageScope.parent
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (packageScope != null) {
|
||||
+" > "
|
||||
|
||||
a {
|
||||
classes = setOf("declaration-parent-link")
|
||||
href = packageScope.urlRelativeTo(pageScope).toString()
|
||||
|
||||
+packageScope.name
|
||||
}
|
||||
}
|
||||
|
||||
val moduleScope =
|
||||
when (pageScope) {
|
||||
is ClassScope -> pageScope.parent
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (moduleScope != null) {
|
||||
+" > "
|
||||
|
||||
a {
|
||||
classes = setOf("declaration-parent-link")
|
||||
href = moduleScope.urlRelativeTo(pageScope).toString()
|
||||
|
||||
+moduleScope.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderClassExtendsClause(clazz: PClass, currScope: DocScope) {
|
||||
val superclass = clazz.superclass ?: return
|
||||
if (superclass.info != PClassInfo.Typed) {
|
||||
+" extends "
|
||||
renderType(clazz.supertype!!, currScope)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderModuleAmendsOrExtendsClause(module: ModuleSchema) {
|
||||
module.supermodule?.let { supermodule ->
|
||||
if (module.isAmend) +" amends " else +" extends "
|
||||
renderModuleName(supermodule.moduleName)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderMemberGroupLinks(
|
||||
vararg groups: Triple<String, String, Boolean>
|
||||
) {
|
||||
ul {
|
||||
classes = setOf("member-group-links")
|
||||
for ((name, _href, show) in groups) {
|
||||
if (show) {
|
||||
li {
|
||||
a {
|
||||
href = _href
|
||||
+name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderModuleName(moduleName: String) {
|
||||
val moduleDocUrl = pageScope.resolveModuleNameToRelativeDocUrl(moduleName)
|
||||
|
||||
if (moduleDocUrl != null) {
|
||||
a {
|
||||
href = moduleDocUrl.toString()
|
||||
classes = setOf("name-ref")
|
||||
+moduleName
|
||||
}
|
||||
} else {
|
||||
span {
|
||||
classes = setOf("member-ref")
|
||||
+moduleName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val PClass.simpleDisplayName: String
|
||||
get() = if (isModuleClass) moduleName.substring(moduleName.lastIndexOf('.') + 1) else simpleName
|
||||
|
||||
protected fun HtmlBlockTag.renderClassName(clazz: PClass, cssClass: String = "name-ref") {
|
||||
val moduleDocUrl = pageScope.resolveModuleNameToDocUrl(clazz.moduleName)
|
||||
|
||||
if (moduleDocUrl != null) {
|
||||
val targetScope = ClassScope(clazz, moduleDocUrl, null)
|
||||
a {
|
||||
href = targetScope.urlRelativeTo(pageScope).toString()
|
||||
classes = setOf(cssClass)
|
||||
+clazz.simpleDisplayName
|
||||
}
|
||||
} else {
|
||||
span {
|
||||
classes = setOf(cssClass)
|
||||
+clazz.simpleDisplayName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderTypeAliasName(
|
||||
typeAlias: TypeAlias,
|
||||
cssClass: String = "name-ref"
|
||||
) {
|
||||
val moduleDocUrl = pageScope.resolveModuleNameToDocUrl(typeAlias.moduleName)
|
||||
|
||||
if (moduleDocUrl != null) {
|
||||
val targetScope = TypeAliasScope(typeAlias, moduleDocUrl, null)
|
||||
a {
|
||||
href = targetScope.urlRelativeTo(pageScope).toString()
|
||||
classes = setOf(cssClass)
|
||||
+typeAlias.simpleName
|
||||
}
|
||||
} else {
|
||||
span {
|
||||
classes = setOf(cssClass)
|
||||
+typeAlias.simpleName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderType(
|
||||
type: PType,
|
||||
currScope: DocScope,
|
||||
isNested: Boolean = false
|
||||
) {
|
||||
when (type) {
|
||||
PType.UNKNOWN -> {
|
||||
+"unknown"
|
||||
}
|
||||
PType.NOTHING -> {
|
||||
+"nothing"
|
||||
}
|
||||
PType.MODULE -> {
|
||||
+"module"
|
||||
}
|
||||
is PType.StringLiteral -> {
|
||||
+"\"${type.literal}\""
|
||||
}
|
||||
is PType.Class -> {
|
||||
renderClassName(type.pClass)
|
||||
renderTypeArguments(type.typeArguments, currScope)
|
||||
}
|
||||
is PType.Nullable -> {
|
||||
renderType(type.baseType, currScope, true)
|
||||
+"?"
|
||||
}
|
||||
is PType.Union -> {
|
||||
if (isNested) +"("
|
||||
var first = true
|
||||
for (elem in type.elementTypes) {
|
||||
if (first) first = false else +"|"
|
||||
renderType(elem, currScope, true)
|
||||
}
|
||||
if (isNested) +")"
|
||||
}
|
||||
is PType.Function -> {
|
||||
+"("
|
||||
var first = true
|
||||
for (paramType in type.parameterTypes) {
|
||||
if (first) first = false else +", "
|
||||
renderType(paramType, currScope, true)
|
||||
}
|
||||
+")"
|
||||
|
||||
+" -> "
|
||||
|
||||
renderType(type.returnType, currScope, true)
|
||||
}
|
||||
is PType.Constrained -> {
|
||||
renderType(type.baseType, currScope, true)
|
||||
+"("
|
||||
var first = true
|
||||
for (constraint in type.constraints) {
|
||||
if (first) first = false else +", "
|
||||
+constraint
|
||||
}
|
||||
+")"
|
||||
}
|
||||
is PType.Alias -> {
|
||||
renderTypeAliasName(type.typeAlias)
|
||||
renderTypeArguments(type.typeArguments, currScope)
|
||||
}
|
||||
is PType.TypeVariable -> renderTypeVariable(type, currScope)
|
||||
else -> throw AssertionError("Unknown PType: $type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderTypeArguments(typeArguments: List<PType>, currentScope: DocScope) {
|
||||
if (typeArguments.isEmpty()) return
|
||||
|
||||
+"<"
|
||||
var first = true
|
||||
for (typeArg in typeArguments) {
|
||||
if (first) first = false else +", "
|
||||
renderType(typeArg, currentScope, true)
|
||||
}
|
||||
+">"
|
||||
|
||||
// method.parameters.entries.forEachIndexed { idx, (name, type) ->
|
||||
// if (first) first = false else +", "
|
||||
// span {
|
||||
// classes = setOf("param${indexOffset + idx + 1}")
|
||||
// +name
|
||||
// }
|
||||
// +": "
|
||||
// renderType(type, methodScope)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun HtmlBlockTag.renderTypeVariable(
|
||||
typeVariable: PType.TypeVariable,
|
||||
currentScope: DocScope
|
||||
) {
|
||||
val parameterScope = currentScope.resolveVariable(typeVariable.name) as? ParameterScope
|
||||
|
||||
if (parameterScope != null) {
|
||||
a {
|
||||
href = parameterScope.urlRelativeTo(pageScope).toString()
|
||||
classes = setOf("name-ref")
|
||||
+typeVariable.name
|
||||
}
|
||||
} else {
|
||||
span {
|
||||
classes = setOf("name-ref")
|
||||
+typeVariable.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderModifiers(modifiers: Set<Modifier>, vararg additional: String) {
|
||||
for (modifier in modifiers) {
|
||||
+modifier.toString()
|
||||
+" "
|
||||
}
|
||||
for (modifier in additional) {
|
||||
+modifier
|
||||
+" "
|
||||
}
|
||||
}
|
||||
|
||||
// best way I could find to offset anchors so that they aren't hidden behind fixed header when
|
||||
// navigated to
|
||||
// (tried several other CSS and JS solutions but all of them fell short in one way or another)
|
||||
// this solution works both for same-page and cross-page links, allows :target selector on
|
||||
// anchors, and requires no JS
|
||||
protected fun HtmlBlockTag.renderAnchor(anchorId: String, cssClass: String = "anchor") {
|
||||
div {
|
||||
id = anchorId
|
||||
classes = setOf(cssClass)
|
||||
+" " // needs some content to be considered a valid anchor by browsers
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderAnchors(clazz: PClass) {
|
||||
clazz.typeParameters.forEachIndexed { idx, param ->
|
||||
renderAnchor(param.name, "anchor-param${idx + 1}")
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderAnchors(typeAlias: TypeAlias) {
|
||||
val baseId = typeAlias.simpleName
|
||||
renderAnchor(baseId)
|
||||
typeAlias.typeParameters
|
||||
.map { it.name }
|
||||
.forEachIndexed { idx, param -> renderAnchor("$baseId.$param", "anchor-param${idx + 1}") }
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderAnchors(method: PClass.Method) {
|
||||
val baseId = "${method.simpleName}()"
|
||||
renderAnchor(baseId)
|
||||
(method.typeParameters.map { it.name } + method.parameters.keys).forEachIndexed { idx, param ->
|
||||
renderAnchor("$baseId.$param", "anchor-param${idx + 1}")
|
||||
}
|
||||
}
|
||||
|
||||
protected fun HtmlBlockTag.renderSelfLink(memberName: String) {
|
||||
a {
|
||||
classes = setOf("member-selflink", "material-icons")
|
||||
href = "#$memberName"
|
||||
+"link"
|
||||
}
|
||||
}
|
||||
|
||||
protected val runtimeDataClasses: Set<String> = setOf("runtime-data", "hidden")
|
||||
|
||||
protected fun collectMemberInfoForPackage(
|
||||
docPackage: DocPackage
|
||||
): Map<MemberInfoKey, HtmlBlockTag.() -> Unit> {
|
||||
val result: MutableMap<MemberInfoKey, HtmlBlockTag.() -> Unit> = mutableMapOf()
|
||||
|
||||
if (docPackage.minPklVersion != null) {
|
||||
result[MemberInfoKey("Pkl version")] = { +"${docPackage.minPklVersion} or higher" }
|
||||
}
|
||||
|
||||
if (docPackage.uri != null) {
|
||||
result[MemberInfoKey("URI")] = {
|
||||
span {
|
||||
classes = setOf("import-uri")
|
||||
+docPackage.uri.toString()
|
||||
}
|
||||
i {
|
||||
classes = setOf("copy-uri-button", "material-icons")
|
||||
+"content_copy"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (docPackage.docPackageInfo.authors?.isNotEmpty() == true) {
|
||||
result[MemberInfoKey("Authors")] = {
|
||||
var first = true
|
||||
for (author in docPackage.docPackageInfo.authors) {
|
||||
if (first) first = false else +", "
|
||||
+author
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result[MemberInfoKey("Version")] = { +docPackage.version }
|
||||
|
||||
if (docPackage.docPackageInfo.sourceCode != null) {
|
||||
val sources = docPackage.docPackageInfo.sourceCode.toString()
|
||||
result[MemberInfoKey("Source code")] = {
|
||||
a {
|
||||
href = sources
|
||||
+sources
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (docPackage.docPackageInfo.issueTracker != null) {
|
||||
val issues = docPackage.docPackageInfo.issueTracker.toString()
|
||||
result[MemberInfoKey("Issue tracker")] = {
|
||||
a {
|
||||
href = issues
|
||||
+issues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (docPackage.docPackageInfo.dependencies.isNotEmpty()) {
|
||||
result[MemberInfoKey("Dependencies")] = {
|
||||
var first = true
|
||||
for (dep in docPackage.docPackageInfo.dependencies) {
|
||||
if (first) first = false else +", "
|
||||
a {
|
||||
href =
|
||||
dep.documentation?.toString()
|
||||
?: pageScope.relativeSiteUrl
|
||||
.resolve("${dep.name}/${dep.version}/index.html")
|
||||
.toString()
|
||||
+dep.name
|
||||
+":"
|
||||
+dep.version
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ((key, value) in docPackage.docPackageInfo.extraAttributes) {
|
||||
result[MemberInfoKey(key)] = { +value }
|
||||
}
|
||||
|
||||
result[MemberInfoKey("Known usages", runtimeDataClasses)] = {
|
||||
id = HtmlConstants.KNOWN_USAGES
|
||||
classes = runtimeDataClasses
|
||||
}
|
||||
|
||||
result[MemberInfoKey("All versions", runtimeDataClasses)] = {
|
||||
id = HtmlConstants.KNOWN_VERSIONS
|
||||
classes = runtimeDataClasses
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
protected class MemberInfoKey(val name: String, val classes: Set<String> = setOf())
|
||||
|
||||
protected fun collectMemberInfo(
|
||||
docModule: DocModule
|
||||
): Map<MemberInfoKey, HtmlBlockTag.() -> Unit> {
|
||||
val importUri = docModule.importUri
|
||||
val sourceUrl = docModule.sourceUrl
|
||||
val examples = docModule.examples
|
||||
|
||||
val result: MutableMap<MemberInfoKey, HtmlBlockTag.() -> Unit> = mutableMapOf()
|
||||
|
||||
result[MemberInfoKey("Module URI")] = {
|
||||
span {
|
||||
classes = setOf("import-uri")
|
||||
+(importUri.toString())
|
||||
}
|
||||
i {
|
||||
classes = setOf("copy-uri-button", "material-icons")
|
||||
+"content_copy"
|
||||
}
|
||||
}
|
||||
|
||||
val moduleInfoAnnotation =
|
||||
docModule.schema.annotations.find { it.classInfo == PClassInfo.ModuleInfo }
|
||||
if (moduleInfoAnnotation != null) {
|
||||
val minPklVersion = moduleInfoAnnotation["minPklVersion"] as String
|
||||
result[MemberInfoKey("Pkl version")] = { +"$minPklVersion or higher" }
|
||||
}
|
||||
|
||||
if (sourceUrl != null) {
|
||||
result[MemberInfoKey("Source code")] = {
|
||||
a {
|
||||
href = sourceUrl.toString()
|
||||
val path = sourceUrl.path
|
||||
val name = path.substring(path.lastIndexOf("/") + 1)
|
||||
+name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (examples.isNotEmpty() && docModule.parent.docPackageInfo.sourceCodeUrlScheme != null) {
|
||||
result[MemberInfoKey("Examples")] = {
|
||||
var first = true
|
||||
for (example in examples) {
|
||||
if (first) first = false else +", "
|
||||
a {
|
||||
href = docModule.parent.docPackageInfo.getModuleSourceCode(example.moduleName)!!
|
||||
+example.shortModuleName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result[MemberInfoKey("Known subtypes", runtimeDataClasses)] = {
|
||||
id = HtmlConstants.KNOWN_SUBTYPES
|
||||
classes = runtimeDataClasses
|
||||
}
|
||||
|
||||
result[MemberInfoKey("Known usages", runtimeDataClasses)] = {
|
||||
id = HtmlConstants.KNOWN_USAGES
|
||||
classes = runtimeDataClasses
|
||||
}
|
||||
|
||||
result[MemberInfoKey("All versions", runtimeDataClasses)] = {
|
||||
id = HtmlConstants.KNOWN_VERSIONS
|
||||
classes = runtimeDataClasses
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
protected inner class MemberDocs(
|
||||
docComment: String?,
|
||||
docScope: DocScope,
|
||||
annotations: List<PObject>,
|
||||
/** Whether these member docs are for the main declaration at the top of a page. */
|
||||
private val isDeclaration: Boolean = false,
|
||||
private val extraMemberInfo: Map<MemberInfoKey, HtmlBlockTag.() -> Unit> = mapOf()
|
||||
) {
|
||||
init {
|
||||
markdownInlineParserFactory.docScope = docScope
|
||||
}
|
||||
|
||||
private val summary: String? =
|
||||
docComment
|
||||
?.let { getDocCommentSummary(it) }
|
||||
?.let { markdownRenderer.render(markdownParser.parse(it)).trim().ifEmpty { null } }
|
||||
|
||||
// whether to only show basic information without the option to expand
|
||||
private val showSummaryOnly: Boolean = !isDeclaration && docScope is PageScope
|
||||
|
||||
private val overflow: String? =
|
||||
if (showSummaryOnly) {
|
||||
null // don't render if not needed
|
||||
} else {
|
||||
docComment
|
||||
?.let { getDocCommentOverflow(it) }
|
||||
?.let { markdownRenderer.render(markdownParser.parse(it)).trim().ifEmpty { null } }
|
||||
}
|
||||
|
||||
private val deprecatedAnnotation: PObject? =
|
||||
annotations.find { it.classInfo == PClassInfo.Deprecated }
|
||||
|
||||
private val alsoKnownAsAnnotation: PObject? =
|
||||
annotations.find { it.classInfo == PClassInfo.AlsoKnownAs }
|
||||
|
||||
val isDeprecatedMember: Boolean = deprecatedAnnotation != null
|
||||
|
||||
// whether there is a "member info" section consisting of key-value pairs
|
||||
private val hasMemberInfo: Boolean =
|
||||
extraMemberInfo.isNotEmpty() || alsoKnownAsAnnotation != null
|
||||
|
||||
// whether the first paragraph of the user-provided doc comment
|
||||
// needs to give way for other information
|
||||
private val summaryMovesDown: Boolean = summary != null && deprecatedAnnotation != null
|
||||
|
||||
val isExpandable: Boolean =
|
||||
!showSummaryOnly && (overflow != null || summaryMovesDown || hasMemberInfo && !isDeclaration)
|
||||
|
||||
fun renderExpandIcon(tag: HtmlBlockTag) {
|
||||
if (isExpandable) {
|
||||
tag.classes += "with-expandable-docs"
|
||||
tag.i {
|
||||
classes = setOf("material-icons", "expandable-docs-icon")
|
||||
+"expand_more"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun renderDocComment(tag: HtmlBlockTag) {
|
||||
if (deprecatedAnnotation != null) {
|
||||
val message = deprecatedAnnotation["message"] as String?
|
||||
|
||||
val replaceWith = deprecatedAnnotation["replaceWith"] as String?
|
||||
|
||||
tag.div {
|
||||
classes = setOf("doc-comment")
|
||||
if (message != null) {
|
||||
+"Deprecated: "
|
||||
unsafe { raw(renderInlineMarkdownText(message)) }
|
||||
} else {
|
||||
+"Deprecated."
|
||||
}
|
||||
if (replaceWith != null) {
|
||||
+" Replace with: "
|
||||
code { +replaceWith }
|
||||
}
|
||||
}
|
||||
} else if (summary != null) {
|
||||
tag.div {
|
||||
classes = setOf("doc-comment")
|
||||
|
||||
unsafe { raw(summary) }
|
||||
}
|
||||
}
|
||||
|
||||
if (showSummaryOnly) return
|
||||
|
||||
if (hasMemberInfo) {
|
||||
tag.dl {
|
||||
classes =
|
||||
if (isExpandable && !isDeclaration) {
|
||||
setOf("member-info", "expandable", "hidden", "collapsed")
|
||||
} else {
|
||||
setOf("member-info")
|
||||
}
|
||||
|
||||
for ((key, content) in extraMemberInfo) {
|
||||
dt {
|
||||
classes = key.classes
|
||||
+key.name
|
||||
+":"
|
||||
}
|
||||
dd { content() }
|
||||
}
|
||||
|
||||
if (alsoKnownAsAnnotation != null) {
|
||||
dt { +"Also known as:" }
|
||||
dd {
|
||||
@Suppress("UNCHECKED_CAST") val names = alsoKnownAsAnnotation["names"] as List<String>
|
||||
var first = true
|
||||
for (name in names) {
|
||||
if (first) first = false else +", "
|
||||
code { +name }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (summaryMovesDown || overflow != null) {
|
||||
tag.div {
|
||||
classes = setOf("doc-comment", "expandable", "hidden", "collapsed")
|
||||
|
||||
unsafe {
|
||||
if (summaryMovesDown) raw(summary!!)
|
||||
if (overflow != null) raw(overflow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderInlineMarkdownText(text: String): String {
|
||||
var node = markdownParser.parse(text.trimIndent().trim())
|
||||
|
||||
// unwrap top-level paragraphs because resulting HTML will be used as inline content
|
||||
while (node.firstChild != null && node.firstChild === node.lastChild) {
|
||||
node = node.firstChild
|
||||
}
|
||||
|
||||
return markdownRenderer.render(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
231
pkl-doc/src/main/kotlin/org/pkl/doc/RuntimeDataGenerator.kt
Normal file
231
pkl-doc/src/main/kotlin/org/pkl/doc/RuntimeDataGenerator.kt
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.nio.file.Path
|
||||
import org.pkl.commons.deleteRecursively
|
||||
import org.pkl.core.util.json.JsonWriter
|
||||
|
||||
// Note: we don't currently make use of persisted type alias data (needs more thought).
|
||||
internal class RuntimeDataGenerator(
|
||||
private val descendingVersionComparator: Comparator<String>,
|
||||
private val outputDir: Path
|
||||
) {
|
||||
|
||||
private val packageVersions = mutableMapOf<PackageId, MutableSet<String>>()
|
||||
private val moduleVersions = mutableMapOf<ModuleId, MutableSet<String>>()
|
||||
private val classVersions = mutableMapOf<TypeId, MutableSet<String>>()
|
||||
private val packageUsages = mutableMapOf<PackageRef, MutableSet<PackageRef>>()
|
||||
private val typeUsages = mutableMapOf<TypeRef, MutableSet<TypeRef>>()
|
||||
private val subtypes = mutableMapOf<TypeRef, MutableSet<TypeRef>>()
|
||||
|
||||
fun deleteDataDir() {
|
||||
outputDir.resolve("data").deleteRecursively()
|
||||
}
|
||||
|
||||
fun generate(packages: List<PackageData>) {
|
||||
collectData(packages)
|
||||
writeData(packages)
|
||||
}
|
||||
|
||||
private fun collectData(packages: List<PackageData>) {
|
||||
for (pkg in packages) {
|
||||
packageVersions.add(pkg.ref.pkg, pkg.ref.version)
|
||||
for (dependency in pkg.dependencies) {
|
||||
packageUsages.add(dependency.ref, pkg.ref)
|
||||
}
|
||||
for (module in pkg.modules) {
|
||||
moduleVersions.add(module.ref.id, module.ref.version)
|
||||
if (module.moduleClass != null) {
|
||||
collectData(module.moduleClass)
|
||||
}
|
||||
for (clazz in module.classes) {
|
||||
collectData(clazz)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectData(clazz: ClassData) {
|
||||
classVersions.add(clazz.ref.id, clazz.ref.version)
|
||||
for (superclass in clazz.superclasses) {
|
||||
subtypes.add(superclass, clazz.ref)
|
||||
}
|
||||
for (type in clazz.usedTypes) {
|
||||
typeUsages.add(type, clazz.ref)
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeData(packages: List<PackageData>) {
|
||||
for (pkg in packages) {
|
||||
writePackageFile(pkg.ref)
|
||||
for (mod in pkg.modules) {
|
||||
writeModuleFile(mod.ref)
|
||||
for (clazz in mod.classes) {
|
||||
writeClassFile(clazz.ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writePackageFile(ref: PackageRef) {
|
||||
outputDir.resolve("data/${ref.pkg}/${ref.version}/index.js").jsonWriter().use { writer ->
|
||||
writer.isLenient = true
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_VERSIONS,
|
||||
packageVersions.getOrDefault(ref.pkg, setOf()).sortedWith(descendingVersionComparator),
|
||||
{ it },
|
||||
{ if (it == ref.version) null else ref.copy(version = it).pageUrlRelativeTo(ref) },
|
||||
{ if (it == ref.version) CssConstants.CURRENT_VERSION else null }
|
||||
)
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_USAGES,
|
||||
packageUsages.getOrDefault(ref, setOf()).packagesWithHighestVersions().sortedBy { it.pkg },
|
||||
PackageRef::pkg,
|
||||
{ it.pageUrlRelativeTo(ref) },
|
||||
{ null }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeModuleFile(ref: ModuleRef) {
|
||||
outputDir.resolve("data/${ref.pkg}/${ref.version}/${ref.module}/index.js").jsonWriter().use {
|
||||
writer ->
|
||||
writer.isLenient = true
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_VERSIONS,
|
||||
moduleVersions.getOrDefault(ref.id, setOf()).sortedWith(descendingVersionComparator),
|
||||
{ it },
|
||||
{ if (it == ref.version) null else ref.copy(version = it).pageUrlRelativeTo(ref) },
|
||||
{ if (it == ref.version) CssConstants.CURRENT_VERSION else null }
|
||||
)
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_USAGES,
|
||||
typeUsages.getOrDefault(ref.moduleClassRef, setOf()).typesWithHighestVersions().sortedBy {
|
||||
it.displayName
|
||||
},
|
||||
TypeRef::displayName,
|
||||
{ it.pageUrlRelativeTo(ref) },
|
||||
{ null }
|
||||
)
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_SUBTYPES,
|
||||
subtypes.getOrDefault(ref.moduleClassRef, setOf()).typesWithHighestVersions().sortedBy {
|
||||
it.displayName
|
||||
},
|
||||
TypeRef::displayName,
|
||||
{ it.pageUrlRelativeTo(ref) },
|
||||
{ null }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeClassFile(ref: TypeRef) {
|
||||
outputDir
|
||||
.resolve("data/${ref.pkg}/${ref.version}/${ref.module}/${ref.type}.js")
|
||||
.jsonWriter()
|
||||
.use { writer ->
|
||||
writer.isLenient = true
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_VERSIONS,
|
||||
classVersions.getOrDefault(ref.id, setOf()).sortedWith(descendingVersionComparator),
|
||||
{ it },
|
||||
{ if (it == ref.version) null else ref.copy(version = it).pageUrlRelativeTo(ref) },
|
||||
{ if (it == ref.version) CssConstants.CURRENT_VERSION else null }
|
||||
)
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_USAGES,
|
||||
typeUsages.getOrDefault(ref, setOf()).typesWithHighestVersions().sortedBy {
|
||||
it.displayName
|
||||
},
|
||||
TypeRef::displayName,
|
||||
{ it.pageUrlRelativeTo(ref) },
|
||||
{ null }
|
||||
)
|
||||
writer.writeLinks(
|
||||
HtmlConstants.KNOWN_SUBTYPES,
|
||||
subtypes.getOrDefault(ref, setOf()).typesWithHighestVersions().sortedBy {
|
||||
it.displayName
|
||||
},
|
||||
TypeRef::displayName,
|
||||
{ it.pageUrlRelativeTo(ref) },
|
||||
{ null }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> JsonWriter.writeLinks(
|
||||
// HTML element ID
|
||||
id: String,
|
||||
// items based on which links are generated
|
||||
items: List<T>,
|
||||
// link text
|
||||
text: (T) -> String,
|
||||
// link href
|
||||
href: (T) -> String?,
|
||||
// link CSS classes
|
||||
classes: (T) -> String?
|
||||
) {
|
||||
if (items.isEmpty()) return
|
||||
|
||||
rawText("runtimeData.links('")
|
||||
rawText(id)
|
||||
rawText("','")
|
||||
|
||||
array {
|
||||
for (item in items) {
|
||||
obj {
|
||||
name("text").value(text(item))
|
||||
name("href").value(href(item))
|
||||
name("classes").value(classes(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rawText("');\n")
|
||||
}
|
||||
|
||||
private fun Set<PackageRef>.packagesWithHighestVersions(): Collection<PackageRef> {
|
||||
val highestVersions = mutableMapOf<PackageId, PackageRef>()
|
||||
for (ref in this) {
|
||||
val prev = highestVersions[ref.pkg]
|
||||
if (prev == null || descendingVersionComparator.compare(prev.version, ref.version) > 0) {
|
||||
highestVersions[ref.pkg] = ref
|
||||
}
|
||||
}
|
||||
return highestVersions.values
|
||||
}
|
||||
|
||||
private fun Set<TypeRef>.typesWithHighestVersions(): Collection<TypeRef> {
|
||||
val highestVersions = mutableMapOf<TypeId, TypeRef>()
|
||||
for (ref in this) {
|
||||
val prev = highestVersions[ref.id]
|
||||
if (prev == null || descendingVersionComparator.compare(prev.version, ref.version) > 0) {
|
||||
highestVersions[ref.id] = ref
|
||||
}
|
||||
}
|
||||
return highestVersions.values
|
||||
}
|
||||
|
||||
private fun <K, V> MutableMap<K, MutableSet<V>>.add(key: K, value: V) {
|
||||
val newValue =
|
||||
when (val oldValue = this[key]) {
|
||||
null -> mutableSetOf(value)
|
||||
else -> oldValue.apply { add(value) }
|
||||
}
|
||||
put(key, newValue)
|
||||
}
|
||||
}
|
||||
290
pkl-doc/src/main/kotlin/org/pkl/doc/SearchIndexGenerator.kt
Normal file
290
pkl-doc/src/main/kotlin/org/pkl/doc/SearchIndexGenerator.kt
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.bufferedWriter
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.core.Member
|
||||
import org.pkl.core.PClass.Method
|
||||
import org.pkl.core.PClass.Property
|
||||
import org.pkl.core.PClassInfo
|
||||
import org.pkl.core.PType
|
||||
import org.pkl.core.util.json.JsonWriter
|
||||
|
||||
internal class SearchIndexGenerator(private val outputDir: Path) {
|
||||
fun generateSiteIndex(packagesData: List<PackageData>) {
|
||||
val path = outputDir.resolve("search-index.js").createParentDirectories()
|
||||
path.jsonWriter().use { writer ->
|
||||
writer.apply {
|
||||
// provide data as JSON string rather than JS literal (more flexible and secure)
|
||||
rawText("searchData='")
|
||||
array {
|
||||
for (pkg in packagesData) {
|
||||
val pkgPath = "${pkg.ref.pkg}/current"
|
||||
obj {
|
||||
name("name").value(pkg.ref.pkg)
|
||||
name("kind").value(0)
|
||||
name("url").value("$pkgPath/index.html")
|
||||
if (pkg.deprecation != null) {
|
||||
name("deprecated").value(true)
|
||||
}
|
||||
}
|
||||
|
||||
for (module in pkg.modules) {
|
||||
obj {
|
||||
name("name").value(module.ref.fullName)
|
||||
name("kind").value(1)
|
||||
name("url").value("$pkgPath/${module.ref.module}/index.html")
|
||||
if (module.deprecation != null) {
|
||||
name("deprecated").value(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rawText("';\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generate(docPackage: DocPackage) {
|
||||
val path =
|
||||
outputDir
|
||||
.resolve("${docPackage.name}/${docPackage.version}/search-index.js")
|
||||
.createParentDirectories()
|
||||
JsonWriter(path.bufferedWriter()).use { writer ->
|
||||
writer.apply {
|
||||
serializeNulls = false
|
||||
// provide data as JSON string rather than JS literal (more flexible and secure)
|
||||
rawText("searchData='")
|
||||
var nextId = 0
|
||||
array {
|
||||
for (docModule in docPackage.docModules) {
|
||||
if (docModule.isUnlisted) continue
|
||||
|
||||
val module = docModule.schema
|
||||
val moduleId = nextId
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(module.moduleName)
|
||||
name("kind").value(1)
|
||||
name("url").value("${docModule.path}/index.html")
|
||||
writeAnnotations(module.moduleClass)
|
||||
}
|
||||
|
||||
for ((propertyName, property) in module.moduleClass.properties) {
|
||||
if (property.isUnlisted) continue
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(propertyName)
|
||||
name("kind").value(5)
|
||||
name("url").value("${docModule.path}/index.html#$propertyName")
|
||||
name("sig").value(renderSignature(property))
|
||||
name("parId").value(moduleId)
|
||||
writeAnnotations(property)
|
||||
}
|
||||
}
|
||||
|
||||
for ((methodName, method) in module.moduleClass.methods) {
|
||||
if (method.isUnlisted) continue
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(methodName)
|
||||
name("kind").value(4)
|
||||
name("url").value("${docModule.path}/index.html#$methodName()")
|
||||
name("sig").value(renderSignature(method))
|
||||
name("parId").value(moduleId)
|
||||
writeAnnotations(method)
|
||||
}
|
||||
}
|
||||
|
||||
for ((className, clazz) in module.classes) {
|
||||
if (clazz.isUnlisted) continue
|
||||
|
||||
val classId = nextId
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(className)
|
||||
name("kind").value(3)
|
||||
name("url").value("${docModule.path}/$className.html")
|
||||
name("parId").value(moduleId)
|
||||
writeAnnotations(clazz)
|
||||
}
|
||||
|
||||
for ((propertyName, property) in clazz.properties) {
|
||||
if (property.isUnlisted) continue
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(propertyName)
|
||||
name("kind").value(5)
|
||||
name("url").value("${docModule.path}/$className.html#$propertyName")
|
||||
name("sig").value(renderSignature(property))
|
||||
name("parId").value(classId)
|
||||
writeAnnotations(property)
|
||||
}
|
||||
}
|
||||
|
||||
for ((methodName, method) in clazz.methods) {
|
||||
if (method.isUnlisted) continue
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(methodName)
|
||||
name("kind").value(4)
|
||||
name("url").value("${docModule.path}/$className.html#$methodName()")
|
||||
name("sig").value(renderSignature(method))
|
||||
name("parId").value(classId)
|
||||
writeAnnotations(method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ((typeAliasName, typeAlias) in module.typeAliases) {
|
||||
if (typeAlias.isUnlisted) continue
|
||||
|
||||
nextId += 1
|
||||
obj {
|
||||
name("name").value(typeAliasName)
|
||||
name("kind").value(2)
|
||||
name("url").value("${docModule.path}/index.html#$typeAliasName")
|
||||
name("parId").value(moduleId)
|
||||
writeAnnotations(typeAlias)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rawText("';\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderSignature(method: Method): String =
|
||||
StringBuilder()
|
||||
.apply {
|
||||
append('(')
|
||||
var first = true
|
||||
for ((name, _) in method.parameters) {
|
||||
if (first) first = false else append(", ")
|
||||
append(name)
|
||||
}
|
||||
append(')')
|
||||
append(": ")
|
||||
appendType(method.returnType)
|
||||
}
|
||||
.toString()
|
||||
|
||||
private fun renderSignature(property: Property): String =
|
||||
StringBuilder()
|
||||
.apply {
|
||||
append(": ")
|
||||
appendType(property.type)
|
||||
}
|
||||
.toString()
|
||||
|
||||
private fun StringBuilder.appendType(type: PType) {
|
||||
when (type) {
|
||||
PType.UNKNOWN -> {
|
||||
append("unknown")
|
||||
}
|
||||
PType.NOTHING -> {
|
||||
append("nothing")
|
||||
}
|
||||
PType.MODULE -> {
|
||||
append("module")
|
||||
}
|
||||
is PType.StringLiteral -> {
|
||||
append("\\\"${type.literal}\\\"")
|
||||
}
|
||||
is PType.Class -> {
|
||||
val pClass = type.pClass
|
||||
val name =
|
||||
if (pClass.isModuleClass) {
|
||||
// use simple module name rather than class name (which is always `ModuleClass`)
|
||||
pClass.moduleName.substring(pClass.moduleName.lastIndexOf('.') + 1)
|
||||
} else {
|
||||
pClass.simpleName
|
||||
}
|
||||
append(name)
|
||||
if (type.typeArguments.isNotEmpty()) {
|
||||
append('<')
|
||||
var first = true
|
||||
for (typeArg in type.typeArguments) {
|
||||
if (first) first = false else append(", ")
|
||||
appendType(typeArg)
|
||||
}
|
||||
append('>')
|
||||
}
|
||||
}
|
||||
is PType.Constrained -> appendType(type.baseType)
|
||||
is PType.Union -> {
|
||||
var first = true
|
||||
for (elemType in type.elementTypes) {
|
||||
if (first) first = false else append("|")
|
||||
appendType(elemType)
|
||||
}
|
||||
}
|
||||
is PType.Nullable -> {
|
||||
appendType(type.baseType)
|
||||
append("?")
|
||||
}
|
||||
is PType.Function -> {
|
||||
if (type.parameterTypes.size == 1) {
|
||||
appendType(type.parameterTypes[0])
|
||||
} else {
|
||||
append('(')
|
||||
var first = true
|
||||
for (paramType in type.parameterTypes) {
|
||||
if (first) first = false else append(", ")
|
||||
appendType(paramType)
|
||||
}
|
||||
append(')')
|
||||
}
|
||||
|
||||
append(" -> ")
|
||||
appendType(type.returnType)
|
||||
}
|
||||
is PType.Alias -> append(type.typeAlias.simpleName)
|
||||
is PType.TypeVariable -> append(type.typeParameter.name)
|
||||
else -> throw AssertionError("Unknown PType: $type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun JsonWriter.writeAnnotations(member: Member?): JsonWriter {
|
||||
if (member == null) return this
|
||||
|
||||
if (member.annotations.any { it.classInfo == PClassInfo.Deprecated }) {
|
||||
name("deprecated")
|
||||
value(true)
|
||||
}
|
||||
|
||||
member.annotations
|
||||
.find { it.classInfo == PClassInfo.AlsoKnownAs }
|
||||
?.let { alsoKnownAs ->
|
||||
name("aka")
|
||||
array {
|
||||
@Suppress("UNCHECKED_CAST") for (name in alsoKnownAs["names"] as List<String>) value(name)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
}
|
||||
39
pkl-doc/src/main/kotlin/org/pkl/doc/Serializers.kt
Normal file
39
pkl-doc/src/main/kotlin/org/pkl/doc/Serializers.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.net.URI
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.encoding.*
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import kotlinx.serialization.modules.contextual
|
||||
import org.pkl.commons.toUri
|
||||
|
||||
val serializers: SerializersModule = SerializersModule { contextual(UriSerializer) }
|
||||
|
||||
object UriSerializer : KSerializer<URI> {
|
||||
override val descriptor: SerialDescriptor =
|
||||
PrimitiveSerialDescriptor("java.net.URI", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: URI) {
|
||||
encoder.encodeString(value.toString())
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): URI {
|
||||
return decoder.decodeString().toUri()
|
||||
}
|
||||
}
|
||||
116
pkl-doc/src/main/kotlin/org/pkl/doc/Util.kt
Normal file
116
pkl-doc/src/main/kotlin/org/pkl/doc/Util.kt
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.doc
|
||||
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.bufferedWriter
|
||||
import kotlin.io.path.outputStream
|
||||
import org.pkl.commons.createParentDirectories
|
||||
import org.pkl.core.*
|
||||
import org.pkl.core.util.json.JsonWriter
|
||||
|
||||
// overwrites any existing file
|
||||
internal fun copyResource(resourceName: String, targetDir: Path) {
|
||||
val targetFile = targetDir.resolve(resourceName).apply { createParentDirectories() }
|
||||
getResourceAsStream(resourceName).use { sourceStream ->
|
||||
targetFile.outputStream().use { targetStream -> sourceStream.copyTo(targetStream) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getResourceAsStreamOrNull(resourceName: String): InputStream? =
|
||||
Thread.currentThread().contextClassLoader.getResourceAsStream("org/pkl/doc/$resourceName")
|
||||
|
||||
internal fun getResourceAsStream(resourceName: String): InputStream =
|
||||
getResourceAsStreamOrNull(resourceName)
|
||||
?: throw DocGeneratorException("Failed to load class path resource `$resourceName`.")
|
||||
|
||||
internal val ModuleSchema?.hasListedClass: Boolean
|
||||
get() = this != null && allClasses.any { !it.value.isUnlisted }
|
||||
|
||||
internal val ModuleSchema?.hasListedTypeAlias: Boolean
|
||||
get() = this != null && allTypeAliases.any { !it.value.isUnlisted }
|
||||
|
||||
internal val PClass?.hasListedProperty: Boolean
|
||||
get() = this != null && allProperties.any { !it.value.isUnlisted }
|
||||
|
||||
internal val PClass?.hasListedMethod: Boolean
|
||||
get() = this != null && allMethods.any { !it.value.isUnlisted }
|
||||
|
||||
internal val Member.isUnlisted: Boolean
|
||||
get() = annotations.isUnlisted
|
||||
|
||||
internal val List<PObject>.isUnlisted: Boolean
|
||||
get() = any { it.classInfo == PClassInfo.Unlisted }
|
||||
|
||||
internal val List<PObject>.deprecation: String?
|
||||
get() = find { it.classInfo == PClassInfo.Deprecated }?.get("message") as String?
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal val List<PObject>.alsoKnownAs: List<String>?
|
||||
get() = find { it.classInfo == PClassInfo.AlsoKnownAs }?.get("names") as List<String>?
|
||||
|
||||
internal fun createDeprecatedAnnotation(message: String): PObject =
|
||||
PObject(PClassInfo.Deprecated, mapOf("message" to message, "replaceWith" to PNull.getInstance()))
|
||||
|
||||
private val paragraphSeparatorRegex: Regex = Regex("(?m:^\\s*(`{3,}\\w*)?\\s*\n)")
|
||||
|
||||
internal fun getDocCommentSummary(docComment: String?): String? {
|
||||
if (docComment == null) return null
|
||||
|
||||
return when (val match = paragraphSeparatorRegex.find(docComment)) {
|
||||
null -> docComment.trim().ifEmpty { null }
|
||||
else -> docComment.substring(0, match.range.first).trim().ifEmpty { null }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getDocCommentOverflow(docComment: String?): String? {
|
||||
if (docComment == null) return null
|
||||
|
||||
return when (val match = paragraphSeparatorRegex.find(docComment)) {
|
||||
null -> null
|
||||
else -> {
|
||||
val index = if (match.groups[1] != null) match.range.first else match.range.last + 1
|
||||
docComment.substring(index).trim().ifEmpty { null }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Path.jsonWriter(): JsonWriter {
|
||||
createParentDirectories()
|
||||
return JsonWriter(bufferedWriter()).apply { serializeNulls = false }
|
||||
}
|
||||
|
||||
internal inline fun JsonWriter.obj(body: JsonWriter.() -> Unit) {
|
||||
beginObject()
|
||||
body()
|
||||
endObject()
|
||||
}
|
||||
|
||||
internal inline fun JsonWriter.array(body: JsonWriter.() -> Unit) {
|
||||
beginArray()
|
||||
body()
|
||||
endArray()
|
||||
}
|
||||
|
||||
internal fun String.replaceSourceCodePlaceholders(
|
||||
path: String,
|
||||
sourceLocation: Member.SourceLocation
|
||||
): String {
|
||||
return replace("%{path}", path)
|
||||
.replace("%{line}", sourceLocation.startLine.toString())
|
||||
.replace("%{endLine}", sourceLocation.endLine.toString())
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
pkl-doc/src/main/resources/org/pkl/doc/images/favicon-16x16.png
Normal file
BIN
pkl-doc/src/main/resources/org/pkl/doc/images/favicon-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 780 B |
BIN
pkl-doc/src/main/resources/org/pkl/doc/images/favicon-32x32.png
Normal file
BIN
pkl-doc/src/main/resources/org/pkl/doc/images/favicon-32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
23
pkl-doc/src/main/resources/org/pkl/doc/images/favicon.svg
Normal file
23
pkl-doc/src/main/resources/org/pkl/doc/images/favicon.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100.58 98.63">
|
||||
<path d="m75.57,19.78l2.43-13.25c-3.69-2.46-7.7-4.42-11.91-5.83l-8.97,10.05c-4.37-.8-8.85-.83-13.23-.08L35.03.5c-4.23,1.35-8.26,3.26-11.99,5.68l2.26,13.28c-3.35,2.92-6.17,6.4-8.32,10.3l-13.46.58c-1.58,4.15-2.6,8.49-3.03,12.91l11.8,6.51c.19,4.44,1.16,8.81,2.86,12.92l-7.94,10.89c2.26,3.82,5.02,7.33,8.2,10.42l12.45-5.16c3.59,2.62,7.62,4.59,11.89,5.82l3.56,13c4.4.62,8.86.64,13.26.08l3.72-12.95c4.29-1.17,8.34-3.09,11.96-5.67l12.38,5.32c3.22-3.05,6.03-6.52,8.33-10.32l-7.8-10.99c1.75-4.08,2.78-8.45,3.03-12.88l11.88-6.36c-.38-4.42-1.34-8.78-2.87-12.95l-13.45-.75c-2.1-3.92-4.87-7.44-8.19-10.4Z"
|
||||
style="fill:#6b9543; stroke-width:0px;"/>
|
||||
<circle cx="51.05" cy="47.72" r="31.49" style="fill:#e9f4ca; stroke-width:0px;"/>
|
||||
<g id="_Radial_Repeat_">
|
||||
<path d="m28.79,62.54c8.22,14.22,24.82,18.97,20.85-10.47h0c-.31-2.29-1.56-4.35-3.45-5.68-24.66-17.36-26.37.64-17.4,16.15Zm15.42-8.25h0c.7-.17,1.24.13,1.49.83,3.27,9.16-2.6,12.49-6.71,10.44-3.77-1.88-3.77-9.01,5.22-11.27Zm-2.14-5.45c.48.57.47,1.19-.03,1.7h0c-6.44,6.67-12.62,3.1-12.37-1.09.27-4.58,6.09-8.01,12.4-.61Z"
|
||||
style="fill:#c8d987; stroke-width:0px;"/>
|
||||
<ellipse cx="38.62" cy="55.01" rx="7.64" ry="14.03" transform="translate(-22.33 26.68) rotate(-30)"
|
||||
style="fill:#c8d987; stroke-width:0px;"/>
|
||||
</g>
|
||||
<g id="_Radial_Repeat_-2">
|
||||
<path d="m49.34,21.03c-16.42.01-28.84,12.01-1.36,23.29h0c2.14.88,4.54.82,6.64-.15,27.37-12.67,12.63-23.16-5.29-23.15Zm-.56,17.48h0c-.2.69-.73,1.01-1.46.88-9.57-1.75-9.52-8.5-5.69-11.03,3.51-2.32,9.69,1.24,7.15,10.16Zm5.79.87c-.73.13-1.27-.18-1.46-.88h0c-2.56-8.91,3.62-12.48,7.13-10.17,3.83,2.53,3.9,9.28-5.67,11.04Z"
|
||||
style="fill:#c8d987; stroke-width:0px;"/>
|
||||
<ellipse cx="50.94" cy="33.31" rx="14.03" ry="7.64" style="fill:#c8d987; stroke-width:0px;"/>
|
||||
</g>
|
||||
<g id="_Radial_Repeat_-3">
|
||||
<path d="m75.02,59.59c8.2-14.23,4.02-30.98-19.5-12.82h0c-1.83,1.41-2.99,3.52-3.19,5.83-2.71,30.04,13.74,22.52,22.69,7Zm-14.86-9.23h0c-.5-.52-.51-1.14-.03-1.7,6.3-7.41,12.12-3.99,12.4.59.26,4.2-5.92,7.77-12.37,1.11Zm-3.65,4.58c.25-.7.79-1,1.49-.83h0c8.99,2.24,9,9.38,5.24,11.26-4.1,2.05-9.98-1.26-6.73-10.43Z"
|
||||
style="fill:#c8d987; stroke-width:0px;"/>
|
||||
<ellipse cx="63.58" cy="54.83" rx="14.03" ry="7.64" transform="translate(-15.7 82.48) rotate(-60)"
|
||||
style="fill:#c8d987; stroke-width:0px;"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
718
pkl-doc/src/main/resources/org/pkl/doc/scripts/pkldoc.js
Normal file
718
pkl-doc/src/main/resources/org/pkl/doc/scripts/pkldoc.js
Normal file
@@ -0,0 +1,718 @@
|
||||
// noinspection DuplicatedCode
|
||||
|
||||
'use strict';
|
||||
|
||||
// Whether the current browser is WebKit.
|
||||
let isWebKitBrowser;
|
||||
|
||||
// The lazily initialized worker for running searches, if any.
|
||||
let searchWorker = null;
|
||||
|
||||
// Tells whether non-worker search is ready for use.
|
||||
// Only relevant if we determined that we can't use a worker.
|
||||
let nonWorkerSearchInitialized = false;
|
||||
|
||||
// The search div containing search input and search results.
|
||||
let searchElement;
|
||||
|
||||
// The search input element.
|
||||
let searchInput;
|
||||
|
||||
// The package name associated with the current page, if any.
|
||||
let packageName;
|
||||
|
||||
let packageVersion;
|
||||
|
||||
// The module name associated with the current page, if any.
|
||||
let moduleName;
|
||||
|
||||
// The class name associated with the current page, if any.
|
||||
let className;
|
||||
|
||||
// Prefix to turn a site-relative URL into a page-relative URL.
|
||||
// One of "", "../", "../../", etc.
|
||||
let rootUrlPrefix;
|
||||
|
||||
// Prefix to turn a package-relative URL into a page-relative URL.
|
||||
// One of "", "../", "../../", etc.
|
||||
let packageUrlPrefix;
|
||||
|
||||
// The search result currently selected in the search results list.
|
||||
let selectedSearchResult = null;
|
||||
|
||||
// Initializes the UI.
|
||||
// Wrapped in a function to avoid execution in tests.
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
function onLoad() {
|
||||
isWebKitBrowser = navigator.userAgent.indexOf('AppleWebKit') !== -1;
|
||||
searchElement = document.getElementById('search');
|
||||
searchInput = document.getElementById('search-input');
|
||||
packageName = searchInput.dataset.packageName || null;
|
||||
packageVersion = searchInput.dataset.packageVersion || null;
|
||||
moduleName = searchInput.dataset.moduleName || null;
|
||||
className = searchInput.dataset.className || null;
|
||||
rootUrlPrefix = searchInput.dataset.rootUrlPrefix;
|
||||
packageUrlPrefix = searchInput.dataset.packageUrlPrefix;
|
||||
|
||||
initExpandTargetMemberDocs();
|
||||
initNavigateToMemberPage();
|
||||
initToggleMemberDocs();
|
||||
initToggleInheritedMembers();
|
||||
initCopyModuleUriToClipboard();
|
||||
initSearchUi();
|
||||
}
|
||||
|
||||
// If page URL contains a fragment, expand the target member's docs.
|
||||
// Handled in JS rather than CSS so that target member can still be manually collapsed.
|
||||
function initExpandTargetMemberDocs() {
|
||||
const expandTargetDocs = () => {
|
||||
const hash = window.location.hash;
|
||||
if (hash.length === 0) return;
|
||||
|
||||
const target = document.getElementById(hash.substring(1));
|
||||
if (!target) return;
|
||||
|
||||
const member = target.nextElementSibling;
|
||||
if (!member || !member.classList.contains('with-expandable-docs')) return;
|
||||
|
||||
expandMemberDocs(member);
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', expandTargetDocs);
|
||||
expandTargetDocs();
|
||||
}
|
||||
|
||||
// For members that have their own page, navigate to that page when the member's box is clicked.
|
||||
function initNavigateToMemberPage() {
|
||||
const elements = document.getElementsByClassName('with-page-link');
|
||||
for (const element of elements) {
|
||||
const memberLink = element.getElementsByClassName('name-decl')[0];
|
||||
// check if this is actually a link
|
||||
// (it isn't if the generator couldn't resolve the link target)
|
||||
if (memberLink.tagName === 'A') {
|
||||
element.addEventListener('click', (e) => {
|
||||
// don't act if user clicked a link
|
||||
if (e.target !== null && e.target.closest('a') !== null) return;
|
||||
|
||||
// don't act if user clicked to select some text
|
||||
if (window.getSelection().toString()) return;
|
||||
|
||||
memberLink.click();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expands and collapses member docs.
|
||||
function initToggleMemberDocs() {
|
||||
const elements = document.getElementsByClassName('with-expandable-docs');
|
||||
for (const element of elements) {
|
||||
element.addEventListener('click', (e) => {
|
||||
// don't act if user clicked a link
|
||||
if (e.target !== null && e.target.closest('a') !== null) return;
|
||||
|
||||
// don't act if user clicked to select some text
|
||||
if (window.getSelection().toString()) return;
|
||||
|
||||
toggleMemberDocs(element);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Shows and hides inherited members.
|
||||
function initToggleInheritedMembers() {
|
||||
const memberGroups = document.getElementsByClassName('member-group');
|
||||
for (const group of memberGroups) {
|
||||
const button = group.getElementsByClassName('toggle-inherited-members-link')[0];
|
||||
if (button !== undefined) {
|
||||
const members = group.getElementsByClassName('inherited');
|
||||
button.addEventListener('click', () => toggleInheritedMembers(button, members));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copies the module URI optionally displayed on a module page to the clipboard.
|
||||
function initCopyModuleUriToClipboard() {
|
||||
const copyUriButtons = document.getElementsByClassName('copy-uri-button');
|
||||
|
||||
for (const button of copyUriButtons) {
|
||||
const moduleUri = button.previousElementSibling;
|
||||
|
||||
button.addEventListener('click', e => {
|
||||
e.stopPropagation();
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(moduleUri);
|
||||
const selection = getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
} catch (e) {
|
||||
} finally {
|
||||
selection.removeAllRanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Expands or collapses member docs.
|
||||
function toggleMemberDocs(memberElem) {
|
||||
const comments = memberElem.getElementsByClassName('expandable');
|
||||
const icon = memberElem.getElementsByClassName('expandable-docs-icon')[0];
|
||||
const isCollapsed = icon.textContent === 'expand_more';
|
||||
|
||||
if (isCollapsed) {
|
||||
for (const comment of comments) expandElement(comment);
|
||||
icon.textContent = 'expand_less';
|
||||
} else {
|
||||
for (const comment of comments) collapseElement(comment);
|
||||
icon.textContent = 'expand_more';
|
||||
}
|
||||
}
|
||||
|
||||
// Expands member docs unless they are already expanded.
|
||||
function expandMemberDocs(memberElem) {
|
||||
const icon = memberElem.getElementsByClassName('expandable-docs-icon')[0];
|
||||
const isCollapsed = icon.textContent === 'expand_more';
|
||||
|
||||
if (!isCollapsed) return;
|
||||
|
||||
const comments = memberElem.getElementsByClassName('expandable');
|
||||
for (const comment of comments) expandElement(comment);
|
||||
icon.textContent = 'expand_less';
|
||||
}
|
||||
|
||||
// Shows and hides inherited members.
|
||||
function toggleInheritedMembers(button, members) {
|
||||
const isCollapsed = button.textContent === 'show inherited';
|
||||
|
||||
if (isCollapsed) {
|
||||
for (const member of members) expandElement(member);
|
||||
button.textContent = 'hide inherited';
|
||||
} else {
|
||||
for (const member of members) collapseElement(member);
|
||||
button.textContent = 'show inherited'
|
||||
}
|
||||
}
|
||||
|
||||
// Expands an element.
|
||||
// Done in two steps to make transition work (can't transition from 'hidden').
|
||||
// For some reason (likely related to removing 'hidden') the transition isn't animated in FF.
|
||||
// When using timeout() instead of requestAnimationFrame()
|
||||
// there is *some* animation in FF but still doesn't look right.
|
||||
function expandElement(element) {
|
||||
element.classList.remove('hidden');
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
element.classList.remove('collapsed');
|
||||
});
|
||||
}
|
||||
|
||||
// Collapses an element.
|
||||
// Done in two steps to make transition work (can't transition to 'hidden').
|
||||
function collapseElement(element) {
|
||||
element.classList.add('collapsed');
|
||||
|
||||
const listener = () => {
|
||||
element.removeEventListener('transitionend', listener);
|
||||
element.classList.add('hidden');
|
||||
};
|
||||
element.addEventListener('transitionend', listener);
|
||||
}
|
||||
|
||||
// Initializes the search UI and sets up delayed initialization of the search engine.
|
||||
function initSearchUi() {
|
||||
// initialize search engine the first time that search input receives focus
|
||||
const onFocus = () => {
|
||||
searchInput.removeEventListener('focus', onFocus);
|
||||
initSearchWorker();
|
||||
};
|
||||
searchInput.addEventListener('focus', onFocus);
|
||||
|
||||
// clear search when search input loses focus,
|
||||
// except if this happens due to a search result being clicked,
|
||||
// in which case clearSearch() will be called by the link's click handler,
|
||||
// and calling it here would prevent the click handler from firing
|
||||
searchInput.addEventListener('focusout', () => {
|
||||
if (document.querySelector('#search-results:hover') === null) clearSearch();
|
||||
});
|
||||
|
||||
// trigger search when user hasn't typed in a while
|
||||
let timeoutId = null;
|
||||
// Using anything other than `overflow: visible` for `#search-results`
|
||||
// slows down painting significantly in WebKit browsers (at least Safari/Mac).
|
||||
// Compensate by using a higher search delay, which is less annoying than a blocking UI.
|
||||
const delay = isWebKitBrowser ? 200 : 100;
|
||||
searchInput.addEventListener('input', () => {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => triggerSearch(searchInput.value), delay);
|
||||
});
|
||||
|
||||
// keyboard shortcut for entering search
|
||||
document.addEventListener('keyup', e => {
|
||||
// could additionally support '/' like GitHub and Gmail do,
|
||||
// but this would require overriding the default behavior of '/' on Firefox
|
||||
if (e.key === 's') searchInput.focus();
|
||||
});
|
||||
|
||||
// keyboard navigation for search results
|
||||
searchInput.addEventListener('keydown', e => {
|
||||
const results = document.getElementById('search-results');
|
||||
if (results !== null) {
|
||||
if (e.key === 'ArrowDown') {
|
||||
selectNextResult(results.firstElementChild);
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
selectPrevResult(results.firstElementChild);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
searchInput.addEventListener('keyup', e => {
|
||||
if (e.key === 'Enter' && selectedSearchResult !== null) {
|
||||
selectedSearchResult.firstElementChild.click();
|
||||
clearSearch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initializes the search worker.
|
||||
function initSearchWorker() {
|
||||
const workerScriptUrl = rootUrlPrefix + 'scripts/search-worker.js';
|
||||
|
||||
try {
|
||||
searchWorker = new Worker(workerScriptUrl, {name: packageName === null ? "main" : packageName + '/' + packageVersion});
|
||||
searchWorker.addEventListener('message', e => handleSearchResults(e.data.query, e.data.results));
|
||||
} catch (e) {
|
||||
// could not initialize worker, presumably because we are a file:/// page and content security policy got in the way
|
||||
// fall back to running searches synchronously without a worker
|
||||
// this requires loading search related scripts that would otherwise be loaded by the worker
|
||||
|
||||
searchWorker = null;
|
||||
let pendingScripts = 3;
|
||||
|
||||
const onScriptLoaded = () => {
|
||||
if (--pendingScripts === 0) {
|
||||
initSearchIndex();
|
||||
nonWorkerSearchInitialized = true;
|
||||
if (searchInput.focused) {
|
||||
triggerSearch(searchInput.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const script1 = document.createElement('script');
|
||||
script1.src = (packageName === null ? rootUrlPrefix : packageUrlPrefix) + 'search-index.js';
|
||||
script1.async = true;
|
||||
script1.onload = onScriptLoaded;
|
||||
document.head.append(script1);
|
||||
|
||||
const script2 = document.createElement('script');
|
||||
script2.src = rootUrlPrefix;
|
||||
script2.async = true;
|
||||
script2.onload = onScriptLoaded;
|
||||
document.head.append(script2);
|
||||
|
||||
const script3 = document.createElement('script');
|
||||
script3.src = workerScriptUrl;
|
||||
script3.async = true;
|
||||
script3.onload = onScriptLoaded;
|
||||
document.head.append(script3);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates search results unless they are stale.
|
||||
function handleSearchResults(query, results) {
|
||||
if (query.inputValue !== searchInput.value) return;
|
||||
|
||||
updateSearchResults(renderSearchResults(query, results));
|
||||
}
|
||||
|
||||
// TODO: Should this (or its callers) use requestAnimationFrame() ?
|
||||
// Removes any currently displayed search results, then displays the given results if non-null.
|
||||
function updateSearchResults(resultsDiv) {
|
||||
selectedSearchResult = null;
|
||||
|
||||
const oldResultsDiv = document.getElementById('search-results');
|
||||
if (oldResultsDiv !== null) {
|
||||
searchElement.removeChild(oldResultsDiv);
|
||||
}
|
||||
|
||||
if (resultsDiv != null) {
|
||||
searchElement.append(resultsDiv);
|
||||
selectNextResult(resultsDiv.firstElementChild);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the module of the given member, or `null` if the given member is a module.
|
||||
function getModule(member) {
|
||||
switch (member.level) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return member.parent;
|
||||
case 2:
|
||||
return member.parent.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Triggers a search unless search input is invalid or incomplete.
|
||||
function triggerSearch(inputValue) {
|
||||
const query = parseSearchInput(inputValue);
|
||||
if (!isActionableQuery(query)) {
|
||||
handleSearchResults(query, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchWorker !== null) {
|
||||
searchWorker.postMessage({query, packageName, moduleName, className});
|
||||
} else if (nonWorkerSearchInitialized) {
|
||||
const results = runSearch(query, packageName, moduleName, className);
|
||||
handleSearchResults(query, results);
|
||||
}
|
||||
}
|
||||
|
||||
// Tells if the given Unicode character is a whitespace character.
|
||||
function isWhitespace(ch) {
|
||||
const cp = ch.codePointAt(0);
|
||||
if (cp >= 9 && cp <= 13 || cp === 32 || cp === 133 || cp === 160) return true;
|
||||
if (cp < 5760) return false;
|
||||
return cp === 5760 || cp >= 8192 && cp <= 8202
|
||||
|| cp === 8232 || cp === 8233 || cp === 8239 || cp === 8287 || cp === 12288;
|
||||
}
|
||||
|
||||
// Trims the given Unicode characters.
|
||||
function trim(chars) {
|
||||
const length = chars.length;
|
||||
let startIdx, endIdx;
|
||||
|
||||
for (startIdx = 0; startIdx < length; startIdx += 1) {
|
||||
if (!isWhitespace(chars[startIdx])) break;
|
||||
}
|
||||
for (endIdx = chars.length - 1; endIdx > startIdx; endIdx -= 1) {
|
||||
if (!isWhitespace(chars[endIdx])) break;
|
||||
}
|
||||
return chars.slice(startIdx, endIdx + 1);
|
||||
}
|
||||
|
||||
// Parses the user provided search input.
|
||||
// Preconditions:
|
||||
// inputValue !== ''
|
||||
function parseSearchInput(inputValue) {
|
||||
const chars = trim(Array.from(inputValue));
|
||||
const char0 = chars[0]; // may be undefined
|
||||
const char1 = chars[1]; // may be undefined
|
||||
const prefix = char1 === ':' ? char0 + char1 : null;
|
||||
const kind =
|
||||
prefix === null ? null :
|
||||
char0 === 'm' ? 1 :
|
||||
char0 === 't' ? 2 :
|
||||
char0 === 'c' ? 3 :
|
||||
char0 === 'f' ? 4 :
|
||||
char0 === 'p' ? 5 :
|
||||
undefined;
|
||||
const unprefixedChars = kind !== null && kind !== undefined ?
|
||||
trim(chars.slice(2, chars.length)) :
|
||||
chars;
|
||||
const normalizedCps = toNormalizedCodePoints(unprefixedChars);
|
||||
return {inputValue, prefix, kind, normalizedCps};
|
||||
}
|
||||
|
||||
// Converts a Unicode character array to an array of normalized Unicode code points.
|
||||
// Normalization turns characters into their base forms, e.g., é into e.
|
||||
// Since JS doesn't support case folding, `toLocaleLowerCase()` is used instead.
|
||||
// Note: Keep in sync with same function in search-worker.js.
|
||||
function toNormalizedCodePoints(characters) {
|
||||
return Uint32Array.from(characters, ch => ch.normalize('NFD')[0].toLocaleLowerCase().codePointAt(0));
|
||||
}
|
||||
|
||||
// Tells if the given query is valid and long enough to be worth running.
|
||||
// Prefixed queries require fewer minimum characters than unprefixed queries.
|
||||
// This avoids triggering a search while typing a prefix yet still enables searching for single-character names.
|
||||
// For example, `p:e` finds `pkl.math#E`.
|
||||
function isActionableQuery(query) {
|
||||
const kind = query.kind;
|
||||
const queryCps = query.normalizedCps;
|
||||
return kind !== undefined && (kind !== null && queryCps.length > 0 || queryCps.length > 1);
|
||||
}
|
||||
|
||||
// Renders the given search results for the given query.
|
||||
// Preconditions:
|
||||
// isActionableQuery(query) ? results !== null : results === null
|
||||
function renderSearchResults(query, results) {
|
||||
const resultsDiv = document.createElement('div');
|
||||
resultsDiv.id = 'search-results';
|
||||
const ul = document.createElement('ul');
|
||||
resultsDiv.append(ul);
|
||||
|
||||
if (results === null) {
|
||||
if (query.kind !== undefined) return null;
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.className = 'heading';
|
||||
li.textContent = 'Unknown search prefix. Use one of <b>m:</b> (module), <b>c:</b> (class), <b>f:</b> (function), or <b>p:</b> (property).';
|
||||
ul.append(li);
|
||||
return resultsDiv;
|
||||
}
|
||||
|
||||
const {exactMatches, classMatches, moduleMatches, otherMatches} = results;
|
||||
|
||||
if (exactMatches.length + classMatches.length + moduleMatches.length + otherMatches.length === 0) {
|
||||
renderHeading('No results found', ul);
|
||||
return resultsDiv;
|
||||
}
|
||||
|
||||
if (exactMatches.length > 0) {
|
||||
renderHeading('Top hits', ul);
|
||||
renderMembers(query.normalizedCps, exactMatches, ul);
|
||||
}
|
||||
if (classMatches.length > 0) {
|
||||
renderHeading('Class', ul, className);
|
||||
renderMembers(query.normalizedCps, classMatches, ul);
|
||||
}
|
||||
if (moduleMatches.length > 0) {
|
||||
renderHeading('Module', ul, moduleName);
|
||||
renderMembers(query.normalizedCps, moduleMatches, ul);
|
||||
}
|
||||
if (otherMatches.length > 0) {
|
||||
renderHeading('Other results', ul);
|
||||
renderMembers(query.normalizedCps, otherMatches, ul);
|
||||
}
|
||||
|
||||
return resultsDiv;
|
||||
}
|
||||
|
||||
// Adds a heading such as `Top matches` to the search results list.
|
||||
function renderHeading(title, ul, name = null) {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'heading';
|
||||
li.append(title);
|
||||
if (name != null) {
|
||||
li.append(' ');
|
||||
li.append(span('heading-name', name))
|
||||
}
|
||||
ul.append(li);
|
||||
}
|
||||
|
||||
// Adds matching members to the search results list.
|
||||
function renderMembers(queryCps, members, ul) {
|
||||
for (const member of members) {
|
||||
ul.append(renderMember(queryCps, member));
|
||||
}
|
||||
}
|
||||
|
||||
// Renders a member to be added to the search result list.
|
||||
function renderMember(queryCps, member) {
|
||||
const result = document.createElement('li');
|
||||
result.className = 'result';
|
||||
if (member.deprecated) result.className = 'deprecated';
|
||||
|
||||
const link = document.createElement('a');
|
||||
result.append(link);
|
||||
|
||||
link.href = (packageName === null ? rootUrlPrefix : packageUrlPrefix) + member.url;
|
||||
link.addEventListener('mousedown', () => selectResult(result));
|
||||
link.addEventListener('click', clearSearch);
|
||||
|
||||
const keyword = getKindKeyword(member.kind);
|
||||
// noinspection JSValidateTypes (IntelliJ bug?)
|
||||
if (keyword !== null) {
|
||||
link.append(span('keyword', keyword), ' ');
|
||||
}
|
||||
|
||||
// prefix with class name if a class member
|
||||
if (member.level === 2) {
|
||||
link.append(span("context", member.parent.name + '.'));
|
||||
}
|
||||
|
||||
const name = span('result-name');
|
||||
if (member.matchNameIdx === 0) { // main name matched
|
||||
highlightMatch(queryCps, member.names[0], member.matchStartIdx, name);
|
||||
} else { // aka name matched
|
||||
name.append(member.name);
|
||||
}
|
||||
link.append(name);
|
||||
|
||||
if (member.signature !== null) {
|
||||
link.append(member.signature);
|
||||
}
|
||||
|
||||
if (member.matchNameIdx > 0) { // aka name matched
|
||||
link.append(' ');
|
||||
const aka = span('aka');
|
||||
aka.append('(known as: ');
|
||||
const name = span('aka-name');
|
||||
highlightMatch(queryCps, member.names[member.matchNameIdx], member.matchStartIdx, name);
|
||||
aka.append(name, ')');
|
||||
link.append(aka);
|
||||
}
|
||||
|
||||
// add module name if not a module
|
||||
const module = getModule(member);
|
||||
if (module !== null) {
|
||||
link.append(' ', span('context', '(' + module.name + ')'));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the keyword for the given member kind.
|
||||
function getKindKeyword(kind) {
|
||||
switch (kind) {
|
||||
case 0:
|
||||
return "package";
|
||||
case 1:
|
||||
return "module";
|
||||
case 2:
|
||||
return "typealias";
|
||||
case 3:
|
||||
return "class";
|
||||
case 4:
|
||||
return "function";
|
||||
case 5:
|
||||
// properties have no keyword
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Highlights the matching characters in a member name.
|
||||
// Preconditions:
|
||||
// queryCps.length > 0
|
||||
// computeMatchFrom(queryCps, name.normalizedCps, name.wordStarts, matchStartIdx)
|
||||
function highlightMatch(queryCps, name, matchStartIdx, parentElem) {
|
||||
const queryLength = queryCps.length;
|
||||
const codePoints = name.codePoints;
|
||||
const nameCps = name.normalizedCps;
|
||||
const nameLength = nameCps.length;
|
||||
const wordStarts = name.wordStarts;
|
||||
|
||||
let queryIdx = 0;
|
||||
let queryCp = queryCps[0];
|
||||
let startIdx = matchStartIdx;
|
||||
|
||||
if (startIdx > 0) {
|
||||
parentElem.append(String.fromCodePoint(...codePoints.subarray(0, startIdx)));
|
||||
}
|
||||
|
||||
for (let nameIdx = startIdx; nameIdx < nameLength; nameIdx += 1) {
|
||||
const nameCp = nameCps[nameIdx];
|
||||
|
||||
if (queryCp !== nameCp) {
|
||||
const newNameIdx = wordStarts[nameIdx];
|
||||
parentElem.append(
|
||||
span('highlight', String.fromCodePoint(...codePoints.subarray(startIdx, nameIdx))));
|
||||
startIdx = newNameIdx;
|
||||
parentElem.append(String.fromCodePoint(...codePoints.subarray(nameIdx, newNameIdx)));
|
||||
nameIdx = newNameIdx;
|
||||
}
|
||||
|
||||
queryIdx += 1;
|
||||
if (queryIdx === queryLength) {
|
||||
parentElem.append(
|
||||
span('highlight', String.fromCodePoint(...codePoints.subarray(startIdx, nameIdx + 1))));
|
||||
if (nameIdx + 1 < nameLength) {
|
||||
parentElem.append(String.fromCodePoint(...codePoints.subarray(nameIdx + 1, nameLength)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
queryCp = queryCps[queryIdx];
|
||||
}
|
||||
|
||||
throw 'Precondition violated: `computeMatchFrom()`';
|
||||
}
|
||||
|
||||
// Creates a span element.
|
||||
function span(className, text = null) {
|
||||
const result = document.createElement('span');
|
||||
result.className = className;
|
||||
result.textContent = text;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Creates a text node.
|
||||
function text(content) {
|
||||
return document.createTextNode(content);
|
||||
}
|
||||
|
||||
// Navigates to the next member entry in the search results list, skipping headings.
|
||||
function selectNextResult(ul) {
|
||||
let next = selectedSearchResult === null ? ul.firstElementChild : selectedSearchResult.nextElementSibling;
|
||||
while (next !== null) {
|
||||
if (!next.classList.contains('heading')) {
|
||||
selectResult(next);
|
||||
scrollIntoView(next, {
|
||||
behavior: 'instant', // better for keyboard navigation
|
||||
scrollMode: 'if-needed',
|
||||
block: 'nearest',
|
||||
inline: 'nearest',
|
||||
});
|
||||
return;
|
||||
}
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
}
|
||||
|
||||
// Navigates to the previous member entry in the search results list, skipping headings.
|
||||
function selectPrevResult(ul) {
|
||||
let prev = selectedSearchResult === null ? ul.lastElementChild : selectedSearchResult.previousElementSibling;
|
||||
while (prev !== null) {
|
||||
if (!prev.classList.contains('heading')) {
|
||||
selectResult(prev);
|
||||
const prev2 = prev.previousElementSibling;
|
||||
// make any immediately preceding heading visible as well (esp. important for first heading)
|
||||
const scrollTo = prev2 !== null && prev2.classList.contains('heading') ? prev2 : prev;
|
||||
scrollIntoView(scrollTo, {
|
||||
behavior: 'instant', // better for keyboard navigation
|
||||
scrollMode: 'if-needed',
|
||||
block: 'nearest',
|
||||
inline: 'nearest',
|
||||
});
|
||||
return;
|
||||
}
|
||||
prev = prev.previousElementSibling;
|
||||
}
|
||||
}
|
||||
|
||||
// Selects the given entry in the search results list.
|
||||
function selectResult(li) {
|
||||
if (selectedSearchResult !== null) {
|
||||
selectedSearchResult.classList.remove('selected');
|
||||
}
|
||||
li.classList.add('selected');
|
||||
selectedSearchResult = li;
|
||||
}
|
||||
|
||||
// Clears the search input and hides/removes the search results list.
|
||||
function clearSearch() {
|
||||
searchInput.value = '';
|
||||
updateSearchResults(null);
|
||||
}
|
||||
|
||||
// Functions called by JS data scripts.
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
const runtimeData = {
|
||||
links: (id, linksJson) => {
|
||||
const links = JSON.parse(linksJson);
|
||||
const fragment = document.createDocumentFragment();
|
||||
let first = true;
|
||||
for (const link of links) {
|
||||
const {text, href, classes} = link
|
||||
const a = document.createElement("a");
|
||||
a.textContent = text;
|
||||
if (href) a.href = href;
|
||||
if (classes) a.className = classes;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
fragment.append(", ");
|
||||
}
|
||||
fragment.append(a);
|
||||
}
|
||||
|
||||
const element = document.getElementById(id);
|
||||
element.append(fragment);
|
||||
element.classList.remove("hidden"); // dd
|
||||
element.previousElementSibling.classList.remove("hidden"); // dt
|
||||
}
|
||||
}
|
||||
30
pkl-doc/src/main/resources/org/pkl/doc/scripts/scroll-into-view.min.js
vendored
Normal file
30
pkl-doc/src/main/resources/org/pkl/doc/scripts/scroll-into-view.min.js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Cody Olsen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
var COMPLETE="complete",CANCELED="canceled";function raf(e){if("requestAnimationFrame"in window)return window.requestAnimationFrame(e);setTimeout(e,16)}function setElementScroll(e,t,n){e.self===e?e.scrollTo(t,n):(e.scrollLeft=t,e.scrollTop=n)}function getTargetScrollLocation(e,t){var n,l,i,o,r,a,s,f=e.align,c=e.target.getBoundingClientRect(),d=f&&null!=f.left?f.left:.5,u=f&&null!=f.top?f.top:.5,g=f&&null!=f.leftOffset?f.leftOffset:0,m=f&&null!=f.topOffset?f.topOffset:0,h=d,p=u;if(e.isWindow(t))a=Math.min(c.width,t.innerWidth),s=Math.min(c.height,t.innerHeight),l=c.left+t.pageXOffset-t.innerWidth*h+a*h,i=c.top+t.pageYOffset-t.innerHeight*p+s*p,i-=m,o=(l-=g)-t.pageXOffset,r=i-t.pageYOffset;else{a=c.width,s=c.height,n=t.getBoundingClientRect();var E=c.left-(n.left-t.scrollLeft),S=c.top-(n.top-t.scrollTop);l=E+a*h-t.clientWidth*h,i=S+s*p-t.clientHeight*p,l-=g,i-=m,l=Math.max(Math.min(l,t.scrollWidth-t.clientWidth),0),i=Math.max(Math.min(i,t.scrollHeight-t.clientHeight),0),o=l-t.scrollLeft,r=i-t.scrollTop}return{x:l,y:i,differenceX:o,differenceY:r}}function animate(e){var t=e._scrollSettings;if(t){var n=t.maxSynchronousAlignments,l=getTargetScrollLocation(t,e),i=Date.now()-t.startTime,o=Math.min(1/t.time*i,1);if(t.endIterations>=n)return setElementScroll(e,l.x,l.y),e._scrollSettings=null,t.end(COMPLETE);var r=1-t.ease(o);if(setElementScroll(e,l.x-l.differenceX*r,l.y-l.differenceY*r),i>=t.time)return t.endIterations++,animate(e);raf(animate.bind(null,e))}}function defaultIsWindow(e){return e.self===e}function transitionScrollTo(e,t,n,l){var i,o=!t._scrollSettings,r=t._scrollSettings,a=Date.now(),s={passive:!0};function f(e){t._scrollSettings=null,t.parentElement&&t.parentElement._scrollSettings&&t.parentElement._scrollSettings.end(e),n.debug&&console.log("Scrolling ended with type",e,"for",t),l(e),i&&(t.removeEventListener("touchstart",i,s),t.removeEventListener("wheel",i,s))}r&&r.end(CANCELED);var c=n.maxSynchronousAlignments;return null==c&&(c=3),t._scrollSettings={startTime:a,endIterations:0,target:e,time:n.time,ease:n.ease,align:n.align,isWindow:n.isWindow||defaultIsWindow,maxSynchronousAlignments:c,end:f},"cancellable"in n&&!n.cancellable||(i=f.bind(null,CANCELED),t.addEventListener("touchstart",i,s),t.addEventListener("wheel",i,s)),o&&animate(t),i}function defaultIsScrollable(e){return"pageXOffset"in e||(e.scrollHeight!==e.clientHeight||e.scrollWidth!==e.clientWidth)&&"hidden"!==getComputedStyle(e).overflow}function defaultValidTarget(){return!0}function findParentElement(e){if(e.assignedSlot)return findParentElement(e.assignedSlot);if(e.parentElement)return"BODY"===e.parentElement.tagName?e.parentElement.ownerDocument.defaultView||e.parentElement.ownerDocument.ownerWindow:e.parentElement;if(e.getRootNode){var t=e.getRootNode();if(11===t.nodeType)return t.host}}module.exports=function(e,t,n){if(e){"function"==typeof t&&(n=t,t=null),t||(t={}),t.time=isNaN(t.time)?1e3:t.time,t.ease=t.ease||function(e){return 1-Math.pow(1-e,e/2)};var l,i=findParentElement(e),o=1,r=t.validTarget||defaultValidTarget,a=t.isScrollable;for(t.debug&&(console.log("About to scroll to",e),i||console.error("Target did not have a parent, is it mounted in the DOM?"));i;)if(t.debug&&console.log("Scrolling parent node",i),r(i,o)&&(a?a(i,defaultIsScrollable):defaultIsScrollable(i))&&(o++,l=transitionScrollTo(e,i,t,s)),!(i=findParentElement(i))){s(COMPLETE);break}return l}function s(e){--o||n&&n(e)}};
|
||||
|
||||
},{}],2:[function(require,module,exports){
|
||||
window.scrollIntoView=require("./scrollIntoView");
|
||||
|
||||
},{"./scrollIntoView":1}]},{},[2]);
|
||||
282
pkl-doc/src/main/resources/org/pkl/doc/scripts/search-worker.js
Normal file
282
pkl-doc/src/main/resources/org/pkl/doc/scripts/search-worker.js
Normal file
@@ -0,0 +1,282 @@
|
||||
// noinspection DuplicatedCode
|
||||
|
||||
'use strict';
|
||||
|
||||
// populated by `initSearchIndex()`
|
||||
let searchIndex;
|
||||
|
||||
// noinspection ThisExpressionReferencesGlobalObjectJS
|
||||
const isWorker = 'DedicatedWorkerGlobalScope' in this;
|
||||
|
||||
if (isWorker) {
|
||||
const workerName = self.name;
|
||||
// relative to this file
|
||||
const searchIndexUrl = workerName === "main" ?
|
||||
'../search-index.js' :
|
||||
'../' + workerName + '/search-index.js';
|
||||
initSearchIndex();
|
||||
addEventListener('message', e => {
|
||||
const {query, packageName, moduleName, className} = e.data;
|
||||
const results = runSearch(query, packageName, moduleName, className);
|
||||
postMessage({query, results});
|
||||
});
|
||||
} else {
|
||||
// non-worker environment
|
||||
// `pkldoc.js` loads scripts and calls `initSearchIndex()`
|
||||
}
|
||||
|
||||
// Initializes the search index.
|
||||
function initSearchIndex() {
|
||||
// noinspection JSUnresolvedVariable
|
||||
const data = JSON.parse(searchData);
|
||||
const index = Array(data.length);
|
||||
let idx = 0;
|
||||
|
||||
for (const entry of data) {
|
||||
const name = entry.name;
|
||||
const names = toIndexedNames(entry);
|
||||
// 0 -> package, 1 -> module, 2 -> type alias, 3 -> class, 4 -> function, 5 -> property
|
||||
const kind = entry.kind;
|
||||
const url = entry.url;
|
||||
// noinspection JSUnresolvedVariable
|
||||
const signature = entry.sig === undefined ? null : entry.sig;
|
||||
// noinspection JSUnresolvedVariable
|
||||
const parent = entry.parId === undefined ? null : index[entry.parId];
|
||||
const level = parent === null ? 0 : parent.parent === null ? 1 : 2;
|
||||
const deprecated = entry.deprecated !== undefined;
|
||||
|
||||
index[idx++] = {
|
||||
name,
|
||||
names,
|
||||
kind,
|
||||
url,
|
||||
signature,
|
||||
parent,
|
||||
level,
|
||||
deprecated,
|
||||
// remaining attributes are set by `computeMatchFrom` and hence aren't strictly part of the search index
|
||||
matchNameIdx: -1, // names[matchNameIdx] is the name that matched
|
||||
matchStartIdx: -1, // names[matchNameIdx].codePoints[matchStartIdx] is the first code point that matched
|
||||
similarity: 0 // number of code points matched relative to total number of code points (between 0.0 and 1.0)
|
||||
};
|
||||
}
|
||||
|
||||
searchIndex = index;
|
||||
}
|
||||
|
||||
// Runs a search and returns its results.
|
||||
function runSearch(query, packageName, moduleName, className) {
|
||||
const queryCps = query.normalizedCps;
|
||||
const queryKind = query.kind;
|
||||
|
||||
let exactMatches = [];
|
||||
let classMatches = [];
|
||||
let moduleMatches = [];
|
||||
let otherMatches = [];
|
||||
|
||||
for (const member of searchIndex) {
|
||||
if (queryKind !== null && queryKind !== member.kind) continue;
|
||||
|
||||
if (!isMatch(queryCps, member)) continue;
|
||||
|
||||
if (member.similarity === 1) {
|
||||
exactMatches.push(member);
|
||||
} else if (moduleName !== null && member.level === 1 && moduleName === member.parent.name) {
|
||||
moduleMatches.push(member);
|
||||
} else if (moduleName !== null && member.level === 2 && moduleName === member.parent.parent.name) {
|
||||
if (className !== null && className === member.parent.name) {
|
||||
classMatches.push(member);
|
||||
} else {
|
||||
moduleMatches.push(member);
|
||||
}
|
||||
} else {
|
||||
otherMatches.push(member);
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts members best-first.
|
||||
function compareMembers(member1, member2) {
|
||||
const normDiff = member2.similarity - member1.similarity; // higher is better
|
||||
if (normDiff !== 0) return normDiff;
|
||||
|
||||
const lengthDiff = member1.matchNameLength - member2.matchNameLength; // lower is better
|
||||
if (lengthDiff !== 0) return lengthDiff;
|
||||
|
||||
const kindDiff = member2.kind - member1.kind; // higher is better
|
||||
if (kindDiff !== 0) return kindDiff;
|
||||
|
||||
return member1.matchNameIdx - member2.matchNameIdx; // lower is better
|
||||
}
|
||||
|
||||
exactMatches.sort(compareMembers);
|
||||
classMatches.sort(compareMembers);
|
||||
moduleMatches.sort(compareMembers);
|
||||
otherMatches.sort(compareMembers);
|
||||
|
||||
return {exactMatches, classMatches, moduleMatches, otherMatches};
|
||||
}
|
||||
|
||||
// Indexes a member's names.
|
||||
function toIndexedNames(entry) {
|
||||
const result = [];
|
||||
result.push(toIndexedName(entry.name));
|
||||
// noinspection JSUnresolvedVariable
|
||||
const alsoKnownAs = entry.aka;
|
||||
if (alsoKnownAs !== undefined) {
|
||||
for (const name of alsoKnownAs) {
|
||||
result.push(toIndexedName(name));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Indexes the given name.
|
||||
function toIndexedName(name) {
|
||||
const characters = Array.from(name);
|
||||
const codePoints = Uint32Array.from(characters, ch => ch.codePointAt(0));
|
||||
const normalizedCps = toNormalizedCodePoints(characters);
|
||||
const wordStarts = toWordStarts(characters);
|
||||
|
||||
return {codePoints, normalizedCps, wordStarts};
|
||||
}
|
||||
|
||||
// Converts a Unicode character array to an array of normalized Unicode code points.
|
||||
// Normalization turns characters into their base forms, e.g., é into e.
|
||||
// Since JS doesn't support case folding, `toLocaleLowerCase()` is used instead.
|
||||
function toNormalizedCodePoints(characters) {
|
||||
return Uint32Array.from(characters, ch => ch.normalize('NFD')[0].toLocaleLowerCase().codePointAt(0));
|
||||
}
|
||||
|
||||
// Returns an array of same length as `characters` that for every index, holds the index of the next word start.
|
||||
// Preconditions:
|
||||
// characters.length > 0
|
||||
function toWordStarts(characters) {
|
||||
const length = characters.length;
|
||||
// -1 is used as 'no next word start exists' -> use signed int array
|
||||
const result = length <= 128 ? new Int8Array(length) : new Int16Array(length);
|
||||
|
||||
if (length > 1) {
|
||||
let class1 = toCharClass(characters[length - 1]);
|
||||
let class2;
|
||||
let wordStart = -1;
|
||||
for (let idx = length - 1; idx >= 1; idx -= 1) {
|
||||
class2 = class1;
|
||||
class1 = toCharClass(characters[idx - 1]);
|
||||
const diff = class1 - class2;
|
||||
// transitions other than uppercase -> other
|
||||
if (diff !== 0 && diff !== 3) wordStart = idx;
|
||||
result[idx] = wordStart;
|
||||
// uppercase -> other
|
||||
if (diff === 3) wordStart = idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// first character is always a word start
|
||||
result[0] = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const regexIsUppercase = /\p{Lu}/u
|
||||
|
||||
const regexIsNumericCharacter = /\p{N}/u
|
||||
|
||||
// Partitions characters into uppercase, digit, dot, and other.
|
||||
function toCharClass(ch) {
|
||||
return regexIsUppercase.test(ch) ? 3 : regexIsNumericCharacter.test(ch) ? 2 : ch === '.' ? 1 : 0;
|
||||
}
|
||||
|
||||
// Tests if `queryCps` matches any of `member`'s names.
|
||||
// If so, records information about the match in `member`.
|
||||
// Preconditions:
|
||||
// queryCps.length > 0
|
||||
function isMatch(queryCps, member) {
|
||||
const queryLength = queryCps.length;
|
||||
let nameIdx = 0;
|
||||
|
||||
for (const name of member.names) {
|
||||
const nameCps = name.normalizedCps;
|
||||
const nameLength = nameCps.length;
|
||||
const wordStarts = name.wordStarts;
|
||||
const maxStartIdx = nameLength - queryLength;
|
||||
|
||||
for (let startIdx = 0; startIdx <= maxStartIdx; startIdx += 1) {
|
||||
const matchLength = computeMatchFrom(queryCps, nameCps, wordStarts, startIdx);
|
||||
if (matchLength > 0) {
|
||||
member.matchNameIdx = nameIdx;
|
||||
member.matchStartIdx = startIdx;
|
||||
// Treat exact match of last module name component as exact match (similarity == 1).
|
||||
// For example, treat "PodSpec" as exact match for "io.k8s.api.core.v1.PodSpec".
|
||||
// Because "ps" is considered an exact match for "PodSpec",
|
||||
// it is also considered an exact match for "io.k8s.api.core.v1.PodSpec".
|
||||
const isExactMatchOfLastModuleNameComponent =
|
||||
startIdx > 0 && nameCps[startIdx - 1] === 46 /* '.' */ && matchLength === nameLength - startIdx;
|
||||
member.similarity = isExactMatchOfLastModuleNameComponent ? 1 : matchLength / nameLength;
|
||||
member.matchNameLength = nameLength;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nameIdx += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tests if the given query matches the given name from `startIdx` on.
|
||||
// Returns the number of code points matched.
|
||||
// Word start matches get special treatment.
|
||||
// For example, `sb` is considered to match all code points of `StringBuilder`.
|
||||
// Preconditions:
|
||||
// queryCps.length > 0
|
||||
// nameCps.length > 0
|
||||
// wordStarts.length === nameCps.length
|
||||
// startIdx < nameCps.length
|
||||
function computeMatchFrom(queryCps, nameCps, wordStarts, startIdx) {
|
||||
const queryLength = queryCps.length;
|
||||
const nameLength = nameCps.length;
|
||||
const beginsWithWordStart = wordStarts[startIdx] === startIdx;
|
||||
|
||||
let queryIdx = 0;
|
||||
let matchLength = 0;
|
||||
let queryCp = queryCps[0];
|
||||
|
||||
for (let nameIdx = startIdx; nameIdx < nameLength; nameIdx += 1) {
|
||||
const nameCp = nameCps[nameIdx];
|
||||
|
||||
if (queryCp === nameCp) {
|
||||
matchLength += 1;
|
||||
} else { // check for word start match
|
||||
if (nameIdx === startIdx || !beginsWithWordStart) return 0;
|
||||
|
||||
const newNameIdx = wordStarts[nameIdx];
|
||||
if (newNameIdx === -1) return 0;
|
||||
|
||||
const newNameCp = nameCps[newNameIdx];
|
||||
if (queryCp !== newNameCp) return 0;
|
||||
|
||||
matchLength += newNameIdx - nameIdx + 1;
|
||||
nameIdx = newNameIdx;
|
||||
}
|
||||
|
||||
queryIdx += 1;
|
||||
if (queryIdx === queryLength) {
|
||||
// in case of a word start match, increase matchLength by number of remaining chars of the last matched word
|
||||
const nextIdx = nameIdx + 1;
|
||||
if (beginsWithWordStart && nextIdx < nameLength) {
|
||||
const nextStart = wordStarts[nextIdx];
|
||||
if (nextStart === -1) {
|
||||
matchLength += nameLength - nextIdx;
|
||||
} else {
|
||||
matchLength += nextStart - nextIdx;
|
||||
}
|
||||
}
|
||||
|
||||
return matchLength;
|
||||
}
|
||||
|
||||
queryCp = queryCps[queryIdx];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
666
pkl-doc/src/main/resources/org/pkl/doc/styles/pkldoc.css
Normal file
666
pkl-doc/src/main/resources/org/pkl/doc/styles/pkldoc.css
Normal file
@@ -0,0 +1,666 @@
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Lato Regular'), local('Lato-Regular'),
|
||||
url('../fonts/lato-v14-latin_latin-ext-regular.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Lato Bold'), local('Lato-Bold'),
|
||||
url('../fonts/lato-v14-latin_latin-ext-700.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans Regular'), local('OpenSans-Regular'),
|
||||
url('../fonts/open-sans-v15-latin_latin-ext-regular.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Open Sans Italic'), local('OpenSans-Italic'),
|
||||
url('../fonts/open-sans-v15-latin_latin-ext-italic.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Open Sans Bold'), local('OpenSans-Bold'),
|
||||
url('../fonts/open-sans-v15-latin_latin-ext-700.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'),
|
||||
url('../fonts/open-sans-v15-latin_latin-ext-700italic.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Code Pro'), local('SourceCodePro-Regular'),
|
||||
url('../fonts/source-code-pro-v7-latin_latin-ext-regular.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Source Code Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Code Pro Bold'), local('SourceCodePro-Bold'),
|
||||
url('../fonts/source-code-pro-v7-latin_latin-ext-700.woff2') format('woff2')
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'),
|
||||
local('MaterialIcons-Regular'),
|
||||
url(../fonts/MaterialIcons-Regular.woff2) format('woff2');
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
/*noinspection CssNoGenericFontName*/
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
|
||||
input[type=search] {
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
input[type=search]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
input::-moz-placeholder {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, font, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td {
|
||||
border: 0;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Lato, Arial, sans-serif;
|
||||
background-color: #f0f3f6;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
a, a:visited, a:hover, a:active {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
transition: 0s;
|
||||
}
|
||||
|
||||
code, .member-modifiers, .member-signature, .doc-comment pre, #search-results li.result, .result-name, .heading-name, .aka-name {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw; /* vw to make sure that positioning is the same whether or not vertical scrollbar is displayed */
|
||||
height: 32px;
|
||||
z-index: 1;
|
||||
background-color: #364550;
|
||||
padding: 7px 0 7px;
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.18), 0 4px 8px rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
|
||||
#doc-title {
|
||||
position: absolute;
|
||||
margin-top: 8px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#doc-title a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#search {
|
||||
position: relative;
|
||||
width: 50vw;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#search-icon {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
padding: 4px;
|
||||
font-size: 21px;
|
||||
color: #a5a9a9;
|
||||
}
|
||||
|
||||
#search-input {
|
||||
margin-top: 2px;
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
text-indent: 28px;
|
||||
font-size: 0.85em;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#search-input:focus {
|
||||
background-color: #6D7880;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#search-input::placeholder {
|
||||
text-align: center;
|
||||
color: #A5A9A9;
|
||||
}
|
||||
|
||||
#search-input:focus::placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
#search-results {
|
||||
position: fixed;
|
||||
box-sizing: border-box;
|
||||
top: 38px;
|
||||
left: 25vw;
|
||||
right: 25vw;
|
||||
width: 50vw;
|
||||
max-height: 80%;
|
||||
color: #103a51;
|
||||
background: white;
|
||||
border: solid 1px #6D7880;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.18), 0 4px 8px rgba(0, 0, 0, 0.28);
|
||||
white-space: nowrap;
|
||||
|
||||
overflow: auto; /* in safari, this slows down painting, blocking the ui */
|
||||
/*noinspection CssUnknownProperty*/
|
||||
overscroll-behavior: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
#search-results a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#search-results a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#search-results ul {
|
||||
list-style: none;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
#search-results li {
|
||||
padding: 0.2ch 3ch;
|
||||
height: 17px; /* used same height regardless of which fonts are used in content */
|
||||
}
|
||||
|
||||
#search-results li.heading {
|
||||
background-color: #f0f3f6;
|
||||
padding: 0.4ch 1ch;
|
||||
}
|
||||
|
||||
#search-results li.result {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
#search-results .keyword {
|
||||
color: #000082;
|
||||
}
|
||||
|
||||
#search-results .highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#search-results .context {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
#search-results .selected, #search-results .selected .keyword, #search-results .selected .aka, #search-results .selected .context {
|
||||
background: darkblue;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#search-results .deprecated {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* make sure that line-through of highlighted region of selected search result has the right color */
|
||||
#search-results .deprecated.selected .highlight {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 70%;
|
||||
margin: 60px auto 20px;
|
||||
}
|
||||
|
||||
.declaration-parent-link {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
#declaration-title {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #103a51;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
#declaration-version {
|
||||
color: #A5A9A9;
|
||||
font-size: 0.9em;
|
||||
vertical-align: bottom;
|
||||
padding-left: 0.25em;
|
||||
}
|
||||
|
||||
.member-group-links {
|
||||
margin: 0.75em 0 1em 0;
|
||||
}
|
||||
|
||||
.member-group-links li {
|
||||
display: inline-block;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.member-info {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
line-height: 1.5;
|
||||
margin-top: 0.5em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.member-info dt {
|
||||
grid-column: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.member-info dd {
|
||||
grid-column: 2;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.copy-uri-button {
|
||||
cursor: pointer;
|
||||
font-size: inherit;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.member-group {
|
||||
/* for absolutely positioned anchors */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.member-group-title {
|
||||
margin: 1rem;
|
||||
font-weight: bold;
|
||||
color: #103a51;
|
||||
}
|
||||
|
||||
.toggle-inherited-members {
|
||||
font-size: 0.9em;
|
||||
font-weight: normal;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.button-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.button-link:hover, .button-link:active {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.member-group ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.member-group li {
|
||||
/* for absolutely positioned anchors */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.anchor,
|
||||
.anchor-param1,
|
||||
.anchor-param2,
|
||||
.anchor-param3,
|
||||
.anchor-param4,
|
||||
.anchor-param5,
|
||||
.anchor-param6,
|
||||
.anchor-param7,
|
||||
.anchor-param8,
|
||||
.anchor-param9 {
|
||||
position: absolute;
|
||||
top: -60px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.anchor:target ~ .member,
|
||||
.anchor-param1:target ~ .member,
|
||||
.anchor-param2:target ~ .member,
|
||||
.anchor-param3:target ~ .member,
|
||||
.anchor-param4:target ~ .member,
|
||||
.anchor-param5:target ~ .member,
|
||||
.anchor-param6:target ~ .member,
|
||||
.anchor-param7:target ~ .member,
|
||||
.anchor-param8:target ~ .member,
|
||||
.anchor-param9:target ~ .member {
|
||||
border-left: 3px solid #222832;
|
||||
}
|
||||
|
||||
.anchor:target ~ .member .name-decl,
|
||||
.anchor-param1:target ~ .member .param1,
|
||||
.anchor-param2:target ~ .member .param2,
|
||||
.anchor-param3:target ~ .member .param3,
|
||||
.anchor-param4:target ~ .member .param4,
|
||||
.anchor-param5:target ~ .member .param5,
|
||||
.anchor-param6:target ~ .member .param6,
|
||||
.anchor-param7:target ~ .member .param7,
|
||||
.anchor-param8:target ~ .member .param8,
|
||||
.anchor-param9:target ~ .member .param9 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.member {
|
||||
border-left: 3px solid transparent;
|
||||
margin: 0 auto 0.5rem;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
font-size: 0.9em;
|
||||
padding: 10px;
|
||||
color: #222832;
|
||||
}
|
||||
|
||||
.member:hover {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.member-left {
|
||||
width: 25%;
|
||||
display: inline;
|
||||
float: left;
|
||||
padding-right: 6px;
|
||||
min-height: 1px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.member-modifiers {
|
||||
color: #000082;
|
||||
}
|
||||
|
||||
.member-main {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.member-deprecated {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.member-selflink {
|
||||
visibility: hidden;
|
||||
display: inline;
|
||||
float: left;
|
||||
padding-right: 20px;
|
||||
color: #222832;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.member-source-link {
|
||||
visibility: hidden;
|
||||
color: #fff;
|
||||
background-color: #868e96;
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
padding: .25em .4em;
|
||||
font-size: 75%;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
vertical-align: bottom;
|
||||
border-radius: .25rem
|
||||
}
|
||||
|
||||
.member-source-link:visited, .member-source-link:hover, .member-source-link:active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.member:hover .member-source-link, .member:hover .member-selflink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.member.inherited, .member.hidden-member {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.member.inherited .context {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.member.with-page-link, .member.with-expandable-docs {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.member .expandable-docs-icon {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
Don't style a.name-decl as link
|
||||
because the entire .member.with-page-link is effectively a link (via JS).
|
||||
*/
|
||||
.member.with-page-link a.name-decl {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.expandable {
|
||||
transform: scaleY(1);
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
|
||||
.expandable.collapsed {
|
||||
transform: scaleY(0);
|
||||
}
|
||||
|
||||
.expandable.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* show an otherwise hidden inherited member if it's a link target */
|
||||
.anchor:target + .expandable.collapsed.hidden {
|
||||
display: inherit;
|
||||
transform: scaleY(1);
|
||||
}
|
||||
|
||||
.doc-comment {
|
||||
color: #103a51;
|
||||
margin-top: 0.5rem;
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.doc-comment p {
|
||||
margin: 0.7em 0;
|
||||
}
|
||||
|
||||
.doc-comment p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.doc-comment p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.doc-comment h1,
|
||||
.doc-comment h2,
|
||||
.doc-comment h3,
|
||||
.doc-comment h4,
|
||||
.doc-comment h5,
|
||||
.doc-comment h6 {
|
||||
margin-bottom: 0.7em;
|
||||
margin-top: 1.4em;
|
||||
display: block;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.doc-comment pre {
|
||||
padding: 0.5em;
|
||||
border: 0 solid #ddd;
|
||||
background-color: #364550;
|
||||
color: #ddd;
|
||||
margin: 5px 0;
|
||||
display: block;
|
||||
border-radius: 0.2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.doc-comment ul {
|
||||
display: block;
|
||||
list-style: circle;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.doc-comment ol {
|
||||
display: block;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
.doc-comment ol.decimal {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.doc-comment ol.lowerAlpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
.doc-comment ol.upperAlpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
.doc-comment ol.lowerRoman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
.doc-comment ol.upperRoman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
.doc-comment li {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
.doc-comment code {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.doc-comment em, .doc-comment i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.doc-comment strong, .doc-comment b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.runtime-data.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.runtime-data .current-version {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
Styling for Markdown tables in doc comments.
|
||||
From: https://gist.github.com/andyferra/2554919
|
||||
*/
|
||||
|
||||
table {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table tr {
|
||||
border-top: 1px solid #cccccc;
|
||||
background-color: white;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table tr:nth-child(2n) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
table tr th {
|
||||
font-weight: bold;
|
||||
border: 1px solid #cccccc;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
|
||||
table tr td {
|
||||
border: 1px solid #cccccc;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
|
||||
table tr th :first-child, table tr td :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
table tr th :last-child, table tr td :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
22
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/doc-package-info.pkl
vendored
Normal file
22
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/doc-package-info.pkl
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
amends "pkl:DocPackageInfo"
|
||||
|
||||
name = "com.externalpackage"
|
||||
version = "1.2.3"
|
||||
importUri = "https://pkl.io/"
|
||||
authors {
|
||||
"publisher-externalpackage@group.apple.com"
|
||||
}
|
||||
sourceCode = "https://example.com/externalpackage/"
|
||||
sourceCodeUrlScheme = "https://example.com/blob/\(version)%{path}#L%{line}-L%{endLine}"
|
||||
issueTracker = "https://example.com/externalpackage/issues"
|
||||
|
||||
dependencies {
|
||||
new {
|
||||
name = "pkl"
|
||||
// use fixed version to avoid churn in expected test outputs
|
||||
version = "0.24.0"
|
||||
sourceCode = "https://github.com/apple/\(name)/blob/dev/stdlib/"
|
||||
sourceCodeUrlScheme = "https://github.com/apple/\(name)/blob/\(version)/stdlib%{path}#L%{line}-L%{endLine}"
|
||||
documentation = "https://pkl-lang.org/stdlib/\(name)/\(version)/"
|
||||
}
|
||||
}
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/external1.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/external1.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.externalpackage.external1
|
||||
|
||||
class MyClass
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/external2.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.externalpackage/external2.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.externalpackage.external2
|
||||
|
||||
class MyClass
|
||||
7
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/baseModule.pkl
vendored
Normal file
7
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/baseModule.pkl
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
open module com.package1.baseModule
|
||||
|
||||
baseProperty = 42
|
||||
|
||||
function baseMethod() = 42
|
||||
|
||||
class BaseClass {}
|
||||
30
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classAnnotations.pkl
vendored
Normal file
30
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
open module com.package1.classAnnotations
|
||||
|
||||
/// This [AnnotatedClss] thought to have a correctly spelled name.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "AnnotatedClass"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "OtherName" }
|
||||
}
|
||||
class AnnotatedClss
|
||||
|
||||
/// This [AnnotatedClssWithExpandableComment] thought to have a correctly spelled name.
|
||||
///
|
||||
/// Unfortunately, it did not, as we explain in this expandable comment.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "AnnotatedClass"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "OtherName" }
|
||||
}
|
||||
class AnnotatedClssWithExpandableComment
|
||||
|
||||
// This [AnnotatedClass] indeed has a properly spelled name, but no doc comment.
|
||||
@AlsoKnownAs {
|
||||
names { "OtherName" }
|
||||
}
|
||||
@Deprecated // omit optional arguments
|
||||
class AnnotatedClass
|
||||
145
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classComments.pkl
vendored
Normal file
145
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classComments.pkl
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/// The greatest breakthrough since ever.
|
||||
///
|
||||
/// ### Installation
|
||||
///
|
||||
/// Just follow these simple steps:
|
||||
///
|
||||
/// 1. Install it
|
||||
/// 1. I promise it's easy.
|
||||
/// 2. You'll figure it out.
|
||||
/// 1. Install it
|
||||
/// ```
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// ```
|
||||
/// 1. Install it
|
||||
///
|
||||
/// Let me **emphasize** how *simple* this is.
|
||||
///
|
||||
/// 😀😀😀 emoji day 😎😎😎 don't get 😡😡😡
|
||||
///
|
||||
/// ### Code
|
||||
///
|
||||
/// The code is beautiful:
|
||||
///
|
||||
/// ```
|
||||
/// /// example module
|
||||
/// module foo.bar
|
||||
///
|
||||
/// person {
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// }
|
||||
///
|
||||
/// function sing() = "tra-la-la"
|
||||
///
|
||||
/// class Person {
|
||||
/// name: String
|
||||
/// age: Int
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Random Tips
|
||||
///
|
||||
/// - don't give up
|
||||
/// - just don't
|
||||
/// - don't give up
|
||||
///
|
||||
/// # Level 1
|
||||
/// ## Level 2
|
||||
/// ### Level 3
|
||||
/// #### Level 4
|
||||
/// ##### Level 5
|
||||
/// ###### Level 6
|
||||
///
|
||||
/// | Command | Description |
|
||||
/// | --- | --- |
|
||||
/// | `git status` | List all *new or modified* files |
|
||||
/// | `git diff` | Show file differences that **haven't been** staged |
|
||||
open module com.package1.classComments
|
||||
|
||||
// Class with single-line code comment.
|
||||
class Comments1
|
||||
|
||||
/*
|
||||
Class with
|
||||
multi-line
|
||||
code comment.
|
||||
*/
|
||||
class Comments2
|
||||
|
||||
/// Class with single-line doc comment.
|
||||
class Comments3
|
||||
|
||||
/// Class with multi-line and multi-paragraph doc comment (paragraph1, line1).
|
||||
/// Class with multi-line and multi-paragraph doc comment (paragraph1, line2).
|
||||
///
|
||||
/// Class with multi-line and multi-paragraph doc comment (paragraph2, line1).
|
||||
/// Class with multi-line and multi-paragraph doc comment (paragraph2, line2).
|
||||
class Comments4
|
||||
|
||||
/// Class with [single-line](https://apple.com) *Markdown* doc comment.
|
||||
class Comments5
|
||||
|
||||
/// Class with
|
||||
/// [multi-line](https://apple.com)
|
||||
/// *Markdown* doc comment.
|
||||
class Comments6
|
||||
|
||||
/// 😀😀😀 Class with 😎😎😎 Unicode doc comment. 😡😡😡
|
||||
class Comments7
|
||||
|
||||
/// The greatest breakthrough since ever.
|
||||
///
|
||||
/// ## Installation
|
||||
///
|
||||
/// Just follow these simple steps:
|
||||
///
|
||||
/// 1. Install it
|
||||
/// 1. I promise it's easy.
|
||||
/// 2. You'll figure it out.
|
||||
/// 1. Install it
|
||||
/// ```
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// ```
|
||||
/// 1. Install it
|
||||
///
|
||||
/// Let me **emphasize** how *simple* this is.
|
||||
///
|
||||
/// 😀😀😀 emoji day 😎😎😎 don't get 😡😡😡
|
||||
///
|
||||
/// ## Code
|
||||
///
|
||||
/// The code is beautiful:
|
||||
///
|
||||
/// ```
|
||||
/// /// example module
|
||||
/// module foo.bar
|
||||
///
|
||||
/// person {
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// }
|
||||
///
|
||||
/// function sing() = "tra-la-la"
|
||||
///
|
||||
/// class Person {
|
||||
/// name: String
|
||||
/// age: Int
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Random Tips
|
||||
///
|
||||
/// - don't give up
|
||||
/// - just don't
|
||||
/// - don't give up
|
||||
///
|
||||
/// # Level 1
|
||||
/// ## Level 2
|
||||
/// ### Level 3
|
||||
/// #### Level 4
|
||||
/// ##### Level 5
|
||||
/// ###### Level 6
|
||||
class Comments8
|
||||
29
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classInheritance.pkl
vendored
Normal file
29
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classInheritance.pkl
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/// Class inheritance involving abstract, open, and final classes.
|
||||
module com.package1.classInheritance
|
||||
|
||||
abstract class MyClass1 {
|
||||
/// Inherited property comment.
|
||||
abstract property1: Boolean
|
||||
|
||||
/// function method1 in class MyClass1.
|
||||
abstract function method1(arg: String): Boolean
|
||||
}
|
||||
|
||||
open class MyClass2 extends MyClass1 {
|
||||
property1: Boolean = false
|
||||
property2: String = ""
|
||||
|
||||
/// function method1 in class MyClass2.
|
||||
function method1(arg: String): Boolean = Undefined()
|
||||
function method2(arg: String): Boolean = Undefined()
|
||||
}
|
||||
|
||||
abstract class MyClass3 extends MyClass2 {
|
||||
property1: Boolean = true
|
||||
function method1(arg: String): Boolean = Undefined()
|
||||
}
|
||||
|
||||
class MyClass4 extends MyClass2 {
|
||||
property4: String = ""
|
||||
function method3(arg: String): Boolean = Undefined()
|
||||
}
|
||||
33
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodComments.pkl
vendored
Normal file
33
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodComments.pkl
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Class methods with different kinds of comments.
|
||||
module com.package1.classMethodComments
|
||||
|
||||
class Comments {
|
||||
// Method with single-line code comment.
|
||||
function method1(): Float = Undefined()
|
||||
|
||||
/*
|
||||
Method with
|
||||
multi-line
|
||||
code comment.
|
||||
*/
|
||||
function method2(): Float = Undefined()
|
||||
|
||||
/// Method with single-line doc comment.
|
||||
function method3(): Float = Undefined()
|
||||
|
||||
/// Method with
|
||||
/// multi-line
|
||||
/// doc comment.
|
||||
function method4(): Float = Undefined()
|
||||
|
||||
/// Method with [single-line](https://apple.com) *Markdown* doc comment.
|
||||
function method5(): Float = Undefined()
|
||||
|
||||
/// Method with
|
||||
/// [multi-line](https://apple.com)
|
||||
/// *Markdown* doc comment.
|
||||
function method6(): Float = Undefined()
|
||||
|
||||
/// 😀😀😀 Method with 😎😎😎 Unicode doc comment. 😡😡😡
|
||||
function method7(): Float = Undefined()
|
||||
}
|
||||
15
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodModifiers.pkl
vendored
Normal file
15
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodModifiers.pkl
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/// Class methods with different modifiers.
|
||||
module com.package1.classMethodModifiers
|
||||
|
||||
abstract class Modifiers {
|
||||
/// Method with `abstract` modifier.
|
||||
abstract function method1(arg: String): Boolean
|
||||
|
||||
/*
|
||||
/// Method with `external` modifier.
|
||||
external function method2(arg: String): Boolean
|
||||
|
||||
/// Method with multiple modifiers.
|
||||
abstract external function method3(arg: String): Boolean
|
||||
*/
|
||||
}
|
||||
43
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodTypeAnnotations.pkl
vendored
Normal file
43
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodTypeAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/// Class methods with different kinds of type annotations.
|
||||
module com.package1.classMethodTypeAnnotations
|
||||
|
||||
class TypeAnnotations {
|
||||
/// Zero-arg method without declared types.
|
||||
function method1() = Undefined()
|
||||
|
||||
/// One-arg method without declared types.
|
||||
function method2(arg1) = Undefined()
|
||||
|
||||
/// Two-arg method without declared types.
|
||||
function method3(arg1, arg2) = Undefined()
|
||||
|
||||
/// Zero-arg method with simple types.
|
||||
function method4(): String = Undefined()
|
||||
|
||||
/// One-arg method with simple types.
|
||||
function method5(arg1: Boolean): Int = Undefined()
|
||||
|
||||
/// Two-arg method with simple types.
|
||||
function method6(arg1: Int, arg2: Float): Duration = Undefined()
|
||||
|
||||
/// Two-arg method with list types.
|
||||
function method7(arg1: List<Int>, arg2: List<Float>): List<Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with set types.
|
||||
function method8(arg1: Set<Int>, arg2: Set<Float>): Set<Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with map types.
|
||||
function method9(arg1: Map<Int, Int>, arg2: Map<Float, Float>): Map<Duration, Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with optional types.
|
||||
function method10(arg1: Int?, arg2: Float?): Duration? = Undefined()
|
||||
|
||||
/// Two-arg method with function types.
|
||||
function method11(arg1: () -> Int, arg2: (Int) -> Float): (Int, Float) -> Duration = Undefined()
|
||||
|
||||
/// Two-arg method with partially declared types.
|
||||
function method12(arg1: String, arg2): Boolean = Undefined()
|
||||
|
||||
/// One-arg method with complex types.
|
||||
function method13(arg1: Map<List<String?>?, (Boolean?) -> Map<Int, Float>>): Map<List<Duration?>?, (DataSize?) -> Map<Any, Number>> = Undefined()
|
||||
}
|
||||
28
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodTypeReferences.pkl
vendored
Normal file
28
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classMethodTypeReferences.pkl
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/// Class methods whose types reference classes from
|
||||
/// the same module, a different module, and external modules.
|
||||
module com.package1.classMethodTypeReferences
|
||||
|
||||
import "shared.pkl"
|
||||
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
|
||||
import "../com.externalpackage/external2.pkl"
|
||||
|
||||
class MyClass
|
||||
|
||||
class TypeReferences {
|
||||
/// Method with intra-module types.
|
||||
function method1(arg1: MyClass, arg2: MyClass): MyClass = Undefined()
|
||||
|
||||
/// Method with inter-module types.
|
||||
function method2(arg1: shared.MyClass, arg2: shared.MyClass): shared.MyClass = Undefined()
|
||||
|
||||
/// Method with external-module types.
|
||||
function method3(arg1: external1.MyClass, arg2: external2.MyClass): List<external1.MyClass> = Undefined()
|
||||
|
||||
/// Method with intra-module, inter-module, and external-module types.
|
||||
function method4(arg1: MyClass, arg2: shared.MyClass): external1.MyClass = Undefined()
|
||||
|
||||
/// Method with complex intra-module, inter-module, and external-module types.
|
||||
function method5(arg1: MyClass?, arg2: Map<shared.MyClass, external1.MyClass>): (external1.MyClass) -> external2.MyClass = Undefined()
|
||||
}
|
||||
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyAnnotations.pkl
vendored
Normal file
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module com.package1.classPropertyAnnotations
|
||||
|
||||
class UserDefinedAnnotation extends Annotation {
|
||||
messageOpt: String?
|
||||
messageReq: String
|
||||
}
|
||||
|
||||
class ClassWithAnnotatedProperty {
|
||||
@UserDefinedAnnotation {
|
||||
messageReq = "Hi!"
|
||||
}
|
||||
propertyUserDefinedAnnotation: Int = 42
|
||||
}
|
||||
33
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyComments.pkl
vendored
Normal file
33
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyComments.pkl
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/// Class properties with different kinds of comments.
|
||||
module com.package1.classPropertyComments
|
||||
|
||||
class Comments {
|
||||
// Property with single-line code comment.
|
||||
property1: Float = 3.14159265359
|
||||
|
||||
/*
|
||||
Property with
|
||||
multi-line
|
||||
code comment.
|
||||
*/
|
||||
property2: Float = 3.14159265359
|
||||
|
||||
/// Property with single-line doc comment.
|
||||
property3: Float = 3.14159265359
|
||||
|
||||
/// Property with
|
||||
/// multi-line
|
||||
/// doc comment.
|
||||
property4: Float = 3.14159265359
|
||||
|
||||
/// Property with [single-line](https://apple.com) *Markdown* doc comment.
|
||||
property5: Float = 3.14159265359
|
||||
|
||||
/// Property with
|
||||
/// [multi-line](https://apple.com)
|
||||
/// *Markdown* doc comment.
|
||||
property6: Float = 3.14159265359
|
||||
|
||||
/// 😀😀😀 Property with 😎😎😎 Unicode doc comment. 😡😡😡
|
||||
property7: Float = 3.14159265359
|
||||
}
|
||||
21
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyModifiers.pkl
vendored
Normal file
21
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyModifiers.pkl
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/// Class properties with different modifiers.
|
||||
module com.package1.classPropertyModifiers
|
||||
|
||||
abstract class Modifiers {
|
||||
/// Property with `local` modifier.
|
||||
local property1 = 3.14159265359
|
||||
|
||||
/// Property with `hidden` modifier.
|
||||
hidden property2: Float = 3.14159265359
|
||||
|
||||
/// Property with `abstract` modifier.
|
||||
abstract property3: Float
|
||||
|
||||
/// Property with multiple modifiers.
|
||||
abstract hidden property4: Float
|
||||
|
||||
/*
|
||||
/// Property with `external` modifier.
|
||||
external property5: Float
|
||||
*/
|
||||
}
|
||||
34
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyTypeAnnotations.pkl
vendored
Normal file
34
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyTypeAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/// Class properties with different kinds of type annotations.
|
||||
module com.package1.classPropertyTypeAnnotations
|
||||
|
||||
class TypeAnnotations {
|
||||
/// Property without declared type.
|
||||
property1 = 3.14159265359
|
||||
|
||||
/// Property with simple type.
|
||||
property2: Float = 3.14159265359
|
||||
|
||||
/// Property with list type.
|
||||
property3: List<String> = List("1", "2", "3")
|
||||
|
||||
/// Property with set type.
|
||||
property4: Set<String> = Set("1", "2", "3")
|
||||
|
||||
/// Property with map type.
|
||||
property5: Map<String, Duration> = Map("one", 1.s, "two", 2.min, "three", 3.h)
|
||||
|
||||
/// Property with optional type.
|
||||
property6: String? = "string"
|
||||
|
||||
/// Property with zero-arg function type.
|
||||
property7: () -> String = () -> "string"
|
||||
|
||||
/// Property with one-arg function type.
|
||||
property8: (String) -> Int = (str) -> str.length
|
||||
|
||||
/// Property with two-arg function type.
|
||||
property9: (String, String) -> Int = (str1, str2) -> str1.length + str2.length
|
||||
|
||||
/// Property with complex type.
|
||||
property10: Map<List<String?>?, (Boolean?) -> Map<Int, Float>> = Map(List("str"), (b) -> Map(3, 3.0))
|
||||
}
|
||||
38
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyTypeReferences.pkl
vendored
Normal file
38
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classPropertyTypeReferences.pkl
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/// Class properties whose types reference classes from
|
||||
/// the same module, a different module, and external modules.
|
||||
module com.package1.classPropertyTypeReferences
|
||||
|
||||
import "shared.pkl"
|
||||
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
|
||||
class MyClass
|
||||
|
||||
class TypeReferences {
|
||||
/// Property with intra-module simple type.
|
||||
property1: MyClass = new MyClass {}
|
||||
|
||||
/// Property with inter-module list type.
|
||||
property2: List<shared.MyClass> = List(new shared.MyClass {})
|
||||
|
||||
/// Property with external-module set type.
|
||||
property3: Set<external1.MyClass> = Set(new external1.MyClass {})
|
||||
|
||||
/// Property with intra-module and inter-module map type.
|
||||
property4: Map<MyClass, shared.MyClass> = Map(new MyClass {}, new shared.MyClass {})
|
||||
|
||||
/// Property with external-module optional type.
|
||||
property5: external1.MyClass? = new external1.MyClass {}
|
||||
|
||||
/// Property with zero-arg intra-module function type.
|
||||
property6: () -> MyClass = () -> new MyClass {}
|
||||
|
||||
/// Property with one-arg inter-module and external-module function type.
|
||||
property7: (shared.MyClass) -> external1.MyClass = (myClass) -> new external1.MyClass {}
|
||||
|
||||
/// Property with two-arg intra-module, inter-module, and external-module function type.
|
||||
property8: (MyClass, shared.MyClass) -> external1.MyClass = (myClass1, myClass2) -> new external1.MyClass {}
|
||||
|
||||
/// Property with intra-module mapping type.
|
||||
property9: Mapping<String, MyClass>
|
||||
}
|
||||
24
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classTypeConstraints.pkl
vendored
Normal file
24
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/classTypeConstraints.pkl
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
module com.package1.classTypeConstraints
|
||||
|
||||
class Person1 {
|
||||
name: String(length >= 3)
|
||||
address: Address(street != city)
|
||||
}
|
||||
|
||||
emailAddress = (str) -> str.matches(Regex(#".+@.+"#))
|
||||
|
||||
class Person2 {
|
||||
email: String(emailAddress)
|
||||
}
|
||||
|
||||
class Address {
|
||||
street: String(!isEmpty)
|
||||
city: String = "San Francisco"
|
||||
}
|
||||
|
||||
class Project {
|
||||
// constraint for element type of optional type
|
||||
type: String(oneOf(List("open-source", "closed-source")))?
|
||||
// constraints for map type and its constituent key/value types
|
||||
contacts: Map<String(!isEmpty), String(emailAddress)>(length > 10, length < 20)
|
||||
}
|
||||
48
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/doc-package-info.pkl
vendored
Normal file
48
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/doc-package-info.pkl
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Docs for Package 1.
|
||||
///
|
||||
/// * [docLinks]
|
||||
/// * [docLinks.age]
|
||||
/// * [docLinks.sing()]
|
||||
/// * [docLinks.Person]
|
||||
/// * [docLinks.Person.name]
|
||||
/// * [docLinks.PersonList]
|
||||
///
|
||||
/// * [external1]
|
||||
/// * [external1.MyClass]
|
||||
@Deprecated { message = "com.package1 is deprecated" }
|
||||
amends "pkl:DocPackageInfo"
|
||||
|
||||
import "docLinks.pkl"
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
|
||||
name = "com.package1"
|
||||
version = "1.2.3"
|
||||
importUri = "https://pkl.io/"
|
||||
authors {
|
||||
"package1-publisher@group.apple.com"
|
||||
}
|
||||
sourceCode = "https://example.com/package1/"
|
||||
sourceCodeUrlScheme = "https://example.com/package1%{path}#L%{line}-L%{endLine}"
|
||||
issueTracker = "https://issues.apple.com/package1/"
|
||||
|
||||
dependencies {
|
||||
new {
|
||||
name = "com.package2"
|
||||
version = "4.5.6"
|
||||
sourceCode = "https://example.com/package2/"
|
||||
}
|
||||
new {
|
||||
name = "com.externalpackage"
|
||||
version = "7.8.9"
|
||||
sourceCode = "https://example.com/externalpackage/"
|
||||
documentation = "https://example.com/docs/externalpackage/"
|
||||
}
|
||||
new {
|
||||
name = "pkl"
|
||||
// use fixed version to avoid churn in expected test outputs
|
||||
version = "0.24.0"
|
||||
sourceCode = "https://github.com/apple/pkl/blob/dev/stdlib/"
|
||||
sourceCodeUrlScheme = "https://github.com/apple/pkl/blob/0.24.0/stdlib%{path}#L%{line}-L%{endLine}"
|
||||
documentation = "https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/"
|
||||
}
|
||||
}
|
||||
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExample.pkl
vendored
Normal file
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExample.pkl
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
@DocExample {
|
||||
subjects {
|
||||
"com.package1.docExampleSubject1"
|
||||
"com.package1.docExampleSubject2"
|
||||
}
|
||||
}
|
||||
module com.package1.docExample
|
||||
|
||||
amends "docExampleSubject1.pkl"
|
||||
|
||||
import "docExampleSubject2.pkl"
|
||||
|
||||
x = docExampleSubject2.y
|
||||
6
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExample2.pkl
vendored
Normal file
6
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExample2.pkl
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
@DocExample { subjects { "com.package1.docExampleSubject1" } }
|
||||
module com.package1.docExample2
|
||||
|
||||
amends "docExampleSubject1.pkl"
|
||||
|
||||
x = 42
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExampleSubject1.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExampleSubject1.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.package1.docExampleSubject1
|
||||
|
||||
x: Int
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExampleSubject2.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docExampleSubject2.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.package1.docExampleSubject2
|
||||
|
||||
y: Int
|
||||
84
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docLinks.pkl
vendored
Normal file
84
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/docLinks.pkl
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
module com.package1.docLinks
|
||||
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
import "shared.pkl"
|
||||
import "docLinks.pkl"
|
||||
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
age: Int
|
||||
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
/// [song]
|
||||
function sing(song: String) = "tra-la-la"
|
||||
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
/// [name], [call()]
|
||||
class Person {
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
/// [name], [call()]
|
||||
name: String
|
||||
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
/// [name], [call()]
|
||||
/// [number]
|
||||
function call(number: String) = "calling $number"
|
||||
}
|
||||
|
||||
/// [external1], [external1.MyClass]
|
||||
/// [shared], [shared.MyClass]
|
||||
/// [age], [sing()], [Person], [Person.name], [Person.call()], [PersonList]
|
||||
/// [docLinks], [docLinks.age], [docLinks.sing()],
|
||||
/// [docLinks.Person], [docLinks.Person.name], [docLinks.PersonList],
|
||||
/// [custom *link* text][docLinks.sing()]
|
||||
/// [module], [module.age], [module.sing()],
|
||||
/// [module.Person], [module.Person.name], [module.PersonList],
|
||||
/// [custom *link* text][module.sing()]
|
||||
typealias PersonList = List<Person>
|
||||
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/methodAnnotations.pkl
vendored
Normal file
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/methodAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
module com.package1.methodAnnotations
|
||||
|
||||
/// This [mthod()] thought to have a correctly spelled name.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "method()"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "function" }
|
||||
}
|
||||
function mthod(): Int = 42
|
||||
|
||||
|
||||
/// This [mthod()] thought to have a correctly spelled name.
|
||||
///
|
||||
/// Unfortunately, it did not, as we explain in this expandable comment.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "method()"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "function" }
|
||||
}
|
||||
function mthodWithExpandableComment(): Int = 42
|
||||
|
||||
|
||||
// This [method()] indeed has a properly spelled name, but no doc comment.
|
||||
@AlsoKnownAs {
|
||||
names { "function" }
|
||||
}
|
||||
function method(): Int = 42
|
||||
54
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleComments.pkl
vendored
Normal file
54
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleComments.pkl
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/// The greatest breakthrough since ever.
|
||||
///
|
||||
/// ### Installation
|
||||
///
|
||||
/// Just follow these simple steps:
|
||||
///
|
||||
/// 1. Install it
|
||||
/// 1. I promise it's easy.
|
||||
/// 2. You'll figure it out.
|
||||
/// 1. Install it
|
||||
/// ```
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// ```
|
||||
/// 1. Install it
|
||||
///
|
||||
/// Let me **emphasize** how *simple* this is.
|
||||
///
|
||||
/// 😀😀😀 emoji day 😎😎😎 don't get 😡😡😡
|
||||
///
|
||||
/// ### Code
|
||||
///
|
||||
/// The code is beautiful:
|
||||
///
|
||||
/// ```
|
||||
/// /// example module
|
||||
/// module foo.bar
|
||||
///
|
||||
/// person {
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// }
|
||||
///
|
||||
/// function sing() = "tra-la-la"
|
||||
///
|
||||
/// class Person {
|
||||
/// name: String
|
||||
/// age: Int
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Random Tips
|
||||
///
|
||||
/// - don't give up
|
||||
/// - just don't
|
||||
/// - don't give up
|
||||
///
|
||||
/// # Level 1
|
||||
/// ## Level 2
|
||||
/// ### Level 3
|
||||
/// #### Level 4
|
||||
/// ##### Level 5
|
||||
/// ###### Level 6
|
||||
module com.package1.moduleComments
|
||||
9
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleExtend.pkl
vendored
Normal file
9
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleExtend.pkl
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module com.package1.moduleExtend
|
||||
|
||||
extends "baseModule.pkl"
|
||||
|
||||
extendProperty = 42
|
||||
|
||||
function extendMethod() = 42
|
||||
|
||||
class ExtendClass {}
|
||||
2
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleInfoAnnotation.pkl
vendored
Normal file
2
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleInfoAnnotation.pkl
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
@ModuleInfo { minPklVersion = "0.10.0" }
|
||||
module com.package1.moduleInfoAnnotation
|
||||
@@ -0,0 +1,5 @@
|
||||
module com.package1.moduleMethodCommentInheritance
|
||||
|
||||
extends "moduleMethodComments.pkl"
|
||||
|
||||
function method3(arg: String): Boolean = Undefined()
|
||||
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodComments.pkl
vendored
Normal file
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodComments.pkl
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/// Module methods with different kinds of comments.
|
||||
open module com.package1.moduleMethodComments
|
||||
|
||||
// Method with single-line code comment.
|
||||
function method1(): Float = Undefined()
|
||||
|
||||
/*
|
||||
Method with
|
||||
multi-line
|
||||
code comment.
|
||||
*/
|
||||
function method2(): Float = Undefined()
|
||||
|
||||
/// Method with single-line doc comment.
|
||||
function method3(): Float = Undefined()
|
||||
|
||||
/// Method with
|
||||
/// multi-line
|
||||
/// doc comment.
|
||||
function method4(): Float = Undefined()
|
||||
|
||||
/// Method with [single-line](https://apple.com) *Markdown* doc comment.
|
||||
function method5(): Float = Undefined()
|
||||
|
||||
/// Method with
|
||||
/// [multi-line](https://apple.com)
|
||||
/// *Markdown* doc comment.
|
||||
function method6(): Float = Undefined()
|
||||
|
||||
/// 😀😀😀 Method with 😎😎😎 Unicode doc comment. 😡😡😡
|
||||
function method7(): Float = Undefined()
|
||||
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodModifiers.pkl
vendored
Normal file
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodModifiers.pkl
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/// Module methods with different modifiers.
|
||||
module com.package1.moduleMethodModifiers
|
||||
|
||||
/// Method with `abstract` modifier.
|
||||
abstract function method1(arg: String): Boolean
|
||||
|
||||
/*
|
||||
/// Method with `external` modifier.
|
||||
external function method2(arg: String): Boolean
|
||||
|
||||
/// Method with multiple modifiers.
|
||||
abstract external function method3(arg: String): Boolean
|
||||
*/
|
||||
41
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodTypeAnnotations.pkl
vendored
Normal file
41
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodTypeAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/// Module methods with different kinds of type annotations.
|
||||
module com.package1.moduleMethodTypeAnnotations
|
||||
|
||||
/// Zero-arg method without declared types.
|
||||
function method1() = Undefined()
|
||||
|
||||
/// One-arg method without declared types.
|
||||
function method2(arg1) = Undefined()
|
||||
|
||||
/// Two-arg method without declared types.
|
||||
function method3(arg1, arg2) = Undefined()
|
||||
|
||||
/// Zero-arg method with simple types.
|
||||
function method4(): String = Undefined()
|
||||
|
||||
/// One-arg method with simple types.
|
||||
function method5(arg1: Boolean): Int = Undefined()
|
||||
|
||||
/// Two-arg method with simple types.
|
||||
function method6(arg1: Int, arg2: Float): Duration = Undefined()
|
||||
|
||||
/// Two-arg method with list types.
|
||||
function method7(arg1: List<Int>, arg2: List<Float>): List<Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with set types.
|
||||
function method8(arg1: Set<Int>, arg2: Set<Float>): Set<Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with map types.
|
||||
function method9(arg1: Map<Int, Int>, arg2: Map<Float, Float>): Map<Duration, Duration> = Undefined()
|
||||
|
||||
/// Two-arg method with optional types.
|
||||
function method10(arg1: Int?, arg2: Float?): Duration? = Undefined()
|
||||
|
||||
/// Two-arg method with function types.
|
||||
function method11(arg1: () -> Int, arg2: (Int) -> Float): (Int, Float) -> Duration = Undefined()
|
||||
|
||||
/// Two-arg method with partially declared types.
|
||||
function method12(arg1: String, arg2): Boolean = Undefined()
|
||||
|
||||
/// One-arg method with complex types.
|
||||
function method13(arg1: Map<List<String?>?, (Boolean?) -> Map<Int, Float>>): Map<List<Duration?>?, (DataSize?) -> Map<Any, Number>> = Undefined()
|
||||
26
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodTypeReferences.pkl
vendored
Normal file
26
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleMethodTypeReferences.pkl
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/// Module methods whose types reference classes from
|
||||
/// the same module, a different module, and external modules.
|
||||
module com.package1.moduleMethodTypeReferences
|
||||
|
||||
import "shared.pkl"
|
||||
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
|
||||
import "../com.externalpackage/external2.pkl"
|
||||
|
||||
class MyClass
|
||||
|
||||
/// Method with intra-module types.
|
||||
function method1(arg1: MyClass, arg2: MyClass): MyClass = Undefined()
|
||||
|
||||
/// Method with inter-module types.
|
||||
function method2(arg1: shared.MyClass, arg2: shared.MyClass): shared.MyClass = Undefined()
|
||||
|
||||
/// Method with external-module types.
|
||||
function method3(arg1: external1.MyClass, arg2: external2.MyClass): List<external1.MyClass> = Undefined()
|
||||
|
||||
/// Method with intra-module, inter-module, and external-module types.
|
||||
function method4(arg1: MyClass, arg2: shared.MyClass): external1.MyClass = Undefined()
|
||||
|
||||
/// Method with complex intra-module, inter-module, and external-module types.
|
||||
function method5(arg1: MyClass?, arg2: Map<shared.MyClass, external1.MyClass>): (external1.MyClass) -> external2.MyClass = Undefined()
|
||||
77
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyAnnotations.pkl
vendored
Normal file
77
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
module com.package1.modulePropertyAnnotations
|
||||
|
||||
/// This [prperty] thought to have a correctly spelled name.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "property"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "field"; "item" }
|
||||
}
|
||||
hidden prperty = 42
|
||||
|
||||
|
||||
/// This [prperty] thought to have a correctly spelled name.
|
||||
///
|
||||
/// Unfortunately, it did not, as we explain in this expandable comment.
|
||||
@Deprecated {
|
||||
message = "Spelling mistake."
|
||||
replaceWith = "property"
|
||||
}
|
||||
@AlsoKnownAs {
|
||||
names { "field"; "item" }
|
||||
}
|
||||
hidden prpertyWithExpandableComment = 42
|
||||
|
||||
|
||||
// This [property] indeed has a properly spelled name, but no doc comment.
|
||||
@AlsoKnownAs {
|
||||
names { "field"; "item" }
|
||||
}
|
||||
hidden property = 42
|
||||
|
||||
|
||||
|
||||
|
||||
class UserDefinedAnnotation extends Annotation {
|
||||
messageOpt: String?
|
||||
messageReq: String
|
||||
}
|
||||
|
||||
@UserDefinedAnnotation {
|
||||
messageReq = "Hi!"
|
||||
}
|
||||
propertyUserDefinedAnnotation: Int = 42
|
||||
|
||||
|
||||
|
||||
|
||||
class UserDefinedAnnotation1 extends Annotation {
|
||||
nested: UserDefinedAnnotation
|
||||
}
|
||||
|
||||
@UserDefinedAnnotation1 {
|
||||
nested = new UserDefinedAnnotation {
|
||||
messageReq = "Hi!"
|
||||
}
|
||||
}
|
||||
propertyUserDefinedAnnotation1: Int = 42
|
||||
|
||||
|
||||
|
||||
|
||||
class UserDefinedAnnotation2 extends Annotation {
|
||||
nested: UserDefinedAnnotation2?
|
||||
}
|
||||
|
||||
@UserDefinedAnnotation2 {
|
||||
nested = new UserDefinedAnnotation2 {
|
||||
nested = new UserDefinedAnnotation2 {
|
||||
nested = new UserDefinedAnnotation2 {
|
||||
nested = new UserDefinedAnnotation2 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
propertyUserDefinedAnnotation2: Int = 42
|
||||
@@ -0,0 +1,5 @@
|
||||
module com.package1.modulePropertyCommentInheritance
|
||||
|
||||
extends "modulePropertyComments.pkl"
|
||||
|
||||
property3: Float = 1.23
|
||||
54
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyComments.pkl
vendored
Normal file
54
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyComments.pkl
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/// Module properties with different kinds of comments.
|
||||
open module com.package1.modulePropertyComments
|
||||
|
||||
// Property with single-line code comment.
|
||||
property1: Float = 3.14159265359
|
||||
|
||||
/*
|
||||
Property with
|
||||
multi-line
|
||||
code comment.
|
||||
*/
|
||||
property2: Float = 3.14159265359
|
||||
|
||||
/// Property with single-line doc comment.
|
||||
property3: Float = 3.14159265359
|
||||
|
||||
/// Property with
|
||||
/// multi-line
|
||||
/// doc comment.
|
||||
property4: Float = 3.14159265359
|
||||
|
||||
/// Property with [single-line](https://apple.com) *Markdown* doc comment.
|
||||
property5: Float = 3.14159265359
|
||||
|
||||
/// Property with
|
||||
/// [multi-line](https://apple.com)
|
||||
/// *Markdown* doc comment.
|
||||
property6: Float = 3.14159265359
|
||||
|
||||
/// 😀😀😀 Property with 😎😎😎 Unicode doc comment. 😡😡😡
|
||||
property7: Float = 3.14159265359
|
||||
|
||||
/// Summary
|
||||
/// ```
|
||||
///
|
||||
/// code = 4 * 10
|
||||
/// ```
|
||||
/// Rest of the body
|
||||
property8: Int = 0
|
||||
|
||||
/// Sumary
|
||||
/// ```java
|
||||
///
|
||||
/// code = 0
|
||||
/// ```
|
||||
/// Rest
|
||||
property9: Int = 1
|
||||
|
||||
/// ```
|
||||
///
|
||||
/// code = 2
|
||||
/// ```
|
||||
/// Rest
|
||||
property10: Int = 2
|
||||
19
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyModifiers.pkl
vendored
Normal file
19
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyModifiers.pkl
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/// Module properties with different modifiers.
|
||||
module com.package1.modulePropertyModifiers
|
||||
|
||||
/// Property with `local` modifier.
|
||||
local property1 = 3.14159265359
|
||||
|
||||
/// Property with `hidden` modifier.
|
||||
hidden property2: Float = 3.14159265359
|
||||
|
||||
/*
|
||||
/// Property with `external` modifier.
|
||||
external property3: Float
|
||||
|
||||
/// Property with `abstract` modifier.
|
||||
abstract property4: Float
|
||||
|
||||
/// Property with multiple modifiers.
|
||||
abstract external hidden property5: Float
|
||||
*/
|
||||
32
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyTypeAnnotations.pkl
vendored
Normal file
32
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyTypeAnnotations.pkl
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/// Module properties with different kinds of type annotations.
|
||||
module com.package1.modulePropertyTypeAnnotations
|
||||
|
||||
/// Property without declared type.
|
||||
property1 = 3.14159265359
|
||||
|
||||
/// Property with simple type.
|
||||
property2: Float = 3.14159265359
|
||||
|
||||
/// Property with list type.
|
||||
property3: List<String> = List("1", "2", "3")
|
||||
|
||||
/// Property with set type.
|
||||
property4: Set<String> = Set("1", "2", "3")
|
||||
|
||||
/// Property with map type.
|
||||
property5: Map<String, Duration> = Map("one", 1.s, "two", 2.min, "three", 3.h)
|
||||
|
||||
/// Property with optional type.
|
||||
property6: String? = "string"
|
||||
|
||||
/// Property with zero-arg function type.
|
||||
property7: () -> String = () -> "string"
|
||||
|
||||
/// Property with one-arg function type.
|
||||
property8: (String) -> Int = (str) -> str.length
|
||||
|
||||
/// Property with two-arg function type.
|
||||
property9: (String, String) -> Int = (str1, str2) -> str1.length + str2.length
|
||||
|
||||
/// Property with complex type.
|
||||
property10: Map<List<String?>?, (Boolean?) -> Map<Int, Float>> = Map(List("str"), (b) -> Map(3, 3.0))
|
||||
36
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyTypeReferences.pkl
vendored
Normal file
36
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/modulePropertyTypeReferences.pkl
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/// Module properties whose types reference classes from
|
||||
/// the same module, a different module, and external modules.
|
||||
module com.package1.modulePropertyTypeReferences
|
||||
|
||||
import "shared.pkl"
|
||||
|
||||
import "../com.externalpackage/external1.pkl"
|
||||
|
||||
class MyClass
|
||||
|
||||
/// Property with intra-module simple type.
|
||||
property1: MyClass = new MyClass {}
|
||||
|
||||
/// Property with inter-module list type.
|
||||
property2: List<shared.MyClass> = List(new shared.MyClass {})
|
||||
|
||||
/// Property with external-module set type.
|
||||
property3: Set<external1.MyClass> = Set(new external1.MyClass {})
|
||||
|
||||
/// Property with intra-module and inter-module map type.
|
||||
property4: Map<MyClass, shared.MyClass> = Map(new MyClass {}, new shared.MyClass {})
|
||||
|
||||
/// Property with external-module optional type.
|
||||
property5: external1.MyClass? = new external1.MyClass {}
|
||||
|
||||
/// Property with zero-arg intra-module function type.
|
||||
property6: () -> MyClass = () -> new MyClass {}
|
||||
|
||||
/// Property with one-arg inter-module and external-module function type.
|
||||
property7: (shared.MyClass) -> external1.MyClass = (myClass) -> new external1.MyClass {}
|
||||
|
||||
/// Property with two-arg intra-module, inter-module, and external-module function type.
|
||||
property8: (MyClass, shared.MyClass) -> external1.MyClass = (myClass1, myClass2) -> new external1.MyClass {}
|
||||
|
||||
/// Property with intra-module mapping type.
|
||||
property9: Mapping<String, MyClass>
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleTypes1.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleTypes1.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.package1.moduleTypes1
|
||||
|
||||
n: Int
|
||||
37
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleTypes2.pkl
vendored
Normal file
37
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/moduleTypes2.pkl
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
module com.package1.moduleTypes2
|
||||
|
||||
import "moduleTypes1.pkl"
|
||||
|
||||
x1: moduleTypes1
|
||||
|
||||
x2: moduleTypes1?
|
||||
|
||||
x3: Listing<moduleTypes1>
|
||||
|
||||
x4: Mapping<moduleTypes1, moduleTypes1>
|
||||
|
||||
x5: String|moduleTypes1|Int
|
||||
|
||||
x6: module
|
||||
|
||||
x7: List<module>
|
||||
|
||||
x8: String|module|Int
|
||||
|
||||
class Foo {
|
||||
x1: moduleTypes1
|
||||
|
||||
x2: moduleTypes1?
|
||||
|
||||
x3: Listing<moduleTypes1>
|
||||
|
||||
x4: Mapping<moduleTypes1, moduleTypes1>
|
||||
|
||||
x5: String|moduleTypes1|Int
|
||||
|
||||
x6: module
|
||||
|
||||
x7: List<module>
|
||||
|
||||
x8: String|module|Int
|
||||
}
|
||||
7
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/nested/nested2/nestedModule.pkl
vendored
Normal file
7
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/nested/nested2/nestedModule.pkl
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
module com.package1.nested.nested2.nestedModule
|
||||
|
||||
myProperty = 42
|
||||
|
||||
function myMethod() = 42
|
||||
|
||||
class MyClass {}
|
||||
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/shared.pkl
vendored
Normal file
3
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/shared.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module com.package1.shared
|
||||
|
||||
class MyClass
|
||||
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliases.pkl
vendored
Normal file
31
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliases.pkl
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
open module com.package1.typealiases
|
||||
|
||||
/// A [String] representing an [Email] address.
|
||||
@AlsoKnownAs { names { "OtherName" } }
|
||||
typealias Email = String(contains("@"))
|
||||
|
||||
uint: UInt
|
||||
|
||||
uints: List<UInt>
|
||||
|
||||
/// My [Email].
|
||||
email: Email
|
||||
|
||||
emails: List<Email>
|
||||
|
||||
/// Sends an [Email].
|
||||
function send(email: Email): Email = "abc"
|
||||
|
||||
open class Person {
|
||||
uint: UInt
|
||||
|
||||
list: List<UInt>
|
||||
|
||||
/// A person's [Email].
|
||||
email: Email
|
||||
|
||||
emails: List<Email>
|
||||
|
||||
/// Sends an [Email].
|
||||
function send(email: Email): Email = "abc"
|
||||
}
|
||||
32
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliases2.pkl
vendored
Normal file
32
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliases2.pkl
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
module com.package1.typealiases2
|
||||
|
||||
class Person { name: String }
|
||||
|
||||
typealias List2<E> = List<E>
|
||||
typealias Map2<V, K> = Map<K, V>
|
||||
typealias StringMap<V> = Map<String, V>
|
||||
typealias MMap<X> = Map<X, X>
|
||||
|
||||
res1: List2<Int>
|
||||
res2: List2<List2<String>>
|
||||
res3: Map2<String, Int>
|
||||
res4: StringMap<Duration>
|
||||
res5: MMap<Person?>
|
||||
|
||||
res6: List2
|
||||
res7: Map2
|
||||
res8: StringMap
|
||||
res9: MMap
|
||||
|
||||
class Foo {
|
||||
res1: List2<Int>
|
||||
res2: List2<List2<String>>
|
||||
res3: Map2<String, Int>
|
||||
res4: StringMap<Duration>
|
||||
res5: MMap<Person?>
|
||||
|
||||
res6: List2
|
||||
res7: Map2
|
||||
res8: StringMap
|
||||
res9: MMap
|
||||
}
|
||||
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliasesInheritance.pkl
vendored
Normal file
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/typeAliasesInheritance.pkl
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module com.package1.typeAliasInheritance
|
||||
|
||||
extends "typeAliases.pkl"
|
||||
|
||||
email2: Email
|
||||
|
||||
emails2: List<Email>
|
||||
|
||||
class Person2 extends Person {
|
||||
email2: Email
|
||||
|
||||
emails2: List<Email>
|
||||
}
|
||||
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unionTypes.pkl
vendored
Normal file
13
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unionTypes.pkl
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
module com.package1.unionTypes
|
||||
|
||||
res1: Boolean|Number
|
||||
|
||||
res2: "foo"|"bar"|"baz"
|
||||
|
||||
res3: Boolean|List<String>
|
||||
|
||||
res4: Boolean|List<String>?
|
||||
|
||||
res5: (Boolean|List<String>)?
|
||||
|
||||
res6: (Boolean|List<String>)?|Number
|
||||
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedClass.pkl
vendored
Normal file
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedClass.pkl
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module com.package1.unlistedClass
|
||||
|
||||
myProperty = 42
|
||||
|
||||
function myMethod() = 42
|
||||
|
||||
@Unlisted
|
||||
class MyClass {}
|
||||
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedMethod.pkl
vendored
Normal file
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedMethod.pkl
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module com.package1.unlistedMethod
|
||||
|
||||
myProperty = 42
|
||||
|
||||
@Unlisted
|
||||
function myMethod() = 42
|
||||
|
||||
class MyClass {}
|
||||
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedModule.pkl
vendored
Normal file
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedModule.pkl
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
@Unlisted
|
||||
module com.package1.unlistedModule
|
||||
|
||||
myProperty = 42
|
||||
|
||||
function myMethod() = 42
|
||||
|
||||
class MyClass {}
|
||||
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedProperty.pkl
vendored
Normal file
8
pkl-doc/src/test/files/DocGeneratorTest/input/com.package1/unlistedProperty.pkl
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module com.package1.unlistedProperty
|
||||
|
||||
@Unlisted
|
||||
myProperty = 42
|
||||
|
||||
function myMethod() = 42
|
||||
|
||||
class MyClass {}
|
||||
11
pkl-doc/src/test/files/DocGeneratorTest/input/com.package2/Module3.pkl
vendored
Normal file
11
pkl-doc/src/test/files/DocGeneratorTest/input/com.package2/Module3.pkl
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
module com.package2.Module3
|
||||
|
||||
property3: String
|
||||
|
||||
function function3(n: Int): String = n.toString()
|
||||
|
||||
class Class3 {
|
||||
property3: String
|
||||
|
||||
function function3(n: Int): String = n.toString()
|
||||
}
|
||||
23
pkl-doc/src/test/files/DocGeneratorTest/input/com.package2/doc-package-info.pkl
vendored
Normal file
23
pkl-doc/src/test/files/DocGeneratorTest/input/com.package2/doc-package-info.pkl
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/// Docs for Package 2.
|
||||
amends "pkl:DocPackageInfo"
|
||||
|
||||
name = "com.package2"
|
||||
version = "4.5.6"
|
||||
importUri = "modulepath:/com/package2/"
|
||||
authors {
|
||||
"package2-publisher@group.apple.com"
|
||||
}
|
||||
sourceCode = "https://sources.apple.com/package2/"
|
||||
sourceCodeUrlScheme = "https://example.com/blob/\(version)%{path}#L%{line}-L%{endLine}"
|
||||
issueTracker = "https://issues.apple.com/package2/"
|
||||
|
||||
dependencies {
|
||||
new {
|
||||
name = "pkl"
|
||||
// use fixed version to avoid churn in expected test outputs
|
||||
version = "0.24.0"
|
||||
sourceCode = "https://github.com/apple/\(name)/blob/dev/stdlib/"
|
||||
sourceCodeUrlScheme = "https://github.com/apple/\(name)/blob/\(version)/stdlib%{path}#L%{line}-L%{endLine}"
|
||||
documentation = "https://pkl-lang.org/stdlib/\(name)/\(version)/"
|
||||
}
|
||||
}
|
||||
65
pkl-doc/src/test/files/DocGeneratorTest/input/docsite-info.pkl
vendored
Normal file
65
pkl-doc/src/test/files/DocGeneratorTest/input/docsite-info.pkl
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/// Let the games begin.
|
||||
///
|
||||
/// ## Great Library
|
||||
///
|
||||
/// Just follow these simple steps. You'll love it.
|
||||
///
|
||||
/// 1. Install it
|
||||
/// 1. I promise it's easy.
|
||||
/// 2. You'll figure it out.
|
||||
/// 1. Install it
|
||||
/// ```
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// ```
|
||||
/// 1. Install it
|
||||
///
|
||||
/// Let me **emphasize** how *simple* this is.
|
||||
///
|
||||
/// 😀😀😀 emoji day 😎😎😎 don't get 😡😡😡
|
||||
///
|
||||
/// ## Code
|
||||
///
|
||||
/// The code is beautiful:
|
||||
///
|
||||
/// ```
|
||||
/// /// example module
|
||||
/// module foo.bar
|
||||
///
|
||||
/// person {
|
||||
/// name = "Pigeon"
|
||||
/// age = 42
|
||||
/// }
|
||||
///
|
||||
/// function sing() = "tra-la-la"
|
||||
///
|
||||
/// class Person {
|
||||
/// name: String
|
||||
/// age: Int
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Random Tips
|
||||
///
|
||||
/// - don't give up
|
||||
/// - just don't
|
||||
/// - don't give up
|
||||
///
|
||||
/// # Level 1
|
||||
/// ## Level 2
|
||||
/// ### Level 3
|
||||
/// #### Level 4
|
||||
/// ##### Level 5
|
||||
/// ###### Level 6
|
||||
///
|
||||
/// * [docLinks]
|
||||
/// * [docLinks.age]
|
||||
/// * [docLinks.sing()]
|
||||
/// * [docLinks.Person]
|
||||
/// * [docLinks.Person.name]
|
||||
/// * [docLinks.PersonList]
|
||||
amends "pkl:DocsiteInfo"
|
||||
|
||||
import "com.package1/docLinks.pkl"
|
||||
|
||||
title = "Docsite Title"
|
||||
150
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/baseModule/BaseClass.html
vendored
Normal file
150
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/baseModule/BaseClass.html
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>BaseClass (com.package1/baseModule:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/baseModule/BaseClass.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.baseModule" data-class-name="BaseClass" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a> > <a class="declaration-parent-link" href="index.html">com.package1.baseModule</a>
|
||||
<h1 id="declaration-title">BaseClass<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member">
|
||||
<div class="member-signature">class <span class="name-decl">BaseClass</span></div>
|
||||
<dl class="member-info">
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="BaseClass.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="BaseClass.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
235
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/baseModule/index.html
vendored
Normal file
235
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/baseModule/index.html
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>baseModule (com.package1:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/baseModule/index.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.baseModule" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a>
|
||||
<h1 id="declaration-title">com.package1.baseModule<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_properties">Properties</a></li>
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
<li><a href="#_classes">Classes</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member">
|
||||
<div class="member-signature">open module <span class="name-decl">com.package1.baseModule</span></div>
|
||||
<dl class="member-info">
|
||||
<dt class="">Module URI:</dt>
|
||||
<dd><span class="import-uri">https://pkl.io/baseModule.pkl</span><i class="copy-uri-button material-icons">content_copy</i></dd>
|
||||
<dt class="">Source code:</dt>
|
||||
<dd><a href="https://example.com/package1/baseModule.pkl">baseModule.pkl</a></dd>
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_properties" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Properties<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="output" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#output">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">hidden </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">output</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/ModuleOutput.html" class="name-ref">ModuleOutput</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>The output of this module.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Defaults to all module properties rendered as either Pcf or the format specified on the command line.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="baseProperty" class="anchor"> </div>
|
||||
<div class="member"><a class="member-selflink material-icons" href="#baseProperty">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers"></div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">baseProperty</span>: unknown<a class="member-source-link" href="https://example.com/package1/baseModule.pkl#L123-L456">Source</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="index.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="index.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="relativePathTo()" class="anchor"> </div>
|
||||
<div id="relativePathTo().other" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#relativePathTo()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">relativePathTo</span>(<span class="param1">other</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Module.html" class="name-ref">Module</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/List.html" class="name-ref">List</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the relative, descendent directory path between this module and <code>other</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if no such path exists.</p>
|
||||
<p>For example, if module <code>mod1</code> has path <code>/dir1/mod1.pkl</code>, and module <code>mod2</code> has path <code>/dir1/dir2/dir3/mod2.pkl</code>,
|
||||
then <code>mod1.relativePathTo(mod2)</code> will return <code>List("dir2", "dir3")</code>.</p>
|
||||
<p>A common use case is to compute the directory path between a template located at the root of a hierarchy
|
||||
(say <code>rootModule.pkl</code>) and the currently evaluated module (accessible via the <code>module</code> keyword):</p>
|
||||
<pre><code>import "rootModule.pkl" // self-import
|
||||
path = rootModule.relativePathTo(module)
|
||||
</code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="baseMethod()" class="anchor"> </div>
|
||||
<div class="member"><a class="member-selflink material-icons" href="#baseMethod()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">baseMethod</span>(): unknown<a class="member-source-link" href="https://example.com/package1/baseModule.pkl#L123-L456">Source</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_classes" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Classes</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="BaseClass" class="anchor"> </div>
|
||||
<div class="member with-page-link"><a class="member-selflink material-icons" href="#BaseClass">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">class </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><a href="BaseClass.html" class="name-decl">BaseClass</a><a class="member-source-link" href="https://example.com/package1/baseModule.pkl#L123-L456">Source</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>AnnotatedClass (com.package1/classAnnotations:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/classAnnotations/AnnotatedClass.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.classAnnotations" data-class-name="AnnotatedClass" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a> > <a class="declaration-parent-link" href="index.html">com.package1.classAnnotations</a>
|
||||
<h1 id="declaration-title">AnnotatedClass<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member">
|
||||
<div class="member-signature member-deprecated">class <span class="name-decl">AnnotatedClass</span></div>
|
||||
<div class="doc-comment">Deprecated.</div>
|
||||
<dl class="member-info">
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
<dt>Also known as:</dt>
|
||||
<dd><code>OtherName</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="AnnotatedClass.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="AnnotatedClass.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,155 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>AnnotatedClss (com.package1/classAnnotations:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/classAnnotations/AnnotatedClss.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.classAnnotations" data-class-name="AnnotatedClss" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a> > <a class="declaration-parent-link" href="index.html">com.package1.classAnnotations</a>
|
||||
<h1 id="declaration-title">AnnotatedClss<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_overview">Overview</a></li>
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i>
|
||||
<div class="member-signature member-deprecated">class <span class="name-decl">AnnotatedClss</span></div>
|
||||
<div class="doc-comment">Deprecated: Spelling mistake. Replace with: <code>AnnotatedClass</code></div>
|
||||
<dl class="member-info">
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
<dt>Also known as:</dt>
|
||||
<dd><code>OtherName</code></dd>
|
||||
</dl>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This <code>AnnotatedClss</code> thought to have a correctly spelled name.</p></div>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="AnnotatedClss.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="AnnotatedClss.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,155 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>AnnotatedClssWithExpandableComment (com.package1/classAnnotations:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/classAnnotations/AnnotatedClssWithExpandableComment.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.classAnnotations" data-class-name="AnnotatedClssWithExpandableComment" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a> > <a class="declaration-parent-link" href="index.html">com.package1.classAnnotations</a>
|
||||
<h1 id="declaration-title">AnnotatedClssWithExpandableComment<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_overview">Overview</a></li>
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i>
|
||||
<div class="member-signature member-deprecated">class <span class="name-decl">AnnotatedClssWithExpandableComment</span></div>
|
||||
<div class="doc-comment">Deprecated: Spelling mistake. Replace with: <code>AnnotatedClass</code></div>
|
||||
<dl class="member-info">
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
<dt>Also known as:</dt>
|
||||
<dd><code>OtherName</code></dd>
|
||||
</dl>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This <code>AnnotatedClssWithExpandableComment</code> thought to have a correctly spelled name.</p><p>Unfortunately, it did not, as we explain in this expandable comment.</p></div>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="AnnotatedClssWithExpandableComment.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="AnnotatedClssWithExpandableComment.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
238
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/classAnnotations/index.html
vendored
Normal file
238
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/classAnnotations/index.html
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>classAnnotations (com.package1:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/classAnnotations/index.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.classAnnotations" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a>
|
||||
<h1 id="declaration-title">com.package1.classAnnotations<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_properties">Properties</a></li>
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
<li><a href="#_classes">Classes</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member">
|
||||
<div class="member-signature">open module <span class="name-decl">com.package1.classAnnotations</span></div>
|
||||
<dl class="member-info">
|
||||
<dt class="">Module URI:</dt>
|
||||
<dd><span class="import-uri">https://pkl.io/classAnnotations.pkl</span><i class="copy-uri-button material-icons">content_copy</i></dd>
|
||||
<dt class="">Source code:</dt>
|
||||
<dd><a href="https://example.com/package1/classAnnotations.pkl">classAnnotations.pkl</a></dd>
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_properties" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Properties<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="output" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#output">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">hidden </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">output</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/ModuleOutput.html" class="name-ref">ModuleOutput</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>The output of this module.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Defaults to all module properties rendered as either Pcf or the format specified on the command line.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="index.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="index.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="relativePathTo()" class="anchor"> </div>
|
||||
<div id="relativePathTo().other" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#relativePathTo()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="name-decl">relativePathTo</span>(<span class="param1">other</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Module.html" class="name-ref">Module</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/List.html" class="name-ref">List</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the relative, descendent directory path between this module and <code>other</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if no such path exists.</p>
|
||||
<p>For example, if module <code>mod1</code> has path <code>/dir1/mod1.pkl</code>, and module <code>mod2</code> has path <code>/dir1/dir2/dir3/mod2.pkl</code>,
|
||||
then <code>mod1.relativePathTo(mod2)</code> will return <code>List("dir2", "dir3")</code>.</p>
|
||||
<p>A common use case is to compute the directory path between a template located at the root of a hierarchy
|
||||
(say <code>rootModule.pkl</code>) and the currently evaluated module (accessible via the <code>module</code> keyword):</p>
|
||||
<pre><code>import "rootModule.pkl" // self-import
|
||||
path = rootModule.relativePathTo(module)
|
||||
</code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_classes" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Classes</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="AnnotatedClss" class="anchor"> </div>
|
||||
<div class="member with-page-link"><a class="member-selflink material-icons" href="#AnnotatedClss">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers member-deprecated">class </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature member-deprecated"><a href="AnnotatedClss.html" class="name-decl">AnnotatedClss</a><a class="member-source-link" href="https://example.com/package1/classAnnotations.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment">Deprecated: Spelling mistake. Replace with: <code>AnnotatedClass</code></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="AnnotatedClssWithExpandableComment" class="anchor"> </div>
|
||||
<div class="member with-page-link"><a class="member-selflink material-icons" href="#AnnotatedClssWithExpandableComment">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers member-deprecated">class </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature member-deprecated"><a href="AnnotatedClssWithExpandableComment.html" class="name-decl">AnnotatedClssWithExpandableComment</a><a class="member-source-link" href="https://example.com/package1/classAnnotations.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment">Deprecated: Spelling mistake. Replace with: <code>AnnotatedClass</code></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="AnnotatedClass" class="anchor"> </div>
|
||||
<div class="member with-page-link"><a class="member-selflink material-icons" href="#AnnotatedClass">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers member-deprecated">class </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature member-deprecated"><a href="AnnotatedClass.html" class="name-decl">AnnotatedClass</a><a class="member-source-link" href="https://example.com/package1/classAnnotations.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment">Deprecated.</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
150
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/classComments/Comments1.html
vendored
Normal file
150
pkl-doc/src/test/files/DocGeneratorTest/output/com.package1/1.2.3/classComments/Comments1.html
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Comments1 (com.package1/classComments:1.2.3) • Docsite Title</title>
|
||||
<script src="../../../scripts/pkldoc.js" defer="defer"></script>
|
||||
<script src="../../../scripts/scroll-into-view.min.js" defer="defer"></script>
|
||||
<script src="../../../data/com.package1/1.2.3/classComments/Comments1.js" defer="defer"></script>
|
||||
<link href="../../../styles/pkldoc.css" media="screen" type="text/css" rel="stylesheet">
|
||||
<link rel="icon" type="image/svg+xml" href="../../../images/favicon.svg">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../../../images/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="../../../images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="../../../images/favicon-16x16.png">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<header>
|
||||
<div id="doc-title"><a href="../../../index.html">Docsite Title</a></div>
|
||||
<div id="search"><i id="search-icon" class="material-icons">search</i><input id="search-input" type="search" placeholder="Click or press 'S' to search this package" autocomplete="off" data-package-name="com.package1" data-package-version="1.2.3" data-package-url-prefix="../" data-module-name="com.package1.classComments" data-class-name="Comments1" data-root-url-prefix="../../../"></div>
|
||||
</header>
|
||||
<main><a class="declaration-parent-link" href="../../../index.html">Docsite Title</a> > <a class="declaration-parent-link" href="../index.html">com.package1</a> > <a class="declaration-parent-link" href="index.html">com.package1.classComments</a>
|
||||
<h1 id="declaration-title">Comments1<span id="declaration-version">1.2.3</span></h1>
|
||||
<ul class="member-group-links">
|
||||
<li><a href="#_methods">Methods</a></li>
|
||||
</ul>
|
||||
<div id="_overview" class="anchor"> </div>
|
||||
<div id="_declaration" class="member">
|
||||
<div class="member-signature">class <span class="name-decl">Comments1</span></div>
|
||||
<dl class="member-info">
|
||||
<dt class="runtime-data hidden">Known subtypes:</dt>
|
||||
<dd id="known-subtypes" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">Known usages:</dt>
|
||||
<dd id="known-usages" class="runtime-data hidden"></dd>
|
||||
<dt class="runtime-data hidden">All versions:</dt>
|
||||
<dd id="known-versions" class="runtime-data hidden"></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="member-group">
|
||||
<div id="_methods" class="anchor"> </div>
|
||||
<h2 class="member-group-title">Methods<span class="toggle-inherited-members">(<span class="toggle-inherited-members-link button-link">show inherited</span>)</span></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<div id="getClass()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#getClass()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">getClass</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Class.html" class="name-ref">Class</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the class of <code>this</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toString()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#toString()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">toString</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns a string representation of <code>this</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is used to convert the values of string interpolation expressions to strings.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ifNonNull()" class="anchor"> </div>
|
||||
<div id="ifNonNull().Result" class="anchor-param1"> </div>
|
||||
<div id="ifNonNull().transform" class="anchor-param2"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#ifNonNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Any.html" class="name-ref">Any</a>.</span><span class="name-decl">ifNonNull</span><<a class="param1">Result</a>>(<span class="param2">transform</span>: (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html#NonNull" class="name-ref">NonNull</a>) -> <a href="Comments1.html#ifNonNull().Result" class="name-ref">Result</a>): <a href="Comments1.html#ifNonNull().Result" class="name-ref">Result</a>?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns <code>this |> transform</code> if <code>this</code> is non-null, and <code>null</code> otherwise.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>This method is the complement of the <code>??</code> operator and the equivalent of an <code>Option</code> type's <code>map</code> and <code>flatMap</code> methods.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="hasProperty()" class="anchor"> </div>
|
||||
<div id="hasProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#hasProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">hasProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Boolean.html" class="name-ref">Boolean</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Tells if this object has a property with the given <code>name</code>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getProperty()" class="anchor"> </div>
|
||||
<div id="getProperty().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getProperty()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getProperty</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Throws if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="getPropertyOrNull()" class="anchor"> </div>
|
||||
<div id="getPropertyOrNull().name" class="anchor-param1"> </div>
|
||||
<div class="member inherited expandable hidden collapsed with-expandable-docs"><i class="material-icons expandable-docs-icon">expand_more</i><a class="member-selflink material-icons" href="#getPropertyOrNull()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">getPropertyOrNull</span>(<span class="param1">name</span>: <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>): unknown?<span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Returns the value of the property with the given <code>name</code>.</p></div>
|
||||
<div class="doc-comment expandable hidden collapsed"><p>Returns <code>null</code> if a property with this name does not exist.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toDynamic()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toDynamic()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toDynamic</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html" class="name-ref">Dynamic</a><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Dynamic.html"><code>Dynamic</code></a> object.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="toMap()" class="anchor"> </div>
|
||||
<div class="member inherited expandable hidden collapsed"><a class="member-selflink material-icons" href="#toMap()">link</a>
|
||||
<div class="member-left">
|
||||
<div class="member-modifiers">function </div>
|
||||
</div>
|
||||
<div class="member-main">
|
||||
<div class="member-signature"><span class="context"><a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Typed.html" class="name-ref">Typed</a>.</span><span class="name-decl">toMap</span>(): <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html" class="name-ref">Map</a><<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/String.html" class="name-ref">String</a>, unknown><span class="context"> (<a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/index.html" class="name-ref">pkl.base</a>)</span><a class="member-source-link" href="https://github.com/apple/pkl/blob/0.24.0/stdlib/base.pkl#L123-L456">Source</a></div>
|
||||
<div class="doc-comment"><p>Converts this object to a <a href="https://pages.github.com/apple/pkl/stdlib/pkl/0.24.0/base/Map.html"><code>Map</code></a>.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user