aboutsummaryrefslogtreecommitdiff
path: root/plugins/base
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2020-07-17 16:36:09 +0200
committerPaweł Marks <pmarks@virtuslab.com>2020-07-17 16:36:09 +0200
commit6996b1135f61c7d2cb60b0652c6a2691dda31990 (patch)
treed568096c25e31c28d14d518a63458b5a7526b896 /plugins/base
parentde56cab76f556e5b4af0b8c8cb08d8b482b86d0a (diff)
parent1c3530dcbb50c347f80bef694829dbefe89eca77 (diff)
downloaddokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.gz
dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.bz2
dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.zip
Merge branch 'dev-0.11.0'
Diffstat (limited to 'plugins/base')
-rw-r--r--plugins/base/.gitignore3
-rw-r--r--plugins/base/build.gradle.kts35
-rw-r--r--plugins/base/frontend/.gitignore2
-rw-r--r--plugins/base/frontend/build.gradle.kts20
-rw-r--r--plugins/base/frontend/package-lock.json15428
-rw-r--r--plugins/base/frontend/package.json57
-rw-r--r--plugins/base/frontend/postcss.config.js16
-rw-r--r--plugins/base/frontend/src/main/components/app/index.scss27
-rw-r--r--plugins/base/frontend/src/main/components/app/index.tsx11
-rw-r--r--plugins/base/frontend/src/main/components/root.tsx43
-rw-r--r--plugins/base/frontend/src/main/components/search/search.scss37
-rw-r--r--plugins/base/frontend/src/main/components/search/search.tsx75
-rw-r--r--plugins/base/frontend/src/main/components/search/types.ts31
-rw-r--r--plugins/base/frontend/src/main/scss/index.scss1
-rw-r--r--plugins/base/frontend/src/main/types/@jetbrains/index.d.ts3
-rw-r--r--plugins/base/frontend/stylelint.config.js4
-rw-r--r--plugins/base/frontend/tsconfig.json30
-rw-r--r--plugins/base/frontend/webpack.config.js64
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt225
-rw-r--r--plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt81
-rw-r--r--plugins/base/src/main/kotlin/parsers/HtmlParser.kt89
-rw-r--r--plugins/base/src/main/kotlin/parsers/MarkdownParser.kt420
-rw-r--r--plugins/base/src/main/kotlin/parsers/Parser.kt42
-rw-r--r--plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt43
-rw-r--r--plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt77
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt200
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt31
-rw-r--r--plugins/base/src/main/kotlin/renderers/FileWriter.kt88
-rw-r--r--plugins/base/src/main/kotlin/renderers/OutputWriter.kt7
-rw-r--r--plugins/base/src/main/kotlin/renderers/PackageListService.kt51
-rw-r--r--plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt7
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt760
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt51
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/Tags.kt12
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt112
-rw-r--r--plugins/base/src/main/kotlin/renderers/preprocessors.kt27
-rw-r--r--plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt9
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt35
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt26
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt37
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt142
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt217
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt23
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt18
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/MultimoduleLocationProvider.kt32
-rw-r--r--plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt141
-rw-r--r--plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt382
-rw-r--r--plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt48
-rw-r--r--plugins/base/src/main/kotlin/signatures/SignatureProvider.kt8
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt84
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt200
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt258
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt327
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt28
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt127
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt85
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt108
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt165
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt82
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt16
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt178
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt12
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt29
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt9
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt40
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/samples/DefaultSamplesTransformer.kt38
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/samples/KotlinWebsiteSamplesTransformer.kt196
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt151
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt130
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt782
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt17
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt525
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt474
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt480
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt216
-rw-r--r--plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
-rw-r--r--plugins/base/src/main/resources/dokka/format/gfm.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/html-as-java.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/html.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/java-layout-html.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/jekyll.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/format/markdown.properties2
-rwxr-xr-xplugins/base/src/main/resources/dokka/images/arrow_down.svg3
-rw-r--r--plugins/base/src/main/resources/dokka/images/docs_logo.svg7
-rwxr-xr-xplugins/base/src/main/resources/dokka/images/logo-icon.svg3
-rwxr-xr-xplugins/base/src/main/resources/dokka/images/logo-text.svg6
-rw-r--r--plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties2
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/clipboard.js52
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/navigationLoader.js54
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js226
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/scripts.js11
-rw-r--r--plugins/base/src/main/resources/dokka/scripts/search.js7
-rw-r--r--plugins/base/src/main/resources/dokka/styles/jetbrains-mono.css13
-rw-r--r--plugins/base/src/main/resources/dokka/styles/style.css1048
-rw-r--r--plugins/base/src/test/kotlin/basic/DRITest.kt317
-rw-r--r--plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt42
-rw-r--r--plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt118
-rw-r--r--plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt221
-rw-r--r--plugins/base/src/test/kotlin/content/annotations/DepredatedAndSinceKotlinTest.kt103
-rw-r--r--plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt611
-rw-r--r--plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt459
-rw-r--r--plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt456
-rw-r--r--plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt254
-rw-r--r--plugins/base/src/test/kotlin/enums/EnumsTest.kt234
-rw-r--r--plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt104
-rw-r--r--plugins/base/src/test/kotlin/expect/ExpectGenerator.kt13
-rw-r--r--plugins/base/src/test/kotlin/expect/ExpectTest.kt24
-rw-r--r--plugins/base/src/test/kotlin/expect/ExpectUtils.kt28
-rw-r--r--plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt173
-rw-r--r--plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt63
-rw-r--r--plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt173
-rw-r--r--plugins/base/src/test/kotlin/issues/IssuesTest.kt73
-rw-r--r--plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt225
-rw-r--r--plugins/base/src/test/kotlin/locationProvider/DefaultLocationProviderTest.kt41
-rw-r--r--plugins/base/src/test/kotlin/markdown/KDocTest.kt47
-rw-r--r--plugins/base/src/test/kotlin/markdown/LinkTest.kt79
-rw-r--r--plugins/base/src/test/kotlin/markdown/ParserTest.kt1123
-rw-r--r--plugins/base/src/test/kotlin/model/ClassesTest.kt533
-rw-r--r--plugins/base/src/test/kotlin/model/CommentTest.kt332
-rw-r--r--plugins/base/src/test/kotlin/model/FunctionsTest.kt396
-rw-r--r--plugins/base/src/test/kotlin/model/InheritorsTest.kt95
-rw-r--r--plugins/base/src/test/kotlin/model/JavaTest.kt346
-rw-r--r--plugins/base/src/test/kotlin/model/PackagesTest.kt134
-rw-r--r--plugins/base/src/test/kotlin/model/PropertyTest.kt265
-rw-r--r--plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt54
-rw-r--r--plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt126
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt328
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt78
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt90
-rw-r--r--plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt139
-rw-r--r--plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt71
-rw-r--r--plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt175
-rw-r--r--plugins/base/src/test/kotlin/signatures/SignatureTest.kt379
-rw-r--r--plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt150
-rw-r--r--plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt403
-rw-r--r--plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt919
-rw-r--r--plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt87
-rw-r--r--plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt144
-rw-r--r--plugins/base/src/test/kotlin/translators/utils.kt16
-rw-r--r--plugins/base/src/test/kotlin/utils/JsoupUtils.kt29
-rw-r--r--plugins/base/src/test/kotlin/utils/ModelUtils.kt37
-rw-r--r--plugins/base/src/test/kotlin/utils/TestUtils.kt79
-rw-r--r--plugins/base/src/test/kotlin/utils/contentUtils.kt243
-rw-r--r--plugins/base/src/test/resources/linkable/includes/include1.md7
-rw-r--r--plugins/base/src/test/resources/linkable/includes/include2.md7
-rw-r--r--plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt9
-rw-r--r--plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt10
-rw-r--r--plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt9
-rw-r--r--plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt10
-rw-r--r--plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt3
-rw-r--r--plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt3
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt15
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt24
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt28
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt10
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt41
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt15
-rw-r--r--plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt32
-rw-r--r--plugins/base/test-utils/build.gradle.kts4
-rw-r--r--plugins/base/test-utils/src/main/kotlin/renderers/RenderingOnlyTestBase.kt8
-rw-r--r--plugins/base/test-utils/src/main/kotlin/renderers/TestPage.kt52
-rw-r--r--plugins/base/test-utils/src/main/kotlin/renderers/defaultSourceSet.kt31
-rw-r--r--plugins/base/test-utils/src/main/kotlin/utils/TestOutputWriter.kt32
166 files changed, 36515 insertions, 0 deletions
diff --git a/plugins/base/.gitignore b/plugins/base/.gitignore
new file mode 100644
index 00000000..d68571db
--- /dev/null
+++ b/plugins/base/.gitignore
@@ -0,0 +1,3 @@
+src/main/resources/dokka/scripts/main.js
+src/main/resources/dokka/scripts/main.js.map
+search-component/dist/ \ No newline at end of file
diff --git a/plugins/base/build.gradle.kts b/plugins/base/build.gradle.kts
new file mode 100644
index 00000000..0fc7f55c
--- /dev/null
+++ b/plugins/base/build.gradle.kts
@@ -0,0 +1,35 @@
+import org.jetbrains.registerDokkaArtifactPublication
+
+plugins {
+ id("com.jfrog.bintray")
+}
+
+dependencies {
+ val coroutines_version: String by project
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
+
+ api(project(":kotlin-analysis"))
+ implementation("org.jsoup:jsoup:1.12.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.10")
+ testImplementation(project(":test-tools"))
+ testImplementation(project(":plugins:base:test-utils"))
+}
+
+task("copy_frontend", Copy::class) {
+ from(File(project(":plugins:base:frontend").projectDir, "dist/"))
+ destinationDir = File(sourceSets.main.get().resources.sourceDirectories.singleFile, "dokka/scripts")
+}.dependsOn(":plugins:base:frontend:generateFrontendFiles")
+
+tasks {
+ processResources {
+ dependsOn("copy_frontend")
+ }
+
+ test {
+ maxHeapSize = "4G"
+ }
+}
+
+registerDokkaArtifactPublication("dokkaBase") {
+ artifactId = "dokka-base"
+}
diff --git a/plugins/base/frontend/.gitignore b/plugins/base/frontend/.gitignore
new file mode 100644
index 00000000..81ce55f2
--- /dev/null
+++ b/plugins/base/frontend/.gitignore
@@ -0,0 +1,2 @@
+/dist/
+/node_modules/ \ No newline at end of file
diff --git a/plugins/base/frontend/build.gradle.kts b/plugins/base/frontend/build.gradle.kts
new file mode 100644
index 00000000..a184c296
--- /dev/null
+++ b/plugins/base/frontend/build.gradle.kts
@@ -0,0 +1,20 @@
+plugins {
+ id("com.github.node-gradle.node") version "2.2.4"
+}
+
+val npmRunBuild = tasks.getByName("npm_run_build") {
+ inputs.dir(file("src/main"))
+ inputs.files(file("package.json"), file("webpack.config.js"))
+ outputs.dir(file("dist/"))
+ outputs.cacheIf { true }
+}
+
+task("generateFrontendFiles") {
+ dependsOn(npmRunBuild)
+}
+
+tasks {
+ clean {
+ delete(file("node_modules"), file("dist"))
+ }
+}
diff --git a/plugins/base/frontend/package-lock.json b/plugins/base/frontend/package-lock.json
new file mode 100644
index 00000000..3c00ffb1
--- /dev/null
+++ b/plugins/base/frontend/package-lock.json
@@ -0,0 +1,15428 @@
+{
+ "name": "search",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
+ "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
+ "requires": {
+ "@babel/highlight": "^7.10.1"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.1.tgz",
+ "integrity": "sha512-CHvCj7So7iCkGKPRFUfryXIkU2gSBw7VSZFYLsqVhrS47269VK2Hfi9S/YcublPMW8k1u2bQBlbDruoQEm4fgw==",
+ "requires": {
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "semver": "^5.5.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz",
+ "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==",
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/generator": "^7.10.2",
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helpers": "^7.10.1",
+ "@babel/parser": "^7.10.2",
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.2",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz",
+ "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==",
+ "requires": {
+ "@babel/types": "^7.10.2",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz",
+ "integrity": "sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.1.tgz",
+ "integrity": "sha512-cQpVq48EkYxUU0xozpGCLla3wlkdRRqLWu1ksFMXA9CM5KQmyyRpSEsYXbao7JUkOw/tAaYKCaYyZq6HOFYtyw==",
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-builder-react-jsx": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.1.tgz",
+ "integrity": "sha512-KXzzpyWhXgzjXIlJU1ZjIXzUPdej1suE6vzqgImZ/cpAsR/CC8gUcX4EWRmDfWz/cs6HOCPMBIJ3nKoXt3BFuw==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-builder-react-jsx-experimental": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.1.tgz",
+ "integrity": "sha512-irQJ8kpQUV3JasXPSFQ+LCCtJSc5ceZrPFVj6TElR6XCHssi3jV8ch3odIrNtjJFRZZVbrOEfJMI79TPU/h1pQ==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz",
+ "integrity": "sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA==",
+ "requires": {
+ "@babel/compat-data": "^7.10.1",
+ "browserslist": "^4.12.0",
+ "invariant": "^2.2.4",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz",
+ "integrity": "sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-member-expression-to-functions": "^7.10.1",
+ "@babel/helper-optimise-call-expression": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1"
+ }
+ },
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz",
+ "integrity": "sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-regex": "^7.10.1",
+ "regexpu-core": "^4.7.0"
+ }
+ },
+ "@babel/helper-define-map": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.1.tgz",
+ "integrity": "sha512-+5odWpX+OnvkD0Zmq7panrMuAGQBu6aPUgvMzuMGo4R+jUOvealEj2hiqI6WhxgKrTpFoFj0+VdsuA8KDxHBDg==",
+ "requires": {
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/types": "^7.10.1",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.1.tgz",
+ "integrity": "sha512-vcUJ3cDjLjvkKzt6rHrl767FeE7pMEYfPanq5L16GRtrXIoznc0HykNW2aEYkcnP76P0isoqJ34dDMFZwzEpJg==",
+ "requires": {
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz",
+ "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz",
+ "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.1.tgz",
+ "integrity": "sha512-vLm5srkU8rI6X3+aQ1rQJyfjvCBLXP8cAGeuw04zeAM2ItKb1e7pmVmLyHb4sDaAYnLL13RHOZPLEtcGZ5xvjg==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz",
+ "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz",
+ "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz",
+ "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1",
+ "@babel/helper-simple-access": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz",
+ "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz",
+ "integrity": "sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA=="
+ },
+ "@babel/helper-regex": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.1.tgz",
+ "integrity": "sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g==",
+ "requires": {
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.1.tgz",
+ "integrity": "sha512-RfX1P8HqsfgmJ6CwaXGKMAqbYdlleqglvVtht0HGPMSsy2V6MqLlOJVF/0Qyb/m2ZCi2z3q3+s6Pv7R/dQuZ6A==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-wrap-function": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz",
+ "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==",
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.1",
+ "@babel/helper-optimise-call-expression": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz",
+ "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==",
+ "requires": {
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
+ "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==",
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz",
+ "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz",
+ "integrity": "sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
+ "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
+ "requires": {
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
+ "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.1",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz",
+ "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ=="
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.1.tgz",
+ "integrity": "sha512-vzZE12ZTdB336POZjmpblWfNNRpMSua45EYnRigE2XsZxcXcIyly2ixnTJasJE4Zq3U7t2d8rRF7XRUuzHxbOw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-remap-async-to-generator": "^7.10.1",
+ "@babel/plugin-syntax-async-generators": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz",
+ "integrity": "sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz",
+ "integrity": "sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz",
+ "integrity": "sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-json-strings": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz",
+ "integrity": "sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-numeric-separator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz",
+ "integrity": "sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.1"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz",
+ "integrity": "sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.10.1"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz",
+ "integrity": "sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.1.tgz",
+ "integrity": "sha512-dqQj475q8+/avvok72CF3AOSV/SGEcH29zT5hhohqqvvZ2+boQoOr7iGldBG5YXTO2qgCgc2B3WvVLUdbeMlGA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.1.tgz",
+ "integrity": "sha512-RZecFFJjDiQ2z6maFprLgrdnm0OzoC23Mx89xf1CcEsxmHuzuXOdniEuI+S3v7vjQG4F5sa6YtUp+19sZuSxHg==",
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz",
+ "integrity": "sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz",
+ "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.1.tgz",
+ "integrity": "sha512-+OxyOArpVFXQeXKLO9o+r2I4dIoVoy6+Uu0vKELrlweDM3QJADZj+Z+5ERansZqIZBcLj42vHnDI8Rz9BnRIuQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz",
+ "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz",
+ "integrity": "sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz",
+ "integrity": "sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz",
+ "integrity": "sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-remap-async-to-generator": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz",
+ "integrity": "sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz",
+ "integrity": "sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.1.tgz",
+ "integrity": "sha512-P9V0YIh+ln/B3RStPoXpEQ/CoAxQIhRSUn7aXqQ+FZJ2u8+oCtjIXR3+X0vsSD8zv+mb56K7wZW1XiDTDGiDRQ==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-define-map": "^7.10.1",
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-optimise-call-expression": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.1.tgz",
+ "integrity": "sha512-mqSrGjp3IefMsXIenBfGcPXxJxweQe2hEIwMQvjtiDQ9b1IBvDUjkAtV/HMXX47/vXf14qDNedXsIiNd1FmkaQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz",
+ "integrity": "sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz",
+ "integrity": "sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz",
+ "integrity": "sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz",
+ "integrity": "sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA==",
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz",
+ "integrity": "sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz",
+ "integrity": "sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw==",
+ "requires": {
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz",
+ "integrity": "sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz",
+ "integrity": "sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz",
+ "integrity": "sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz",
+ "integrity": "sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-simple-access": "^7.10.1",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.1.tgz",
+ "integrity": "sha512-ewNKcj1TQZDL3YnO85qh9zo1YF1CHgmSTlRQgHqe63oTrMI85cthKtZjAiZSsSNjPQ5NCaYo5QkbYqEw1ZBgZA==",
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.10.1",
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz",
+ "integrity": "sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz",
+ "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz",
+ "integrity": "sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz",
+ "integrity": "sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz",
+ "integrity": "sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz",
+ "integrity": "sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-display-name": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.1.tgz",
+ "integrity": "sha512-rBjKcVwjk26H3VX8pavMxGf33LNlbocMHdSeldIEswtQ/hrjyTG8fKKILW1cSkODyRovckN/uZlGb2+sAV9JUQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-jsx": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.1.tgz",
+ "integrity": "sha512-MBVworWiSRBap3Vs39eHt+6pJuLUAaK4oxGc8g+wY+vuSJvLiEQjW1LSTqKb8OUPtDvHCkdPhk7d6sjC19xyFw==",
+ "requires": {
+ "@babel/helper-builder-react-jsx": "^7.10.1",
+ "@babel/helper-builder-react-jsx-experimental": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-jsx": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-development": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz",
+ "integrity": "sha512-XwDy/FFoCfw9wGFtdn5Z+dHh6HXKHkC6DwKNWpN74VWinUagZfDcEJc3Y8Dn5B3WMVnAllX8Kviaw7MtC5Epwg==",
+ "requires": {
+ "@babel/helper-builder-react-jsx-experimental": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-jsx": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-self": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz",
+ "integrity": "sha512-4p+RBw9d1qV4S749J42ZooeQaBomFPrSxa9JONLHJ1TxCBo3TzJ79vtmG2S2erUT8PDDrPdw4ZbXGr2/1+dILA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-jsx": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-source": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz",
+ "integrity": "sha512-neAbaKkoiL+LXYbGDvh6PjPG+YeA67OsZlE78u50xbWh2L1/C81uHiNP5d1fw+uqUIoiNdCC8ZB+G4Zh3hShJA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-jsx": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.1.tgz",
+ "integrity": "sha512-mfhoiai083AkeewsBHUpaS/FM1dmUENHBMpS/tugSJ7VXqXO5dCN1Gkint2YvM1Cdv1uhmAKt1ZOuAjceKmlLA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.1.tgz",
+ "integrity": "sha512-B3+Y2prScgJ2Bh/2l9LJxKbb8C8kRfsG4AdPT+n7ixBHIxJaIG8bi8tgjxUMege1+WqSJ+7gu1YeoMVO3gPWzw==",
+ "requires": {
+ "regenerator-transform": "^0.14.2"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz",
+ "integrity": "sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-runtime": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz",
+ "integrity": "sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "resolve": "^1.8.1",
+ "semver": "^5.5.1"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz",
+ "integrity": "sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz",
+ "integrity": "sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz",
+ "integrity": "sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-regex": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-strict-mode": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-strict-mode/-/plugin-transform-strict-mode-7.10.1.tgz",
+ "integrity": "sha512-Q8GDTT75F35KgGGW01KcCn3OhEAIJIcMSxMZGcmxjeY8Asj0reAGodt6wN5wfrvSSuPLhmtU1zOaOy3vR8uCRg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.1.tgz",
+ "integrity": "sha512-t7B/3MQf5M1T9hPCRG28DNGZUuxAuDqLYS03rJrIk2prj/UV7Z6FOneijhQhnv/Xa039vidXeVbvjK2SK5f7Gg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz",
+ "integrity": "sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-unicode-escapes": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.1.tgz",
+ "integrity": "sha512-zZ0Poh/yy1d4jeDWpx/mNwbKJVwUYJX73q+gyh4bwtG0/iUlzdEu0sLMda8yuDFS6LBQlT/ST1SJAR6zYwXWgw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz",
+ "integrity": "sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.2.tgz",
+ "integrity": "sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==",
+ "requires": {
+ "@babel/compat-data": "^7.10.1",
+ "@babel/helper-compilation-targets": "^7.10.2",
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-proposal-async-generator-functions": "^7.10.1",
+ "@babel/plugin-proposal-class-properties": "^7.10.1",
+ "@babel/plugin-proposal-dynamic-import": "^7.10.1",
+ "@babel/plugin-proposal-json-strings": "^7.10.1",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
+ "@babel/plugin-proposal-numeric-separator": "^7.10.1",
+ "@babel/plugin-proposal-object-rest-spread": "^7.10.1",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.10.1",
+ "@babel/plugin-proposal-optional-chaining": "^7.10.1",
+ "@babel/plugin-proposal-private-methods": "^7.10.1",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.10.1",
+ "@babel/plugin-syntax-async-generators": "^7.8.0",
+ "@babel/plugin-syntax-class-properties": "^7.10.1",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.1",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0",
+ "@babel/plugin-syntax-top-level-await": "^7.10.1",
+ "@babel/plugin-transform-arrow-functions": "^7.10.1",
+ "@babel/plugin-transform-async-to-generator": "^7.10.1",
+ "@babel/plugin-transform-block-scoped-functions": "^7.10.1",
+ "@babel/plugin-transform-block-scoping": "^7.10.1",
+ "@babel/plugin-transform-classes": "^7.10.1",
+ "@babel/plugin-transform-computed-properties": "^7.10.1",
+ "@babel/plugin-transform-destructuring": "^7.10.1",
+ "@babel/plugin-transform-dotall-regex": "^7.10.1",
+ "@babel/plugin-transform-duplicate-keys": "^7.10.1",
+ "@babel/plugin-transform-exponentiation-operator": "^7.10.1",
+ "@babel/plugin-transform-for-of": "^7.10.1",
+ "@babel/plugin-transform-function-name": "^7.10.1",
+ "@babel/plugin-transform-literals": "^7.10.1",
+ "@babel/plugin-transform-member-expression-literals": "^7.10.1",
+ "@babel/plugin-transform-modules-amd": "^7.10.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.10.1",
+ "@babel/plugin-transform-modules-systemjs": "^7.10.1",
+ "@babel/plugin-transform-modules-umd": "^7.10.1",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
+ "@babel/plugin-transform-new-target": "^7.10.1",
+ "@babel/plugin-transform-object-super": "^7.10.1",
+ "@babel/plugin-transform-parameters": "^7.10.1",
+ "@babel/plugin-transform-property-literals": "^7.10.1",
+ "@babel/plugin-transform-regenerator": "^7.10.1",
+ "@babel/plugin-transform-reserved-words": "^7.10.1",
+ "@babel/plugin-transform-shorthand-properties": "^7.10.1",
+ "@babel/plugin-transform-spread": "^7.10.1",
+ "@babel/plugin-transform-sticky-regex": "^7.10.1",
+ "@babel/plugin-transform-template-literals": "^7.10.1",
+ "@babel/plugin-transform-typeof-symbol": "^7.10.1",
+ "@babel/plugin-transform-unicode-escapes": "^7.10.1",
+ "@babel/plugin-transform-unicode-regex": "^7.10.1",
+ "@babel/preset-modules": "^0.1.3",
+ "@babel/types": "^7.10.2",
+ "browserslist": "^4.12.0",
+ "core-js-compat": "^3.6.2",
+ "invariant": "^2.2.2",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ }
+ },
+ "@babel/preset-modules": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
+ "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ }
+ },
+ "@babel/preset-react": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.10.1.tgz",
+ "integrity": "sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-transform-react-display-name": "^7.10.1",
+ "@babel/plugin-transform-react-jsx": "^7.10.1",
+ "@babel/plugin-transform-react-jsx-development": "^7.10.1",
+ "@babel/plugin-transform-react-jsx-self": "^7.10.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.10.1",
+ "@babel/plugin-transform-react-pure-annotations": "^7.10.1"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.2.tgz",
+ "integrity": "sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "@babel/template": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz",
+ "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==",
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/parser": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz",
+ "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==",
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/generator": "^7.10.1",
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1",
+ "@babel/parser": "^7.10.1",
+ "@babel/types": "^7.10.1",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz",
+ "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.1",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@csstools/convert-colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
+ "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw=="
+ },
+ "@hypnosphi/react-virtualized": {
+ "version": "9.21.2",
+ "resolved": "https://registry.npmjs.org/@hypnosphi/react-virtualized/-/react-virtualized-9.21.2.tgz",
+ "integrity": "sha512-6pd6R1Iz0sD/IwlMQdja6FHvm9WqqOUrnDP42Z/179abCb5m3isv9kNiWTF6wAJYprHkEDG+SCkChzJ7uUIUoA==",
+ "requires": {
+ "@babel/runtime": "^7.7.2",
+ "clsx": "^1.0.4",
+ "dom-helpers": "^5.1.3",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.7.2",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "@jetbrains/angular-elastic": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@jetbrains/angular-elastic/-/angular-elastic-2.5.1.tgz",
+ "integrity": "sha512-/XU38+J5c3vKKoiwGmqze0UaKt7mnrR0mQJg1WxuZFBSTf6e1co8rN8bgxik0jAX5s8yXUMWhPhmrIYKaR140Q==",
+ "requires": {
+ "angular": ">=1.0.6"
+ }
+ },
+ "@jetbrains/babel-preset-jetbrains": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@jetbrains/babel-preset-jetbrains/-/babel-preset-jetbrains-2.1.4.tgz",
+ "integrity": "sha512-0W3p5gczcrcUxymF6p5Y9gq3duBqJvkANpHLfHYz5CrP8Y0PmerJiYFvS200+xMeal1wpcuu90jD+AWwgf0o6w==",
+ "requires": {
+ "@babel/plugin-proposal-class-properties": "^7.4.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.4.3",
+ "@babel/plugin-proposal-optional-chaining": "^7.2.0",
+ "@babel/plugin-transform-runtime": "^7.4.3",
+ "@babel/plugin-transform-strict-mode": "^7.2.0",
+ "@babel/preset-env": "^7.4.3",
+ "@babel/preset-react": "^7.0.0",
+ "@babel/runtime": "^7.4.3",
+ "babel-plugin-angularjs-annotate": "^0.9.0"
+ }
+ },
+ "@jetbrains/icons": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@jetbrains/icons/-/icons-3.7.0.tgz",
+ "integrity": "sha512-i7+U7iceYiewMEXhz227I0P461iN9v7008RllzXcxh7ZybMduKRqpvzpbIpx2oJXYTlVOTsuFinaBT+yNl3WDQ=="
+ },
+ "@jetbrains/logos": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@jetbrains/logos/-/logos-1.1.5.tgz",
+ "integrity": "sha512-Hm0aRFrH1+z0P+OSKCp65B1LOsQJ2VdEiaE/ZV2JDt1MA8ooutkXy3tjTmYx69yYul58RbHhWusiVF4hBaM5sg=="
+ },
+ "@jetbrains/postcss-require-hover": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@jetbrains/postcss-require-hover/-/postcss-require-hover-0.1.2.tgz",
+ "integrity": "sha512-U094mXSp0KOfqZLTlkPLz4vHdIZYm1gJFRFJP7nMrGA1OI4Nigwl0TUwFt/7YDNAff57Eo9Zttu9Ln5QoXguAw==",
+ "requires": {
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "@jetbrains/ring-ui": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/@jetbrains/ring-ui/-/ring-ui-2.1.16.tgz",
+ "integrity": "sha512-tx7fDglrKoo61iAIJf+XcWNn5e+MdnTLqvkUHfB/SFYrLZMX8fZK4DG9S/HoVNSSWKQ3cFbrsszH8RaTz5zgXg==",
+ "requires": {
+ "@babel/core": "^7.7.7",
+ "@hypnosphi/react-virtualized": "^9.21.2",
+ "@jetbrains/angular-elastic": "^2.5.1",
+ "@jetbrains/babel-preset-jetbrains": "^2.1.4",
+ "@jetbrains/icons": "^3.6.0",
+ "@jetbrains/logos": "^1.1.5",
+ "@jetbrains/postcss-require-hover": "^0.1.2",
+ "angular-sanitize": "^1.7.9",
+ "babel-loader": "^8.0.6",
+ "babel-plugin-transform-define": "^2.0.0",
+ "browserslist": "^4.7.0",
+ "change-case": "^3.1.0",
+ "classnames": "^2.2.6",
+ "combokeys": "^3.0.1",
+ "compile-code-loader": "^0.2.0",
+ "conic-gradient": "^1.0.0",
+ "css-loader": "^3.4.0",
+ "deep-equal": "^2.0.1",
+ "dom4": "^1.8.5",
+ "element-resize-detector": "^1.2.0",
+ "es6-error": "^4.1.1",
+ "extricate-loader": "^3.0.0",
+ "file-loader": "^5.0.2",
+ "focus-trap": "^5.1.0",
+ "focus-visible": "^5.0.2",
+ "highlight.js": "^9.17.1",
+ "html-loader": "^0.5.5",
+ "imports-loader": "^0.8.0",
+ "interpolate-loader": "^2.0.1",
+ "just-debounce-it": "^1.1.0",
+ "memoize-one": "^5.1.1",
+ "moment": "^2.24.0",
+ "postcss": "^7.0.25",
+ "postcss-calc": "^7.0.1",
+ "postcss-flexbugs-fixes": "^4.1.0",
+ "postcss-font-family-system-ui": "^4.2.0",
+ "postcss-loader": "^3.0.0",
+ "postcss-modules-values-replace": "^3.0.1",
+ "postcss-preset-env": "^6.7.0",
+ "prop-types": "^15.7.2",
+ "react-markdown": "^4.2.2",
+ "react-measure": "^2.3.0",
+ "react-sortable-hoc": "^1.10.1",
+ "react-virtualized": "^9.21.1",
+ "react-waypoint": "^9.0.2",
+ "recompose": "^0.30.0",
+ "remark-breaks": "^1.0.3",
+ "sass": "^1.24.0",
+ "sass-loader": "^8.0.0",
+ "scrollbar-width": "^3.1.1",
+ "simply-uuid": "^1.0.1",
+ "sniffr": "^1.2.0",
+ "style-loader": "~1.0.2",
+ "svg-inline-loader": "^0.8.0",
+ "url-loader": "^3.0.0",
+ "url-search-params": "^1.1.0",
+ "util-deprecate": "^1.0.2",
+ "whatwg-fetch": "^3.0.0"
+ }
+ },
+ "@jetbrains/stylelint-config": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@jetbrains/stylelint-config/-/stylelint-config-2.0.1.tgz",
+ "integrity": "sha512-cIdiPQQMXn2bYvoQ8631KS3By2v65wMg1L/S4MGPRPdj7MGR/1pGOWkQT34wiWu+YxojxIERnP/bcFeimuvhCg==",
+ "dev": true,
+ "requires": {
+ "stylelint-config-css-modules": "^2.1.0",
+ "stylelint-config-standard": "^19.0.0",
+ "stylelint-order": "^3.1.1"
+ }
+ },
+ "@mrmlnc/readdir-enhanced": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+ "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+ "dev": true,
+ "requires": {
+ "call-me-maybe": "^1.0.1",
+ "glob-to-regexp": "^0.3.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
+ "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.3",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
+ "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.3",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@sindresorhus/is": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
+ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
+ "dev": true
+ },
+ "@stylelint/postcss-css-in-js": {
+ "version": "0.37.1",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.1.tgz",
+ "integrity": "sha512-UMf2Rni3JGKi3ZwYRGMYJ5ipOA5ENJSKMtYA/pE1ZLURwdh7B5+z2r73RmWvub+N0UuH1Lo+TGfCgYwPvqpXNw==",
+ "dev": true,
+ "requires": {
+ "@babel/core": ">=7.9.0"
+ }
+ },
+ "@stylelint/postcss-markdown": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-markdown/-/postcss-markdown-0.36.1.tgz",
+ "integrity": "sha512-iDxMBWk9nB2BPi1VFQ+Dc5+XpvODBHw2n3tYpaBZuEAFQlbtF9If0Qh5LTTwSi/XwdbJ2jt+0dis3i8omyggpw==",
+ "dev": true,
+ "requires": {
+ "remark": "^12.0.0",
+ "unist-util-find-all-after": "^3.0.1"
+ }
+ },
+ "@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+ "dev": true
+ },
+ "@types/glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==",
+ "requires": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
+ "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ=="
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
+ },
+ "@types/minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "12.12.47",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.47.tgz",
+ "integrity": "sha512-yzBInQFhdY8kaZmqoL2+3U5dSTMrKaYcb561VU+lDzAYvqt+2lojvBEy+hmpSNuXnPTx7m9+04CzWYOUqWME2A=="
+ },
+ "@types/normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
+ "dev": true
+ },
+ "@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+ "dev": true
+ },
+ "@types/prop-types": {
+ "version": "15.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
+ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
+ },
+ "@types/react": {
+ "version": "16.9.36",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.36.tgz",
+ "integrity": "sha512-mGgUb/Rk/vGx4NCvquRuSH0GHBQKb1OqpGS9cT9lFxlTLHZgkksgI60TuIxubmn7JuCb+sENHhQciqa0npm0AQ==",
+ "requires": {
+ "@types/prop-types": "*",
+ "csstype": "^2.2.0"
+ }
+ },
+ "@types/react-dom": {
+ "version": "16.9.8",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.8.tgz",
+ "integrity": "sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
+ "@types/unist": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
+ "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
+ "dev": true
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
+ "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/wast-parser": "1.9.0"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
+ "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA=="
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
+ "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw=="
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
+ "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA=="
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
+ "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.9.0"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
+ "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw=="
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
+ "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0"
+ }
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
+ "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw=="
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
+ "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
+ "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
+ "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
+ "requires": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
+ "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w=="
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
+ "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/helper-wasm-section": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0",
+ "@webassemblyjs/wasm-opt": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0",
+ "@webassemblyjs/wast-printer": "1.9.0"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
+ "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/ieee754": "1.9.0",
+ "@webassemblyjs/leb128": "1.9.0",
+ "@webassemblyjs/utf8": "1.9.0"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
+ "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-buffer": "1.9.0",
+ "@webassemblyjs/wasm-gen": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
+ "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-api-error": "1.9.0",
+ "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
+ "@webassemblyjs/ieee754": "1.9.0",
+ "@webassemblyjs/leb128": "1.9.0",
+ "@webassemblyjs/utf8": "1.9.0"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
+ "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/floating-point-hex-parser": "1.9.0",
+ "@webassemblyjs/helper-api-error": "1.9.0",
+ "@webassemblyjs/helper-code-frame": "1.9.0",
+ "@webassemblyjs/helper-fsm": "1.9.0",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
+ "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/wast-parser": "1.9.0",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+ },
+ "@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "acorn": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
+ },
+ "acorn-jsx": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
+ "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
+ "dev": true
+ },
+ "aggregate-error": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
+ "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
+ },
+ "angular": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.0.tgz",
+ "integrity": "sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg=="
+ },
+ "angular-sanitize": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.8.0.tgz",
+ "integrity": "sha512-j5GiOPCvfcDWK5svEOVoPb11X3UDVy/mdHPRWuy14Iyw86xaq+Bb+x/em2sAOa5MQQeY5ciLXbF3RRp8iCKcNg=="
+ },
+ "ansi": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz",
+ "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=",
+ "dev": true
+ },
+ "ansi-align": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+ "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "ansi-colors": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA=="
+ },
+ "ansi-escapes": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
+ "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.11.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
+ "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+ "dev": true
+ }
+ }
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4="
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "dev": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+ },
+ "array-differ": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz",
+ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==",
+ "dev": true
+ },
+ "array-filter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
+ "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ=="
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ },
+ "arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+ },
+ "ast-types": {
+ "version": "0.9.6",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
+ "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk="
+ },
+ "astral-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "dev": true
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
+ },
+ "autoprefixer": {
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz",
+ "integrity": "sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A==",
+ "requires": {
+ "browserslist": "^4.12.0",
+ "caniuse-lite": "^1.0.30001061",
+ "chalk": "^2.4.2",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.30",
+ "postcss-value-parser": "^4.1.0"
+ }
+ },
+ "available-typed-arrays": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
+ "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
+ "requires": {
+ "array-filter": "^1.0.0"
+ }
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz",
+ "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==",
+ "dev": true
+ },
+ "axios": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
+ "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
+ "dev": true,
+ "requires": {
+ "follow-redirects": "1.5.10",
+ "is-buffer": "^2.0.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+ "dev": true,
+ "requires": {
+ "debug": "=3.1.0"
+ }
+ },
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ }
+ }
+ },
+ "babel-eslint": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
+ "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.7.0",
+ "@babel/traverse": "^7.7.0",
+ "@babel/types": "^7.7.0",
+ "eslint-visitor-keys": "^1.0.0",
+ "resolve": "^1.12.0"
+ }
+ },
+ "babel-loader": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
+ "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
+ "requires": {
+ "find-cache-dir": "^2.1.0",
+ "loader-utils": "^1.4.0",
+ "mkdirp": "^0.5.3",
+ "pify": "^4.0.1",
+ "schema-utils": "^2.6.5"
+ }
+ },
+ "babel-plugin-angularjs-annotate": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-angularjs-annotate/-/babel-plugin-angularjs-annotate-0.9.0.tgz",
+ "integrity": "sha512-erYvZAJgnrgeyEZqIJOAiK6vUK44HsVb0+Tid4zTBcsvdQuas0Z5Teh0w/hcINKW3G0xweqA5LGfg2ZWlp3nMA==",
+ "requires": {
+ "babel-code-frame": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "simple-is": "~0.2.0"
+ }
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-plugin-transform-define": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-define/-/babel-plugin-transform-define-2.0.0.tgz",
+ "integrity": "sha512-0dv5RNRUlUKxGYIIErl01lpvi8b7W2R04Qcl1mCj70ahwZcgiklfXnFlh4FGnRh6aayCfSZKdhiMryVzcq5Dmg==",
+ "requires": {
+ "lodash": "^4.17.11",
+ "traverse": "0.6.6"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.4",
+ "to-fast-properties": "^1.0.3"
+ },
+ "dependencies": {
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+ }
+ }
+ },
+ "bail": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
+ "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ=="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
+ },
+ "batch-processor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz",
+ "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
+ },
+ "bin-version": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-2.0.0.tgz",
+ "integrity": "sha1-LMldg7Uive8umZeOdq61SRyBFP8=",
+ "dev": true,
+ "requires": {
+ "execa": "^0.1.1",
+ "find-versions": "^2.0.0"
+ },
+ "dependencies": {
+ "execa": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.1.1.tgz",
+ "integrity": "sha1-sJwqkwm8DvBQFHlHLbMYD41MPt0=",
+ "dev": true,
+ "requires": {
+ "cross-spawn-async": "^2.1.1",
+ "object-assign": "^4.0.1",
+ "strip-eof": "^1.0.0"
+ }
+ }
+ }
+ },
+ "bin-version-check": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-3.0.0.tgz",
+ "integrity": "sha1-4k6/prY8sDh8X8F0+G5cyBLKfMk=",
+ "dev": true,
+ "requires": {
+ "bin-version": "^2.0.0",
+ "semver": "^5.1.0",
+ "semver-truncate": "^1.0.0"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
+ },
+ "binaryextensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz",
+ "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==",
+ "dev": true
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "bn.js": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
+ "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA=="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ },
+ "dependencies": {
+ "deep-equal": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
+ "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
+ "requires": {
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.2.0"
+ }
+ }
+ }
+ },
+ "boolean": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz",
+ "integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==",
+ "dev": true
+ },
+ "boxen": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+ "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "browserify-sign": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
+ "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
+ "requires": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.2",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
+ "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001043",
+ "electron-to-chromium": "^1.3.413",
+ "node-releases": "^1.1.53",
+ "pkg-up": "^2.0.0"
+ }
+ },
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ }
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+ },
+ "cacache": {
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+ "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "cacheable-request": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+ "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=",
+ "dev": true,
+ "requires": {
+ "clone-response": "1.0.2",
+ "get-stream": "3.0.0",
+ "http-cache-semantics": "3.8.1",
+ "keyv": "3.0.0",
+ "lowercase-keys": "1.0.0",
+ "normalize-url": "2.0.1",
+ "responselike": "1.0.2"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "lowercase-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
+ "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=",
+ "dev": true
+ }
+ }
+ },
+ "call-me-maybe": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
+ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
+ "dev": true
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "requires": {
+ "callsites": "^2.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+ },
+ "camel-case": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+ },
+ "camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001081",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001081.tgz",
+ "integrity": "sha512-iZdh3lu09jsUtLE6Bp8NAbJskco4Y3UDtkR3GTCJGsbMowBU5IWDFF79sV2ws7lSqTzWyKazxam2thasHymENQ=="
+ },
+ "capture-stack-trace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+ "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "ccount": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.5.tgz",
+ "integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "change-case": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/change-case/-/change-case-3.1.0.tgz",
+ "integrity": "sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw==",
+ "requires": {
+ "camel-case": "^3.0.0",
+ "constant-case": "^2.0.0",
+ "dot-case": "^2.1.0",
+ "header-case": "^1.0.0",
+ "is-lower-case": "^1.1.0",
+ "is-upper-case": "^1.1.0",
+ "lower-case": "^1.1.1",
+ "lower-case-first": "^1.0.0",
+ "no-case": "^2.3.2",
+ "param-case": "^2.1.0",
+ "pascal-case": "^2.0.0",
+ "path-case": "^2.1.0",
+ "sentence-case": "^2.1.0",
+ "snake-case": "^2.1.0",
+ "swap-case": "^1.1.0",
+ "title-case": "^2.1.0",
+ "upper-case": "^1.1.1",
+ "upper-case-first": "^1.1.0"
+ }
+ },
+ "change-emitter": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
+ "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
+ },
+ "character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw=="
+ },
+ "character-entities-html4": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz",
+ "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==",
+ "dev": true
+ },
+ "character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="
+ },
+ "character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
+ "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.4.0"
+ }
+ },
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
+ "chrome-trace-event": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+ "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "classnames": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+ "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+ },
+ "clean-css": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
+ "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "cli-boxes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-list": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/cli-list/-/cli-list-0.2.0.tgz",
+ "integrity": "sha1-fmc+4N05phGkhkduU/PGs5QctYI=",
+ "dev": true
+ },
+ "cli-table": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
+ "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=",
+ "dev": true,
+ "requires": {
+ "colors": "1.0.3"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
+ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-buffer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
+ "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
+ "clone-regexp": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz",
+ "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==",
+ "dev": true,
+ "requires": {
+ "is-regexp": "^2.0.0"
+ }
+ },
+ "clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "clone-stats": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
+ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
+ "dev": true
+ },
+ "cloneable-readable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz",
+ "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "process-nextick-args": "^2.0.0",
+ "readable-stream": "^2.3.5"
+ }
+ },
+ "clsx": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
+ "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "collapse-white-space": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
+ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ=="
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "combokeys": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/combokeys/-/combokeys-3.0.1.tgz",
+ "integrity": "sha512-5nAfaLZ3oO3kA+/xdoL7t197UJTz2WWidyH3BBeU6hqHtvyFERICd0y3DQFrQkJFTKBrtUDck/xCLLoFpnjaCw=="
+ },
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+ },
+ "compile-code-loader": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/compile-code-loader/-/compile-code-loader-0.2.0.tgz",
+ "integrity": "sha1-29nGZM0aS2pyCe92qo9eAMcNoh8=",
+ "requires": {
+ "loader-utils": "1.1.x"
+ },
+ "dependencies": {
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0"
+ }
+ }
+ }
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "requires": {
+ "mime-db": ">= 1.43.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "conf": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz",
+ "integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "env-paths": "^1.0.0",
+ "make-dir": "^1.0.0",
+ "pkg-up": "^2.0.0",
+ "write-file-atomic": "^2.3.0"
+ },
+ "dependencies": {
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ }
+ }
+ },
+ "config-chain": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
+ "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "configstore": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
+ "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "dependencies": {
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+ "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ }
+ }
+ },
+ "conic-gradient": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/conic-gradient/-/conic-gradient-1.0.0.tgz",
+ "integrity": "sha512-TEmM3Ondx8nid2AN0Rsw6eQG7PgTUkL6gs90UqX1cNqO/bpt/H/Rw6DwbzoylQ9SSxqLG1SsteAr9/yBsAzdtw==",
+ "requires": {
+ "prefixfree": "^1.0.0"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg=="
+ },
+ "console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
+ },
+ "consolidated-events": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz",
+ "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ=="
+ },
+ "constant-case": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-2.0.0.tgz",
+ "integrity": "sha1-QXV2TTidP6nI7NKRhu1gBSQ7akY=",
+ "requires": {
+ "snake-case": "^2.1.0",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+ },
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
+ },
+ "core-js-compat": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
+ "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
+ "requires": {
+ "browserslist": "^4.8.5",
+ "semver": "7.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "create-error-class": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+ "dev": true,
+ "requires": {
+ "capture-stack-trace": "^1.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "cross-spawn-async": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+ "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.0",
+ "which": "^1.2.8"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "crypto-random-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
+ "dev": true
+ },
+ "css-blank-pseudo": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
+ "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==",
+ "requires": {
+ "postcss": "^7.0.5"
+ }
+ },
+ "css-has-pseudo": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz",
+ "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==",
+ "requires": {
+ "postcss": "^7.0.6",
+ "postcss-selector-parser": "^5.0.0-rc.4"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "css-loader": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
+ "integrity": "sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw==",
+ "requires": {
+ "camelcase": "^5.3.1",
+ "cssesc": "^3.0.0",
+ "icss-utils": "^4.1.1",
+ "loader-utils": "^1.2.3",
+ "normalize-path": "^3.0.0",
+ "postcss": "^7.0.27",
+ "postcss-modules-extract-imports": "^2.0.0",
+ "postcss-modules-local-by-default": "^3.0.2",
+ "postcss-modules-scope": "^2.2.0",
+ "postcss-modules-values": "^3.0.0",
+ "postcss-value-parser": "^4.0.3",
+ "schema-utils": "^2.6.6",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "css-prefers-color-scheme": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz",
+ "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==",
+ "requires": {
+ "postcss": "^7.0.5"
+ }
+ },
+ "cssdb": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
+ "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ=="
+ },
+ "cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
+ },
+ "csstype": {
+ "version": "2.6.10",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz",
+ "integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w=="
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "cyclist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
+ },
+ "dargs": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.1.0.tgz",
+ "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "dateformat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decamelize-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+ "dev": true,
+ "requires": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ }
+ }
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+ },
+ "decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "deep-equal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz",
+ "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==",
+ "requires": {
+ "es-abstract": "^1.17.5",
+ "es-get-iterator": "^1.1.0",
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.2",
+ "is-regex": "^1.0.5",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.2",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "regexp.prototype.flags": "^1.3.0",
+ "side-channel": "^1.0.2",
+ "which-boxed-primitive": "^1.0.1",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.2"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "default-gateway": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
+ "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
+ "requires": {
+ "execa": "^1.0.0",
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "default-uid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/default-uid/-/default-uid-1.0.0.tgz",
+ "integrity": "sha1-/O+p359axAyJFtkS3R/hFGqjxZ4=",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
+ "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "globby": "^6.1.0",
+ "is-path-cwd": "^2.0.0",
+ "is-path-in-cwd": "^2.0.0",
+ "p-map": "^2.0.0",
+ "pify": "^4.0.1",
+ "rimraf": "^2.6.3"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+ "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "detect-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc="
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0="
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-helpers": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz",
+ "integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==",
+ "requires": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^2.6.7"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ }
+ },
+ "dom4": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/dom4/-/dom4-1.8.5.tgz",
+ "integrity": "sha512-ehHzOGGkVQOwU9HyZ99gHwkx4ybrRl/P1vJM7EH1nS9XsgHwO+J0KwCnVQrn8iQvpstGwFrtrX7aSNQ43QuK4A=="
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
+ },
+ "domelementtype": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
+ "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
+ },
+ "domhandler": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz",
+ "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==",
+ "requires": {
+ "domelementtype": "^2.0.1"
+ }
+ },
+ "domutils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz",
+ "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==",
+ "requires": {
+ "dom-serializer": "^0.2.1",
+ "domelementtype": "^2.0.1",
+ "domhandler": "^3.0.0"
+ }
+ },
+ "dot-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz",
+ "integrity": "sha1-NNzzf1Co6TwrO8qLt/uRVcfaO+4=",
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "downgrade-root": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/downgrade-root/-/downgrade-root-1.2.2.tgz",
+ "integrity": "sha1-UxMZcVsOgf/MIusoR4uidkPhLGw=",
+ "dev": true,
+ "requires": {
+ "default-uid": "^1.0.0",
+ "is-root": "^1.0.0"
+ }
+ },
+ "download-stats": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/download-stats/-/download-stats-0.3.4.tgz",
+ "integrity": "sha512-ic2BigbyUWx7/CBbsfGjf71zUNZB4edBGC3oRliSzsoNmvyVx3Ycfp1w3vp2Y78Ee0eIIkjIEO5KzW0zThDGaA==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.2.1",
+ "lazy-cache": "^2.0.1",
+ "moment": "^2.15.1"
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "editions": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz",
+ "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==",
+ "dev": true,
+ "requires": {
+ "errlop": "^2.0.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "ejs": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
+ "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.468",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.468.tgz",
+ "integrity": "sha512-+KAppdklzPd5v8nLOvtDiD/S67mCT9gFRAvngYe8zuFy9azHhT9vWWH6WEPPCcyjQ1JMYVgqbN29yZ0paqxsEw=="
+ },
+ "element-resize-detector": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.1.tgz",
+ "integrity": "sha512-BdFsPepnQr9fznNPF9nF4vQ457U/ZJXQDSNF1zBe7yaga8v9AdZf3/NElYxFdUh7SitSGt040QygiTo6dtatIw==",
+ "requires": {
+ "batch-processor": "1.0.0"
+ }
+ },
+ "elliptic": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
+ "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
+ "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "object-assign": "^4.0.1",
+ "tapable": "^0.2.7"
+ }
+ },
+ "entities": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+ "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
+ },
+ "env-paths": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz",
+ "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=",
+ "dev": true
+ },
+ "errlop": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz",
+ "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz",
+ "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==",
+ "dev": true,
+ "requires": {
+ "string-template": "~0.2.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "error-stack-parser": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz",
+ "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=",
+ "requires": {
+ "stackframe": "^0.3.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.17.5",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+ "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.1.5",
+ "is-regex": "^1.0.5",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimleft": "^2.1.1",
+ "string.prototype.trimright": "^2.1.1"
+ }
+ },
+ "es-get-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
+ "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
+ "requires": {
+ "es-abstract": "^1.17.4",
+ "has-symbols": "^1.0.1",
+ "is-arguments": "^1.0.4",
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-string": "^1.0.5",
+ "isarray": "^2.0.5"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-error": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="
+ },
+ "es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "es6-templates": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz",
+ "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=",
+ "requires": {
+ "recast": "~0.11.12",
+ "through": "~2.3.6"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "eslint": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
+ "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.10.0",
+ "chalk": "^2.1.0",
+ "cross-spawn": "^6.0.5",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^1.4.3",
+ "eslint-visitor-keys": "^1.1.0",
+ "espree": "^6.1.2",
+ "esquery": "^1.0.1",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^5.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^7.0.0",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.14",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.3",
+ "progress": "^2.0.0",
+ "regexpp": "^2.0.1",
+ "semver": "^6.1.2",
+ "strip-ansi": "^5.2.0",
+ "strip-json-comments": "^3.0.1",
+ "table": "^5.2.3",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
+ "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ },
+ "import-fresh": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+ "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+ "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
+ "integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
+ "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.1.1",
+ "acorn-jsx": "^5.2.0",
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
+ "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+ },
+ "esquery": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
+ "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
+ "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "eventemitter3": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
+ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
+ },
+ "events": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+ "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg=="
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "execall": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz",
+ "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==",
+ "dev": true,
+ "requires": {
+ "clone-regexp": "^2.1.0"
+ }
+ },
+ "exit-hook": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz",
+ "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "expand-tilde": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+ "requires": {
+ "homedir-polyfill": "^1.0.1"
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extricate-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/extricate-loader/-/extricate-loader-3.0.0.tgz",
+ "integrity": "sha512-Ts6BIh25xhFpeGaG0La345bYQdRXWv3ZvUwmJB6/QsXRywWrZmM1hGz8eZfQaBwy/HsmGOZevzGLesVtsrrmyg==",
+ "requires": {
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "fast-glob": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz",
+ "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.0",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.2",
+ "picomatch": "^2.2.1"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
+ },
+ "fastq": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz",
+ "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "fbjs": {
+ "version": "0.8.17",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
+ "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+ "requires": {
+ "core-js": "^1.0.0",
+ "isomorphic-fetch": "^2.1.1",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.18"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ }
+ }
+ },
+ "figgy-pudding": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
+ "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+ "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^2.0.1"
+ }
+ },
+ "file-loader": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-5.1.0.tgz",
+ "integrity": "sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==",
+ "requires": {
+ "loader-utils": "^1.4.0",
+ "schema-utils": "^2.5.0"
+ }
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "optional": true
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "filter-obj": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-2.0.1.tgz",
+ "integrity": "sha512-yDEp513p7+iLdFHWBVdZFnRiOYwg8ZqmpaAiZCMjzqsbo7tCS4Qm4ulXOht337NGzkukKa9u3W4wqQ9tQPm3Ug==",
+ "dev": true
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "find-versions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-2.0.0.tgz",
+ "integrity": "sha1-KtkNSQ9oKMGqQCks9wmsMxghDDw=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.0",
+ "semver-regex": "^1.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
+ "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
+ "requires": {
+ "detect-file": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "micromatch": "^3.0.4",
+ "resolve-dir": "^1.0.1"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "first-chunk-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz",
+ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "flat-cache": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+ "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+ "dev": true,
+ "requires": {
+ "flatted": "^2.0.0",
+ "rimraf": "2.6.3",
+ "write": "1.0.3"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
+ "flatted": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
+ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+ "dev": true
+ },
+ "flatten": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
+ "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "focus-trap": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-5.1.0.tgz",
+ "integrity": "sha512-CkB/nrO55069QAUjWFBpX6oc+9V90Qhgpe6fBWApzruMq5gnlh90Oo7iSSDK7pKiV5ugG6OY2AXM5mxcmL3lwQ==",
+ "requires": {
+ "tabbable": "^4.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "focus-visible": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.1.0.tgz",
+ "integrity": "sha512-nPer0rjtzdZ7csVIu233P2cUm/ks/4aVSI+5KUkYrYpgA7ujgC3p6J7FtFU+AIMWwnwYQOB/yeiOITxFeYIXiw=="
+ },
+ "follow-redirects": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz",
+ "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==",
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+ },
+ "foreachasync": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz",
+ "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "optional": true
+ },
+ "fullname": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/fullname/-/fullname-4.0.1.tgz",
+ "integrity": "sha512-jVT8q9Ah9JwqfIGKwKzTdbRRthdPpIjEe9kgvxM104Tv+q6SgOAQqJMVP90R0DBRAqejGMHDRWJtl3Ats6BjfQ==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "filter-obj": "^2.0.0",
+ "mem": "^5.1.0",
+ "p-any": "^2.1.0",
+ "passwd-user": "^3.0.0",
+ "rc": "^1.2.8"
+ },
+ "dependencies": {
+ "mem": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz",
+ "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.3",
+ "mimic-fn": "^2.1.0",
+ "p-is-promise": "^2.1.0"
+ }
+ }
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "gauge": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz",
+ "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=",
+ "dev": true,
+ "requires": {
+ "ansi": "^0.3.0",
+ "has-unicode": "^2.0.0",
+ "lodash.pad": "^4.1.0",
+ "lodash.padend": "^4.1.0",
+ "lodash.padstart": "^4.1.0"
+ }
+ },
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg=="
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
+ "get-node-dimensions": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz",
+ "integrity": "sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ=="
+ },
+ "get-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "gh-got": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-5.0.0.tgz",
+ "integrity": "sha1-7pW+NxBv2HSKlvjR20uuqJ4b+oo=",
+ "dev": true,
+ "requires": {
+ "got": "^6.2.0",
+ "is-plain-obj": "^1.1.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "dev": true,
+ "requires": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ }
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ }
+ }
+ },
+ "github-username": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/github-username/-/github-username-3.0.0.tgz",
+ "integrity": "sha1-CnciGbMTB0NCnyRW0L3T21Xc57E=",
+ "dev": true,
+ "requires": {
+ "gh-got": "^5.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "glob-to-regexp": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
+ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
+ "dev": true
+ },
+ "global-agent": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz",
+ "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==",
+ "dev": true,
+ "requires": {
+ "boolean": "^3.0.1",
+ "core-js": "^3.6.5",
+ "es6-error": "^4.1.1",
+ "matcher": "^3.0.0",
+ "roarr": "^2.15.3",
+ "semver": "^7.3.2",
+ "serialize-error": "^7.0.1"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
+ "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "dev": true
+ }
+ }
+ },
+ "global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.4"
+ }
+ },
+ "global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "requires": {
+ "global-prefix": "^3.0.0"
+ },
+ "dependencies": {
+ "global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "requires": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ }
+ }
+ }
+ },
+ "global-prefix": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+ "requires": {
+ "expand-tilde": "^2.0.2",
+ "homedir-polyfill": "^1.0.1",
+ "ini": "^1.3.4",
+ "is-windows": "^1.0.1",
+ "which": "^1.2.14"
+ }
+ },
+ "global-tunnel-ng": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz",
+ "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "^1.0.2",
+ "lodash": "^4.17.10",
+ "npm-conf": "^1.1.3",
+ "tunnel": "^0.0.6"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ },
+ "globalthis": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz",
+ "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3"
+ }
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "globjoin": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+ "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
+ "dev": true
+ },
+ "gonzales-pe": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz",
+ "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "got": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
+ "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "^0.7.0",
+ "cacheable-request": "^2.1.1",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "into-stream": "^3.1.0",
+ "is-retry-allowed": "^1.1.0",
+ "isurl": "^1.0.0-alpha5",
+ "lowercase-keys": "^1.0.0",
+ "mimic-response": "^1.0.0",
+ "p-cancelable": "^0.4.0",
+ "p-timeout": "^2.0.1",
+ "pify": "^3.0.0",
+ "safe-buffer": "^5.1.1",
+ "timed-out": "^4.0.1",
+ "url-parse-lax": "^3.0.0",
+ "url-to-options": "^1.0.1"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "p-cancelable": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
+ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
+ },
+ "grouped-queue": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-1.1.0.tgz",
+ "integrity": "sha512-rZOFKfCqLhsu5VqjBjEWiwrYqJR07KxIkH4mLZlNlGDfntbb4FbMyGFP14TlvRPrU9S3Hnn/sgxbC5ZeN0no3Q==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.15"
+ }
+ },
+ "handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg=="
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "has-symbol-support-x": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
+ "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ },
+ "has-to-string-tag-x": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
+ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
+ "dev": true,
+ "requires": {
+ "has-symbol-support-x": "^1.4.1"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "requires": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ }
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
+ },
+ "header-case": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz",
+ "integrity": "sha1-lTWXMZfBRLCWE81l0xfvGZY70C0=",
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.3"
+ }
+ },
+ "highlight.js": {
+ "version": "9.18.1",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
+ "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg=="
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hoist-non-react-statics": {
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
+ "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
+ },
+ "homedir-polyfill": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
+ "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
+ "requires": {
+ "parse-passwd": "^1.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "dev": true
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "html-entities": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
+ "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
+ },
+ "html-loader": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz",
+ "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==",
+ "requires": {
+ "es6-templates": "^0.2.3",
+ "fastparse": "^1.1.1",
+ "html-minifier": "^3.5.8",
+ "loader-utils": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "html-minifier": {
+ "version": "3.5.21",
+ "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
+ "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "requires": {
+ "camel-case": "3.0.x",
+ "clean-css": "4.2.x",
+ "commander": "2.17.x",
+ "he": "1.2.x",
+ "param-case": "2.1.x",
+ "relateurl": "0.2.x",
+ "uglify-js": "3.4.x"
+ }
+ },
+ "html-tags": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
+ "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==",
+ "dev": true
+ },
+ "html-to-react": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.4.3.tgz",
+ "integrity": "sha512-txe09A3vxW8yEZGJXJ1is5gGDfBEVACmZDSgwDyH5EsfRdOubBwBCg63ZThZP0xBn0UE4FyvMXZXmohusCxDcg==",
+ "requires": {
+ "domhandler": "^3.0",
+ "htmlparser2": "^4.1.0",
+ "lodash.camelcase": "^4.3.0",
+ "ramda": "^0.27"
+ }
+ },
+ "htmlparser2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
+ "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^3.0.0",
+ "domutils": "^2.0.0",
+ "entities": "^2.0.0"
+ }
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
+ "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+ "requires": {
+ "http-proxy": "^1.17.0",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.11",
+ "micromatch": "^3.1.10"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true
+ },
+ "humanize-string": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/humanize-string/-/humanize-string-1.0.2.tgz",
+ "integrity": "sha512-PH5GBkXqFxw5+4eKaKRIkD23y6vRd/IXSl7IldyJxEXpDH9SEIXRORkBtkGni/ae2P7RVOw6Wxypd2tGXhha1w==",
+ "dev": true,
+ "requires": {
+ "decamelize": "^1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "icss-utils": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
+ "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==",
+ "requires": {
+ "postcss": "^7.0.14"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "import-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
+ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+ "requires": {
+ "import-from": "^2.1.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-from": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
+ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-lazy": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
+ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+ "dev": true
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "imports-loader": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-0.8.0.tgz",
+ "integrity": "sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ==",
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "indexes-of": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
+ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc="
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ },
+ "inquirer": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
+ "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^3.0.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.15",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.5.3",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "insight": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/insight/-/insight-0.10.3.tgz",
+ "integrity": "sha512-YOncxSN6Omh+1Oqxt+OJAvJVMDKw7l6IEG0wT2cTMGxjsTcroOGW4IR926QDzxg/uZHcFZ2cZbckDWdZhc2pZw==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "chalk": "^2.4.2",
+ "conf": "^1.4.0",
+ "inquirer": "^6.3.1",
+ "lodash.debounce": "^4.0.8",
+ "os-name": "^3.1.0",
+ "request": "^2.88.0",
+ "tough-cookie": "^3.0.1",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "inquirer": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+ "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.2.0",
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^2.0.0",
+ "lodash": "^4.17.12",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.4.0",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^5.1.0",
+ "through": "^2.3.6"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "internal-ip": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
+ "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
+ "requires": {
+ "default-gateway": "^4.2.0",
+ "ipaddr.js": "^1.9.0"
+ }
+ },
+ "interpolate-loader": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/interpolate-loader/-/interpolate-loader-2.0.1.tgz",
+ "integrity": "sha512-X5/cKHUnAS5gV/oK9Z6pEjg2xVH5EGgnC5QmaOPwK/o7qMOMyyafwFL1mtH3yAK+COCjyaH56MOs9G8uXG12yA==",
+ "requires": {
+ "escape-string-regexp": "^2.0.0",
+ "loader-utils": "^1.1.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
+ }
+ }
+ },
+ "interpret": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw=="
+ },
+ "into-stream": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+ "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=",
+ "dev": true,
+ "requires": {
+ "from2": "^2.1.1",
+ "p-is-promise": "^1.1.0"
+ },
+ "dependencies": {
+ "p-is-promise": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=",
+ "dev": true
+ }
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
+ },
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
+ },
+ "is-absolute-url": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
+ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q=="
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="
+ },
+ "is-alphanumeric": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz",
+ "integrity": "sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ=",
+ "dev": true
+ },
+ "is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "requires": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ }
+ },
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz",
+ "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g=="
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz",
+ "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ=="
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "is-callable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
+ },
+ "is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^1.5.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
+ },
+ "is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw=="
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+ },
+ "is-docker": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz",
+ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
+ "is-finite": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+ "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
+ },
+ "is-installed-globally": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+ "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ },
+ "dependencies": {
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ }
+ }
+ },
+ "is-lower-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz",
+ "integrity": "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=",
+ "requires": {
+ "lower-case": "^1.1.0"
+ }
+ },
+ "is-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
+ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw=="
+ },
+ "is-npm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ },
+ "is-number-object": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
+ "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
+ "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
+ "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ=="
+ },
+ "is-path-in-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
+ "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
+ "requires": {
+ "is-path-inside": "^2.1.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
+ "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
+ "requires": {
+ "path-is-inside": "^1.0.2"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-redirect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
+ "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-regexp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz",
+ "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==",
+ "dev": true
+ },
+ "is-retry-allowed": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+ "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
+ "dev": true
+ },
+ "is-root": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-root/-/is-root-1.0.0.tgz",
+ "integrity": "sha1-B7bCM7w5TNnQK6FclmvWZg1jQtU=",
+ "dev": true
+ },
+ "is-scoped": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz",
+ "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=",
+ "dev": true,
+ "requires": {
+ "scoped-regex": "^1.0.0"
+ }
+ },
+ "is-set": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
+ "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA=="
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-string": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ=="
+ },
+ "is-supported-regexp-flag": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz",
+ "integrity": "sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-typed-array": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz",
+ "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==",
+ "requires": {
+ "available-typed-arrays": "^1.0.0",
+ "es-abstract": "^1.17.4",
+ "foreach": "^2.0.5",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-upper-case": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz",
+ "integrity": "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=",
+ "requires": {
+ "upper-case": "^1.1.0"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA=="
+ },
+ "is-weakset": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
+ "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw=="
+ },
+ "is-whitespace-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
+ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w=="
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+ },
+ "is-word-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+ "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA=="
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
+ },
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+ },
+ "isbinaryfile": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz",
+ "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "istextorbinary": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz",
+ "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==",
+ "dev": true,
+ "requires": {
+ "binaryextensions": "^2.1.2",
+ "editions": "^2.2.0",
+ "textextensions": "^2.5.0"
+ }
+ },
+ "isurl": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
+ "dev": true,
+ "requires": {
+ "has-to-string-tag-x": "^1.2.0",
+ "is-object": "^1.0.1"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ }
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "json3": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
+ "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA=="
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "just-debounce-it": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/just-debounce-it/-/just-debounce-it-1.1.0.tgz",
+ "integrity": "sha512-87Nnc0qZKgBZuhFZjYVjSraic0x7zwjhaTMrCKlj0QYKH6lh0KbFzVnfu6LHan03NO7J8ygjeBeD0epejn5Zcg=="
+ },
+ "keyv": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
+ "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg=="
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+ },
+ "known-css-properties": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.19.0.tgz",
+ "integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==",
+ "dev": true
+ },
+ "latest-version": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+ "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+ "dev": true,
+ "requires": {
+ "package-json": "^4.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "dev": true,
+ "requires": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ }
+ },
+ "package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+ "dev": true,
+ "requires": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ }
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ }
+ }
+ },
+ "lazy-cache": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
+ "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=",
+ "dev": true,
+ "requires": {
+ "set-getter": "^0.1.0"
+ }
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
+ },
+ "levenary": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
+ "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
+ "requires": {
+ "leven": "^3.1.0"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "lines-and-columns": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
+ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ },
+ "dependencies": {
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw=="
+ },
+ "loader-utils": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+ "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ }
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "locutus": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/locutus/-/locutus-2.0.11.tgz",
+ "integrity": "sha512-C0q1L38lK5q1t+wE0KY21/9szrBHxye6o2z5EJzU+5B79tubNOC+nLAEzTTn1vPUGoUuehKh8kYKqiVUTWRyaQ==",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.2.5"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
+ },
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
+ },
+ "lodash.pad": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz",
+ "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=",
+ "dev": true
+ },
+ "lodash.padend": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
+ "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=",
+ "dev": true
+ },
+ "lodash.padstart": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz",
+ "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=",
+ "dev": true
+ },
+ "lodash.template": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
+ "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
+ "requires": {
+ "lodash._reinterpolate": "^3.0.0",
+ "lodash.templatesettings": "^4.0.0"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
+ "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
+ "requires": {
+ "lodash._reinterpolate": "^3.0.0"
+ }
+ },
+ "log-symbols": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
+ "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "loglevel": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
+ "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA=="
+ },
+ "longest-streak": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
+ "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
+ },
+ "lower-case-first": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-1.0.2.tgz",
+ "integrity": "sha1-5dp8JvKacHO+AtUrrJmA5ZIq36E=",
+ "requires": {
+ "lower-case": "^1.1.2"
+ }
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "macos-release": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz",
+ "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+ },
+ "map-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz",
+ "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "markdown-escapes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg=="
+ },
+ "markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dev": true,
+ "requires": {
+ "repeat-string": "^1.0.0"
+ }
+ },
+ "matcher": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
+ "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^4.0.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ }
+ }
+ },
+ "mathml-tag-names": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
+ "dev": true
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "mdast-add-list-metadata": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz",
+ "integrity": "sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==",
+ "requires": {
+ "unist-util-visit-parents": "1.1.2"
+ }
+ },
+ "mdast-util-compact": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz",
+ "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==",
+ "dev": true,
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz",
+ "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==",
+ "dev": true
+ },
+ "unist-util-visit": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz",
+ "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz",
+ "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "mem-fs": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.2.0.tgz",
+ "integrity": "sha512-b8g0jWKdl8pM0LqAPdK9i8ERL7nYrzmJfRhxMiWH2uYdfYnb7uXnmwVb0ZGe7xyEl4lj+nLIU3yf4zPUT+XsVQ==",
+ "dev": true,
+ "requires": {
+ "through2": "^3.0.0",
+ "vinyl": "^2.0.1",
+ "vinyl-file": "^3.0.0"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
+ "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2 || 3"
+ }
+ }
+ }
+ },
+ "mem-fs-editor": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-6.0.0.tgz",
+ "integrity": "sha512-e0WfJAMm8Gv1mP5fEq/Blzy6Lt1VbLg7gNnZmZak7nhrBTibs+c6nQ4SKs/ZyJYHS1mFgDJeopsLAv7Ow0FMFg==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "deep-extend": "^0.6.0",
+ "ejs": "^2.6.1",
+ "glob": "^7.1.4",
+ "globby": "^9.2.0",
+ "isbinaryfile": "^4.0.0",
+ "mkdirp": "^0.5.0",
+ "multimatch": "^4.0.0",
+ "rimraf": "^2.6.3",
+ "through2": "^3.0.1",
+ "vinyl": "^2.2.0"
+ },
+ "dependencies": {
+ "@nodelib/fs.stat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+ "dev": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ }
+ },
+ "fast-glob": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
+ "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==",
+ "dev": true,
+ "requires": {
+ "@mrmlnc/readdir-enhanced": "^2.2.1",
+ "@nodelib/fs.stat": "^1.1.2",
+ "glob-parent": "^3.1.0",
+ "is-glob": "^4.0.0",
+ "merge2": "^1.2.3",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "globby": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz",
+ "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^1.0.2",
+ "dir-glob": "^2.2.2",
+ "fast-glob": "^2.2.6",
+ "glob": "^7.1.3",
+ "ignore": "^4.0.3",
+ "pify": "^4.0.1",
+ "slash": "^2.0.0"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "through2": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
+ "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2 || 3"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "memoize-one": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
+ "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "meow": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
+ "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
+ "dev": true,
+ "requires": {
+ "@types/minimist": "^1.2.0",
+ "arrify": "^2.0.1",
+ "camelcase": "^6.0.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "^4.0.2",
+ "normalize-package-data": "^2.5.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.13.1",
+ "yargs-parser": "^18.1.3"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
+ "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "micromatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+ "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.0.5"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "mime": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
+ "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
+ },
+ "mime-db": {
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+ "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+ },
+ "mime-types": {
+ "version": "2.1.27",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+ "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+ "requires": {
+ "mime-db": "1.44.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ },
+ "mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "dev": true
+ },
+ "min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ },
+ "dependencies": {
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ }
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "moment": {
+ "version": "2.26.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
+ "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
+ },
+ "multimatch": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz",
+ "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "^3.0.3",
+ "array-differ": "^3.0.0",
+ "array-union": "^2.1.0",
+ "arrify": "^2.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "dependencies": {
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ }
+ }
+ },
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+ "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "neo-async": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "requires": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
+ "node-forge": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
+ "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ=="
+ },
+ "node-libs-browser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+ "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.1",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "^1.0.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "node-releases": {
+ "version": "1.1.58",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.58.tgz",
+ "integrity": "sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg=="
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI="
+ },
+ "normalize-selector": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz",
+ "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
+ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0",
+ "query-string": "^5.0.1",
+ "sort-keys": "^2.0.0"
+ }
+ },
+ "npm-api": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/npm-api/-/npm-api-1.0.0.tgz",
+ "integrity": "sha512-gtJhIhGq07g9H5sIAB9TZzTySW8MYtcYqg+e+J+5q1GmDsDLLVfyvVBL1VklzjtRsElph11GUtLBS191RDOJxQ==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.3.5",
+ "clone-deep": "^4.0.1",
+ "download-stats": "^0.3.4",
+ "moment": "^2.24.0",
+ "paged-request": "^2.0.1",
+ "request": "^2.88.0"
+ }
+ },
+ "npm-conf": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
+ "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
+ "dev": true,
+ "requires": {
+ "config-chain": "^1.1.11",
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "npm-keyword": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/npm-keyword/-/npm-keyword-5.0.0.tgz",
+ "integrity": "sha1-mbha7Cn8s4jS3TUfABO/Umh4fmc=",
+ "dev": true,
+ "requires": {
+ "got": "^7.1.0",
+ "registry-url": "^3.0.3"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "got": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz",
+ "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
+ "dev": true,
+ "requires": {
+ "decompress-response": "^3.2.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-plain-obj": "^1.1.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "isurl": "^1.0.0-alpha5",
+ "lowercase-keys": "^1.0.0",
+ "p-cancelable": "^0.3.0",
+ "p-timeout": "^1.1.1",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "url-parse-lax": "^1.0.0",
+ "url-to-options": "^1.0.1"
+ }
+ },
+ "p-cancelable": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
+ "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==",
+ "dev": true
+ },
+ "p-timeout": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
+ "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0"
+ }
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ }
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz",
+ "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=",
+ "dev": true,
+ "requires": {
+ "ansi": "~0.3.1",
+ "are-we-there-yet": "~1.1.2",
+ "gauge": "~1.2.5"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4="
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
+ },
+ "object-is": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
+ "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+ "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
+ "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "opn": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
+ "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-name": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz",
+ "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==",
+ "dev": true,
+ "requires": {
+ "macos-release": "^2.2.0",
+ "windows-release": "^3.1.0"
+ }
+ },
+ "os-shim": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
+ "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=",
+ "dev": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "p-any": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-any/-/p-any-2.1.0.tgz",
+ "integrity": "sha512-JAERcaMBLYKMq+voYw36+x5Dgh47+/o7yuv2oQYuSSUml4YeqJEFznBrY2UeEkoSHqBua6hz518n/PsowTYLLg==",
+ "dev": true,
+ "requires": {
+ "p-cancelable": "^2.0.0",
+ "p-some": "^4.0.0",
+ "type-fest": "^0.3.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+ "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+ "dev": true
+ }
+ }
+ },
+ "p-cancelable": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz",
+ "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==",
+ "dev": true
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="
+ },
+ "p-retry": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
+ "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
+ "requires": {
+ "retry": "^0.12.0"
+ }
+ },
+ "p-some": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-some/-/p-some-4.1.0.tgz",
+ "integrity": "sha512-MF/HIbq6GeBqTrTIl5OJubzkGU+qfFhAFi0gnTAK6rgEIJIknEiABHOTtQu4e6JiXjIwuMPMUFQzyHh5QjCl1g==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0",
+ "p-cancelable": "^2.0.0"
+ }
+ },
+ "p-timeout": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
+ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ },
+ "package-json": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-5.0.0.tgz",
+ "integrity": "sha512-EeHQFFTlEmLrkIQoxbE9w0FuAWHoc1XpthDqnZ/i9keOt701cteyXwAxQFLpVqVjj3feh2TodkihjLaRUtIgLg==",
+ "dev": true,
+ "requires": {
+ "got": "^8.3.1",
+ "registry-auth-token": "^3.3.2",
+ "registry-url": "^3.1.0",
+ "semver": "^5.5.0"
+ }
+ },
+ "pad-component": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/pad-component/-/pad-component-0.0.1.tgz",
+ "integrity": "sha1-rR8izhvw/cDW3dkIrxfzUaQEuKw=",
+ "dev": true
+ },
+ "paged-request": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/paged-request/-/paged-request-2.0.1.tgz",
+ "integrity": "sha512-C0bB/PFk9rQskD1YEiz7uuchzqKDQGgdsEHN1ahify0UUWzgmMK4NDG9fhlQg2waogmNFwEvEeHfMRvJySpdVw==",
+ "dev": true,
+ "requires": {
+ "axios": "^0.18.0"
+ }
+ },
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+ },
+ "parallel-transform": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+ "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+ "requires": {
+ "cyclist": "^1.0.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "param-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ }
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+ "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-entities": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz",
+ "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==",
+ "requires": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ }
+ },
+ "parse-help": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-help/-/parse-help-1.0.0.tgz",
+ "integrity": "sha512-dlOrbBba6Rrw/nrJ+V7/vkGZdiimWJQzMHZZrYsUq03JE8AV3fAv6kOYX7dP/w2h67lIdmRf8ES8mU44xAgE/Q==",
+ "dev": true,
+ "requires": {
+ "execall": "^1.0.0"
+ },
+ "dependencies": {
+ "clone-regexp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz",
+ "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==",
+ "dev": true,
+ "requires": {
+ "is-regexp": "^1.0.0",
+ "is-supported-regexp-flag": "^1.0.0"
+ }
+ },
+ "execall": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz",
+ "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=",
+ "dev": true,
+ "requires": {
+ "clone-regexp": "^1.0.0"
+ }
+ },
+ "is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
+ "dev": true
+ }
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "pascal-case": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-2.0.1.tgz",
+ "integrity": "sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=",
+ "requires": {
+ "camel-case": "^3.0.0",
+ "upper-case-first": "^1.1.0"
+ }
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+ },
+ "passwd-user": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/passwd-user/-/passwd-user-3.0.0.tgz",
+ "integrity": "sha512-Iu90rROks+uDK00ppSewoZyqeCwjGR6W8PcY0Phl8YFWju/lRmIogQb98+vSb5RUeYkONL3IC4ZLBFg4FiE0Hg==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0"
+ }
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ=="
+ },
+ "path-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/path-case/-/path-case-2.1.1.tgz",
+ "integrity": "sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=",
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "pbkdf2": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
+ "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "requires": {
+ "find-up": "^3.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ }
+ }
+ },
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "portfinder": {
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
+ "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
+ "requires": {
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+ },
+ "postcss": {
+ "version": "7.0.32",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
+ "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==",
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-attribute-case-insensitive": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz",
+ "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-selector-parser": "^6.0.2"
+ }
+ },
+ "postcss-calc": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz",
+ "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==",
+ "requires": {
+ "postcss": "^7.0.27",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "postcss-color-functional-notation": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz",
+ "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-color-gray": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz",
+ "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==",
+ "requires": {
+ "@csstools/convert-colors": "^1.4.0",
+ "postcss": "^7.0.5",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-color-hex-alpha": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz",
+ "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==",
+ "requires": {
+ "postcss": "^7.0.14",
+ "postcss-values-parser": "^2.0.1"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-color-mod-function": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz",
+ "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==",
+ "requires": {
+ "@csstools/convert-colors": "^1.4.0",
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-color-rebeccapurple": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz",
+ "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-custom-media": {
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz",
+ "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==",
+ "requires": {
+ "postcss": "^7.0.14"
+ }
+ },
+ "postcss-custom-properties": {
+ "version": "8.0.11",
+ "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz",
+ "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==",
+ "requires": {
+ "postcss": "^7.0.17",
+ "postcss-values-parser": "^2.0.1"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-custom-selectors": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz",
+ "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-selector-parser": "^5.0.0-rc.3"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-dir-pseudo-class": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz",
+ "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-selector-parser": "^5.0.0-rc.3"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-double-position-gradients": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz",
+ "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==",
+ "requires": {
+ "postcss": "^7.0.5",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-env-function": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz",
+ "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-flexbugs-fixes": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz",
+ "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==",
+ "requires": {
+ "postcss": "^7.0.26"
+ }
+ },
+ "postcss-focus-visible": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz",
+ "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-focus-within": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz",
+ "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-font-family-system-ui": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-4.2.0.tgz",
+ "integrity": "sha512-qTizXw0iwu/9K1+UPmu2BsC65VX2NiZI2hMreL/SkqJd+EwmCktE+juz/xoy7XH2WGfb9x0ES2yA4LuwUyV/Yg==",
+ "requires": {
+ "browserslist": "^4.8.2",
+ "caniuse-lite": "^1.0.30001016",
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-font-variant": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz",
+ "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-gap-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz",
+ "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-html": {
+ "version": "0.36.0",
+ "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz",
+ "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==",
+ "dev": true,
+ "requires": {
+ "htmlparser2": "^3.10.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-image-set-function": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz",
+ "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-import": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
+ "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
+ "requires": {
+ "postcss": "^7.0.1",
+ "postcss-value-parser": "^3.2.3",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "dependencies": {
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
+ }
+ }
+ },
+ "postcss-initial": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz",
+ "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==",
+ "requires": {
+ "lodash.template": "^4.5.0",
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-lab-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz",
+ "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==",
+ "requires": {
+ "@csstools/convert-colors": "^1.4.0",
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-less": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz",
+ "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.14"
+ }
+ },
+ "postcss-load-config": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
+ "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "import-cwd": "^2.0.0"
+ }
+ },
+ "postcss-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^7.0.0",
+ "postcss-load-config": "^2.0.0",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "postcss-logical": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz",
+ "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-media-minmax": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz",
+ "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-media-query-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+ "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=",
+ "dev": true
+ },
+ "postcss-modules-extract-imports": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
+ "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
+ "requires": {
+ "postcss": "^7.0.5"
+ }
+ },
+ "postcss-modules-local-by-default": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz",
+ "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==",
+ "requires": {
+ "icss-utils": "^4.1.1",
+ "postcss": "^7.0.16",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.0.0"
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz",
+ "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==",
+ "requires": {
+ "postcss": "^7.0.6",
+ "postcss-selector-parser": "^6.0.0"
+ }
+ },
+ "postcss-modules-values": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz",
+ "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==",
+ "requires": {
+ "icss-utils": "^4.0.0",
+ "postcss": "^7.0.6"
+ }
+ },
+ "postcss-modules-values-replace": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values-replace/-/postcss-modules-values-replace-3.1.0.tgz",
+ "integrity": "sha512-9UPidpGUjJPZEangWQF09JNKm2A3LeWytV2KuSY9OgUXZm6sQw5W6lIIG4XoGji43CD0gZf17nR5br5WMUCMyQ==",
+ "requires": {
+ "enhanced-resolve": "^3.1.0",
+ "es6-promisify": "^5.0.0",
+ "postcss": "^6.0.1",
+ "postcss-values-parser": "^1.3.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "postcss-nesting": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz",
+ "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-overflow-shorthand": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz",
+ "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-page-break": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz",
+ "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-place": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz",
+ "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-values-parser": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss-values-parser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz",
+ "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-preset-env": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz",
+ "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==",
+ "requires": {
+ "autoprefixer": "^9.6.1",
+ "browserslist": "^4.6.4",
+ "caniuse-lite": "^1.0.30000981",
+ "css-blank-pseudo": "^0.1.4",
+ "css-has-pseudo": "^0.10.0",
+ "css-prefers-color-scheme": "^3.1.1",
+ "cssdb": "^4.4.0",
+ "postcss": "^7.0.17",
+ "postcss-attribute-case-insensitive": "^4.0.1",
+ "postcss-color-functional-notation": "^2.0.1",
+ "postcss-color-gray": "^5.0.0",
+ "postcss-color-hex-alpha": "^5.0.3",
+ "postcss-color-mod-function": "^3.0.3",
+ "postcss-color-rebeccapurple": "^4.0.1",
+ "postcss-custom-media": "^7.0.8",
+ "postcss-custom-properties": "^8.0.11",
+ "postcss-custom-selectors": "^5.1.2",
+ "postcss-dir-pseudo-class": "^5.0.0",
+ "postcss-double-position-gradients": "^1.0.0",
+ "postcss-env-function": "^2.0.2",
+ "postcss-focus-visible": "^4.0.0",
+ "postcss-focus-within": "^3.0.0",
+ "postcss-font-variant": "^4.0.0",
+ "postcss-gap-properties": "^2.0.0",
+ "postcss-image-set-function": "^3.0.1",
+ "postcss-initial": "^3.0.0",
+ "postcss-lab-function": "^2.0.1",
+ "postcss-logical": "^3.0.0",
+ "postcss-media-minmax": "^4.0.0",
+ "postcss-nesting": "^7.0.0",
+ "postcss-overflow-shorthand": "^2.0.0",
+ "postcss-page-break": "^2.0.0",
+ "postcss-place": "^4.0.1",
+ "postcss-pseudo-class-any-link": "^6.0.0",
+ "postcss-replace-overflow-wrap": "^3.0.0",
+ "postcss-selector-matches": "^4.0.0",
+ "postcss-selector-not": "^4.0.0"
+ }
+ },
+ "postcss-pseudo-class-any-link": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz",
+ "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==",
+ "requires": {
+ "postcss": "^7.0.2",
+ "postcss-selector-parser": "^5.0.0-rc.3"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-replace-overflow-wrap": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz",
+ "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==",
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-reporter": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-6.0.1.tgz",
+ "integrity": "sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "lodash": "^4.17.11",
+ "log-symbols": "^2.2.0",
+ "postcss": "^7.0.7"
+ },
+ "dependencies": {
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ }
+ }
+ },
+ "postcss-resolve-nested-selector": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
+ "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=",
+ "dev": true
+ },
+ "postcss-safe-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz",
+ "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.26"
+ }
+ },
+ "postcss-sass": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.4.4.tgz",
+ "integrity": "sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==",
+ "dev": true,
+ "requires": {
+ "gonzales-pe": "^4.3.0",
+ "postcss": "^7.0.21"
+ }
+ },
+ "postcss-scss": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz",
+ "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.6"
+ }
+ },
+ "postcss-selector-matches": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz",
+ "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-selector-not": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz",
+ "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "postcss": "^7.0.2"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
+ "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
+ "requires": {
+ "cssesc": "^3.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "postcss-sorting": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-5.0.1.tgz",
+ "integrity": "sha512-Y9fUFkIhfrm6i0Ta3n+89j56EFqaNRdUKqXyRp6kvTcSXnmgEjaVowCXH+JBe9+YKWqd4nc28r2sgwnzJalccA==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14",
+ "postcss": "^7.0.17"
+ }
+ },
+ "postcss-syntax": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
+ "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
+ "dev": true
+ },
+ "postcss-value-parser": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
+ "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
+ },
+ "postcss-values-parser": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-1.5.0.tgz",
+ "integrity": "sha512-3M3p+2gMp0AH3da530TlX8kiO1nxdTnc3C6vr8dMxRLIlh8UYkz0/wcwptSXjhtx2Fr0TySI7a+BHDQ8NL7LaQ==",
+ "requires": {
+ "flatten": "^1.0.2",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "prefixfree": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prefixfree/-/prefixfree-1.0.0.tgz",
+ "integrity": "sha1-grDtu6wQfyo+LcVp1sPfQDXNeRA="
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "pretty-bytes": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz",
+ "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+ },
+ "prop-types": {
+ "version": "15.7.2",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
+ "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.8.1"
+ }
+ },
+ "proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=",
+ "dev": true
+ },
+ "proxy-addr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
+ "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.1"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.11.9",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
+ "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ }
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "query-string": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
+ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
+ "dev": true,
+ "requires": {
+ "decode-uri-component": "^0.2.0",
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
+ },
+ "quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true
+ },
+ "ramda": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz",
+ "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA=="
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ }
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ }
+ }
+ },
+ "react": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
+ "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2"
+ }
+ },
+ "react-dom": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
+ "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "scheduler": "^0.19.1"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "react-markdown": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-4.3.1.tgz",
+ "integrity": "sha512-HQlWFTbDxTtNY6bjgp3C3uv1h2xcjCSi1zAEzfBW9OwJJvENSYiLXWNXN5hHLsoqai7RnZiiHzcnWdXk2Splzw==",
+ "requires": {
+ "html-to-react": "^1.3.4",
+ "mdast-add-list-metadata": "1.0.1",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.6",
+ "remark-parse": "^5.0.0",
+ "unified": "^6.1.5",
+ "unist-util-visit": "^1.3.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "react-measure": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/react-measure/-/react-measure-2.3.0.tgz",
+ "integrity": "sha512-dwAvmiOeblj5Dvpnk8Jm7Q8B4THF/f1l1HtKVi0XDecsG6LXwGvzV5R1H32kq3TW6RW64OAf5aoQxpIgLa4z8A==",
+ "requires": {
+ "@babel/runtime": "^7.2.0",
+ "get-node-dimensions": "^1.2.1",
+ "prop-types": "^15.6.2",
+ "resize-observer-polyfill": "^1.5.0"
+ }
+ },
+ "react-sortable-hoc": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.11.0.tgz",
+ "integrity": "sha512-v1CDCvdfoR3zLGNp6qsBa4J1BWMEVH25+UKxF/RvQRh+mrB+emqtVHMgZ+WreUiKJoEaiwYoScaueIKhMVBHUg==",
+ "requires": {
+ "@babel/runtime": "^7.2.0",
+ "invariant": "^2.2.4",
+ "prop-types": "^15.5.7"
+ }
+ },
+ "react-virtualized": {
+ "version": "9.21.2",
+ "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.21.2.tgz",
+ "integrity": "sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA==",
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "clsx": "^1.0.1",
+ "dom-helpers": "^5.0.0",
+ "loose-envify": "^1.3.0",
+ "prop-types": "^15.6.0",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "react-waypoint": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/react-waypoint/-/react-waypoint-9.0.2.tgz",
+ "integrity": "sha512-6tIr9NozeDH789Ox2tOkyDcmprYOx1+eII40dERLrZclFe6RhWAQ/bbd6B7cGild6onXNwPzg16y0/wHWQ/q+g==",
+ "requires": {
+ "consolidated-events": "^1.1.0 || ^2.0.0",
+ "prop-types": "^15.0.0",
+ "react-is": "^16.6.3"
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+ "requires": {
+ "pify": "^2.3.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "read-chunk": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz",
+ "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "with-open-file": "^0.1.6"
+ }
+ },
+ "read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "requires": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "dependencies": {
+ "parse-json": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+ "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ }
+ }
+ },
+ "readdirp": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+ "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "recast": {
+ "version": "0.11.23",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz",
+ "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=",
+ "requires": {
+ "ast-types": "0.9.6",
+ "esprima": "~3.1.0",
+ "private": "~0.1.5",
+ "source-map": "~0.5.0"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.1.6"
+ }
+ },
+ "recompose": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz",
+ "integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==",
+ "requires": {
+ "@babel/runtime": "^7.0.0",
+ "change-emitter": "^0.1.2",
+ "fbjs": "^0.8.1",
+ "hoist-non-react-statics": "^2.3.1",
+ "react-lifecycles-compat": "^3.0.2",
+ "symbol-observable": "^1.0.4"
+ }
+ },
+ "redbox-react": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/redbox-react/-/redbox-react-1.6.0.tgz",
+ "integrity": "sha512-mLjM5eYR41yOp5YKHpd3syFeGq6B4Wj5vZr64nbLvTZW5ZLff4LYk7VE4ITpVxkZpCY6OZuqh0HiP3A3uEaCpg==",
+ "requires": {
+ "error-stack-parser": "^1.3.6",
+ "object-assign": "^4.0.1",
+ "prop-types": "^15.5.4",
+ "sourcemapped-stacktrace": "^1.1.6"
+ }
+ },
+ "redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "requires": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ }
+ },
+ "regenerate": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
+ "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A=="
+ },
+ "regenerate-unicode-properties": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
+ "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
+ "requires": {
+ "regenerate": "^1.4.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+ "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
+ },
+ "regenerator-transform": {
+ "version": "0.14.4",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz",
+ "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==",
+ "requires": {
+ "@babel/runtime": "^7.8.4",
+ "private": "^0.1.8"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
+ "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ }
+ },
+ "regexpp": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
+ "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
+ "requires": {
+ "regenerate": "^1.4.0",
+ "regenerate-unicode-properties": "^8.2.0",
+ "regjsgen": "^0.5.1",
+ "regjsparser": "^0.6.4",
+ "unicode-match-property-ecmascript": "^1.0.4",
+ "unicode-match-property-value-ecmascript": "^1.2.0"
+ }
+ },
+ "registry-auth-token": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+ "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+ "dev": true,
+ "requires": {
+ "rc": "^1.0.1"
+ }
+ },
+ "regjsgen": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
+ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A=="
+ },
+ "regjsparser": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz",
+ "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==",
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+ }
+ }
+ },
+ "relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
+ },
+ "remark": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.0.tgz",
+ "integrity": "sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A==",
+ "dev": true,
+ "requires": {
+ "remark-parse": "^8.0.0",
+ "remark-stringify": "^8.0.0",
+ "unified": "^9.0.0"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
+ "parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "requires": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ }
+ },
+ "remark-parse": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz",
+ "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==",
+ "dev": true,
+ "requires": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "unified": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.0.0.tgz",
+ "integrity": "sha512-ssFo33gljU3PdlWLjNp15Inqb77d6JnJSfyplGJPT/a+fNRNyCBeveBAYJdO5khKdF6WVHa/yYCC7Xl6BDwZUQ==",
+ "dev": true,
+ "requires": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ }
+ },
+ "unist-util-is": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz",
+ "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==",
+ "dev": true
+ },
+ "unist-util-remove-position": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz",
+ "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==",
+ "dev": true,
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ }
+ },
+ "unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.2"
+ }
+ },
+ "unist-util-visit": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz",
+ "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz",
+ "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ },
+ "vfile": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.1.1.tgz",
+ "integrity": "sha512-lRjkpyDGjVlBA7cDQhQ+gNcvB1BGaTHYuSOcY3S7OhDmBtnzX95FhtZZDecSTDm6aajFymyve6S5DN4ZHGezdQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "replace-ext": "1.0.0",
+ "unist-util-stringify-position": "^2.0.0",
+ "vfile-message": "^2.0.0"
+ }
+ },
+ "vfile-location": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz",
+ "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==",
+ "dev": true
+ },
+ "vfile-message": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
+ "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ }
+ }
+ }
+ },
+ "remark-breaks": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-1.0.5.tgz",
+ "integrity": "sha512-lr8+TlJI273NjEqL27eUthPYPTCgXEj4NaLbnazS3bQaQL2FySlsbtgo52gE36fE1gWeQgkn1VdmWsoT+uA7FA=="
+ },
+ "remark-parse": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz",
+ "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==",
+ "requires": {
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^1.1.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^1.0.0",
+ "vfile-location": "^2.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "remark-stringify": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.0.tgz",
+ "integrity": "sha512-FSPZv1ds76oAZjurhhuV5qXSUSoz6QRPuwYK38S41sLHwg4oB7ejnmZshj7qwjgYLf93kdz6BOX9j5aidNE7rA==",
+ "dev": true,
+ "requires": {
+ "ccount": "^1.0.0",
+ "is-alphanumeric": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "longest-streak": "^2.0.1",
+ "markdown-escapes": "^1.0.0",
+ "markdown-table": "^2.0.0",
+ "mdast-util-compact": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "stringify-entities": "^3.0.0",
+ "unherit": "^1.0.4",
+ "xtend": "^4.0.1"
+ },
+ "dependencies": {
+ "parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "requires": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ }
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "replace-ext": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
+ "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs="
+ },
+ "request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ }
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
+ },
+ "resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-dir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+ "requires": {
+ "expand-tilde": "^2.0.0",
+ "global-modules": "^1.0.0"
+ },
+ "dependencies": {
+ "global-modules": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+ "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+ "requires": {
+ "global-prefix": "^1.0.1",
+ "is-windows": "^1.0.1",
+ "resolve-dir": "^1.0.0"
+ }
+ }
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+ },
+ "responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "dev": true,
+ "requires": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
+ },
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "roarr": {
+ "version": "2.15.3",
+ "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.3.tgz",
+ "integrity": "sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==",
+ "dev": true,
+ "requires": {
+ "boolean": "^3.0.0",
+ "detect-node": "^2.0.4",
+ "globalthis": "^1.0.1",
+ "json-stringify-safe": "^5.0.1",
+ "semver-compare": "^1.0.0",
+ "sprintf-js": "^1.1.2"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "dev": true
+ }
+ }
+ },
+ "root-check": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/root-check/-/root-check-1.0.0.tgz",
+ "integrity": "sha1-xSp5S/Dbn61WdTbkGJjwyeCoZpc=",
+ "dev": true,
+ "requires": {
+ "downgrade-root": "^1.0.0",
+ "sudo-block": "^1.1.0"
+ }
+ },
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true
+ },
+ "run-parallel": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
+ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
+ "dev": true
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rx": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+ "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.5.5",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
+ "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sass": {
+ "version": "1.26.8",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.8.tgz",
+ "integrity": "sha512-yvtzyrKLGiXQu7H12ekXqsfoGT/aTKeMDyVzCB675k1HYuaj0py63i8Uf4SI9CHXj6apDhpfwbUr3gGOjdpu2Q==",
+ "requires": {
+ "chokidar": ">=2.0.0 <4.0.0"
+ }
+ },
+ "sass-loader": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz",
+ "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==",
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "loader-utils": "^1.2.3",
+ "neo-async": "^2.6.1",
+ "schema-utils": "^2.6.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "scheduler": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
+ "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ },
+ "schema-utils": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
+ "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
+ "requires": {
+ "@types/json-schema": "^7.0.4",
+ "ajv": "^6.12.2",
+ "ajv-keywords": "^3.4.1"
+ }
+ },
+ "scoped-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz",
+ "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=",
+ "dev": true
+ },
+ "scrollbar-width": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/scrollbar-width/-/scrollbar-width-3.1.1.tgz",
+ "integrity": "sha1-xi5j76WTTaw3tD2jT3VQysqERKI="
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
+ },
+ "selfsigned": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
+ "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "requires": {
+ "node-forge": "0.9.0"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "semver-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
+ "dev": true
+ },
+ "semver-diff": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.3"
+ }
+ },
+ "semver-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
+ "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=",
+ "dev": true
+ },
+ "semver-truncate": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz",
+ "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "sentence-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-2.1.1.tgz",
+ "integrity": "sha1-H24t2jnBaL+S0T+G1KkYkz9mftQ=",
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case-first": "^1.1.2"
+ }
+ },
+ "serialize-error": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
+ "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.13.1"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
+ "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-getter": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
+ "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=",
+ "dev": true,
+ "requires": {
+ "to-object-path": "^0.3.0"
+ }
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "shelljs": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
+ "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ }
+ },
+ "side-channel": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
+ "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==",
+ "requires": {
+ "es-abstract": "^1.17.0-next.1",
+ "object-inspect": "^1.7.0"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
+ },
+ "simple-html-tokenizer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz",
+ "integrity": "sha1-BcLuxXn//+FFoDCsJs/qYbmA+r4="
+ },
+ "simple-is": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz",
+ "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA="
+ },
+ "simply-uuid": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simply-uuid/-/simply-uuid-1.0.1.tgz",
+ "integrity": "sha1-U5JB2BUolpzvI4kvr0WIAF+pmrg="
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+ "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "astral-regex": "^1.0.0",
+ "is-fullwidth-code-point": "^2.0.0"
+ }
+ },
+ "snake-case": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz",
+ "integrity": "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=",
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "sniffr": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/sniffr/-/sniffr-1.2.0.tgz",
+ "integrity": "sha512-k7C0ZcHBU330LcSkKyc2cOOB0uHosME8b2t9qFJqdqB1cKwGmZWd7BVwBz5mWOMJ5dggK1dy2qv+DSwteKLBzQ=="
+ },
+ "sockjs": {
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz",
+ "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==",
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.4.0",
+ "websocket-driver": "0.6.5"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz",
+ "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==",
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ }
+ }
+ },
+ "sort-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^1.0.0"
+ }
+ },
+ "sort-on": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/sort-on/-/sort-on-3.0.0.tgz",
+ "integrity": "sha512-e2RHeY1iM6dT9od3RoqeJSyz3O7naNFsGy34+EFEcwghjAncuOXC2/Xwq87S4FbypqLVp6PcizYEsGEGsGIDXA==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.0",
+ "dot-prop": "^4.1.1"
+ },
+ "dependencies": {
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
+ },
+ "sourcemapped-stacktrace": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/sourcemapped-stacktrace/-/sourcemapped-stacktrace-1.1.11.tgz",
+ "integrity": "sha512-O0pcWjJqzQFVsisPlPXuNawJHHg9N9UgpJ/aDmvi9+vnS3x1C0NhwkVFzzZ1VN0Xo+bekyweoqYvBw5ZBKiNnQ==",
+ "requires": {
+ "source-map": "0.5.6"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI="
+ }
+ }
+ },
+ "spawn-sync": {
+ "version": "1.0.15",
+ "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
+ "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.4.7",
+ "os-shim": "^0.1.2"
+ }
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ }
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "specificity": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
+ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "stackframe": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz",
+ "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ="
+ },
+ "state-toggle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
+ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ=="
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
+ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
+ "dev": true
+ },
+ "string-length": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
+ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=",
+ "dev": true,
+ "requires": {
+ "astral-regex": "^1.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string-template": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz",
+ "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+ "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+ "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimstart": "^1.0.0"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+ "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimend": "^1.0.0"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+ "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "stringify-entities": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.1.tgz",
+ "integrity": "sha512-Lsk3ISA2++eJYqBMPKcr/8eby1I6L0gP0NlxF8Zja6c05yr/yCYyb2c9PwXjd08Ib3If1vn1rbs1H5ZtVuOfvQ==",
+ "dev": true,
+ "requires": {
+ "character-entities-html4": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.2",
+ "is-hexadecimal": "^1.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-bom-buf": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz",
+ "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.1"
+ }
+ },
+ "strip-bom-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz",
+ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "requires": {
+ "min-indent": "^1.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz",
+ "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==",
+ "dev": true
+ },
+ "style-loader": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.2.tgz",
+ "integrity": "sha512-xehHGWeCPrr+R/bU82To0j7L7ENzH30RHYmMhmAumbuIpQ/bHmv3SAj1aTRfBSszkXoqNtpKnJyWXEDydS+KeA==",
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^2.0.1"
+ }
+ },
+ "style-search": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
+ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
+ "dev": true
+ },
+ "stylelint": {
+ "version": "13.6.0",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.6.0.tgz",
+ "integrity": "sha512-55gG2pNjVr183JJM/tlr3KAua6vTVX7Ho/lgKKuCIWszTZ1gmrXjX4Wok53SI8wRYFPbwKAcJGULQ77OJxTcNw==",
+ "dev": true,
+ "requires": {
+ "@stylelint/postcss-css-in-js": "^0.37.1",
+ "@stylelint/postcss-markdown": "^0.36.1",
+ "autoprefixer": "^9.8.0",
+ "balanced-match": "^1.0.0",
+ "chalk": "^4.0.0",
+ "cosmiconfig": "^6.0.0",
+ "debug": "^4.1.1",
+ "execall": "^2.0.0",
+ "file-entry-cache": "^5.0.1",
+ "get-stdin": "^8.0.0",
+ "global-modules": "^2.0.0",
+ "globby": "^11.0.1",
+ "globjoin": "^0.1.4",
+ "html-tags": "^3.1.0",
+ "ignore": "^5.1.8",
+ "import-lazy": "^4.0.0",
+ "imurmurhash": "^0.1.4",
+ "known-css-properties": "^0.19.0",
+ "leven": "^3.1.0",
+ "lodash": "^4.17.15",
+ "log-symbols": "^4.0.0",
+ "mathml-tag-names": "^2.1.3",
+ "meow": "^7.0.1",
+ "micromatch": "^4.0.2",
+ "normalize-selector": "^0.2.0",
+ "postcss": "^7.0.32",
+ "postcss-html": "^0.36.0",
+ "postcss-less": "^3.1.4",
+ "postcss-media-query-parser": "^0.2.3",
+ "postcss-reporter": "^6.0.1",
+ "postcss-resolve-nested-selector": "^0.1.1",
+ "postcss-safe-parser": "^4.0.2",
+ "postcss-sass": "^0.4.4",
+ "postcss-scss": "^2.1.1",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-syntax": "^0.36.2",
+ "postcss-value-parser": "^4.1.0",
+ "resolve-from": "^5.0.0",
+ "slash": "^3.0.0",
+ "specificity": "^0.4.1",
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "style-search": "^0.1.0",
+ "sugarss": "^2.0.0",
+ "svg-tags": "^1.0.0",
+ "table": "^5.4.6",
+ "v8-compile-cache": "^2.1.1",
+ "write-file-atomic": "^3.0.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "cosmiconfig": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+ "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "dev": true,
+ "requires": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.7.2"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "globby": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
+ "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+ "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ }
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+ "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "v8-compile-cache": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
+ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+ "dev": true
+ }
+ }
+ },
+ "stylelint-config-css-modules": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-css-modules/-/stylelint-config-css-modules-2.2.0.tgz",
+ "integrity": "sha512-+zjcDbot+zbuxy1UA31k4G2lUG+nHUwnLyii3uT2F09B8kT2YrT9LZYNfMtAWlDidrxr7sFd5HX9EqPHGU3WKA==",
+ "dev": true
+ },
+ "stylelint-config-recommended": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz",
+ "integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==",
+ "dev": true
+ },
+ "stylelint-config-standard": {
+ "version": "19.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-19.0.0.tgz",
+ "integrity": "sha512-VvcODsL1PryzpYteWZo2YaA5vU/pWfjqBpOvmeA8iB2MteZ/ZhI1O4hnrWMidsS4vmEJpKtjdhLdfGJmmZm6Cg==",
+ "dev": true,
+ "requires": {
+ "stylelint-config-recommended": "^3.0.0"
+ }
+ },
+ "stylelint-order": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-3.1.1.tgz",
+ "integrity": "sha512-4gP/r8j/6JGZ/LL41b2sYtQqfwZl4VSqTp7WeIwI67v/OXNQ08dnn64BGXNwAUSgb2+YIvIOxQaMzqMyQMzoyQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.15",
+ "postcss": "^7.0.17",
+ "postcss-sorting": "^5.0.1"
+ }
+ },
+ "sudo-block": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/sudo-block/-/sudo-block-1.2.0.tgz",
+ "integrity": "sha1-zFOb+BkWJNT1B9g+60W0zqJ/NGM=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.0.0",
+ "is-docker": "^1.0.0",
+ "is-root": "^1.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "sugarss": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz",
+ "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svg-inline-loader": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz",
+ "integrity": "sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==",
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "object-assign": "^4.0.1",
+ "simple-html-tokenizer": "^0.1.1"
+ }
+ },
+ "svg-tags": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+ "dev": true
+ },
+ "swap-case": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-1.1.2.tgz",
+ "integrity": "sha1-w5IDpFhzhfrTyFCgvRvK+ggZdOM=",
+ "requires": {
+ "lower-case": "^1.1.1",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+ },
+ "tabbable": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz",
+ "integrity": "sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ=="
+ },
+ "table": {
+ "version": "5.4.6",
+ "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+ "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.10.2",
+ "lodash": "^4.17.14",
+ "slice-ansi": "^2.1.0",
+ "string-width": "^3.0.0"
+ }
+ },
+ "tabtab": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-1.3.2.tgz",
+ "integrity": "sha1-u5wspjJPZZ/edjTCyvPAluEYfKc=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.2.0",
+ "inquirer": "^1.0.2",
+ "minimist": "^1.2.0",
+ "mkdirp": "^0.5.1",
+ "npmlog": "^2.0.3",
+ "object-assign": "^4.1.0"
+ },
+ "dependencies": {
+ "ansi-escapes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+ "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "cli-cursor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
+ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^1.0.1"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "external-editor": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz",
+ "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=",
+ "dev": true,
+ "requires": {
+ "extend": "^3.0.0",
+ "spawn-sync": "^1.0.15",
+ "tmp": "^0.0.29"
+ }
+ },
+ "figures": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
+ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5",
+ "object-assign": "^4.1.0"
+ }
+ },
+ "inquirer": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz",
+ "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^1.1.0",
+ "chalk": "^1.0.0",
+ "cli-cursor": "^1.0.1",
+ "cli-width": "^2.0.0",
+ "external-editor": "^1.1.0",
+ "figures": "^1.3.5",
+ "lodash": "^4.3.0",
+ "mute-stream": "0.0.6",
+ "pinkie-promise": "^2.0.0",
+ "run-async": "^2.2.0",
+ "rx": "^4.1.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.0",
+ "through": "^2.3.6"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz",
+ "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=",
+ "dev": true
+ },
+ "onetime": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+ "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
+ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
+ "dev": true,
+ "requires": {
+ "exit-hook": "^1.0.0",
+ "onetime": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
+ "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.1"
+ }
+ }
+ }
+ },
+ "taketalk": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/taketalk/-/taketalk-1.0.0.tgz",
+ "integrity": "sha1-tNTw3u0gauffd1sSnqLKbeUvJt0=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "minimist": "^1.1.0"
+ },
+ "dependencies": {
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ }
+ }
+ },
+ "tapable": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz",
+ "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A=="
+ },
+ "term-size": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+ "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "terser": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz",
+ "integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==",
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.12"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
+ "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
+ "requires": {
+ "cacache": "^12.0.2",
+ "find-cache-dir": "^2.1.0",
+ "is-wsl": "^1.1.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^3.1.0",
+ "source-map": "^0.6.1",
+ "terser": "^4.1.2",
+ "webpack-sources": "^1.4.0",
+ "worker-farm": "^1.7.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "textextensions": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz",
+ "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+ "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "title-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
+ "integrity": "sha1-PhJyFtpY0rxb7PE3q5Ha46fNj6o=",
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.0.3"
+ }
+ },
+ "titleize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz",
+ "integrity": "sha512-rUwGDruKq1gX+FFHbTl5qjI7teVO7eOe+C8IcQ7QT+1BK3eEUXJqbZcBOeaRP4FwSC/C1A5jDoIVta0nIQ9yew==",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "tough-cookie": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz",
+ "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==",
+ "dev": true,
+ "requires": {
+ "ip-regex": "^2.1.0",
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ },
+ "traverse": {
+ "version": "0.6.6",
+ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
+ "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
+ },
+ "trim": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
+ },
+ "trim-newlines": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
+ "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
+ "dev": true
+ },
+ "trim-trailing-lines": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz",
+ "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA=="
+ },
+ "trough": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
+ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA=="
+ },
+ "ts-loader": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.5.tgz",
+ "integrity": "sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==",
+ "requires": {
+ "chalk": "^2.3.0",
+ "enhanced-resolve": "^4.0.0",
+ "loader-utils": "^1.0.2",
+ "micromatch": "^4.0.0",
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "enhanced-resolve": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
+ "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.5.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
+ "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q=="
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "tunnel": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "twig": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/twig/-/twig-1.15.1.tgz",
+ "integrity": "sha512-SPGkUM0p7hjgo+y5Dlm/XCSuZe0G3kfcgRPrxkMFln5e8bvQbxDOsia8QEo8xqXfjLR1Emp9FGkVYHya2b8qdA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.8.4",
+ "locutus": "^2.0.11",
+ "minimatch": "3.0.x",
+ "walk": "2.3.x"
+ }
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "3.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
+ "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ=="
+ },
+ "ua-parser-js": {
+ "version": "0.7.21",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
+ "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
+ },
+ "uglify-js": {
+ "version": "3.4.10",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
+ "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
+ "requires": {
+ "commander": "~2.19.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+ "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "unherit": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
+ "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
+ "requires": {
+ "inherits": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ=="
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^1.0.4",
+ "unicode-property-aliases-ecmascript": "^1.0.4"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
+ "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ=="
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
+ "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg=="
+ },
+ "unified": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz",
+ "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==",
+ "requires": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^1.1.0",
+ "trough": "^1.0.0",
+ "vfile": "^2.0.0",
+ "x-is-string": "^0.1.0"
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "uniq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
+ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8="
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "unique-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+ "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^1.0.0"
+ }
+ },
+ "unist-util-find-all-after": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.1.tgz",
+ "integrity": "sha512-0GICgc++sRJesLwEYDjFVJPJttBpVQaTNgc6Jw0Jhzvfs+jtKePEMu+uD+PqkRUrAvGQqwhpDwLGWo1PK8PDEw==",
+ "dev": true,
+ "requires": {
+ "unist-util-is": "^4.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.2.tgz",
+ "integrity": "sha512-Ofx8uf6haexJwI1gxWMGg6I/dLnF2yE+KibhD3/diOqY2TinLcqHXCV6OI5gFVn3xQqDH+u0M625pfKwIwgBKQ==",
+ "dev": true
+ }
+ }
+ },
+ "unist-util-is": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz",
+ "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A=="
+ },
+ "unist-util-remove-position": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz",
+ "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==",
+ "requires": {
+ "unist-util-visit": "^1.1.0"
+ }
+ },
+ "unist-util-stringify-position": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
+ "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ=="
+ },
+ "unist-util-visit": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
+ "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
+ "requires": {
+ "unist-util-visit-parents": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit-parents": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
+ "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
+ "requires": {
+ "unist-util-is": "^3.0.0"
+ }
+ }
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz",
+ "integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q=="
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ }
+ }
+ },
+ "untildify": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz",
+ "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==",
+ "dev": true
+ },
+ "unzip-response": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+ "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
+ "dev": true
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
+ },
+ "update-notifier": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+ "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
+ "dev": true,
+ "requires": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "dependencies": {
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "dev": true
+ }
+ }
+ },
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
+ },
+ "upper-case-first": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-1.1.2.tgz",
+ "integrity": "sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=",
+ "requires": {
+ "upper-case": "^1.1.1"
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "url-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-3.0.0.tgz",
+ "integrity": "sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A==",
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "mime": "^2.4.4",
+ "schema-utils": "^2.5.0"
+ }
+ },
+ "url-parse": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+ "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0"
+ }
+ },
+ "url-search-params": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/url-search-params/-/url-search-params-1.1.0.tgz",
+ "integrity": "sha512-XiO5GLAxmlZgdLob/RmKZRc2INHrssMbpwD6O46JkB1aEJO4fkV3x3mR6+CDX01ijfEUwvfwCiUQZrKqfm1ILw=="
+ },
+ "url-to-options": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
+ "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=",
+ "dev": true
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
+ },
+ "user-home": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
+ "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=",
+ "dev": true,
+ "requires": {
+ "os-homedir": "^1.0.0"
+ }
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+ "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "v8-compile-cache": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
+ "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vfile": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz",
+ "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==",
+ "requires": {
+ "is-buffer": "^1.1.4",
+ "replace-ext": "1.0.0",
+ "unist-util-stringify-position": "^1.0.0",
+ "vfile-message": "^1.0.0"
+ }
+ },
+ "vfile-location": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz",
+ "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA=="
+ },
+ "vfile-message": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz",
+ "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==",
+ "requires": {
+ "unist-util-stringify-position": "^1.1.1"
+ }
+ },
+ "vinyl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
+ "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "clone-buffer": "^1.0.0",
+ "clone-stats": "^1.0.0",
+ "cloneable-readable": "^1.0.0",
+ "remove-trailing-separator": "^1.0.1",
+ "replace-ext": "^1.0.0"
+ }
+ },
+ "vinyl-file": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz",
+ "integrity": "sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.3.0",
+ "strip-bom-buf": "^1.0.0",
+ "strip-bom-stream": "^2.0.0",
+ "vinyl": "^2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
+ },
+ "walk": {
+ "version": "2.3.14",
+ "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz",
+ "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==",
+ "dev": true,
+ "requires": {
+ "foreachasync": "^3.0.0"
+ }
+ },
+ "watchpack": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
+ "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==",
+ "requires": {
+ "chokidar": "^3.4.0",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0",
+ "watchpack-chokidar2": "^2.0.0"
+ }
+ },
+ "watchpack-chokidar2": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
+ "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
+ "optional": true,
+ "requires": {
+ "chokidar": "^2.1.8"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "optional": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "optional": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "optional": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "optional": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "optional": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "optional": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "optional": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "optional": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "optional": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webpack": {
+ "version": "4.43.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
+ "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
+ "requires": {
+ "@webassemblyjs/ast": "1.9.0",
+ "@webassemblyjs/helper-module-context": "1.9.0",
+ "@webassemblyjs/wasm-edit": "1.9.0",
+ "@webassemblyjs/wasm-parser": "1.9.0",
+ "acorn": "^6.4.1",
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.3",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.4.0",
+ "loader-utils": "^1.2.3",
+ "memory-fs": "^0.4.1",
+ "micromatch": "^3.1.10",
+ "mkdirp": "^0.5.3",
+ "neo-async": "^2.6.1",
+ "node-libs-browser": "^2.2.1",
+ "schema-utils": "^1.0.0",
+ "tapable": "^1.1.3",
+ "terser-webpack-plugin": "^1.4.3",
+ "watchpack": "^1.6.1",
+ "webpack-sources": "^1.4.1"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz",
+ "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.5.0",
+ "tapable": "^1.0.0"
+ },
+ "dependencies": {
+ "memory-fs": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
+ "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "webpack-cli": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.11.tgz",
+ "integrity": "sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==",
+ "requires": {
+ "chalk": "2.4.2",
+ "cross-spawn": "6.0.5",
+ "enhanced-resolve": "4.1.0",
+ "findup-sync": "3.0.0",
+ "global-modules": "2.0.0",
+ "import-local": "2.0.0",
+ "interpret": "1.2.0",
+ "loader-utils": "1.2.3",
+ "supports-color": "6.1.0",
+ "v8-compile-cache": "2.0.3",
+ "yargs": "13.2.4"
+ },
+ "dependencies": {
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
+ "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==",
+ "requires": {
+ "memory-fs": "^0.4.1",
+ "mime": "^2.4.4",
+ "mkdirp": "^0.5.1",
+ "range-parser": "^1.2.1",
+ "webpack-log": "^2.0.0"
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz",
+ "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==",
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.1.8",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^1.6.0",
+ "debug": "^4.1.1",
+ "del": "^4.1.1",
+ "express": "^4.17.1",
+ "html-entities": "^1.3.1",
+ "http-proxy-middleware": "0.19.1",
+ "import-local": "^2.0.0",
+ "internal-ip": "^4.3.0",
+ "ip": "^1.1.5",
+ "is-absolute-url": "^3.0.3",
+ "killable": "^1.0.1",
+ "loglevel": "^1.6.8",
+ "opn": "^5.5.0",
+ "p-retry": "^3.0.1",
+ "portfinder": "^1.0.26",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.10.7",
+ "semver": "^6.3.0",
+ "serve-index": "^1.9.1",
+ "sockjs": "0.3.20",
+ "sockjs-client": "1.4.0",
+ "spdy": "^4.0.2",
+ "strip-ansi": "^3.0.1",
+ "supports-color": "^6.1.0",
+ "url": "^0.11.0",
+ "webpack-dev-middleware": "^3.7.2",
+ "webpack-log": "^2.0.0",
+ "ws": "^6.2.1",
+ "yargs": "^13.3.2"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "websocket-driver": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
+ "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=",
+ "requires": {
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
+ },
+ "whatwg-fetch": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz",
+ "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==",
+ "requires": {
+ "is-bigint": "^1.0.0",
+ "is-boolean-object": "^1.0.0",
+ "is-number-object": "^1.0.3",
+ "is-string": "^1.0.4",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "requires": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "which-typed-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz",
+ "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==",
+ "requires": {
+ "available-typed-arrays": "^1.0.2",
+ "es-abstract": "^1.17.5",
+ "foreach": "^2.0.5",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.1",
+ "is-typed-array": "^1.1.3"
+ }
+ },
+ "widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "windows-release": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.1.tgz",
+ "integrity": "sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0"
+ }
+ },
+ "with-open-file": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz",
+ "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0",
+ "p-try": "^2.1.0",
+ "pify": "^4.0.1"
+ },
+ "dependencies": {
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ }
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+ "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "x-is-string": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz",
+ "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI="
+ },
+ "xdg-basedir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ },
+ "yaml": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
+ "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz",
+ "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==",
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yeoman-character": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/yeoman-character/-/yeoman-character-1.1.0.tgz",
+ "integrity": "sha1-kNS1vq+SdZCGF3AVsv36LgaE18c=",
+ "dev": true,
+ "requires": {
+ "supports-color": "^3.1.2"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true,
+ "requires": {
+ "has-flag": "^1.0.0"
+ }
+ }
+ }
+ },
+ "yeoman-doctor": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yeoman-doctor/-/yeoman-doctor-4.0.0.tgz",
+ "integrity": "sha512-CP0fwGk5Y+jel+A0AQbyqnIFZRRpkKOeYUibiTSmlgV9PcgNFFVwn86VcUIpDLOqVjF+9v+O9FWQMo+IUcV2mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "bin-version-check": "^3.0.0",
+ "chalk": "^2.3.0",
+ "global-agent": "^2.0.0",
+ "global-tunnel-ng": "^2.5.3",
+ "latest-version": "^3.1.0",
+ "log-symbols": "^2.1.0",
+ "semver": "^5.0.3",
+ "twig": "^1.10.5",
+ "user-home": "^2.0.0"
+ },
+ "dependencies": {
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ }
+ }
+ },
+ "yeoman-environment": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.10.3.tgz",
+ "integrity": "sha512-pLIhhU9z/G+kjOXmJ2bPFm3nejfbH+f1fjYRSOteEXDBrv1EoJE/e+kuHixSXfCYfTkxjYsvRaDX+1QykLCnpQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "debug": "^3.1.0",
+ "diff": "^3.5.0",
+ "escape-string-regexp": "^1.0.2",
+ "execa": "^4.0.0",
+ "globby": "^8.0.1",
+ "grouped-queue": "^1.1.0",
+ "inquirer": "^7.1.0",
+ "is-scoped": "^1.0.0",
+ "lodash": "^4.17.10",
+ "log-symbols": "^2.2.0",
+ "mem-fs": "^1.1.0",
+ "mem-fs-editor": "^6.0.0",
+ "npm-api": "^1.0.0",
+ "semver": "^7.1.3",
+ "strip-ansi": "^4.0.0",
+ "text-table": "^0.2.0",
+ "untildify": "^3.0.3",
+ "yeoman-generator": "^4.8.2"
+ },
+ "dependencies": {
+ "@nodelib/fs.stat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "dir-glob": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz",
+ "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "path-type": "^3.0.0"
+ }
+ },
+ "execa": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz",
+ "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "fast-glob": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
+ "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==",
+ "dev": true,
+ "requires": {
+ "@mrmlnc/readdir-enhanced": "^2.2.1",
+ "@nodelib/fs.stat": "^1.1.2",
+ "glob-parent": "^3.1.0",
+ "is-glob": "^4.0.0",
+ "merge2": "^1.2.3",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "get-stream": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+ "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "globby": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz",
+ "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "2.0.0",
+ "fast-glob": "^2.0.2",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "yeoman-generator": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-4.10.1.tgz",
+ "integrity": "sha512-QgbtHSaqBAkyJJM0heQUhT63ubCt34NBFMEBydOBUdAuy8RBvGSzeqVBSZOjdh1tSLrwWXlU3Ck6y14awinF6Q==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "chalk": "^2.4.2",
+ "cli-table": "^0.3.1",
+ "cross-spawn": "^6.0.5",
+ "dargs": "^6.1.0",
+ "dateformat": "^3.0.3",
+ "debug": "^4.1.1",
+ "diff": "^4.0.1",
+ "error": "^7.0.2",
+ "find-up": "^3.0.0",
+ "github-username": "^3.0.0",
+ "grouped-queue": "^1.1.0",
+ "istextorbinary": "^2.5.1",
+ "lodash": "^4.17.11",
+ "make-dir": "^3.0.0",
+ "mem-fs-editor": "^6.0.0",
+ "minimist": "^1.2.5",
+ "pretty-bytes": "^5.2.0",
+ "read-chunk": "^3.2.0",
+ "read-pkg-up": "^5.0.0",
+ "rimraf": "^2.6.3",
+ "run-async": "^2.0.0",
+ "semver": "^7.2.1",
+ "shelljs": "^0.8.3",
+ "text-table": "^0.2.0",
+ "through2": "^3.0.1",
+ "yeoman-environment": "^2.9.5"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "read-pkg-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-5.0.0.tgz",
+ "integrity": "sha512-XBQjqOBtTzyol2CpsQOw8LHV0XbDZVG7xMMjmXAJomlVY03WOBRmYgDJETlvcg0H63AJvPRwT7GFi5rvOzUOKg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0",
+ "read-pkg": "^5.0.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "dev": true
+ },
+ "through2": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz",
+ "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2 || 3"
+ }
+ }
+ }
+ },
+ "yo": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yo/-/yo-3.1.1.tgz",
+ "integrity": "sha512-GFg4QC1xi3gkbHGGUFme8/8XPg3kDISu/qJfx56X207yuv1FSevGY/eKuym7kh0bniCB4n3rseWW+QZXPH8LIw==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.1",
+ "chalk": "^2.4.1",
+ "cli-list": "^0.2.0",
+ "configstore": "^3.1.2",
+ "cross-spawn": "^6.0.5",
+ "figures": "^2.0.0",
+ "fullname": "^4.0.1",
+ "global-agent": "^2.0.0",
+ "global-tunnel-ng": "^2.7.1",
+ "got": "^8.3.2",
+ "humanize-string": "^1.0.2",
+ "inquirer": "^6.0.0",
+ "insight": "^0.10.3",
+ "lodash": "^4.17.15",
+ "meow": "^3.0.0",
+ "npm-keyword": "^5.0.0",
+ "open": "^6.3.0",
+ "package-json": "^5.0.0",
+ "parse-help": "^1.0.0",
+ "read-pkg-up": "^4.0.0",
+ "root-check": "^1.0.0",
+ "sort-on": "^3.0.0",
+ "string-length": "^2.0.0",
+ "tabtab": "^1.3.2",
+ "titleize": "^1.0.1",
+ "update-notifier": "^2.5.0",
+ "user-home": "^2.0.0",
+ "yeoman-character": "^1.0.0",
+ "yeoman-doctor": "^4.0.0",
+ "yeoman-environment": "^2.4.0",
+ "yosay": "^2.0.2"
+ },
+ "dependencies": {
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ }
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inquirer": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+ "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.2.0",
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^2.0.0",
+ "lodash": "^4.17.12",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.4.0",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^5.1.0",
+ "through": "^2.3.6"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ },
+ "dependencies": {
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ }
+ }
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+ "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0",
+ "read-pkg": "^3.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ }
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ }
+ }
+ },
+ "yosay": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/yosay/-/yosay-2.0.2.tgz",
+ "integrity": "sha512-avX6nz2esp7IMXGag4gu6OyQBsMh/SEn+ZybGu3yKPlOTE6z9qJrzG/0X5vCq/e0rPFy0CUYCze0G5hL310ibA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0",
+ "ansi-styles": "^3.0.0",
+ "chalk": "^1.0.0",
+ "cli-boxes": "^1.0.0",
+ "pad-component": "0.0.1",
+ "string-width": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "taketalk": "^1.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ }
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/frontend/package.json b/plugins/base/frontend/package.json
new file mode 100644
index 00000000..120d7f34
--- /dev/null
+++ b/plugins/base/frontend/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "search",
+ "version": "1.0.0",
+ "private": true,
+ "config": {
+ "components": "./src/main/components",
+ "dist": "./dist"
+ },
+ "scripts": {
+ "build": "webpack --mode=production --devtool sourcemap",
+ "lint": "eslint . && npm run stylelint",
+ "stylelint": "stylelint --ignore-path .gitignore ./src/main/**/*.scss",
+ "start": "webpack-dev-server -d --history-api-fallback --inline --hot --colors --port 9010"
+ },
+ "babel": {
+ "presets": [
+ [
+ "@jetbrains/jetbrains",
+ {
+ "useBuiltIns": "usage"
+ }
+ ]
+ ]
+ },
+ "dependencies": {
+ "@babel/core": "^7.8.3",
+ "@jetbrains/babel-preset-jetbrains": "^2.1.4",
+ "@jetbrains/logos": "1.1.5",
+ "@jetbrains/ring-ui": "2.1.16",
+ "@types/node": "^12.12.36",
+ "@types/react": "^16.9.0",
+ "@types/react-dom": "^16.9.0",
+ "babel-loader": "^8.0.6",
+ "postcss-import": "^12.0.1",
+ "postcss-preset-env": "^6.7.0",
+ "react": "^16.12.0",
+ "react-dom": "^16.12.0",
+ "redbox-react": "^1.6.0",
+ "ts-loader": "^7.0.0",
+ "typescript": "^3.8.3",
+ "webpack": "^4.41.5",
+ "webpack-cli": "^3.3.10",
+ "webpack-dev-server": "^3.10.1"
+ },
+ "devDependencies": {
+ "@jetbrains/stylelint-config": "^2.0.0",
+ "babel-eslint": "^10.0.3",
+ "eslint": "^6.8.0",
+ "sass": "^1.26.3",
+ "sass-loader": "^8.0.2",
+ "stylelint": "^13.3.2",
+ "yo": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+}
diff --git a/plugins/base/frontend/postcss.config.js b/plugins/base/frontend/postcss.config.js
new file mode 100644
index 00000000..66c94ee0
--- /dev/null
+++ b/plugins/base/frontend/postcss.config.js
@@ -0,0 +1,16 @@
+module.exports = () => ({
+ plugins: [
+ require('postcss-import'),
+ require('postcss-preset-env')({
+ features: {
+ stage: 3, // See https://cssdb.org/#staging-process
+ features: {
+ 'nesting-rules': true,
+ 'custom-properties': {
+ preserve: true
+ }
+ }
+ }
+ })
+ ]
+});
diff --git a/plugins/base/frontend/src/main/components/app/index.scss b/plugins/base/frontend/src/main/components/app/index.scss
new file mode 100644
index 00000000..da5042b1
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/app/index.scss
@@ -0,0 +1,27 @@
+@import "src/main/scss/index.scss";
+
+html,
+.app-root {
+ height: 100%;
+}
+
+.search-root {
+ margin: 0;
+ padding: 0;
+
+ background: var(--ring-content-background-color);
+
+ font-family: var(--ring-font-family);
+ font-size: var(--ring-font-size);
+ line-height: var(--ring-line-height);
+}
+
+.search-content {
+ padding-top: 24px;
+ margin: 0 41px;
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 8;
+ background-color: #f4f4f4
+}
diff --git a/plugins/base/frontend/src/main/components/app/index.tsx b/plugins/base/frontend/src/main/components/app/index.tsx
new file mode 100644
index 00000000..4081dec4
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/app/index.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import {WithFuzzySearchFilter} from '../search/search';
+import './index.scss';
+
+const App: React.FC = () => {
+ return <div className="search-content">
+ <WithFuzzySearchFilter/>
+ </div>
+}
+
+export default App
diff --git a/plugins/base/frontend/src/main/components/root.tsx b/plugins/base/frontend/src/main/components/root.tsx
new file mode 100644
index 00000000..70ed9550
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/root.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import {render} from 'react-dom';
+import RedBox from 'redbox-react';
+
+import App from "./app";
+import './app/index.scss';
+
+const appEl = document.getElementById('searchBar');
+const rootEl = document.createElement('div');
+
+let renderApp = () => {
+ render(
+ <App/>,
+ rootEl
+ );
+};
+
+// @ts-ignore
+if (module.hot) {
+ const renderAppHot = renderApp;
+ const renderError = (error: Error) => {
+ render(
+ <RedBox error={error}/>,
+ rootEl
+ );
+ };
+
+ renderApp = () => {
+ try {
+ renderAppHot();
+ } catch (error) {
+ renderError(error);
+ }
+ };
+
+ // @ts-ignore
+ module.hot.accept('./app', () => {
+ setTimeout(renderApp);
+ });
+}
+
+renderApp();
+appEl!.appendChild(rootEl);
diff --git a/plugins/base/frontend/src/main/components/search/search.scss b/plugins/base/frontend/src/main/components/search/search.scss
new file mode 100644
index 00000000..cc5a61ac
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/search.scss
@@ -0,0 +1,37 @@
+.search {
+ button {
+ border: none;
+ fill: #637282;
+ background: #F4F4F4;
+
+ &:focus {
+ outline: none;
+ }
+ }
+}
+
+.popup-wrapper {
+ min-width: calc(100% - 360px) !important;
+}
+
+.indented {
+ text-indent: 10px;
+}
+
+.disabled {
+ color: gray;
+}
+
+.template-wrapper {
+ display: grid;
+ grid-template-columns: auto auto;
+}
+
+.template-name {
+ justify-self: start;
+}
+
+.template-description {
+ color: gray;
+ justify-self: end;
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/search.tsx b/plugins/base/frontend/src/main/components/search/search.tsx
new file mode 100644
index 00000000..c7b36654
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/search.tsx
@@ -0,0 +1,75 @@
+import React, {useCallback, useState} from 'react';
+import {Select} from '@jetbrains/ring-ui';
+import {List} from '@jetbrains/ring-ui';
+import '@jetbrains/ring-ui/components/input-size/input-size.scss';
+import './search.scss';
+import {IWindow, Option, Props, Page} from "./types";
+
+const WithFuzzySearchFilterComponent: React.FC<Props> = ({data}: Props) => {
+ const [selected, onSelected] = useState<Option>(data[0]);
+ const onChangeSelected = useCallback(
+ (option: Option) => {
+ window.location.replace(`${(window as IWindow).pathToRoot}${option.location}?query=${option.name}`)
+ onSelected(option);
+ },
+ [data]
+ );
+
+ return (
+ <div className="search-container">
+ <div className="search">
+ <Select
+ selectedLabel="Search"
+ label="Please type page name"
+ filter={{fuzzy: true}}
+ type={Select.Type.CUSTOM}
+ clear
+ selected={selected}
+ data={data}
+ popupClassName={"popup-wrapper"}
+ onSelect={onChangeSelected}
+ customAnchor={({wrapperProps, buttonProps, popup}) => (
+ <span {...wrapperProps}>
+ <button type="button" {...buttonProps}>
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+ <path d="M19.64 18.36l-6.24-6.24a7.52 7.52 0 1 0-1.28 1.28l6.24 6.24zM7.5 13.4a5.9 5.9 0 1 1 5.9-5.9 5.91 5.91 0 0 1-5.9 5.9z"/>
+ </svg>
+ </button>
+ {popup}
+ </span>
+ )}
+ />
+ </div>
+ </div>
+ )
+}
+
+const templateGenerator = (page:Page) => {
+ let classGenerator = (page:Page) => {
+ let classes = ""
+ if(page.level !== undefined) classes = classes + " indented"
+ if(page.disabled) classes = classes + " disabled"
+ return classes
+ }
+ return <div className="template-wrapper">
+ <span className= {classGenerator(page)}>{page.name}</span>
+ <span className="template-description">{page.description}</span>
+ </div>
+}
+
+export const WithFuzzySearchFilter = () => {
+ let data: Option[] = [];
+ const pages = (window as IWindow).pages;
+ if (pages) {
+ data = pages.map((page, i) => ({
+ ...page,
+ label: page.searchKey,
+ key: i + 1,
+ type: page.kind,
+ template: templateGenerator(page),
+ rgItemType: List.ListProps.Type.CUSTOM
+ }));
+ }
+
+ return <WithFuzzySearchFilterComponent data={data}/>;
+};
diff --git a/plugins/base/frontend/src/main/components/search/types.ts b/plugins/base/frontend/src/main/components/search/types.ts
new file mode 100644
index 00000000..881a16d8
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/types.ts
@@ -0,0 +1,31 @@
+export type Page = {
+ name: string;
+ kind: string;
+ location: string;
+ searchKey: string;
+ level: number;
+ index: string;
+ description: string;
+ disabled: boolean;
+}
+
+export type Option = Page & {
+ label: string;
+ key: number;
+ location: string;
+ name: string;
+}
+
+export type IWindow = typeof window & {
+ pathToRoot: string
+ pages: Page[]
+}
+
+export type Props = {
+ data: Option[]
+};
+
+
+export type State = {
+ selected: any
+}
diff --git a/plugins/base/frontend/src/main/scss/index.scss b/plugins/base/frontend/src/main/scss/index.scss
new file mode 100644
index 00000000..74af970d
--- /dev/null
+++ b/plugins/base/frontend/src/main/scss/index.scss
@@ -0,0 +1 @@
+@import "~@jetbrains/ring-ui/components/global/variables.css";
diff --git a/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts b/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts
new file mode 100644
index 00000000..1dc9983c
--- /dev/null
+++ b/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts
@@ -0,0 +1,3 @@
+declare module '@jetbrains/ring-ui' {
+ export const Select: any;
+}
diff --git a/plugins/base/frontend/stylelint.config.js b/plugins/base/frontend/stylelint.config.js
new file mode 100644
index 00000000..02b3f4ac
--- /dev/null
+++ b/plugins/base/frontend/stylelint.config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ extends: '@jetbrains/stylelint-config',
+ rules: {}
+};
diff --git a/plugins/base/frontend/tsconfig.json b/plugins/base/frontend/tsconfig.json
new file mode 100644
index 00000000..4cc8fd37
--- /dev/null
+++ b/plugins/base/frontend/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "sourceMap": true,
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "noImplicitAny": true,
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react",
+ "typeRoots": [
+ "src/main/types"
+ ]
+ },
+ "include": [
+ "./node_modules/@types/node/globals.d.ts"
+ ]
+}
diff --git a/plugins/base/frontend/webpack.config.js b/plugins/base/frontend/webpack.config.js
new file mode 100644
index 00000000..559f5792
--- /dev/null
+++ b/plugins/base/frontend/webpack.config.js
@@ -0,0 +1,64 @@
+const {join, resolve} = require('path');
+
+const ringUiWebpackConfig = require('@jetbrains/ring-ui/webpack.config');
+
+const pkgConfig = require('./package.json').config;
+
+const componentsPath = join(__dirname, pkgConfig.components);
+
+// Patch @jetbrains/ring-ui svg-sprite-loader config
+ringUiWebpackConfig.loaders.svgInlineLoader.include.push(
+ require('@jetbrains/logos'),
+ require('@jetbrains/icons')
+);
+
+const webpackConfig = () => ({
+ entry: `${componentsPath}/root.tsx`,
+ resolve: {
+ mainFields: ['module', 'browser', 'main'],
+ extensions: ['.tsx', '.ts', '.js'],
+ alias: {
+ react: resolve('./node_modules/react'),
+ 'react-dom': resolve('./node_modules/react-dom'),
+ '@jetbrains/ring-ui': resolve('./node_modules/@jetbrains/ring-ui')
+ }
+ },
+ output: {
+ path: resolve(__dirname, pkgConfig.dist),
+ filename: '[name].js',
+ publicPath: '',
+ devtoolModuleFilenameTemplate: '/[absolute-resource-path]'
+ },
+ module: {
+ rules: [
+ ...ringUiWebpackConfig.config.module.rules,
+ {
+ test: /\.s[ac]ss$/i,
+ use: [
+ 'style-loader',
+ 'css-loader',
+ 'sass-loader',
+ ],
+ include: componentsPath,
+ exclude: ringUiWebpackConfig.componentsPath,
+ },
+ {
+ test: /\.tsx?$/,
+ use: [
+ {
+ loader: 'ts-loader',
+ options: {
+ transpileOnly: true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ plugins: [],
+ output: {
+ path: __dirname + '/dist/'
+ }
+});
+
+module.exports = webpackConfig;
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
new file mode 100644
index 00000000..6586f2dc
--- /dev/null
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -0,0 +1,225 @@
+@file:Suppress("unused")
+
+package org.jetbrains.dokka.base
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.analysis.KotlinAnalysis
+import org.jetbrains.dokka.base.allModulePage.MultimodulePageCreator
+import org.jetbrains.dokka.base.renderers.*
+import org.jetbrains.dokka.base.renderers.html.*
+import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.resolvers.external.*
+import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory
+import org.jetbrains.dokka.base.transformers.documentables.*
+import org.jetbrains.dokka.base.transformers.documentables.DefaultDocumentableMerger
+import org.jetbrains.dokka.base.transformers.documentables.ModuleAndPackageDocumentationTransformer
+import org.jetbrains.dokka.base.transformers.documentables.ReportUndocumentedTransformer
+import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
+import org.jetbrains.dokka.base.transformers.pages.merger.FallbackPageMergerStrategy
+import org.jetbrains.dokka.base.transformers.pages.merger.PageMerger
+import org.jetbrains.dokka.base.transformers.pages.merger.PageMergerStrategy
+import org.jetbrains.dokka.base.transformers.pages.merger.SameMethodNamePageMergerStrategy
+import org.jetbrains.dokka.base.transformers.pages.samples.DefaultSamplesTransformer
+import org.jetbrains.dokka.base.transformers.pages.sourcelinks.SourceLinksTransformer
+import org.jetbrains.dokka.base.translators.descriptors.DefaultDescriptorToDocumentableTranslator
+import org.jetbrains.dokka.base.translators.documentables.DefaultDocumentableToPageTranslator
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.base.translators.psi.DefaultPsiToDocumentableTranslator
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+
+class DokkaBase : DokkaPlugin() {
+ val pageMergerStrategy by extensionPoint<PageMergerStrategy>()
+ val commentsToContentConverter by extensionPoint<CommentsToContentConverter>()
+ val signatureProvider by extensionPoint<SignatureProvider>()
+ val locationProviderFactory by extensionPoint<LocationProviderFactory>()
+ val externalLocationProviderFactory by extensionPoint<ExternalLocationProviderFactory>()
+ val outputWriter by extensionPoint<OutputWriter>()
+ val htmlPreprocessors by extensionPoint<PageTransformer>()
+ val kotlinAnalysis by extensionPoint<KotlinAnalysis>()
+ val tabSortingStrategy by extensionPoint<TabSortingStrategy>()
+
+
+ val descriptorToDocumentableTranslator by extending {
+ CoreExtensions.sourceToDocumentableTranslator providing { ctx ->
+ DefaultDescriptorToDocumentableTranslator(ctx.single(kotlinAnalysis))
+ }
+ }
+
+ val psiToDocumentableTranslator by extending {
+ CoreExtensions.sourceToDocumentableTranslator providing { ctx ->
+ DefaultPsiToDocumentableTranslator(ctx.single(kotlinAnalysis))
+ }
+ }
+
+ val documentableMerger by extending {
+ CoreExtensions.documentableMerger with DefaultDocumentableMerger
+ }
+
+ val deprecatedDocumentableFilter by extending {
+ CoreExtensions.preMergeDocumentableTransformer providing ::DeprecatedDocumentableFilterTransformer
+ }
+
+ val documentableVisbilityFilter by extending {
+ CoreExtensions.preMergeDocumentableTransformer providing ::DocumentableVisibilityFilterTransformer
+ }
+
+ val emptyPackagesFilter by extending {
+ CoreExtensions.preMergeDocumentableTransformer providing ::EmptyPackagesFilterTransformer order {
+ after(deprecatedDocumentableFilter, documentableVisbilityFilter)
+ }
+ }
+
+ val actualTypealiasAdder by extending {
+ CoreExtensions.documentableTransformer with ActualTypealiasAdder()
+ }
+
+ val modulesAndPackagesDocumentation by extending {
+ CoreExtensions.preMergeDocumentableTransformer providing { ctx ->
+ ModuleAndPackageDocumentationTransformer(ctx, ctx.single(kotlinAnalysis))
+ }
+ }
+
+ val kotlinSignatureProvider by extending {
+ signatureProvider providing { ctx ->
+ KotlinSignatureProvider(ctx.single(commentsToContentConverter), ctx.logger)
+ }
+ }
+
+ val sinceKotlinTransformer by extending {
+ CoreExtensions.documentableTransformer providing ::SinceKotlinTransformer
+ }
+
+ val inheritorsExtractor by extending {
+ CoreExtensions.documentableTransformer with InheritorsExtractorTransformer()
+ }
+
+
+ val undocumentedCodeReporter by extending {
+ CoreExtensions.documentableTransformer with ReportUndocumentedTransformer()
+ }
+
+ val extensionsExtractor by extending {
+ CoreExtensions.documentableTransformer with ExtensionExtractorTransformer()
+ }
+
+ val documentableToPageTranslator by extending {
+ CoreExtensions.documentableToPageTranslator providing { ctx ->
+ DefaultDocumentableToPageTranslator(
+ ctx.single(commentsToContentConverter),
+ ctx.single(signatureProvider),
+ ctx.logger
+ )
+ }
+ }
+
+ val docTagToContentConverter by extending {
+ commentsToContentConverter with DocTagToContentConverter
+ }
+
+ val pageMerger by extending {
+ CoreExtensions.pageTransformer providing { ctx -> PageMerger(ctx[pageMergerStrategy]) }
+ }
+
+ val fallbackMerger by extending {
+ pageMergerStrategy providing { ctx -> FallbackPageMergerStrategy(ctx.logger) }
+ }
+
+ val sameMethodNameMerger by extending {
+ pageMergerStrategy providing { ctx -> SameMethodNamePageMergerStrategy(ctx.logger) } order {
+ before(fallbackMerger)
+ }
+ }
+
+ val defaultTabSortingStrategy by extending {
+ tabSortingStrategy with DefaultTabSortingStrategy()
+ }
+
+ val htmlRenderer by extending {
+ CoreExtensions.renderer providing ::HtmlRenderer
+ }
+
+
+ val defaultKotlinAnalysis by extending {
+ kotlinAnalysis providing { ctx -> KotlinAnalysis(ctx) }
+ }
+
+ val locationProvider by extending {
+ locationProviderFactory providing ::DefaultLocationProviderFactory
+ }
+
+ val javadocLocationProvider by extending {
+ externalLocationProviderFactory with JavadocExternalLocationProviderFactory()
+ }
+
+ val dokkaLocationProvider by extending {
+ externalLocationProviderFactory with DokkaExternalLocationProviderFactory()
+ }
+
+ val fileWriter by extending {
+ outputWriter providing ::FileWriter
+ }
+
+ val rootCreator by extending {
+ htmlPreprocessors with RootCreator
+ }
+
+ val defaultSamplesTransformer by extending {
+ CoreExtensions.pageTransformer providing ::DefaultSamplesTransformer order {
+ before(pageMerger)
+ }
+ }
+
+ val sourceLinksTransformer by extending {
+ htmlPreprocessors providing {
+ SourceLinksTransformer(
+ it,
+ PageContentBuilder(
+ it.single(commentsToContentConverter),
+ it.single(signatureProvider),
+ it.logger
+ )
+ )
+ } order { after(rootCreator) }
+ }
+
+ val navigationPageInstaller by extending {
+ htmlPreprocessors with NavigationPageInstaller order { after(rootCreator) }
+ }
+
+ val searchPageInstaller by extending {
+ htmlPreprocessors with SearchPageInstaller order { after(rootCreator) }
+ }
+
+ val resourceInstaller by extending {
+ htmlPreprocessors with ResourceInstaller order { after(rootCreator) }
+ }
+
+ val styleAndScriptsAppender by extending {
+ htmlPreprocessors with StyleAndScriptsAppender order { after(rootCreator) }
+ }
+
+ val packageListCreator by extending {
+ htmlPreprocessors providing {
+ PackageListCreator(
+ it,
+ "html",
+ "html"
+ )
+ } order { after(rootCreator) }
+ }
+
+ val sourcesetDependencyAppender by extending {
+ htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator) }
+ }
+
+ val allModulePageCreators by extending {
+ CoreExtensions.allModulePageCreator providing {
+ MultimodulePageCreator(it)
+ }
+ }
+}
diff --git a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
new file mode 100644
index 00000000..de2242f2
--- /dev/null
+++ b/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt
@@ -0,0 +1,81 @@
+package org.jetbrains.dokka.base.allModulePage
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.DokkaException
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.resolvers.local.MultimoduleLocationProvider.Companion.MULTIMODULE_PACKAGE_PLACEHOLDER
+import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.model.doc.P
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.base.parsers.MarkdownParser
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.querySingle
+import org.jetbrains.dokka.transformers.pages.PageCreator
+import org.jetbrains.dokka.utilities.DokkaLogger
+import java.io.File
+
+class MultimodulePageCreator(
+ val context: DokkaContext
+) : PageCreator {
+ private val logger: DokkaLogger = context.logger
+
+ override fun invoke(): RootPageNode {
+ val parser = MarkdownParser(logger = logger)
+ val modules = context.configuration.modules
+ modules.forEach(::throwOnMissingModuleDocFile)
+
+ val commentsConverter = context.plugin(DokkaBase::class)?.querySingle { commentsToContentConverter }
+ val signatureProvider = context.plugin(DokkaBase::class)?.querySingle { signatureProvider }
+ if (commentsConverter == null || signatureProvider == null)
+ throw IllegalStateException("Both comments converter and signature provider must not be null")
+
+ val sourceSetData = emptySet<DokkaSourceSet>()
+ val builder = PageContentBuilder(commentsConverter, signatureProvider, context.logger)
+ val contentNode = builder.contentFor(
+ dri = DRI(MULTIMODULE_PACKAGE_PLACEHOLDER),
+ kind = ContentKind.Cover,
+ sourceSets = sourceSetData
+ ) {
+ header(2, "All modules:")
+ table(styles = setOf(MultimoduleTable)) {
+ modules.mapNotNull { module ->
+ val paragraph = module.docFile.let(::File).readText().let { parser.parse(it).firstParagraph() }
+ paragraph?.let {
+ val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name)
+ val dci = DCI(setOf(dri), ContentKind.Main)
+ val header =
+ ContentHeader(listOf(linkNode(module.name, dri)), 2, dci, emptySet(), emptySet())
+ val content = ContentGroup(
+ DocTagToContentConverter.buildContent(it, dci, emptySet()),
+ dci,
+ emptySet(),
+ emptySet()
+ )
+ ContentGroup(listOf(header, content), dci, emptySet(), emptySet())
+ }
+ }
+ }
+ }
+ return MultimoduleRootPageNode(
+ "Modules",
+ setOf(DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = "allModules")),
+ contentNode
+ )
+ }
+
+ private fun throwOnMissingModuleDocFile(module: DokkaConfiguration.DokkaModuleDescription) {
+ val docFile = File(module.docFile)
+ if (!docFile.exists() || !docFile.isFile) {
+ throw DokkaException(
+ "Missing documentation file for module ${module.name}: ${docFile.absolutePath}"
+ )
+ }
+ }
+
+ private fun DocumentationNode.firstParagraph() =
+ this.children.flatMap { it.root.children }.filterIsInstance<P>().firstOrNull()
+}
diff --git a/plugins/base/src/main/kotlin/parsers/HtmlParser.kt b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt
new file mode 100644
index 00000000..ece3cf24
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/HtmlParser.kt
@@ -0,0 +1,89 @@
+package org.jetbrains.dokka.base.parsers
+
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.base.parsers.factories.DocTagsFromStringFactory
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Node
+import org.jsoup.select.NodeFilter
+import org.jsoup.select.NodeTraversor
+
+class HtmlParser : Parser() {
+
+ inner class NodeFilterImpl : NodeFilter {
+
+ private val nodesCache: MutableMap<Int, MutableList<DocTag>> = mutableMapOf()
+ private var currentDepth = 0
+
+ fun collect(): DocTag = nodesCache[currentDepth]!![0]
+
+ override fun tail(node: Node?, depth: Int): NodeFilter.FilterResult {
+ val nodeName = node!!.nodeName()
+ val nodeAttributes = node.attributes()
+
+ if(nodeName in listOf("#document", "html", "head"))
+ return NodeFilter.FilterResult.CONTINUE
+
+ val body: String
+ val params: Map<String, String>
+
+
+ if(nodeName != "#text") {
+ body = ""
+ params = nodeAttributes.map { it.key to it.value }.toMap()
+ } else {
+ body = nodeAttributes["#text"]
+ params = emptyMap()
+ }
+
+ val docNode = if(depth < currentDepth) {
+ DocTagsFromStringFactory.getInstance(nodeName, nodesCache.getOrDefault(currentDepth, mutableListOf()).toList(), params, body).also {
+ nodesCache[currentDepth] = mutableListOf()
+ currentDepth = depth
+ }
+ } else {
+ DocTagsFromStringFactory.getInstance(nodeName, emptyList(), params, body)
+ }
+
+ nodesCache.getOrDefault(depth, mutableListOf()) += docNode
+ return NodeFilter.FilterResult.CONTINUE
+ }
+
+ override fun head(node: Node?, depth: Int): NodeFilter.FilterResult {
+
+ val nodeName = node!!.nodeName()
+
+ if(currentDepth < depth) {
+ currentDepth = depth
+ nodesCache[currentDepth] = mutableListOf()
+ }
+
+ if(nodeName in listOf("#document", "html", "head"))
+ return NodeFilter.FilterResult.CONTINUE
+
+ return NodeFilter.FilterResult.CONTINUE
+ }
+ }
+
+
+ private fun htmlToDocNode(string: String): DocTag {
+ val document = Jsoup.parse(string)
+ val nodeFilterImpl = NodeFilterImpl()
+ NodeTraversor.filter(nodeFilterImpl, document.root())
+ return nodeFilterImpl.collect()
+ }
+
+ private fun replaceLinksWithHrefs(javadoc: String): String = Regex("\\{@link .*?}").replace(javadoc) {
+ val split = it.value.dropLast(1).split(" ")
+ if(split.size !in listOf(2, 3))
+ return@replace it.value
+ if(split.size == 3)
+ return@replace "<documentationlink href=\"${split[1]}\">${split[2]}</documentationlink>"
+ else
+ return@replace "<documentationlink href=\"${split[1]}\">${split[1]}</documentationlink>"
+ }
+
+ override fun parseStringToDocNode(extractedString: String) = htmlToDocNode(extractedString)
+ override fun preparse(text: String) = replaceLinksWithHrefs(text)
+}
+
+
diff --git a/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
new file mode 100644
index 00000000..05eb71ab
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/MarkdownParser.kt
@@ -0,0 +1,420 @@
+package org.jetbrains.dokka.base.parsers
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.dokka.model.doc.*
+import org.intellij.markdown.MarkdownElementTypes
+import org.intellij.markdown.MarkdownTokenTypes
+import org.intellij.markdown.ast.ASTNode
+import org.intellij.markdown.ast.CompositeASTNode
+import org.intellij.markdown.ast.LeafASTNode
+import org.intellij.markdown.ast.impl.ListItemCompositeNode
+import org.intellij.markdown.flavours.gfm.GFMElementTypes
+import org.intellij.markdown.flavours.gfm.GFMFlavourDescriptor
+import org.intellij.markdown.flavours.gfm.GFMTokenTypes
+import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.base.parsers.factories.DocTagsFromIElementFactory
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
+import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
+import java.net.MalformedURLException
+import org.intellij.markdown.parser.MarkdownParser as IntellijMarkdownParser
+
+class MarkdownParser(
+ private val resolutionFacade: DokkaResolutionFacade? = null,
+ private val declarationDescriptor: DeclarationDescriptor? = null,
+ private val logger: DokkaLogger
+) : Parser() {
+
+ inner class MarkdownVisitor(val text: String, val destinationLinksMap: Map<String, String>) {
+
+ private fun headersHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ visitNode(node.children.find { it.type == MarkdownTokenTypes.ATX_CONTENT }
+ ?: throw IllegalStateException("Wrong AST Tree. ATX Header does not contain expected content")).children
+ )
+
+ private fun horizontalRulesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(MarkdownTokenTypes.HORIZONTAL_RULE)
+
+ private fun emphasisHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = listOf(visitNode(node.children[node.children.size / 2]))
+ )
+
+ private fun blockquotesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type, children = node.children
+ .filterIsInstance<CompositeASTNode>()
+ .evaluateChildren()
+ )
+
+ private fun listsHandler(node: ASTNode): DocTag {
+
+ val children = node.children.filterIsInstance<ListItemCompositeNode>().flatMap {
+ if (it.children.last().type in listOf(
+ MarkdownElementTypes.ORDERED_LIST,
+ MarkdownElementTypes.UNORDERED_LIST
+ )
+ ) {
+ val nestedList = it.children.last()
+ (it.children as MutableList).removeAt(it.children.lastIndex)
+ listOf(it, nestedList)
+ } else
+ listOf(it)
+ }
+
+ return DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children =
+ children
+ .map {
+ if (it.type == MarkdownElementTypes.LIST_ITEM)
+ DocTagsFromIElementFactory.getInstance(
+ it.type,
+ children = it
+ .children
+ .filterIsInstance<CompositeASTNode>()
+ .evaluateChildren()
+ )
+ else
+ visitNode(it)
+ },
+ params =
+ if (node.type == MarkdownElementTypes.ORDERED_LIST) {
+ val listNumberNode = node.children.first().children.first()
+ mapOf(
+ "start" to text.substring(
+ listNumberNode.startOffset,
+ listNumberNode.endOffset
+ ).trim().dropLast(1)
+ )
+ } else
+ emptyMap()
+ )
+ }
+
+ private fun resolveDRI(mdLink: String): DRI? =
+ mdLink
+ .removePrefix("[")
+ .removeSuffix("]")
+ .let { link ->
+ try {
+ java.net.URL(link)
+ null
+ } catch (e: MalformedURLException) {
+ try {
+ if (resolutionFacade != null && declarationDescriptor != null) {
+ resolveKDocLink(
+ resolutionFacade.resolveSession.bindingContext,
+ resolutionFacade,
+ declarationDescriptor,
+ null,
+ link.split('.')
+ ).minByOrNull { it is ClassDescriptor }?.let { DRI.from(it) }
+ } else null
+ } catch (e1: IllegalArgumentException) {
+ logger.warn("Couldn't resolve link for $mdLink")
+ null
+ }
+ }
+ }
+
+ private fun referenceLinksHandler(node: ASTNode): DocTag {
+ val linkLabel = node.children.find { it.type == MarkdownElementTypes.LINK_LABEL }
+ ?: throw IllegalStateException("Wrong AST Tree. Reference link does not contain expected content")
+ val linkText = node.children.findLast { it.type == MarkdownElementTypes.LINK_TEXT } ?: linkLabel
+
+ val linkKey = text.substring(linkLabel.startOffset, linkLabel.endOffset)
+
+ val link = destinationLinksMap[linkKey.toLowerCase()] ?: linkKey
+
+ return linksHandler(linkText, link)
+ }
+
+ private fun inlineLinksHandler(node: ASTNode): DocTag {
+ val linkText = node.children.find { it.type == MarkdownElementTypes.LINK_TEXT }
+ ?: throw IllegalStateException("Wrong AST Tree. Inline link does not contain expected content")
+ val linkDestination = node.children.find { it.type == MarkdownElementTypes.LINK_DESTINATION }
+ ?: throw IllegalStateException("Wrong AST Tree. Inline link does not contain expected content")
+ val linkTitle = node.children.find { it.type == MarkdownElementTypes.LINK_TITLE }
+
+ val link = text.substring(linkDestination.startOffset, linkDestination.endOffset)
+
+ return linksHandler(linkText, link, linkTitle)
+ }
+
+ private fun autoLinksHandler(node: ASTNode): DocTag {
+ val link = text.substring(node.startOffset + 1, node.endOffset - 1)
+
+ return linksHandler(node, link)
+ }
+
+ private fun linksHandler(linkText: ASTNode, link: String, linkTitle: ASTNode? = null): DocTag {
+ val dri: DRI? = resolveDRI(link)
+ val params = if (linkTitle == null)
+ mapOf("href" to link)
+ else
+ mapOf("href" to link, "title" to text.substring(linkTitle.startOffset + 1, linkTitle.endOffset - 1))
+
+ return DocTagsFromIElementFactory.getInstance(
+ MarkdownElementTypes.INLINE_LINK,
+ params = params,
+ children = linkText.children.drop(1).dropLast(1).evaluateChildren(),
+ dri = dri
+ )
+ }
+
+ private fun imagesHandler(node: ASTNode): DocTag {
+ val linkNode =
+ node.children.last().children.find { it.type == MarkdownElementTypes.LINK_LABEL }!!.children[1]
+ val link = text.substring(linkNode.startOffset, linkNode.endOffset)
+ val src = mapOf("src" to link)
+ return DocTagsFromIElementFactory.getInstance(
+ node.type,
+ params = src,
+ children = listOf(visitNode(node.children.last().children.find { it.type == MarkdownElementTypes.LINK_TEXT }!!))
+ )
+ }
+
+ private fun codeSpansHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = listOf(
+ DocTagsFromIElementFactory.getInstance(
+ MarkdownTokenTypes.TEXT,
+ body = text.substring(node.startOffset + 1, node.endOffset - 1).replace('\n', ' ').trimIndent()
+ )
+
+ )
+ )
+
+ private fun codeFencesHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ node.type,
+ children = node
+ .children
+ .dropWhile { it.type != MarkdownTokenTypes.CODE_FENCE_CONTENT }
+ .dropLastWhile { it.type != MarkdownTokenTypes.CODE_FENCE_CONTENT }
+ .map {
+ if (it.type == MarkdownTokenTypes.EOL)
+ LeafASTNode(MarkdownTokenTypes.HARD_LINE_BREAK, 0, 0)
+ else
+ it
+ }.evaluateChildren(),
+ params = node
+ .children
+ .find { it.type == MarkdownTokenTypes.FENCE_LANG }
+ ?.let { mapOf("lang" to text.substring(it.startOffset, it.endOffset)) }
+ ?: emptyMap()
+ )
+
+ private fun codeBlocksHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(node.type, children = node.children.evaluateChildren())
+
+ private fun defaultHandler(node: ASTNode): DocTag =
+ DocTagsFromIElementFactory.getInstance(
+ MarkdownElementTypes.PARAGRAPH,
+ children = node.children.evaluateChildren()
+ )
+
+ fun visitNode(node: ASTNode): DocTag =
+ when (node.type) {
+ MarkdownElementTypes.ATX_1,
+ MarkdownElementTypes.ATX_2,
+ MarkdownElementTypes.ATX_3,
+ MarkdownElementTypes.ATX_4,
+ MarkdownElementTypes.ATX_5,
+ MarkdownElementTypes.ATX_6 -> headersHandler(node)
+ MarkdownTokenTypes.HORIZONTAL_RULE -> horizontalRulesHandler(node)
+ MarkdownElementTypes.STRONG,
+ MarkdownElementTypes.EMPH -> emphasisHandler(node)
+ MarkdownElementTypes.FULL_REFERENCE_LINK,
+ MarkdownElementTypes.SHORT_REFERENCE_LINK -> referenceLinksHandler(node)
+ MarkdownElementTypes.INLINE_LINK -> inlineLinksHandler(node)
+ MarkdownElementTypes.AUTOLINK -> autoLinksHandler(node)
+ MarkdownElementTypes.BLOCK_QUOTE -> blockquotesHandler(node)
+ MarkdownElementTypes.UNORDERED_LIST,
+ MarkdownElementTypes.ORDERED_LIST -> listsHandler(node)
+ MarkdownElementTypes.CODE_BLOCK -> codeBlocksHandler(node)
+ MarkdownElementTypes.CODE_FENCE -> codeFencesHandler(node)
+ MarkdownElementTypes.CODE_SPAN -> codeSpansHandler(node)
+ MarkdownElementTypes.IMAGE -> imagesHandler(node)
+ MarkdownTokenTypes.HARD_LINE_BREAK -> DocTagsFromIElementFactory.getInstance(node.type)
+ MarkdownTokenTypes.CODE_FENCE_CONTENT,
+ MarkdownTokenTypes.CODE_LINE,
+ MarkdownTokenTypes.TEXT -> DocTagsFromIElementFactory.getInstance(
+ MarkdownTokenTypes.TEXT,
+ body = text
+ .substring(node.startOffset, node.endOffset).transform()
+ )
+ MarkdownElementTypes.MARKDOWN_FILE -> if (node.children.size == 1) visitNode(node.children.first()) else defaultHandler(
+ node
+ )
+ GFMElementTypes.STRIKETHROUGH -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.STRIKETHROUGH,
+ body = text
+ .substring(node.startOffset, node.endOffset).transform()
+ )
+ GFMElementTypes.TABLE -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.TABLE,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ GFMElementTypes.HEADER -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.HEADER,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ GFMElementTypes.ROW -> DocTagsFromIElementFactory.getInstance(
+ GFMElementTypes.ROW,
+ children = node.children.filterTabSeparators().evaluateChildren()
+ )
+ else -> defaultHandler(node)
+ }
+
+ private fun List<ASTNode>.filterTabSeparators() =
+ this.filterNot { it.type == GFMTokenTypes.TABLE_SEPARATOR }
+
+ private fun List<ASTNode>.evaluateChildren(): List<DocTag> =
+ this.removeUselessTokens().mergeLeafASTNodes().map { visitNode(it) }
+
+ private fun List<ASTNode>.removeUselessTokens(): List<ASTNode> =
+ this.filterIndexed { index, node ->
+ !(node.type == MarkdownElementTypes.LINK_DEFINITION || (
+ node.type == MarkdownTokenTypes.EOL &&
+ this.getOrNull(index - 1)?.type == MarkdownTokenTypes.HARD_LINE_BREAK
+ ))
+ }
+
+ private val notLeafNodes = listOf(MarkdownTokenTypes.HORIZONTAL_RULE, MarkdownTokenTypes.HARD_LINE_BREAK)
+
+ private fun List<ASTNode>.isNotLeaf(index: Int): Boolean =
+ if (index in 0..this.lastIndex)
+ (this[index] is CompositeASTNode) || this[index].type in notLeafNodes
+ else
+ false
+
+ private fun List<ASTNode>.mergeLeafASTNodes(): List<ASTNode> {
+ val children: MutableList<ASTNode> = mutableListOf()
+ var index = 0
+ while (index <= this.lastIndex) {
+ if (this.isNotLeaf(index)) {
+ children += this[index]
+ } else {
+ val startOffset = this[index].startOffset
+ while (index < this.lastIndex) {
+ if (this.isNotLeaf(index + 1) || this[index + 1].startOffset != this[index].endOffset) {
+ val endOffset = this[index].endOffset
+ if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty())
+ children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset)
+ break
+ }
+ index++
+ }
+ if (index == this.lastIndex) {
+ val endOffset = this[index].endOffset
+ if (text.substring(startOffset, endOffset).transform().trim().isNotEmpty())
+ children += LeafASTNode(MarkdownTokenTypes.TEXT, startOffset, endOffset)
+ }
+ }
+ index++
+ }
+ return children
+ }
+
+ private fun String.transform() = this
+ .replace(Regex("\n\n+"), "") // Squashing new lines between paragraphs
+ .replace(Regex("\n"), " ")
+ .replace(Regex(" >+ +"), " ") // Replacement used in blockquotes, get rid of garbage
+ }
+
+
+ private fun getAllDestinationLinks(text: String, node: ASTNode): List<Pair<String, String>> =
+ node.children
+ .filter { it.type == MarkdownElementTypes.LINK_DEFINITION }
+ .map {
+ text.substring(it.children[0].startOffset, it.children[0].endOffset).toLowerCase() to
+ text.substring(it.children[2].startOffset, it.children[2].endOffset)
+ } +
+ node.children.filterIsInstance<CompositeASTNode>().flatMap { getAllDestinationLinks(text, it) }
+
+
+ private fun markdownToDocNode(text: String): DocTag {
+
+ val flavourDescriptor = GFMFlavourDescriptor()
+ val markdownAstRoot: ASTNode = IntellijMarkdownParser(flavourDescriptor).buildMarkdownTreeFromString(text)
+
+ return MarkdownVisitor(text, getAllDestinationLinks(text, markdownAstRoot).toMap()).visitNode(markdownAstRoot)
+ }
+
+ override fun parseStringToDocNode(extractedString: String) = markdownToDocNode(extractedString)
+ override fun preparse(text: String) = text
+
+ private fun findParent(kDoc: PsiElement): PsiElement =
+ if (kDoc is KDocSection) findParent(kDoc.parent) else kDoc
+
+ private fun getAllKDocTags(kDocImpl: PsiElement): List<KDocTag> =
+ kDocImpl.children.filterIsInstance<KDocTag>().filterNot { it is KDocSection } + kDocImpl.children.flatMap {
+ getAllKDocTags(
+ it
+ )
+ }
+
+ fun parseFromKDocTag(kDocTag: KDocTag?): DocumentationNode {
+ return if (kDocTag == null)
+ DocumentationNode(emptyList())
+ else
+ DocumentationNode(
+ (listOf(kDocTag) + getAllKDocTags(findParent(kDocTag))).map {
+ when (it.knownTag) {
+ null -> if (it.name == null) Description(parseStringToDocNode(it.getContent())) else CustomTagWrapper(
+ parseStringToDocNode(it.getContent()),
+ it.name!!
+ )
+ KDocKnownTag.AUTHOR -> Author(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.THROWS -> Throws(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.EXCEPTION -> Throws(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.PARAM -> Param(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.RECEIVER -> Receiver(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.RETURN -> Return(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.SEE -> See(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty(),
+ parseStringToDocNode("[${it.getSubjectName()}]")
+ .let {
+ val link = it.children[0]
+ if (link is DocumentationLink) link.dri
+ else null
+ }
+ )
+ KDocKnownTag.SINCE -> Since(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.CONSTRUCTOR -> Constructor(parseStringToDocNode(it.getContent()))
+ KDocKnownTag.PROPERTY -> Property(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.SAMPLE -> Sample(
+ parseStringToDocNode(it.getContent()),
+ it.getSubjectName().orEmpty()
+ )
+ KDocKnownTag.SUPPRESS -> Suppress(parseStringToDocNode(it.getContent()))
+ }
+ }
+ )
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/Parser.kt b/plugins/base/src/main/kotlin/parsers/Parser.kt
new file mode 100644
index 00000000..1dd0c34a
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/Parser.kt
@@ -0,0 +1,42 @@
+package org.jetbrains.dokka.base.parsers
+
+import org.jetbrains.dokka.model.doc.*
+
+abstract class Parser {
+
+ abstract fun parseStringToDocNode(extractedString: String): DocTag
+ abstract fun preparse(text: String): String
+
+ fun parse(text: String): DocumentationNode {
+
+ val list = jkdocToListOfPairs(preparse(text))
+
+ val mappedList: List<TagWrapper> = list.map {
+ when(it.first) {
+ "description" -> Description(parseStringToDocNode(it.second))
+ "author" -> Author(parseStringToDocNode(it.second))
+ "version" -> Version(parseStringToDocNode(it.second))
+ "since" -> Since(parseStringToDocNode(it.second))
+ "see" -> See(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '), null)
+ "param" -> Param(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "property" -> Property(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "return" -> Return(parseStringToDocNode(it.second))
+ "constructor" -> Constructor(parseStringToDocNode(it.second))
+ "receiver" -> Receiver(parseStringToDocNode(it.second))
+ "throws", "exception" -> Throws(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "deprecated" -> Deprecated(parseStringToDocNode(it.second))
+ "sample" -> Sample(parseStringToDocNode(it.second.substringAfter(' ')), it.second.substringBefore(' '))
+ "suppress" -> Suppress(parseStringToDocNode(it.second))
+ else -> CustomTagWrapper(parseStringToDocNode(it.second), it.first)
+ }
+ }
+ return DocumentationNode(mappedList)
+ }
+
+ private fun jkdocToListOfPairs(javadoc: String): List<Pair<String, String>> =
+ "description $javadoc"
+ .split("\n@")
+ .map {
+ it.substringBefore(' ') to it.substringAfter(' ')
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
new file mode 100644
index 00000000..277fd35e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromIElementFactory.kt
@@ -0,0 +1,43 @@
+package org.jetbrains.dokka.base.parsers.factories
+
+import org.jetbrains.dokka.model.doc.*
+import org.intellij.markdown.IElementType
+import org.intellij.markdown.MarkdownElementTypes
+import org.intellij.markdown.MarkdownTokenTypes
+import org.intellij.markdown.flavours.gfm.GFMElementTypes
+import org.jetbrains.dokka.links.DRI
+import java.lang.NullPointerException
+
+object DocTagsFromIElementFactory {
+ fun getInstance(type: IElementType, children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap(), body: String? = null, dri: DRI? = null) =
+ when(type) {
+ MarkdownElementTypes.SHORT_REFERENCE_LINK,
+ MarkdownElementTypes.FULL_REFERENCE_LINK,
+ MarkdownElementTypes.INLINE_LINK -> if(dri == null) A(children, params) else DocumentationLink(dri, children, params)
+ MarkdownElementTypes.STRONG -> B(children, params)
+ MarkdownElementTypes.BLOCK_QUOTE -> BlockQuote(children, params)
+ MarkdownElementTypes.CODE_SPAN -> CodeInline(children, params)
+ MarkdownElementTypes.CODE_BLOCK,
+ MarkdownElementTypes.CODE_FENCE -> CodeBlock(children, params)
+ MarkdownElementTypes.ATX_1 -> H1(children, params)
+ MarkdownElementTypes.ATX_2 -> H2(children, params)
+ MarkdownElementTypes.ATX_3 -> H3(children, params)
+ MarkdownElementTypes.ATX_4 -> H4(children, params)
+ MarkdownElementTypes.ATX_5 -> H5(children, params)
+ MarkdownElementTypes.ATX_6 -> H6(children, params)
+ MarkdownElementTypes.EMPH -> I(children, params)
+ MarkdownElementTypes.IMAGE -> Img(children, params)
+ MarkdownElementTypes.LIST_ITEM -> Li(children, params)
+ MarkdownElementTypes.ORDERED_LIST -> Ol(children, params)
+ MarkdownElementTypes.UNORDERED_LIST -> Ul(children, params)
+ MarkdownElementTypes.PARAGRAPH -> P(children, params)
+ MarkdownTokenTypes.TEXT -> Text(body ?: throw NullPointerException("Text body should be at least empty string passed to DocNodes factory!"), children, params )
+ MarkdownTokenTypes.HORIZONTAL_RULE -> HorizontalRule
+ MarkdownTokenTypes.HARD_LINE_BREAK -> Br
+ GFMElementTypes.STRIKETHROUGH -> Strikethrough(children, params)
+ GFMElementTypes.TABLE -> Table(children, params)
+ GFMElementTypes.HEADER -> Th(children, params)
+ GFMElementTypes.ROW -> Tr(children, params)
+ else -> CustomDocTag(children, params)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt
new file mode 100644
index 00000000..124dc3b4
--- /dev/null
+++ b/plugins/base/src/main/kotlin/parsers/factories/DocTagsFromStringFactory.kt
@@ -0,0 +1,77 @@
+package org.jetbrains.dokka.base.parsers.factories
+
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.links.DRI
+import java.lang.NullPointerException
+
+object DocTagsFromStringFactory {
+ fun getInstance(name: String, children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap(), body: String? = null, dri: DRI? = null) =
+ when(name) {
+ "a" -> A(children, params)
+ "big" -> Big(children, params)
+ "b" -> B(children, params)
+ "blockquote" -> BlockQuote(children, params)
+ "br" -> Br
+ "cite" -> Cite(children, params)
+ "code" -> if(params.isEmpty()) CodeInline(children, params) else CodeBlock(children, params)
+ "dd" -> Dd(children, params)
+ "dfn" -> Dfn(children, params)
+ "dir" -> Dir(children, params)
+ "div" -> Div(children, params)
+ "dl" -> Dl(children, params)
+ "dt" -> Dt(children, params)
+ "Em" -> Em(children, params)
+ "font" -> Font(children, params)
+ "footer" -> Footer(children, params)
+ "frame" -> Frame(children, params)
+ "frameset" -> FrameSet(children, params)
+ "h1" -> H1(children, params)
+ "h2" -> H2(children, params)
+ "h3" -> H3(children, params)
+ "h4" -> H4(children, params)
+ "h5" -> H5(children, params)
+ "h6" -> H6(children, params)
+ "head" -> Head(children, params)
+ "header" -> Header(children, params)
+ "html" -> Html(children, params)
+ "i" -> I(children, params)
+ "iframe" -> IFrame(children, params)
+ "img" -> Img(children, params)
+ "input" -> Input(children, params)
+ "li" -> Li(children, params)
+ "link" -> Link(children, params)
+ "listing" -> Listing(children, params)
+ "main" -> Main(children, params)
+ "menu" -> Menu(children, params)
+ "meta" -> Meta(children, params)
+ "nav" -> Nav(children, params)
+ "noframes" -> NoFrames(children, params)
+ "noscript" -> NoScript(children, params)
+ "ol" -> Ol(children, params)
+ "p" -> P(children, params)
+ "pre" -> Pre(children, params)
+ "script" -> Script(children, params)
+ "section" -> Section(children, params)
+ "small" -> Small(children, params)
+ "span" -> Span(children, params)
+ "strong" -> Strong(children, params)
+ "sub" -> Sub(children, params)
+ "sup" -> Sup(children, params)
+ "table" -> Table(children, params)
+ "#text" -> Text(body ?: throw NullPointerException("Text body should be at least empty string passed to DocNodes factory!"), children, params)
+ "tBody" -> TBody(children, params)
+ "td" -> Td(children, params)
+ "tFoot" -> TFoot(children, params)
+ "th" -> Th(children, params)
+ "tHead" -> THead(children, params)
+ "title" -> Title(children, params)
+ "tr" -> Tr(children, params)
+ "tt" -> Tt(children, params)
+ "u" -> U(children, params)
+ "ul" -> Ul(children, params)
+ "var" -> Var(children, params)
+ "documentationlink" -> DocumentationLink(dri ?: throw NullPointerException("DRI cannot be passed null while constructing documentation link!"), children, params)
+ "hr" -> HorizontalRule
+ else -> CustomDocTag(children, params)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
new file mode 100644
index 00000000..afee1b33
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -0,0 +1,200 @@
+package org.jetbrains.dokka.base.renderers
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.resolvers.local.LocationProvider
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+import org.jetbrains.dokka.renderers.Renderer
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+
+abstract class DefaultRenderer<T>(
+ protected val context: DokkaContext
+) : Renderer {
+
+ protected val outputWriter = context.plugin<DokkaBase>().querySingle { outputWriter }
+
+ protected lateinit var locationProvider: LocationProvider
+ private set
+
+ protected open val preprocessors: Iterable<PageTransformer> = emptyList()
+
+ abstract fun T.buildHeader(level: Int, node: ContentHeader, content: T.() -> Unit)
+ abstract fun T.buildLink(address: String, content: T.() -> Unit)
+ abstract fun T.buildList(
+ node: ContentList,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ )
+
+ abstract fun T.buildNewLine()
+ abstract fun T.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage)
+ abstract fun T.buildTable(
+ node: ContentTable,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ )
+
+ abstract fun T.buildText(textNode: ContentText)
+ abstract fun T.buildNavigation(page: PageNode)
+
+ abstract fun buildPage(page: ContentPage, content: (T, ContentPage) -> Unit): String
+ abstract fun buildError(node: ContentNode)
+
+ open fun T.buildPlatformDependent(
+ content: PlatformHintedContent,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?
+ ) = buildContentNode(content.inner, pageContext)
+
+ open fun T.buildGroup(
+ node: ContentGroup,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) =
+ wrapGroup(node, pageContext) { node.children.forEach { it.build(this, pageContext, sourceSetRestriction) } }
+
+ open fun T.buildDivergent(node: ContentDivergentGroup, pageContext: ContentPage) =
+ node.children.forEach { it.build(this, pageContext) }
+
+ open fun T.wrapGroup(node: ContentGroup, pageContext: ContentPage, childrenCallback: T.() -> Unit) =
+ childrenCallback()
+
+ open fun T.buildLinkText(
+ nodes: List<ContentNode>,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) {
+ nodes.forEach { it.build(this, pageContext, sourceSetRestriction) }
+ }
+
+ open fun T.buildCodeBlock(code: ContentCodeBlock, pageContext: ContentPage) {
+ code.children.forEach { it.build(this, pageContext) }
+ }
+
+ open fun T.buildCodeInline(code: ContentCodeInline, pageContext: ContentPage) {
+ code.children.forEach { it.build(this, pageContext) }
+ }
+
+ open fun T.buildHeader(
+ node: ContentHeader,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) {
+ buildHeader(node.level, node) { node.children.forEach { it.build(this, pageContext, sourceSetRestriction) } }
+ }
+
+ open fun ContentNode.build(
+ builder: T,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) =
+ builder.buildContentNode(this, pageContext, sourceSetRestriction)
+
+ open fun T.buildContentNode(
+ node: ContentNode,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) {
+ if (sourceSetRestriction == null || node.sourceSets.any { it in sourceSetRestriction }) {
+ when (node) {
+ is ContentText -> buildText(node)
+ is ContentHeader -> buildHeader(node, pageContext, sourceSetRestriction)
+ is ContentCodeBlock -> buildCodeBlock(node, pageContext)
+ is ContentCodeInline -> buildCodeInline(node, pageContext)
+ is ContentDRILink ->
+ buildLink(locationProvider.resolve(node.address, node.sourceSets, pageContext)) {
+ buildLinkText(node.children, pageContext, sourceSetRestriction)
+ }
+ is ContentResolvedLink -> buildLink(node.address) {
+ buildLinkText(node.children, pageContext, sourceSetRestriction)
+ }
+ is ContentEmbeddedResource -> buildResource(node, pageContext)
+ is ContentList -> buildList(node, pageContext, sourceSetRestriction)
+ is ContentTable -> buildTable(node, pageContext, sourceSetRestriction)
+ is ContentGroup -> buildGroup(node, pageContext, sourceSetRestriction)
+ is ContentBreakLine -> buildNewLine()
+ is PlatformHintedContent -> buildPlatformDependent(node, pageContext, sourceSetRestriction)
+ is ContentDivergentGroup -> buildDivergent(node, pageContext)
+ is ContentDivergentInstance -> buildDivergentInstance(node, pageContext)
+ else -> buildError(node)
+ }
+ }
+ }
+
+ open fun T.buildDivergentInstance(node: ContentDivergentInstance, pageContext: ContentPage) {
+ node.before?.build(this, pageContext)
+ node.divergent.build(this, pageContext)
+ node.after?.build(this, pageContext)
+ }
+
+ open fun buildPageContent(context: T, page: ContentPage) {
+ context.buildNavigation(page)
+ page.content.build(context, page)
+ }
+
+ open suspend fun renderPage(page: PageNode) {
+ val path by lazy { locationProvider.resolve(page, skipExtension = true) }
+ when (page) {
+ is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".html")
+ is RendererSpecificPage -> when (val strategy = page.strategy) {
+ is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path)
+ is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "")
+ is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".html")
+ RenderingStrategy.DoNothing -> Unit
+ }
+ else -> throw AssertionError(
+ "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content"
+ )
+ }
+ }
+
+ private suspend fun renderPages(root: PageNode) {
+ coroutineScope {
+ renderPage(root)
+
+ root.children.forEach {
+ launch { renderPages(it) }
+ }
+ }
+ }
+
+ override fun render(root: RootPageNode) {
+ val newRoot = preprocessors.fold(root) { acc, t -> t(acc) }
+
+ locationProvider =
+ context.plugin<DokkaBase>().querySingle { locationProviderFactory }.getLocationProvider(newRoot)
+
+ runBlocking(Dispatchers.Default) {
+ renderPages(newRoot)
+ }
+ }
+
+ protected fun ContentDivergentGroup.groupDivergentInstances(
+ pageContext: ContentPage,
+ beforeTransformer: (ContentDivergentInstance, ContentPage, DokkaSourceSet) -> String,
+ afterTransformer: (ContentDivergentInstance, ContentPage, DokkaSourceSet) -> String
+ ): Map<SerializedBeforeAndAfter, List<InstanceWithSource>> =
+ children.flatMap { instance ->
+ instance.sourceSets.map { sourceSet ->
+ Pair(instance, sourceSet) to Pair(
+ beforeTransformer(instance, pageContext, sourceSet),
+ afterTransformer(instance, pageContext, sourceSet)
+ )
+ }
+ }.groupBy(
+ Pair<InstanceWithSource, SerializedBeforeAndAfter>::second,
+ Pair<InstanceWithSource, SerializedBeforeAndAfter>::first
+ )
+}
+
+internal typealias SerializedBeforeAndAfter = Pair<String, String>
+internal typealias InstanceWithSource = Pair<ContentDivergentInstance, DokkaSourceSet>
+
+fun ContentPage.sourceSets() = this.content.sourceSets \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt b/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt
new file mode 100644
index 00000000..3b849fec
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/DefaultTabSortingStrategy.kt
@@ -0,0 +1,31 @@
+package org.jetbrains.dokka.base.renderers
+
+import org.jetbrains.dokka.pages.ContentKind
+import org.jetbrains.dokka.pages.ContentNode
+import org.jetbrains.dokka.pages.Kind
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+private val kindsOrder = listOf(
+ ContentKind.Classlikes,
+ ContentKind.Constructors,
+ ContentKind.Functions,
+ ContentKind.Properties,
+ ContentKind.Extensions,
+ ContentKind.Parameters,
+ ContentKind.Inheritors,
+ ContentKind.Source,
+ ContentKind.Sample,
+ ContentKind.Comment
+)
+
+class DefaultTabSortingStrategy : TabSortingStrategy {
+ override fun <T: ContentNode> sort(tabs: Collection<T>): List<T> {
+ val tabMap: Map<Kind, MutableList<T>> = kindsOrder.asSequence().map { it to mutableListOf<T>() }.toMap()
+ val unrecognized: MutableList<T> = mutableListOf()
+ tabs.forEach {
+ tabMap[it.dci.kind]?.add(it) ?: unrecognized.add(it)
+ }
+ return tabMap.values.flatten() + unrecognized
+ }
+
+}
diff --git a/plugins/base/src/main/kotlin/renderers/FileWriter.kt b/plugins/base/src/main/kotlin/renderers/FileWriter.kt
new file mode 100644
index 00000000..181295c0
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/FileWriter.kt
@@ -0,0 +1,88 @@
+package org.jetbrains.dokka.base.renderers
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.jetbrains.dokka.plugability.DokkaContext
+import java.io.File
+import java.io.IOException
+import java.net.URI
+import java.nio.file.*
+
+class FileWriter(val context: DokkaContext): OutputWriter {
+ private val createdFiles: MutableSet<String> = mutableSetOf()
+ private val jarUriPrefix = "jar:file:"
+ private val root = context.configuration.outputDir
+
+ override suspend fun write(path: String, text: String, ext: String) {
+ if (createdFiles.contains(path)) {
+ context.logger.error("An attempt to write ${root}/$path several times!")
+ return
+ }
+ createdFiles.add(path)
+
+ try {
+ val dir = Paths.get(root, path.dropLastWhile { it != '/' }).toFile()
+ withContext(Dispatchers.IO) {
+ dir.mkdirsOrFail()
+ Files.write(Paths.get(root, "$path$ext"), text.lines())
+ }
+ } catch (e: Throwable) {
+ context.logger.error("Failed to write $this. ${e.message}")
+ e.printStackTrace()
+ }
+ }
+
+ override suspend fun writeResources(pathFrom: String, pathTo: String) =
+ if (javaClass.getResource(pathFrom).toURI().toString().startsWith(jarUriPrefix)) {
+ copyFromJar(pathFrom, pathTo)
+ } else {
+ copyFromDirectory(pathFrom, pathTo)
+ }
+
+
+ private suspend fun copyFromDirectory(pathFrom: String, pathTo: String) {
+ val dest = Paths.get(root, pathTo).toFile()
+ val uri = javaClass.getResource(pathFrom).toURI()
+ withContext(Dispatchers.IO) {
+ File(uri).copyRecursively(dest, true)
+ }
+ }
+
+ private suspend fun copyFromJar(pathFrom: String, pathTo: String) {
+ val rebase = fun(path: String) =
+ "$pathTo/${path.removePrefix(pathFrom)}"
+ val dest = Paths.get(root, pathTo).toFile()
+ dest.mkdirsOrFail()
+ val uri = javaClass.getResource(pathFrom).toURI()
+ val fs = getFileSystemForURI(uri)
+ val path = fs.getPath(pathFrom)
+ for (file in Files.walk(path).iterator()) {
+ if (Files.isDirectory(file)) {
+ val dirPath = file.toAbsolutePath().toString()
+ withContext(Dispatchers.IO) {
+ Paths.get(root, rebase(dirPath)).toFile().mkdirsOrFail()
+ }
+ } else {
+ val filePath = file.toAbsolutePath().toString()
+ withContext(Dispatchers.IO) {
+ Paths.get(root, rebase(filePath)).toFile().writeBytes(
+ this@FileWriter.javaClass.getResourceAsStream(filePath).readBytes()
+ )
+ }
+ }
+ }
+ }
+
+ private fun File.mkdirsOrFail() {
+ if (!mkdirs() && !exists()) {
+ throw IOException("Failed to create directory $this")
+ }
+ }
+
+ private fun getFileSystemForURI(uri: URI): FileSystem =
+ try {
+ FileSystems.newFileSystem(uri, emptyMap<String, Any>())
+ } catch (e: FileSystemAlreadyExistsException) {
+ FileSystems.getFileSystem(uri)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/OutputWriter.kt b/plugins/base/src/main/kotlin/renderers/OutputWriter.kt
new file mode 100644
index 00000000..1827c7f0
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/OutputWriter.kt
@@ -0,0 +1,7 @@
+package org.jetbrains.dokka.base.renderers
+
+interface OutputWriter {
+
+ suspend fun write(path: String, text: String, ext: String)
+ suspend fun writeResources(pathFrom: String, pathTo: String)
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/PackageListService.kt b/plugins/base/src/main/kotlin/renderers/PackageListService.kt
new file mode 100644
index 00000000..d4333200
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/PackageListService.kt
@@ -0,0 +1,51 @@
+package org.jetbrains.dokka.base.renderers
+
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.parent
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+class PackageListService(val context: DokkaContext) {
+
+ fun formatPackageList(module: RootPageNode, format: String, linkExtension: String): String {
+
+ val packages = mutableSetOf<String>()
+ val nonStandardLocations = mutableMapOf<String, String>()
+
+ val locationProvider =
+ context.plugin<DokkaBase>().querySingle { locationProviderFactory }.getLocationProvider(module)
+
+ fun visit(node: PageNode, parentDris: Set<DRI>) {
+
+ if (node is PackagePageNode) {
+ packages.add(node.name)
+ }
+
+ val contentPage = node.safeAs<ContentPage>()
+ contentPage?.dri?.forEach {
+ if (parentDris.isNotEmpty() && it.parent !in parentDris) {
+ nonStandardLocations[it.toString()] = locationProvider.resolve(node)
+ }
+ }
+
+ node.children.forEach { visit(it, contentPage?.dri ?: setOf()) }
+ }
+
+ visit(module, setOf())
+
+ return buildString {
+ appendln("\$dokka.format:${format}")
+ appendln("\$dokka.linkExtension:${linkExtension}")
+ nonStandardLocations.map { (signature, location) -> "\$dokka.location:$signature\u001f$location" }
+ .sorted().joinTo(this, separator = "\n", postfix = "\n")
+
+ packages.sorted().joinTo(this, separator = "\n", postfix = "\n")
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt b/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt
new file mode 100644
index 00000000..dcf49ca9
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt
@@ -0,0 +1,7 @@
+package org.jetbrains.dokka.base.renderers
+
+import org.jetbrains.dokka.pages.ContentNode
+
+interface TabSortingStrategy {
+ fun <T: ContentNode> sort(tabs: Collection<T>) : List<T>
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
new file mode 100644
index 00000000..614d8f6e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
@@ -0,0 +1,760 @@
+package org.jetbrains.dokka.base.renderers.html
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.html.*
+import kotlinx.html.stream.createHTML
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.renderers.DefaultRenderer
+import org.jetbrains.dokka.base.renderers.TabSortingStrategy
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.model.withDescendants
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.query
+import org.jetbrains.dokka.plugability.querySingle
+import java.io.File
+import java.net.URI
+
+open class HtmlRenderer(
+ context: DokkaContext
+) : DefaultRenderer<FlowContent>(context) {
+
+ private val sourceSetDependencyMap = context.configuration.sourceSets.map { sourceSet ->
+ sourceSet to context.configuration.sourceSets.filter { sourceSet.dependentSourceSets.contains(it.sourceSetID) }
+ }.toMap()
+
+ private val isMultiplatform by lazy {
+ sourceSetDependencyMap.size > 1
+ }
+
+ private val pageList = mutableMapOf<String, Pair<String, String>>()
+
+ override val preprocessors = context.plugin<DokkaBase>().query { htmlPreprocessors }
+
+ private val tabSortingStrategy = context.plugin<DokkaBase>().querySingle { tabSortingStrategy }
+
+ private fun <T : ContentNode> sortTabs(strategy: TabSortingStrategy, tabs: Collection<T>): List<T> {
+ val sorted = strategy.sort(tabs)
+ if (sorted.size != tabs.size)
+ context.logger.warn("Tab sorting strategy has changed number of tabs from ${tabs.size} to ${sorted.size}")
+ return sorted;
+ }
+
+ override fun FlowContent.wrapGroup(
+ node: ContentGroup,
+ pageContext: ContentPage,
+ childrenCallback: FlowContent.() -> Unit
+ ) {
+ val additionalClasses = node.style.joinToString(" ") { it.toString().toLowerCase() }
+ return when {
+ node.hasStyle(ContentStyle.TabbedContent) -> div(additionalClasses) {
+ val secondLevel = node.children.filterIsInstance<ContentComposite>().flatMap { it.children }
+ .filterIsInstance<ContentHeader>().flatMap { it.children }.filterIsInstance<ContentText>()
+ val firstLevel = node.children.filterIsInstance<ContentHeader>().flatMap { it.children }
+ .filterIsInstance<ContentText>()
+
+ val renderable = firstLevel.union(secondLevel).let { sortTabs(tabSortingStrategy, it) }
+
+ div(classes = "tabs-section") {
+ attributes["tabs-section"] = "tabs-section"
+ renderable.forEachIndexed { index, node ->
+ button(classes = "section-tab") {
+ if (index == 0) attributes["data-active"] = ""
+ attributes["data-togglable"] = node.text
+ text(node.text)
+ }
+ }
+ }
+ div(classes = "tabs-section-body") {
+ childrenCallback()
+ }
+ }
+ node.hasStyle(ContentStyle.WithExtraAttributes) -> div() {
+ node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
+ childrenCallback()
+ }
+ node.dci.kind in setOf(ContentKind.Symbol) -> div("symbol $additionalClasses") {
+ childrenCallback()
+ if (node.hasStyle(TextStyle.Monospace)) copyButton()
+ }
+ node.hasStyle(TextStyle.BreakableAfter) -> {
+ span() { childrenCallback() }
+ wbr { }
+ }
+ node.hasStyle(TextStyle.Breakable) -> {
+ span("breakable-word") { childrenCallback() }
+ }
+ node.hasStyle(TextStyle.Span) -> span() { childrenCallback() }
+ node.dci.kind == ContentKind.Symbol -> div("symbol $additionalClasses") { childrenCallback() }
+ node.dci.kind == ContentKind.BriefComment -> div("brief $additionalClasses") { childrenCallback() }
+ node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") {
+ filterButtons(pageContext)
+ childrenCallback()
+ }
+ node.hasStyle(TextStyle.Paragraph) -> p(additionalClasses) { childrenCallback() }
+ node.hasStyle(TextStyle.Block) -> div(additionalClasses) { childrenCallback() }
+ else -> childrenCallback()
+ }
+ }
+
+ private fun FlowContent.filterButtons(page: ContentPage) {
+ if (isMultiplatform) {
+ div(classes = "filter-section") {
+ id = "filter-section"
+ page.content.withDescendants().flatMap { it.sourceSets }.distinct().forEach {
+ button(classes = "platform-tag platform-selector") {
+ attributes["data-active"] = ""
+ attributes["data-filter"] = it.sourceSetID.toString()
+ when (it.analysisPlatform.key) {
+ "common" -> classes = classes + "common-like"
+ "native" -> classes = classes + "native-like"
+ "jvm" -> classes = classes + "jvm-like"
+ "js" -> classes = classes + "js-like"
+ }
+ text(it.displayName)
+ }
+ }
+ }
+ }
+ }
+
+ private fun FlowContent.copyButton() = span(classes = "top-right-position") {
+ span("copy-icon") {
+ unsafe {
+ raw(
+ """<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M5 4H15V16H5V4ZM17 7H19V18V20H17H8V18H17V7Z" fill="black"/>
+ </svg>""".trimIndent()
+ )
+ }
+ }
+ copiedPopup("Content copied to clipboard", "popup-to-left")
+ }
+
+ private fun FlowContent.copiedPopup(notificationContent: String, additionalClasses: String = "") =
+ div("copy-popup-wrapper $additionalClasses") {
+ unsafe {
+ raw(
+ """
+ <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M18 9C18 14 14 18 9 18C4 18 0 14 0 9C0 4 4 0 9 0C14 0 18 4 18 9ZM14.2 6.2L12.8 4.8L7.5 10.1L5.3 7.8L3.8 9.2L7.5 13L14.2 6.2Z" fill="#4DBB5F"/>
+ </svg>
+ """.trimIndent()
+ )
+ }
+ span {
+ text(notificationContent)
+ }
+ }
+
+ override fun FlowContent.buildPlatformDependent(
+ content: PlatformHintedContent,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?
+ ) =
+ buildPlatformDependent(
+ content.sourceSets.filter {
+ sourceSetRestriction == null || it in sourceSetRestriction
+ }.map { it to setOf(content.inner) }.toMap(),
+ pageContext,
+ content.extra,
+ content.style
+ )
+
+ private fun FlowContent.buildPlatformDependent(
+ nodes: Map<DokkaSourceSet, Collection<ContentNode>>,
+ pageContext: ContentPage,
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
+ styles: Set<Style> = emptySet()
+ ) {
+ val contents = contentsForSourceSetDependent(nodes, pageContext)
+ val shouldHaveTabs = contents.size != 1
+
+ val styles = "platform-hinted ${styles.joinToString()}" + if (shouldHaveTabs) " with-platform-tabs" else ""
+ div(styles) {
+ attributes["data-platform-hinted"] = "data-platform-hinted"
+ extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
+ if (shouldHaveTabs) {
+ div("platform-bookmarks-row") {
+ attributes["data-toggle-list"] = "data-toggle-list"
+ contents.forEachIndexed { index, pair ->
+ button(classes = "platform-bookmark") {
+ attributes["data-filterable-current"] = pair.first.sourceSetID.toString()
+ attributes["data-filterable-set"] = pair.first.sourceSetID.toString()
+ if (index == 0) attributes["data-active"] = ""
+ attributes["data-toggle"] = pair.first.sourceSetID.toString()
+ when (pair.first.analysisPlatform.key) {
+ "common" -> classes = classes + "common-like"
+ "native" -> classes = classes + "native-like"
+ "jvm" -> classes = classes + "jvm-like"
+ "js" -> classes = classes + "js-like"
+ }
+ attributes["data-toggle"] = pair.first.sourceSetID.toString()
+ text(pair.first.displayName)
+ }
+ }
+ }
+ }
+ contents.forEach {
+ consumer.onTagContentUnsafe { +it.second }
+ }
+ }
+ }
+
+ private fun contentsForSourceSetDependent(
+ nodes: Map<DokkaSourceSet, Collection<ContentNode>>,
+ pageContext: ContentPage,
+ ): List<Pair<DokkaSourceSet, String>> {
+ var counter = 0
+ return nodes.toList().map { (sourceSet, elements) ->
+ sourceSet to createHTML(prettyPrint = false).div {
+ elements.forEach {
+ buildContentNode(it, pageContext, setOf(sourceSet))
+ }
+ }.stripDiv()
+ }.groupBy(
+ Pair<DokkaSourceSet, String>::second,
+ Pair<DokkaSourceSet, String>::first
+ ).entries.flatMap { (html, sourceSets) ->
+ sourceSets.filterNot {
+ sourceSetDependencyMap[it].orEmpty().any { dependency -> sourceSets.contains(dependency) }
+ }.map {
+ it to createHTML(prettyPrint = false).div(classes = "content sourceset-depenent-content") {
+ if (counter++ == 0) attributes["data-active"] = ""
+ attributes["data-togglable"] = it.sourceSetID.toString()
+ unsafe {
+ +html
+ }
+ }
+ }
+ }
+ }
+
+ override fun FlowContent.buildDivergent(node: ContentDivergentGroup, pageContext: ContentPage) {
+
+ val distinct =
+ node.groupDivergentInstances(pageContext, { instance, contentPage, sourceSet ->
+ createHTML(prettyPrint = false).div {
+ instance.before?.let { before ->
+ buildContentNode(before, pageContext, setOf(sourceSet))
+ }
+ }.stripDiv()
+ }, { instance, contentPage, sourceSet ->
+ createHTML(prettyPrint = false).div {
+ instance.after?.let { after ->
+ buildContentNode(after, pageContext, setOf(sourceSet))
+ }
+ }.stripDiv()
+ })
+
+ distinct.forEach {
+ val groupedDivergent = it.value.groupBy { it.second }
+
+ consumer.onTagContentUnsafe {
+ +createHTML().div("divergent-group") {
+ attributes["data-filterable-current"] = groupedDivergent.keys.joinToString(" ") {
+ it.sourceSetID.toString()
+ }
+ attributes["data-filterable-set"] = groupedDivergent.keys.joinToString(" ") {
+ it.sourceSetID.toString()
+ }
+
+ val divergentForPlatformDependent = groupedDivergent.map { (sourceSet, elements) ->
+ sourceSet to elements.map { e -> e.first.divergent }
+ }.toMap()
+
+ val content = contentsForSourceSetDependent(divergentForPlatformDependent, pageContext)
+
+ consumer.onTagContentUnsafe {
+ +createHTML().div("brief-with-platform-tags") {
+ consumer.onTagContentUnsafe {
+ +createHTML().div("inner-brief-with-platform-tags") {
+ consumer.onTagContentUnsafe { +it.key.first }
+ }
+ }
+
+ consumer.onTagContentUnsafe {
+ +createHTML().span("pull-right") {
+ if ((distinct.size > 1 && groupedDivergent.size == 1) || groupedDivergent.size == 1 || content.size == 1) {
+ if (node.sourceSets.size != 1) {
+ createPlatformTags(node, setOf(content.first().first))
+ }
+ }
+ }
+ }
+ }
+ }
+ div("main-subrow") {
+ if (node.implicitlySourceSetHinted) {
+ buildPlatformDependent(divergentForPlatformDependent, pageContext)
+ } else {
+ it.value.forEach {
+ buildContentNode(it.first.divergent, pageContext, setOf(it.second))
+ }
+ }
+ }
+ consumer.onTagContentUnsafe { +it.key.second }
+ }
+ }
+ }
+ }
+
+ override fun FlowContent.buildList(
+ node: ContentList,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?
+ ) = if (node.ordered) ol { buildListItems(node.children, pageContext, sourceSetRestriction) }
+ else ul { buildListItems(node.children, pageContext, sourceSetRestriction) }
+
+ open fun OL.buildListItems(
+ items: List<ContentNode>,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) {
+ items.forEach {
+ if (it is ContentList)
+ buildList(it, pageContext)
+ else
+ li { it.build(this, pageContext, sourceSetRestriction) }
+ }
+ }
+
+ open fun UL.buildListItems(
+ items: List<ContentNode>,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>? = null
+ ) {
+ items.forEach {
+ if (it is ContentList)
+ buildList(it, pageContext)
+ else
+ li { it.build(this, pageContext) }
+ }
+ }
+
+ override fun FlowContent.buildResource(
+ node: ContentEmbeddedResource,
+ pageContext: ContentPage
+ ) { // TODO: extension point there
+ val imageExtensions = setOf("png", "jpg", "jpeg", "gif", "bmp", "tif", "webp", "svg")
+ return if (File(node.address).extension.toLowerCase() in imageExtensions) {
+ //TODO: add imgAttrs parsing
+ val imgAttrs = node.extra.allOfType<SimpleAttr>().joinAttr()
+ img(src = node.address, alt = node.altText)
+ } else {
+ println("Unrecognized resource type: $node")
+ }
+ }
+
+ private fun FlowContent.buildRow(
+ node: ContentGroup,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?,
+ style: Set<Style>
+ ) {
+ node.children
+ .filter { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }
+ .takeIf { it.isNotEmpty() }
+ ?.let {
+ val anchorName = node.dci.dri.first().toString()
+ withAnchor(anchorName) {
+ div(classes = "table-row") {
+ if (!style.contains(MultimoduleTable)) {
+ attributes["data-filterable-current"] = node.sourceSets.joinToString(" ") {
+ it.sourceSetID.toString()
+ }
+ attributes["data-filterable-set"] = node.sourceSets.joinToString(" ") {
+ it.sourceSetID.toString()
+ }
+ }
+
+ it.filterIsInstance<ContentLink>().takeIf { it.isNotEmpty() }?.let {
+ div("main-subrow " + node.style.joinToString(" ")) {
+ it.filter { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }
+ .forEach {
+ span {
+ it.build(this, pageContext, sourceSetRestriction)
+ buildAnchor(anchorName)
+ }
+ if (ContentKind.shouldBePlatformTagged(node.dci.kind) && (node.sourceSets.size == 1))
+ createPlatformTags(node)
+ }
+ }
+ }
+
+ it.filter { it !is ContentLink }.takeIf { it.isNotEmpty() }?.let {
+ div("platform-dependent-row keyValue") {
+ val title = it.filter { it.style.contains(ContentStyle.RowTitle) }
+ div {
+ title.forEach {
+ it.build(this, pageContext, sourceSetRestriction)
+ }
+ }
+ div("title") {
+ (it - title).forEach {
+ it.build(this, pageContext, sourceSetRestriction)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun FlowContent.createPlatformTagBubbles(sourceSets: List<DokkaSourceSet>) {
+ if (isMultiplatform) {
+ div("platform-tags") {
+ sourceSets.forEach {
+ div("platform-tag") {
+ when (it.analysisPlatform.key) {
+ "common" -> classes = classes + "common-like"
+ "native" -> classes = classes + "native-like"
+ "jvm" -> classes = classes + "jvm-like"
+ "js" -> classes = classes + "js-like"
+ }
+ text(it.displayName)
+ }
+ }
+ }
+ }
+ }
+
+ private fun FlowContent.createPlatformTags(node: ContentNode, sourceSetRestriction: Set<DokkaSourceSet>? = null) {
+ node.takeIf { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }?.let {
+ createPlatformTagBubbles(node.sourceSets.filter {
+ sourceSetRestriction == null || it in sourceSetRestriction
+ })
+ }
+ }
+
+ override fun FlowContent.buildTable(
+ node: ContentTable,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?
+ ) {
+ when (node.dci.kind) {
+ ContentKind.Comment -> buildDefaultTable(node, pageContext, sourceSetRestriction)
+ else -> div(classes = "table") {
+ node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
+ node.children.forEach {
+ buildRow(it, pageContext, sourceSetRestriction, node.style)
+ }
+ }
+ }
+
+ }
+
+ fun FlowContent.buildDefaultTable(
+ node: ContentTable,
+ pageContext: ContentPage,
+ sourceSetRestriction: Set<DokkaSourceSet>?
+ ) {
+ table {
+ thead {
+ node.header.forEach {
+ tr {
+ it.children.forEach {
+ th {
+ it.build(this@table, pageContext, sourceSetRestriction)
+ }
+ }
+ }
+ }
+ }
+ tbody {
+ node.children.forEach {
+ tr {
+ it.children.forEach {
+ td {
+ it.build(this, pageContext, sourceSetRestriction)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ override fun FlowContent.buildHeader(level: Int, node: ContentHeader, content: FlowContent.() -> Unit) {
+ val anchor = node.extra[SimpleAttr.SimpleAttrKey("anchor")]?.extraValue
+ val classes = node.style.joinToString { it.toString() }.toLowerCase()
+ when (level) {
+ 1 -> h1(classes = classes) { withAnchor(anchor, content) }
+ 2 -> h2(classes = classes) { withAnchor(anchor, content) }
+ 3 -> h3(classes = classes) { withAnchor(anchor, content) }
+ 4 -> h4(classes = classes) { withAnchor(anchor, content) }
+ 5 -> h5(classes = classes) { withAnchor(anchor, content) }
+ else -> h6(classes = classes) { withAnchor(anchor, content) }
+ }
+ }
+
+ private fun FlowContent.withAnchor(anchorName: String?, content: FlowContent.() -> Unit) {
+ a {
+ anchorName?.let { attributes["data-name"] = it }
+ }
+ content()
+ }
+
+
+ override fun FlowContent.buildNavigation(page: PageNode) =
+ div(classes = "breadcrumbs") {
+ locationProvider.ancestors(page).asReversed().forEach { node ->
+ text("/")
+ if (node.isNavigable) buildLink(node, page)
+ else text(node.name)
+ }
+ }
+
+ private fun FlowContent.buildLink(to: PageNode, from: PageNode) =
+ buildLink(locationProvider.resolve(to, from)) {
+ text(to.name)
+ }
+
+ private fun FlowContent.buildAnchor(pointingTo: String) {
+ span(classes = "anchor-wrapper") {
+ span(classes = "anchor-icon") {
+ attributes["pointing-to"] = pointingTo
+ unsafe {
+ raw(
+ """
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M21.2496 5.3C20.3496 4.5 19.2496 4 18.0496 4C16.8496 4 15.6496 4.5 14.8496 5.3L10.3496 9.8L11.7496 11.2L16.2496 6.7C17.2496 5.7 18.8496 5.7 19.8496 6.7C20.8496 7.7 20.8496 9.3 19.8496 10.3L15.3496 14.8L16.7496 16.2L21.2496 11.7C22.1496 10.8 22.5496 9.7 22.5496 8.5C22.5496 7.3 22.1496 6.2 21.2496 5.3Z"/>
+ <path d="M8.35 16.7998C7.35 17.7998 5.75 17.7998 4.75 16.7998C3.75 15.7998 3.75 14.1998 4.75 13.1998L9.25 8.6998L7.85 7.2998L3.35 11.7998C1.55 13.5998 1.55 16.3998 3.35 18.1998C4.25 19.0998 5.35 19.4998 6.55 19.4998C7.75 19.4998 8.85 19.0998 9.75 18.1998L14.25 13.6998L12.85 12.2998L8.35 16.7998Z"/>
+ </svg>
+ """.trimIndent()
+ )
+ }
+ }
+ copiedPopup("Link copied to clipboard")
+ }
+ }
+
+ fun FlowContent.buildLink(
+ to: DRI,
+ platforms: List<DokkaSourceSet>,
+ from: PageNode? = null,
+ block: FlowContent.() -> Unit
+ ) = buildLink(locationProvider.resolve(to, platforms.toSet(), from), block)
+
+ override fun buildError(node: ContentNode) {
+ context.logger.error("Unknown ContentNode type: $node")
+ }
+
+ override fun FlowContent.buildNewLine() {
+ br()
+ }
+
+ override fun FlowContent.buildLink(address: String, content: FlowContent.() -> Unit) =
+ a(href = address, block = content)
+
+ override fun FlowContent.buildCodeBlock(
+ code: ContentCodeBlock,
+ pageContext: ContentPage
+ ) {
+ div("sample-container") {
+ code(code.style.joinToString(" ") { it.toString().toLowerCase() }) {
+ attributes["theme"] = "idea"
+ code.children.forEach { buildContentNode(it, pageContext) }
+ }
+ }
+ }
+
+ override fun FlowContent.buildCodeInline(
+ code: ContentCodeInline,
+ pageContext: ContentPage
+ ) {
+ code {
+ code.children.forEach { buildContentNode(it, pageContext) }
+ }
+ }
+
+ private fun getSymbolSignature(page: ContentPage) = page.content.dfs { it.dci.kind == ContentKind.Symbol }
+
+ private fun flattenToText(node: ContentNode): String {
+ fun getContentTextNodes(node: ContentNode, sourceSetRestriction: DokkaSourceSet): List<ContentText> =
+ when (node) {
+ is ContentText -> listOf(node)
+ is ContentComposite -> node.children
+ .filter { sourceSetRestriction in it.sourceSets }
+ .flatMap { getContentTextNodes(it, sourceSetRestriction) }
+ .takeIf { node.dci.kind != ContentKind.Annotations }
+ .orEmpty()
+ else -> emptyList()
+ }
+
+ val sourceSetRestriction =
+ node.sourceSets.find { it.analysisPlatform == Platform.common } ?: node.sourceSets.first()
+ return getContentTextNodes(node, sourceSetRestriction).joinToString("") { it.text }
+ }
+
+ override suspend fun renderPage(page: PageNode) {
+ super.renderPage(page)
+ if (page is ContentPage && page !is ModulePageNode && page !is PackagePageNode) {
+ val signature = getSymbolSignature(page)
+ val textNodes = signature?.let { flattenToText(it) }
+ val documentable = page.documentable
+ if (documentable != null) {
+ listOf(
+ documentable.dri.packageName,
+ documentable.dri.classNames,
+ documentable.dri.callable?.name
+ )
+ .filter { !it.isNullOrEmpty() }
+ .takeIf { it.isNotEmpty() }
+ ?.joinToString(".")
+ ?.let {
+ pageList.put(it, Pair(textNodes ?: page.name, locationProvider.resolve(page)))
+ }
+
+ }
+ }
+ }
+
+ override fun FlowContent.buildText(textNode: ContentText) {
+ when {
+ textNode.hasStyle(TextStyle.Indented) -> consumer.onTagContentEntity(Entities.nbsp)
+ }
+ text(textNode.text)
+ }
+
+ private fun generatePagesList() =
+ pageList.entries
+ .filter { !it.key.isNullOrEmpty() }
+ .groupBy { it.key.substringAfterLast(".") }
+ .entries
+ .mapIndexed { topLevelIndex, entry ->
+ if (entry.value.size > 1) {
+ listOf(
+ "{\'name\': \'${entry.key}\', \'index\': \'$topLevelIndex\', \'disabled\': true, \'searchKey\':\'${entry.key}\' }"
+ ) + entry.value.mapIndexed { index, subentry ->
+ "{\'name\': \'${subentry.value.first}\', \'level\': 1, \'index\': \'$topLevelIndex.$index\', \'description\':\'${subentry.key}\', \'location\':\'${subentry.value.second}\', 'searchKey':'${entry.key}'}"
+ }
+ } else {
+ val subentry = entry.value.single()
+ listOf(
+ "{\'name\': \'${subentry.value.first}\', \'index\': \'$topLevelIndex\', \'description\':\'${subentry.key}\', \'location\':\'${subentry.value.second}\', 'searchKey':'${entry.key}'}"
+ )
+ }
+ }
+ .flatten()
+ .joinToString(prefix = "[", separator = ",\n", postfix = "]")
+
+ override fun render(root: RootPageNode) {
+ super.render(root)
+ runBlocking(Dispatchers.Default) {
+ launch {
+ outputWriter.write("scripts/pages", "var pages = ${generatePagesList()}", ".js")
+ }
+ }
+ }
+
+ private fun PageNode.root(path: String) = locationProvider.resolveRoot(this) + path
+
+ override fun buildPage(page: ContentPage, content: (FlowContent, ContentPage) -> Unit): String =
+ buildHtml(page, page.embeddedResources) {
+ div {
+ id = "content"
+ attributes["pageIds"] = page.dri.first().toString()
+ content(this, page)
+ }
+ }
+
+ private fun resolveLink(link: String, page: PageNode): String = if (URI(link).isAbsolute) link else page.root(link)
+
+ open fun buildHtml(page: PageNode, resources: List<String>, content: FlowContent.() -> Unit) =
+ createHTML().html {
+ head {
+ meta(name = "viewport", content = "width=device-width, initial-scale=1", charset = "UTF-8")
+ title(page.name)
+ resources.forEach {
+ when {
+ it.substringBefore('?').substringAfterLast('.') == "css" -> link(
+ rel = LinkRel.stylesheet,
+ href = resolveLink(it, page)
+ )
+ it.substringBefore('?').substringAfterLast('.') == "js" -> script(
+ type = ScriptType.textJavaScript,
+ src = resolveLink(it, page)
+ ) {
+ async = true
+ }
+ else -> unsafe { +it }
+ }
+ }
+ script { unsafe { +"""var pathToRoot = "${locationProvider.resolveRoot(page)}";""" } }
+ }
+ body {
+ div {
+ id = "container"
+ div {
+ id = "leftColumn"
+ div {
+ id = "logo"
+ }
+ div {
+ id = "sideMenu"
+ }
+ }
+ div {
+ id = "main"
+ div {
+ id = "searchBar"
+ }
+ script(type = ScriptType.textJavaScript, src = page.root("scripts/pages.js")) {}
+ script(type = ScriptType.textJavaScript, src = page.root("scripts/main.js")) {}
+ content()
+ div(classes = "footer") {
+ span("go-to-top-icon") {
+ a(href = "#container") {
+ unsafe {
+ raw(
+ """
+ <svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M11.3337 9.66683H0.666992L6.00033 3.66683L11.3337 9.66683Z" fill="black"/>
+ <path d="M0.666992 0.333496H11.3337V1.66683H0.666992V0.333496Z" fill="black"/>
+ </svg>
+ """.trimIndent()
+ )
+ }
+ }
+ }
+ span { text("© 2020 Copyright") }
+ span("pull-right") {
+ span { text("Sponsored and developed by dokka") }
+ a(href= "https://github.com/Kotlin/dokka") {
+ span(classes = "padded-icon") {
+ unsafe {
+ raw(
+ """
+ <svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M8 0H2.3949L4.84076 2.44586L0 7.28662L0.713376 8L5.55414 3.15924L8 5.6051V0Z" fill="black"/>
+ </svg>
+ """.trimIndent()
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fun List<SimpleAttr>.joinAttr() = joinToString(" ") { it.extraKey + "=" + it.extraValue }
+
+private fun String.stripDiv() = drop(5).dropLast(6) // TODO: Find a way to do it without arbitrary trims
+
+private val PageNode.isNavigable: Boolean
+ get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
+
+fun PropertyContainer<ContentNode>.extraHtmlAttributes() = allOfType<SimpleAttr>()
diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt
new file mode 100644
index 00000000..8fe2a6c8
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt
@@ -0,0 +1,51 @@
+package org.jetbrains.dokka.base.renderers.html
+
+import kotlinx.html.*
+import kotlinx.html.stream.createHTML
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.pages.RendererSpecificPage
+import org.jetbrains.dokka.pages.RenderingStrategy
+
+class NavigationPage(val root: NavigationNode) : RendererSpecificPage {
+ override val name = "navigation"
+
+ override val children = emptyList<PageNode>()
+
+ override fun modified(name: String, children: List<PageNode>) = this
+
+ override val strategy = RenderingStrategy<HtmlRenderer> {
+ createHTML().visit(root, "nav-submenu", this)
+ }
+
+ private fun <R> TagConsumer<R>.visit(node: NavigationNode, navId: String, renderer: HtmlRenderer): R =
+ with(renderer) {
+ div("sideMenuPart") {
+ id = navId
+ attributes["pageId"] = node.dri.toString()
+ div("overview") {
+ buildLink(node.dri, node.sourceSets.toList()) { +node.name }
+ if (node.children.isNotEmpty()) {
+ span("navButton") {
+ onClick = """document.getElementById("$navId").classList.toggle("hidden");"""
+ span("navButtonContent")
+ }
+ }
+ }
+ node.children.withIndex().forEach { (n, p) -> visit(p, "$navId-$n", renderer) }
+ }
+ }
+}
+
+class NavigationNode(
+ val name: String,
+ val dri: DRI,
+ val sourceSets: Set<DokkaSourceSet>,
+ val children: List<NavigationNode>
+)
+
+fun NavigationPage.transform(block: (NavigationNode) -> NavigationNode) = NavigationPage(root.transform(block))
+
+fun NavigationNode.transform(block: (NavigationNode) -> NavigationNode) =
+ run(block).let { NavigationNode(it.name, it.dri, it.sourceSets, it.children.map(block)) }
diff --git a/plugins/base/src/main/kotlin/renderers/html/Tags.kt b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
new file mode 100644
index 00000000..a3951eff
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
@@ -0,0 +1,12 @@
+package org.jetbrains.dokka.base.renderers.html
+
+import kotlinx.html.*
+
+@HtmlTagMarker
+fun FlowOrPhrasingContent.wbr(classes : String? = null, block : WBR.() -> Unit = {}) : Unit = WBR(attributesMapOf("class", classes), consumer).visit(block)
+
+@Suppress("unused")
+open class WBR(initialAttributes : Map<String, String>, override val consumer : TagConsumer<*>) : HTMLTag("wbr", consumer, initialAttributes, null, true, false),
+ HtmlBlockInlineTag {
+
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
new file mode 100644
index 00000000..2f7c8ee1
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
@@ -0,0 +1,112 @@
+package org.jetbrains.dokka.base.renderers.html
+
+import kotlinx.html.h1
+import kotlinx.html.id
+import kotlinx.html.table
+import kotlinx.html.tbody
+import org.jetbrains.dokka.base.renderers.sourceSets
+import org.jetbrains.dokka.model.DEnum
+import org.jetbrains.dokka.model.DEnumEntry
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+
+
+object SearchPageInstaller : PageTransformer {
+ override fun invoke(input: RootPageNode) = input.modified(children = input.children + searchPage)
+
+ private val searchPage = RendererSpecificResourcePage(
+ name = "Search",
+ children = emptyList(),
+ strategy = RenderingStrategy<HtmlRenderer> {
+ buildHtml(it, listOf("styles/style.css", "scripts/pages.js", "scripts/search.js")) {
+ h1 {
+ id = "searchTitle"
+ text("Search results for ")
+ }
+ table {
+ tbody {
+ id = "searchTable"
+ }
+ }
+ }
+ })
+}
+
+object NavigationPageInstaller : PageTransformer {
+ override fun invoke(input: RootPageNode) = input.modified(
+ children = input.children + NavigationPage(
+ input.children.filterIsInstance<ContentPage>().single()
+ .let(NavigationPageInstaller::visit)
+ )
+ )
+
+ private fun visit(page: ContentPage): NavigationNode =
+ NavigationNode(
+ page.name,
+ page.dri.first(),
+ page.sourceSets(),
+ page.navigableChildren()
+ )
+
+ private fun ContentPage.navigableChildren(): List<NavigationNode> {
+ if (this !is ClasslikePageNode) {
+ return children.filterIsInstance<ContentPage>()
+ .map { visit(it) }
+ } else if (documentable is DEnum) {
+ return children.filter { it is ContentPage && it.documentable is DEnumEntry }
+ .map { visit(it as ContentPage) }
+ }
+
+ return emptyList()
+ }
+}
+
+object ResourceInstaller : PageTransformer {
+ override fun invoke(input: RootPageNode) = input.modified(children = input.children + resourcePages)
+
+ private val resourcePages = listOf("styles", "scripts", "images").map {
+ RendererSpecificResourcePage(it, emptyList(), RenderingStrategy.Copy("/dokka/$it"))
+ }
+}
+
+object StyleAndScriptsAppender : PageTransformer {
+ override fun invoke(input: RootPageNode) = input.transformContentPagesTree {
+ it.modified(
+ embeddedResources = it.embeddedResources + listOf(
+ "styles/style.css",
+ "scripts/navigationLoader.js",
+ "scripts/platformContentHandler.js",
+ "scripts/sourceset_dependencies.js",
+ "scripts/clipboard.js",
+ "styles/jetbrains-mono.css"
+ )
+ )
+ }
+}
+
+class SourcesetDependencyAppender(val context: DokkaContext) : PageTransformer {
+ override fun invoke(input: RootPageNode): RootPageNode {
+ val dependenciesMap = context.configuration.sourceSets.map {
+ it.sourceSetID to it.dependentSourceSets
+ }.toMap()
+
+ fun createDependenciesJson(): String = "sourceset_dependencies = '{${
+ dependenciesMap.entries.joinToString(", ") {
+ "\"${it.key}\": [${it.value.joinToString(",") {
+ "\"$it\""
+ }}]"
+ }
+ }}'"
+
+ val deps = RendererSpecificResourcePage(
+ name = "scripts/sourceset_dependencies.js",
+ children = emptyList(),
+ strategy = RenderingStrategy.Write(createDependenciesJson())
+ )
+
+ return input.modified(
+ children = input.children + deps
+ )
+ }
+}
diff --git a/plugins/base/src/main/kotlin/renderers/preprocessors.kt b/plugins/base/src/main/kotlin/renderers/preprocessors.kt
new file mode 100644
index 00000000..bf2a9eb4
--- /dev/null
+++ b/plugins/base/src/main/kotlin/renderers/preprocessors.kt
@@ -0,0 +1,27 @@
+package org.jetbrains.dokka.base.renderers
+
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+
+object RootCreator : PageTransformer {
+ override fun invoke(input: RootPageNode) =
+ RendererSpecificRootPage("", listOf(input), RenderingStrategy.DoNothing)
+}
+
+
+class PackageListCreator(val context: DokkaContext, val format: String, val linkExtension: String) : PageTransformer {
+ override fun invoke(input: RootPageNode) =
+ input.modified(children = input.children.map {
+ it.takeUnless { it is ModulePageNode }
+ ?: it.modified(children = it.children + packageList(input)) // TODO packageList should take module as an input
+ })
+
+
+ private fun packageList(pageNode: RootPageNode) =
+ RendererSpecificResourcePage(
+ "${pageNode.name}/package-list",
+ emptyList(),
+ RenderingStrategy.Write(PackageListService(context).formatPackageList(pageNode, format, linkExtension))
+ )
+}
diff --git a/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt b/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt
new file mode 100644
index 00000000..1b741484
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt
@@ -0,0 +1,9 @@
+package org.jetbrains.dokka.base.resolvers.anchors
+
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.pages.ContentNode
+
+// TODO IMPORTANT: https://github.com/Kotlin/dokka/issues/1054
+object SymbolAnchorHint: ExtraProperty<ContentNode>, ExtraProperty.Key<ContentNode, SymbolAnchorHint> {
+ override val key = this
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..ff9186f7
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt
@@ -0,0 +1,35 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.base.resolvers.local.identifierToFilename
+import org.jetbrains.dokka.links.DRI
+
+
+class DokkaExternalLocationProviderFactory : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
+ object : ExternalLocationProviderFactory {
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ when (param) {
+ "kotlin-website-html", "html" -> DokkaExternalLocationProvider(param, ".html")
+ "markdown" -> DokkaExternalLocationProvider(param, ".md")
+ else -> null
+ }
+ }
+)
+
+class DokkaExternalLocationProvider(override val param: String, val extension: String) : ExternalLocationProvider {
+
+ override fun DRI.toLocation(): String { // TODO: classes without packages?
+
+ val classNamesChecked = classNames ?: return "${packageName ?: ""}/index$extension"
+
+ val classLink = (listOfNotNull(packageName) + classNamesChecked.split('.')).joinToString(
+ "/",
+ transform = ::identifierToFilename
+ )
+
+ val callableChecked = callable ?: return "$classLink/index$extension"
+
+ return "$classLink/${identifierToFilename(
+ callableChecked.name
+ )}$extension"
+ }
+}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..83de9911
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
@@ -0,0 +1,26 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.links.DRI
+import java.util.concurrent.ConcurrentHashMap
+
+
+interface ExternalLocationProvider {
+
+ val param: String
+ fun DRI.toLocation(): String
+}
+
+interface ExternalLocationProviderFactory {
+
+ fun getExternalLocationProvider(param: String): ExternalLocationProvider?
+}
+
+class ExternalLocationProviderFactoryWithCache(val ext: ExternalLocationProviderFactory) : ExternalLocationProviderFactory {
+
+ private val locationProviders = ConcurrentHashMap<String, CacheWrapper>()
+
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ locationProviders.getOrPut(param) { CacheWrapper(ext.getExternalLocationProvider(param)) }.provider
+}
+
+private class CacheWrapper(val provider: ExternalLocationProvider?) \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..c52c9bbb
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt
@@ -0,0 +1,37 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.utilities.htmlEscape
+
+class JavadocExternalLocationProviderFactory : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
+ object : ExternalLocationProviderFactory {
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ when(param) {
+ "javadoc1" -> JavadocExternalLocationProvider(param, "()", ", ") // Covers JDK 1 - 7
+ "javadoc8" -> JavadocExternalLocationProvider(param, "--", "-") // Covers JDK 8 - 9
+ "javadoc10" -> JavadocExternalLocationProvider(param, "()", ",") // Covers JDK 10
+ else -> null
+ }
+ }
+)
+
+class JavadocExternalLocationProvider(override val param: String, val brackets: String, val separator: String) : ExternalLocationProvider {
+
+ override fun DRI.toLocation(): String {
+
+ val packageLink = packageName?.replace(".", "/")
+ if (classNames == null) {
+ return "$packageLink/package-summary.html".htmlEscape()
+ }
+ val classLink = if (packageLink == null) "$classNames.html" else "$packageLink/$classNames.html"
+ val callableChecked = callable ?: return classLink.htmlEscape()
+
+ val callableLink = "$classLink#" +
+ callableChecked.name +
+ "${brackets.first()}" +
+ callableChecked.params.joinToString(separator) +
+ "${brackets.last()}"
+
+ return callableLink.htmlEscape()
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt
new file mode 100644
index 00000000..4204006e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt
@@ -0,0 +1,142 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.query
+import java.net.HttpURLConnection
+import java.net.URL
+import java.net.URLConnection
+import java.util.concurrent.locks.ReentrantReadWriteLock
+import kotlin.concurrent.read
+import kotlin.concurrent.write
+
+abstract class BaseLocationProvider(protected val dokkaContext: DokkaContext) : LocationProvider {
+
+ protected val externalLocationProviderFactories =
+ dokkaContext.plugin<DokkaBase>().query { externalLocationProviderFactory }
+ private val cache: MutableMap<URL, DefaultLocationProvider.LocationInfo> = mutableMapOf()
+ private val lock = ReentrantReadWriteLock()
+
+ protected fun getExternalLocation(
+ dri: DRI,
+ sourceSets: Set<DokkaSourceSet>
+ ): String {
+ val jdkToExternalDocumentationLinks = dokkaContext.configuration.sourceSets
+ .filter { sourceSet ->
+ sourceSets.contains(sourceSet)
+ }
+ .groupBy({ it.jdkVersion }, { it.externalDocumentationLinks })
+ .map { it.key to it.value.flatten().distinct() }.toMap()
+
+ val toResolve: MutableMap<Int, MutableList<DokkaConfiguration.ExternalDocumentationLink>> = mutableMapOf()
+ for ((jdk, links) in jdkToExternalDocumentationLinks) {
+ for (link in links) {
+ val info = lock.read { cache[link.packageListUrl] }
+ if (info == null) {
+ toResolve.getOrPut(jdk) { mutableListOf() }.add(link)
+ } else if (info.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, info)
+ }
+ }
+ }
+ // Not in cache, resolve packageLists
+ for ((jdk, links) in toResolve) {
+ for (link in links) {
+ if (dokkaContext.configuration.offlineMode && link.packageListUrl.protocol.toLowerCase() != "file")
+ continue
+ val locationInfo =
+ loadPackageList(jdk, link.packageListUrl)
+ if (locationInfo.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, locationInfo)
+ }
+ }
+ toResolve.remove(jdk)
+ }
+ return ""
+ }
+
+ private fun getLink(dri: DRI, locationInfo: DefaultLocationProvider.LocationInfo): String =
+ locationInfo.locations[dri.packageName + "." + dri.classNames]
+ ?: // Not sure if it can be here, previously it shadowed only kotlin/dokka related sources, here it shadows both dokka/javadoc, cause I cannot distinguish what LocationProvider has been hypothetically chosen
+ if (locationInfo.externalLocationProvider != null)
+ with(locationInfo.externalLocationProvider) {
+ dri.toLocation()
+ }
+ else
+ throw IllegalStateException("Have not found any convenient ExternalLocationProvider for $dri DRI!")
+
+ private fun loadPackageList(jdk: Int, url: URL): DefaultLocationProvider.LocationInfo = lock.write {
+ val packageListStream = url.doOpenConnectionToReadContent().getInputStream()
+ val (params, packages) =
+ packageListStream
+ .bufferedReader()
+ .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } }
+
+ val paramsMap = params.asSequence()
+ .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) }
+ .groupBy({ (key, _) -> key }, { (_, value) -> value })
+
+ val format = paramsMap["format"]?.singleOrNull() ?: when {
+ jdk < 8 -> "javadoc1" // Covers JDK 1 - 7
+ jdk < 10 -> "javadoc8" // Covers JDK 8 - 9
+ else -> "javadoc10" // Covers JDK 10+
+ }
+
+ val locations = paramsMap["location"].orEmpty()
+ .map { it.split("\u001f", limit = 2) }
+ .map { (key, value) -> key to value }
+ .toMap()
+
+ val externalLocationProvider =
+ externalLocationProviderFactories.asSequence().map { it.getExternalLocationProvider(format) }
+ .filterNotNull().take(1).firstOrNull()
+
+ val info = DefaultLocationProvider.LocationInfo(
+ externalLocationProvider,
+ packages.toSet(),
+ locations
+ )
+ cache[url] = info
+ return info
+ }
+
+ private fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection {
+ val connection = this.openConnection().apply {
+ connectTimeout = timeout
+ readTimeout = timeout
+ }
+
+ when (connection) {
+ is HttpURLConnection -> {
+ return when (connection.responseCode) {
+ in 200..299 -> {
+ connection
+ }
+ HttpURLConnection.HTTP_MOVED_PERM,
+ HttpURLConnection.HTTP_MOVED_TEMP,
+ HttpURLConnection.HTTP_SEE_OTHER -> {
+ if (redirectsAllowed > 0) {
+ val newUrl = connection.getHeaderField("Location")
+ URL(newUrl).doOpenConnectionToReadContent(timeout, redirectsAllowed - 1)
+ } else {
+ throw RuntimeException("Too many redirects")
+ }
+ }
+ else -> {
+ throw RuntimeException("Unhandled http code: ${connection.responseCode}")
+ }
+ }
+ }
+ else -> return connection
+ }
+ }
+
+ companion object {
+ const val DOKKA_PARAM_PREFIX = "\$dokka."
+ }
+
+}
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
new file mode 100644
index 00000000..1df0a700
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
@@ -0,0 +1,217 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
+import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProvider
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.withDescendants
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import java.net.HttpURLConnection
+import java.net.URL
+import java.net.URLConnection
+import java.util.*
+
+private const val PAGE_WITH_CHILDREN_SUFFIX = "index"
+
+open class DefaultLocationProvider(
+ protected val pageGraphRoot: RootPageNode,
+ dokkaContext: DokkaContext
+) : BaseLocationProvider(dokkaContext) {
+ protected open val extension = ".html"
+
+ protected val pagesIndex: Map<DRI, ContentPage> = pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
+ .map { it.dri.map { dri -> dri to it } }.flatten()
+ .groupingBy { it.first }
+ .aggregate { dri, _, (_, page), first ->
+ if (first) page else throw AssertionError("Multiple pages associated with dri: $dri")
+ }
+
+ protected val anchorsIndex = pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
+ .flatMap { page ->
+ page.content.withDescendants()
+ .filter { it.extra[SymbolAnchorHint] != null }
+ .mapNotNull { it.dci.dri.singleOrNull() }
+ .distinct()
+ .map { it to page }
+ }.toMap()
+
+
+ protected val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
+ fun registerPath(page: PageNode, prefix: List<String>) {
+ val newPrefix = prefix + page.pathName
+ put(page, newPrefix)
+ page.children.forEach { registerPath(it, newPrefix) }
+ }
+ put(pageGraphRoot, emptyList())
+ pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
+ }
+
+ override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
+ pathTo(node, context) + if (!skipExtension) extension else ""
+
+ override fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode?): String =
+ pagesIndex[dri]?.let { resolve(it, context) }
+ ?: anchorsIndex[dri]?.let { resolve(it, context) + "#$dri" }
+ // Not found in PageGraph, that means it's an external link
+ ?: getExternalLocation(dri, sourceSets)
+
+ override fun resolveRoot(node: PageNode): String =
+ pathTo(pageGraphRoot, node).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
+
+ override fun ancestors(node: PageNode): List<PageNode> =
+ generateSequence(node) { it.parent() }.toList()
+
+ protected open fun pathTo(node: PageNode, context: PageNode?): String {
+ fun pathFor(page: PageNode) = pathsIndex[page] ?: throw AssertionError(
+ "${page::class.simpleName}(${page.name}) does not belong to current page graph so it is impossible to compute its path"
+ )
+
+ val contextNode =
+ if (context !is ClasslikePageNode && context?.children?.isEmpty() == true && context.parent() != null) context.parent() else context
+ val nodePath = pathFor(node)
+ val contextPath = contextNode?.let { pathFor(it) }.orEmpty()
+
+ val commonPathElements = nodePath.asSequence().zip(contextPath.asSequence())
+ .takeWhile { (a, b) -> a == b }.count()
+
+ return (List(contextPath.size - commonPathElements) { ".." } + nodePath.drop(commonPathElements) +
+ if (node is ClasslikePageNode || node.children.isNotEmpty())
+ listOf(PAGE_WITH_CHILDREN_SUFFIX)
+ else
+ emptyList()
+ ).joinToString("/")
+ }
+
+ private fun PageNode.parent() = pageGraphRoot.parentMap[this]
+
+ private val cache: MutableMap<URL, LocationInfo> = mutableMapOf()
+
+ private fun getLocation(
+ dri: DRI,
+ jdkToExternalDocumentationLinks: Map<Int, List<DokkaConfiguration.ExternalDocumentationLink>>
+ ): String {
+ val toResolve: MutableMap<Int, MutableList<DokkaConfiguration.ExternalDocumentationLink>> = mutableMapOf()
+ for ((jdk, links) in jdkToExternalDocumentationLinks) {
+ for (link in links) {
+ val info = cache[link.packageListUrl]
+ if (info == null) {
+ toResolve.getOrPut(jdk) { mutableListOf() }.add(link)
+ } else if (info.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, info)
+ }
+ }
+ }
+ // Not in cache, resolve packageLists
+ for ((jdk, links) in toResolve) {
+ for (link in links) {
+ if(dokkaContext.configuration.offlineMode && link.packageListUrl.protocol.toLowerCase() != "file")
+ continue
+ val locationInfo =
+ loadPackageList(jdk, link.packageListUrl)
+ if (locationInfo.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, locationInfo)
+ }
+ }
+ toResolve.remove(jdk)
+ }
+ return ""
+ }
+
+ private fun getLink(dri: DRI, locationInfo: LocationInfo): String =
+ locationInfo.locations[dri.packageName + "." + dri.classNames]
+ ?: // Not sure if it can be here, previously it shadowed only kotlin/dokka related sources, here it shadows both dokka/javadoc, cause I cannot distinguish what LocationProvider has been hypothetically chosen
+ if (locationInfo.externalLocationProvider != null)
+ with(locationInfo.externalLocationProvider) {
+ dri.toLocation()
+ }
+ else
+ throw IllegalStateException("Have not found any convenient ExternalLocationProvider for $dri DRI!")
+
+ private fun loadPackageList(jdk: Int, url: URL): LocationInfo {
+ val packageListStream = url.doOpenConnectionToReadContent().getInputStream()
+ val (params, packages) =
+ packageListStream
+ .bufferedReader()
+ .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } }
+
+ val paramsMap = params.asSequence()
+ .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) }
+ .groupBy({ (key, _) -> key }, { (_, value) -> value })
+
+ val format = paramsMap["format"]?.singleOrNull() ?: when {
+ jdk < 8 -> "javadoc1" // Covers JDK 1 - 7
+ jdk < 10 -> "javadoc8" // Covers JDK 8 - 9
+ else -> "javadoc10" // Covers JDK 10+
+ }
+
+ val locations = paramsMap["location"].orEmpty()
+ .map { it.split("\u001f", limit = 2) }
+ .map { (key, value) -> key to value }
+ .toMap()
+
+ val externalLocationProvider =
+ externalLocationProviderFactories.asSequence().map { it.getExternalLocationProvider(format) }
+ .filterNotNull().take(1).firstOrNull()
+
+ val info = LocationInfo(
+ externalLocationProvider,
+ packages.toSet(),
+ locations
+ )
+ cache[url] = info
+ return info
+ }
+
+ private fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection {
+ val connection = this.openConnection().apply {
+ connectTimeout = timeout
+ readTimeout = timeout
+ }
+
+ when (connection) {
+ is HttpURLConnection -> {
+ return when (connection.responseCode) {
+ in 200..299 -> {
+ connection
+ }
+ HttpURLConnection.HTTP_MOVED_PERM,
+ HttpURLConnection.HTTP_MOVED_TEMP,
+ HttpURLConnection.HTTP_SEE_OTHER -> {
+ if (redirectsAllowed > 0) {
+ val newUrl = connection.getHeaderField("Location")
+ URL(newUrl).doOpenConnectionToReadContent(timeout, redirectsAllowed - 1)
+ } else {
+ throw RuntimeException("Too many redirects")
+ }
+ }
+ else -> {
+ throw RuntimeException("Unhandled http code: ${connection.responseCode}")
+ }
+ }
+ }
+ else -> return connection
+ }
+ }
+
+ data class LocationInfo(
+ val externalLocationProvider: ExternalLocationProvider?,
+ val packages: Set<String>,
+ val locations: Map<String, String>
+ )
+}
+
+private val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out")
+
+internal fun identifierToFilename(name: String): String {
+ if (name.isEmpty()) return "--root--"
+ val escaped = name.replace("<|>".toRegex(), "-")
+ val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }
+ return if (lowercase in reservedFilenames) "--$lowercase--" else lowercase
+}
+
+private val PageNode.pathName: String
+ get() = if (this is PackagePageNode) name else identifierToFilename(
+ name
+ )
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt
new file mode 100644
index 00000000..442d2e6d
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt
@@ -0,0 +1,23 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.pages.MultimoduleRootPageNode
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+import java.util.*
+import java.util.concurrent.ConcurrentHashMap
+
+class DefaultLocationProviderFactory(private val context: DokkaContext) : LocationProviderFactory {
+
+ private val cache = ConcurrentHashMap<CacheWrapper, LocationProvider>()
+
+ override fun getLocationProvider(pageNode: RootPageNode) = cache.computeIfAbsent(CacheWrapper(pageNode)) {
+ if (pageNode.children.first() is MultimoduleRootPageNode) MultimoduleLocationProvider(pageNode, context)
+ else DefaultLocationProvider(pageNode, context)
+ }
+}
+
+private class CacheWrapper(val pageNode: RootPageNode) {
+ override fun equals(other: Any?) = other is CacheWrapper && other.pageNode == this.pageNode
+
+ override fun hashCode() = System.identityHashCode(pageNode)
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
new file mode 100644
index 00000000..745636d0
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
@@ -0,0 +1,18 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.pages.RootPageNode
+
+interface LocationProvider {
+ fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode? = null): String
+ fun resolve(node: PageNode, context: PageNode? = null, skipExtension: Boolean = false): String
+ fun resolveRoot(node: PageNode): String
+ fun ancestors(node: PageNode): List<PageNode>
+}
+
+interface LocationProviderFactory {
+ fun getLocationProvider(pageNode: RootPageNode): LocationProvider
+}
+
diff --git a/plugins/base/src/main/kotlin/resolvers/local/MultimoduleLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/MultimoduleLocationProvider.kt
new file mode 100644
index 00000000..54aded35
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/MultimoduleLocationProvider.kt
@@ -0,0 +1,32 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+
+class MultimoduleLocationProvider(private val root: RootPageNode, context: DokkaContext) : LocationProvider {
+
+ private val defaultLocationProvider = DefaultLocationProvider(root, context)
+
+ val paths = context.configuration.modules.map {
+ it.name to it.path
+ }.toMap()
+
+ override fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode?): String =
+ dri.takeIf { it.packageName == MULTIMODULE_PACKAGE_PLACEHOLDER }?.classNames?.let { paths[it] }?.let {
+ "$it/${identifierToFilename(dri.classNames.orEmpty())}/index.html"
+ } ?: defaultLocationProvider.resolve(dri, sourceSets, context)
+
+ override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
+ defaultLocationProvider.resolve(node, context, skipExtension)
+
+ override fun resolveRoot(node: PageNode): String = defaultLocationProvider.resolveRoot(node)
+
+ override fun ancestors(node: PageNode): List<PageNode> = listOf(root)
+
+ companion object {
+ const val MULTIMODULE_PACKAGE_PLACEHOLDER = ".ext"
+ }
+}
diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
new file mode 100644
index 00000000..689f6db5
--- /dev/null
+++ b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
@@ -0,0 +1,141 @@
+package org.jetbrains.dokka.base.signatures
+
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+
+interface JvmSignatureUtils {
+
+ fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Documentable)
+
+ fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Documentable)
+
+ fun <T : Documentable> WithExtraProperties<T>.modifiers(): SourceSetDependent<Set<ExtraModifiers>>
+
+ fun Collection<ExtraModifiers>.toSignatureString(): String =
+ joinToString("") { it.name.toLowerCase() + " " }
+
+ fun <T : Documentable> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
+ extra[Annotations]?.content ?: emptyMap()
+
+ private fun PageContentBuilder.DocumentableContentBuilder.annotations(
+ d: Documentable,
+ ignored: Set<Annotations.Annotation>,
+ styles: Set<Style>,
+ operation: PageContentBuilder.DocumentableContentBuilder.(Annotations.Annotation) -> Unit
+ ): Unit = when (d) {
+ is DFunction -> d.annotations()
+ is DProperty -> d.annotations()
+ is DClass -> d.annotations()
+ is DInterface -> d.annotations()
+ is DObject -> d.annotations()
+ is DEnum -> d.annotations()
+ is DAnnotation -> d.annotations()
+ is DTypeParameter -> d.annotations()
+ is DEnumEntry -> d.annotations()
+ is DTypeAlias -> d.annotations()
+ is DParameter -> d.annotations()
+ else -> null
+ }?.let {
+ it.entries.forEach {
+ it.value.filter { it !in ignored && it.mustBeDocumented }.takeIf { it.isNotEmpty() }?.let { annotations ->
+ group(sourceSets = setOf(it.key), styles = styles, kind = ContentKind.Annotations) {
+ annotations.forEach {
+ operation(it)
+ }
+ }
+ }
+ }
+ } ?: Unit
+
+ fun PageContentBuilder.DocumentableContentBuilder.toSignatureString(
+ a: Annotations.Annotation,
+ renderAtStrategy: AtStrategy,
+ listBrackets: Pair<Char, Char>,
+ classExtension: String
+ ) {
+
+ when (renderAtStrategy) {
+ is All, is OnlyOnce -> text("@")
+ is Never -> Unit
+ }
+ link(a.dri.classNames!!, a.dri)
+ text("(")
+ a.params.entries.forEachIndexed { i, it ->
+ group(styles = setOf(TextStyle.BreakableAfter)) {
+ text(it.key + " = ")
+ when (renderAtStrategy) {
+ is All -> All
+ is Never, is OnlyOnce -> Never
+ }.let { strategy ->
+ valueToSignature(it.value, strategy, listBrackets, classExtension)
+ }
+ if (i != a.params.entries.size - 1) text(", ")
+ }
+ }
+ text(")")
+ }
+
+ private fun PageContentBuilder.DocumentableContentBuilder.valueToSignature(
+ a: AnnotationParameterValue,
+ renderAtStrategy: AtStrategy,
+ listBrackets: Pair<Char, Char>,
+ classExtension: String
+ ): Unit = when (a) {
+ is AnnotationValue -> toSignatureString(a.annotation, renderAtStrategy, listBrackets, classExtension)
+ is ArrayValue -> {
+ text(listBrackets.first.toString())
+ a.value.forEachIndexed { i, it ->
+ group(styles = setOf(TextStyle.BreakableAfter)) {
+ valueToSignature(it, renderAtStrategy, listBrackets, classExtension)
+ if (i != a.value.size - 1) text(", ")
+ }
+ }
+ text(listBrackets.second.toString())
+ }
+ is EnumValue -> link(a.enumName, a.enumDri)
+ is ClassValue -> link(a.className + classExtension, a.classDRI)
+ is StringValue -> group(styles = setOf(TextStyle.Breakable)) { text(a.value) }
+ }
+
+ fun PageContentBuilder.DocumentableContentBuilder.annotationsBlockWithIgnored(
+ d: Documentable,
+ ignored: Set<Annotations.Annotation>,
+ renderAtStrategy: AtStrategy,
+ listBrackets: Pair<Char, Char>,
+ classExtension: String
+ ) {
+ annotations(d, ignored, setOf(TextStyle.Block)) {
+ group {
+ toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
+ }
+ }
+ }
+
+ fun PageContentBuilder.DocumentableContentBuilder.annotationsInlineWithIgnored(
+ d: Documentable,
+ ignored: Set<Annotations.Annotation>,
+ renderAtStrategy: AtStrategy,
+ listBrackets: Pair<Char, Char>,
+ classExtension: String
+ ) {
+ annotations(d, ignored, setOf(TextStyle.Span)) {
+ toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
+ text(Typography.nbsp.toString())
+ }
+ }
+
+ fun <T : Documentable> WithExtraProperties<T>.stylesIfDeprecated(sourceSetData: DokkaSourceSet): Set<TextStyle> =
+ if (extra[Annotations]?.content?.get(sourceSetData)?.any {
+ it.dri == DRI("kotlin", "Deprecated")
+ || it.dri == DRI("java.lang", "Deprecated")
+ } == true) setOf(TextStyle.Strikethrough) else emptySet()
+}
+
+sealed class AtStrategy
+object All : AtStrategy()
+object OnlyOnce : AtStrategy()
+object Never : AtStrategy()
diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
new file mode 100644
index 00000000..37e0ea83
--- /dev/null
+++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
@@ -0,0 +1,382 @@
+package org.jetbrains.dokka.base.signatures
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.dri
+import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.driOrNull
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.*
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.Nullable
+import org.jetbrains.dokka.model.TypeConstructor
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.pages.ContentKind
+import org.jetbrains.dokka.pages.ContentNode
+import org.jetbrains.dokka.pages.TextStyle
+import org.jetbrains.dokka.utilities.DokkaLogger
+import kotlin.text.Typography.nbsp
+
+class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider,
+ JvmSignatureUtils by KotlinSignatureUtils {
+ private val contentBuilder = PageContentBuilder(ctcc, this, logger)
+
+ private val ignoredVisibilities = setOf(JavaVisibility.Public, KotlinVisibility.Public)
+ private val ignoredModifiers = setOf(JavaModifier.Final, KotlinModifier.Final)
+ private val ignoredExtraModifiers = setOf(
+ ExtraModifiers.KotlinOnlyModifiers.TailRec,
+ ExtraModifiers.KotlinOnlyModifiers.External
+ )
+ private val platformSpecificModifiers: Map<ExtraModifiers, Set<Platform>> = mapOf(
+ ExtraModifiers.KotlinOnlyModifiers.External to setOf(Platform.js)
+ )
+
+ override fun signature(documentable: Documentable): List<ContentNode> = when (documentable) {
+ is DFunction -> functionSignature(documentable)
+ is DProperty -> propertySignature(documentable)
+ is DClasslike -> classlikeSignature(documentable)
+ is DTypeParameter -> signature(documentable)
+ is DEnumEntry -> signature(documentable)
+ is DTypeAlias -> signature(documentable)
+ else -> throw NotImplementedError(
+ "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}"
+ )
+ }
+
+ private fun <T> PageContentBuilder.DocumentableContentBuilder.processExtraModifiers(t: T)
+ where T : Documentable, T : WithExtraProperties<T> {
+ sourceSetDependentText(
+ t.modifiers()
+ .mapValues { entry ->
+ entry.value.filter {
+ it !in ignoredExtraModifiers || entry.key.analysisPlatform in (platformSpecificModifiers[it]
+ ?: emptySet())
+ }
+ }
+ ) {
+ it.toSignatureString()
+ }
+ }
+
+ private fun signature(e: DEnumEntry): List<ContentNode> =
+ e.sourceSets.map {
+ contentBuilder.contentFor(
+ e,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace, TextStyle.Block) + e.stylesIfDeprecated(it),
+ sourceSets = setOf(it)
+ ) {
+ group(styles = setOf(TextStyle.Block)) {
+ annotationsBlock(e)
+ link(e.name, e.dri, styles = emptySet())
+ e.extra[ConstructorValues]?.let { constructorValues ->
+ constructorValues.values[it]
+ text(constructorValues.values[it]?.joinToString(prefix = "(", postfix = ")") ?: "")
+ }
+ }
+ }
+ }
+
+ private fun actualTypealiasedSignature(c: DClasslike, sourceSet: DokkaSourceSet, aliasedType: Bound) =
+ contentBuilder.contentFor(
+ c,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace) + ((c as? WithExtraProperties<out Documentable>)?.stylesIfDeprecated(sourceSet)
+ ?: emptySet()),
+ sourceSets = setOf(sourceSet)
+ ) {
+ text("actual typealias ")
+ link(c.name.orEmpty(), c.dri)
+ text(" = ")
+ signatureForProjection(aliasedType)
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private fun <T : DClasslike> classlikeSignature(c: T): List<ContentNode> =
+ c.sourceSets.map { sourceSetData ->
+ (c as? WithExtraProperties<out DClasslike>)?.extra?.get(ActualTypealias)?.underlyingType?.get(sourceSetData)
+ ?.let {
+ actualTypealiasedSignature(c, sourceSetData, it)
+ } ?: regularSignature(c, sourceSetData)
+ }
+
+
+ private fun regularSignature(c: DClasslike, sourceSet: DokkaSourceSet) =
+ contentBuilder.contentFor(
+ c,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace) + ((c as? WithExtraProperties<out Documentable>)?.stylesIfDeprecated(sourceSet)
+ ?: emptySet()),
+ sourceSets = setOf(sourceSet)
+ ) {
+ annotationsBlock(c)
+ text(c.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "")
+ if (c is DClass) {
+ text(
+ if (c.modifier[sourceSet] !in ignoredModifiers)
+ when {
+ c.extra[AdditionalModifiers]?.content?.contains(ExtraModifiers.KotlinOnlyModifiers.Data) == true -> ""
+ c.modifier[sourceSet] is JavaModifier.Empty -> "${KotlinModifier.Open.name} "
+ else -> c.modifier[sourceSet]?.name?.let { "$it " } ?: ""
+ }
+ else
+ ""
+ )
+ }
+ if (c is DInterface) {
+ c.extra[AdditionalModifiers]?.content?.let { additionalModifiers ->
+ sourceSetDependentText(additionalModifiers, setOf(sourceSet)) { extraModifiers ->
+ if (ExtraModifiers.KotlinOnlyModifiers.Fun in extraModifiers) "fun "
+ else ""
+ }
+ }
+ }
+ when (c) {
+ is DClass -> {
+ processExtraModifiers(c)
+ text("class ")
+ }
+ is DInterface -> {
+ processExtraModifiers(c)
+ text("interface ")
+ }
+ is DEnum -> {
+ processExtraModifiers(c)
+ text("enum ")
+ }
+ is DObject -> {
+ processExtraModifiers(c)
+ text("object ")
+ }
+ is DAnnotation -> {
+ processExtraModifiers(c)
+ text("annotation class ")
+ }
+ }
+ link(c.name!!, c.dri)
+ if (c is WithGenerics) {
+ list(c.generics, prefix = "<", suffix = "> ") {
+ +buildSignature(it)
+ }
+ }
+ if (c is WithConstructors) {
+ val pConstructor = c.constructors.singleOrNull { it.extra[PrimaryConstructorExtra] != null }
+ if (pConstructor?.sourceSets?.contains(sourceSet) == true) {
+ if (pConstructor.annotations().values.any { it.isNotEmpty() }) {
+ text(nbsp.toString())
+ annotationsInline(pConstructor)
+ text("constructor")
+ }
+ list(
+ pConstructor.parameters,
+ "(",
+ ")",
+ ",",
+ pConstructor.sourceSets.toSet()
+ ) {
+ annotationsInline(it)
+ text(it.name ?: "", styles = mainStyles.plus(TextStyle.Bold))
+ text(": ")
+ signatureForProjection(it.type)
+ }
+ }
+ }
+ if (c is WithSupertypes) {
+ c.supertypes.filter { it.key == sourceSet }.map { (s, dris) ->
+ list(dris, prefix = " : ", sourceSets = setOf(s)) {
+ link(it.dri.sureClassNames, it.dri, sourceSets = setOf(s))
+ }
+ }
+ }
+ }
+
+ private fun propertySignature(p: DProperty) =
+ p.sourceSets.map {
+ contentBuilder.contentFor(
+ p,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace) + p.stylesIfDeprecated(it),
+ sourceSets = setOf(it)
+ ) {
+ annotationsBlock(p)
+ text(p.visibility[it].takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "")
+ text(
+ p.modifier[it].takeIf { it !in ignoredModifiers }?.let {
+ if (it is JavaModifier.Empty) KotlinModifier.Open else it
+ }?.name?.let { "$it " } ?: ""
+ )
+ text(p.modifiers()[it]?.toSignatureString() ?: "")
+ p.setter?.let { text("var ") } ?: text("val ")
+ list(p.generics, prefix = "<", suffix = "> ") {
+ +buildSignature(it)
+ }
+ p.receiver?.also {
+ signatureForProjection(it.type)
+ text(".")
+ }
+ link(p.name, p.dri)
+ text(": ")
+ signatureForProjection(p.type)
+ }
+ }
+
+ private fun functionSignature(f: DFunction) =
+ f.sourceSets.map {
+ contentBuilder.contentFor(
+ f,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace) + f.stylesIfDeprecated(it),
+ sourceSets = setOf(it)
+ ) {
+ annotationsBlock(f)
+ text(f.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "")
+ text(f.modifier[it]?.takeIf { it !in ignoredModifiers }?.let {
+ if (it is JavaModifier.Empty) KotlinModifier.Open else it
+ }?.name?.let { "$it " } ?: ""
+ )
+ text(f.modifiers()[it]?.toSignatureString() ?: "")
+ text("fun ")
+ list(f.generics, prefix = "<", suffix = "> ") {
+ +buildSignature(it)
+ }
+ f.receiver?.also {
+ signatureForProjection(it.type)
+ text(".")
+ }
+ link(f.name, f.dri)
+ text("(")
+ list(f.parameters) {
+ annotationsInline(it)
+ processExtraModifiers(it)
+ text(it.name!!)
+ text(": ")
+ signatureForProjection(it.type)
+ }
+ text(")")
+ if (f.documentReturnType()) {
+ text(": ")
+ signatureForProjection(f.type)
+ }
+ }
+ }
+
+ private fun DFunction.documentReturnType() = when {
+ this.isConstructor -> false
+ this.type is TypeConstructor && (this.type as TypeConstructor).dri == DriOfUnit -> false
+ this.type is Void -> false
+ else -> true
+ }
+
+ private fun signature(t: DTypeAlias) =
+ t.sourceSets.map {
+ contentBuilder.contentFor(t, styles = t.stylesIfDeprecated(it), sourceSets = setOf(it)) {
+ t.underlyingType.entries.groupBy({ it.value }, { it.key }).map { (type, platforms) ->
+ +contentBuilder.contentFor(
+ t,
+ ContentKind.Symbol,
+ setOf(TextStyle.Monospace),
+ sourceSets = platforms.toSet()
+ ) {
+ text(t.visibility[it]?.takeIf { it !in ignoredVisibilities }?.name?.let { "$it " } ?: "")
+ processExtraModifiers(t)
+ text("typealias ")
+ signatureForProjection(t.type)
+ text(" = ")
+ signatureForTypealiasTarget(t, type)
+ }
+ }
+ }
+ }
+
+ private fun signature(t: DTypeParameter) =
+ t.sourceSets.map {
+ contentBuilder.contentFor(t, styles = t.stylesIfDeprecated(it), sourceSets = setOf(it)) {
+ link(t.name, t.dri.withTargetToDeclaration())
+ list(t.bounds, prefix = " : ") {
+ signatureForProjection(it)
+ }
+ }
+ }
+
+ private fun PageContentBuilder.DocumentableContentBuilder.signatureForTypealiasTarget(
+ typeAlias: DTypeAlias, bound: Bound
+ ) {
+ signatureForProjection(
+ p = bound,
+ showFullyQualifiedName =
+ bound.driOrNull?.packageName != typeAlias.dri.packageName &&
+ bound.driOrNull?.packageName != "kotlin"
+ )
+ }
+
+ private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(
+ p: Projection, showFullyQualifiedName: Boolean = false
+ ): Unit =
+ when (p) {
+ is OtherParameter -> link(p.name, p.declarationDRI)
+
+ is TypeConstructor -> if (p.function)
+ +funType(mainDRI.single(), mainSourcesetData, p)
+ else
+ group(styles = emptySet()) {
+ val linkText = if (showFullyQualifiedName && p.dri.packageName != null) {
+ "${p.dri.packageName}.${p.dri.classNames.orEmpty()}"
+ } else p.dri.classNames.orEmpty()
+
+ link(linkText, p.dri)
+ list(p.projections, prefix = "<", suffix = ">") {
+ signatureForProjection(it, showFullyQualifiedName)
+ }
+ }
+
+ is Variance -> group(styles = emptySet()) {
+ text(p.kind.toString() + " ")
+ signatureForProjection(p.inner, showFullyQualifiedName)
+ }
+
+ is Star -> text("*")
+
+ is Nullable -> group(styles = emptySet()) {
+ signatureForProjection(p.inner, showFullyQualifiedName)
+ text("?")
+ }
+
+ is JavaObject -> link("Any", DriOfAny)
+ is Void -> link("Unit", DriOfUnit)
+ is PrimitiveJavaType -> signatureForProjection(p.translateToKotlin(), showFullyQualifiedName)
+ is Dynamic -> text("dynamic")
+ is UnresolvedBound -> text(p.name)
+ }
+
+ private fun funType(dri: DRI, sourceSets: Set<DokkaSourceSet>, type: TypeConstructor) =
+ contentBuilder.contentFor(dri, sourceSets, ContentKind.Main) {
+ if (type.extension) {
+ signatureForProjection(type.projections.first())
+ text(".")
+ }
+
+ val args = if (type.extension)
+ type.projections.drop(1)
+ else
+ type.projections
+
+ text("(")
+ args.subList(0, args.size - 1).forEachIndexed { i, arg ->
+ signatureForProjection(arg)
+ if (i < args.size - 2) text(", ")
+ }
+ text(") -> ")
+ signatureForProjection(args.last())
+ }
+}
+
+private fun PrimitiveJavaType.translateToKotlin() = TypeConstructor(
+ dri = dri,
+ projections = emptyList()
+)
+
+val TypeConstructor.function
+ get() = modifier == FunctionModifiers.FUNCTION || modifier == FunctionModifiers.EXTENSION
+
+val TypeConstructor.extension
+ get() = modifier == FunctionModifiers.EXTENSION
diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt
new file mode 100644
index 00000000..0a10875a
--- /dev/null
+++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt
@@ -0,0 +1,48 @@
+package org.jetbrains.dokka.base.signatures
+
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.DriOfAny
+import org.jetbrains.dokka.links.DriOfUnit
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+
+object KotlinSignatureUtils : JvmSignatureUtils {
+
+ private val strategy = OnlyOnce
+ private val listBrackets = Pair('[', ']')
+ private val classExtension = "::class"
+ private val ignoredAnnotations = setOf(
+ Annotations.Annotation(DRI("kotlin", "SinceKotlin"), emptyMap()),
+ Annotations.Annotation(DRI("kotlin", "Deprecated"), emptyMap())
+ )
+
+
+ override fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Documentable) =
+ annotationsBlockWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)
+
+ override fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Documentable) =
+ annotationsInlineWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)
+
+ override fun <T : Documentable> WithExtraProperties<T>.modifiers() =
+ extra[AdditionalModifiers]?.content?.entries?.map {
+ it.key to it.value.filterIsInstance<ExtraModifiers.KotlinOnlyModifiers>().toSet()
+ }?.toMap() ?: emptyMap()
+
+
+ val PrimitiveJavaType.dri: DRI get() = DRI("kotlin", name.capitalize())
+
+ val Bound.driOrNull: DRI?
+ get() {
+ return when (this) {
+ is OtherParameter -> this.declarationDRI
+ is TypeConstructor -> this.dri
+ is Nullable -> this.inner.driOrNull
+ is PrimitiveJavaType -> this.dri
+ is Void -> DriOfUnit
+ is JavaObject -> DriOfAny
+ is Dynamic -> null
+ is UnresolvedBound -> null
+ }
+ }
+}
diff --git a/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt
new file mode 100644
index 00000000..e1933fb8
--- /dev/null
+++ b/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt
@@ -0,0 +1,8 @@
+package org.jetbrains.dokka.base.signatures
+
+import org.jetbrains.dokka.model.Documentable
+import org.jetbrains.dokka.pages.ContentNode
+
+interface SignatureProvider {
+ fun signature(documentable: Documentable): List<ContentNode>
+}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt b/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt
new file mode 100644
index 00000000..1b65fc22
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt
@@ -0,0 +1,84 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+
+class ActualTypealiasAdder : DocumentableTransformer {
+
+ override fun invoke(modules: DModule, context: DokkaContext) = modules.generateTypealiasesMap().let { aliases ->
+ modules.copy(packages = modules.packages.map { it.copy(classlikes = addActualTypeAliasToClasslikes(it.classlikes, aliases)) })
+ }
+
+ private fun DModule.generateTypealiasesMap(): Map<DRI, DTypeAlias> =
+ packages.flatMap { pkg ->
+ pkg.typealiases.map { typeAlias ->
+ typeAlias.dri to typeAlias
+ }
+ }.toMap()
+
+
+ private fun addActualTypeAliasToClasslikes(
+ elements: Iterable<DClasslike>,
+ typealiases: Map<DRI, DTypeAlias>
+ ): List<DClasslike> = elements.flatMap {
+ when (it) {
+ is DClass -> addActualTypeAlias(
+ it.copy(
+ classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
+ ).let(::listOf),
+ typealiases
+ )
+ is DEnum -> addActualTypeAlias(
+ it.copy(
+ classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
+ ).let(::listOf),
+ typealiases
+ )
+ is DInterface -> addActualTypeAlias(
+ it.copy(
+ classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
+ ).let(::listOf),
+ typealiases
+ )
+ is DObject -> addActualTypeAlias(
+ it.copy(
+ classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
+ ).let(::listOf),
+ typealiases
+ )
+ is DAnnotation -> addActualTypeAlias(
+ it.copy(
+ classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
+ ).let(::listOf),
+ typealiases
+ )
+ else -> throw IllegalStateException("${it::class.qualifiedName} ${it.name} cannot have extra added")
+ }
+ }
+
+ private fun <T> addActualTypeAlias(
+ elements: Iterable<T>,
+ typealiases: Map<DRI, DTypeAlias>
+ ): List<T> where T : DClasslike, T : WithExtraProperties<T>, T : WithExpectActual =
+ elements.map { element ->
+ if (element.expectPresentInSet != null) {
+ typealiases[element.dri]?.let { ta ->
+ element.withNewExtras(element.extra + ActualTypealias(ta.underlyingType)).let {
+ when(it) {
+ is DClass -> it.copy(sourceSets = element.sourceSets + ta.sourceSets)
+ is DEnum -> it.copy(sourceSets = element.sourceSets + ta.sourceSets)
+ is DInterface -> it.copy(sourceSets = element.sourceSets + ta.sourceSets)
+ is DObject -> it.copy(sourceSets = element.sourceSets + ta.sourceSets)
+ is DAnnotation -> it.copy(sourceSets = element.sourceSets + ta.sourceSets)
+ else -> throw IllegalStateException("${it::class.qualifiedName} ${it.name} cannot have copy its sourceSets")
+ }
+ } as T
+ } ?: element
+ } else {
+ element
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
new file mode 100644
index 00000000..c8e4f565
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
@@ -0,0 +1,200 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.mergeExtras
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableMerger
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+
+internal object DefaultDocumentableMerger : DocumentableMerger {
+
+ override fun invoke(modules: Collection<DModule>, context: DokkaContext): DModule {
+
+ val projectName =
+ modules.fold(modules.first().name) { acc, module -> acc.commonPrefixWith(module.name) }
+ .takeIf { it.isNotEmpty() }
+ ?: "project"
+
+ return modules.reduce { left, right ->
+ val list = listOf(left, right)
+ DModule(
+ name = projectName,
+ packages = merge(
+ list.flatMap { it.packages },
+ DPackage::mergeWith
+ ),
+ documentation = list.map { it.documentation }.flatMap { it.entries }.associate { (k,v) -> k to v },
+ expectPresentInSet = list.firstNotNullResult { it.expectPresentInSet },
+ sourceSets = list.flatMap { it.sourceSets }.toSet()
+ ).mergeExtras(left, right)
+ }
+ }
+}
+
+private fun <T : Documentable> merge(elements: List<T>, reducer: (T, T) -> T): List<T> =
+ elements.groupingBy { it.dri }
+ .reduce { _, left, right -> reducer(left, right) }
+ .values.toList()
+
+private fun <T> mergeExpectActual(
+ elements: List<T>,
+ reducer: (T, T) -> T
+): List<T> where T : Documentable, T : WithExpectActual {
+
+ fun analyzeExpectActual(sameDriElements: List<T>) = sameDriElements.reduce(reducer)
+
+ return elements.groupBy { it.dri }.values.map(::analyzeExpectActual)
+}
+
+fun DPackage.mergeWith(other: DPackage): DPackage = copy(
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ typealiases = merge(typealiases + other.typealiases, DTypeAlias::mergeWith),
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DFunction.mergeWith(other: DFunction): DFunction = copy(
+ parameters = merge(this.parameters + other.parameters, DParameter::mergeWith),
+ receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ modifier = modifier + other.modifier,
+ sourceSets = sourceSets + other.sourceSets,
+ generics = merge(generics + other.generics, DTypeParameter::mergeWith)
+).mergeExtras(this, other)
+
+fun DProperty.mergeWith(other: DProperty): DProperty = copy(
+ receiver = receiver?.let { r -> other.receiver?.let { r.mergeWith(it) } ?: r } ?: other.receiver,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ modifier = modifier + other.modifier,
+ sourceSets = sourceSets + other.sourceSets,
+ getter = getter?.let { g -> other.getter?.let { g.mergeWith(it) } ?: g } ?: other.getter,
+ setter = setter?.let { s -> other.setter?.let { s.mergeWith(it) } ?: s } ?: other.setter,
+ generics = merge(generics + other.generics, DTypeParameter::mergeWith)
+).mergeExtras(this, other)
+
+fun DClasslike.mergeWith(other: DClasslike): DClasslike = when {
+ this is DClass && other is DClass -> mergeWith(other)
+ this is DEnum && other is DEnum -> mergeWith(other)
+ this is DInterface && other is DInterface -> mergeWith(other)
+ this is DObject && other is DObject -> mergeWith(other)
+ this is DAnnotation && other is DAnnotation -> mergeWith(other)
+ else -> throw IllegalStateException("${this::class.qualifiedName} ${this.name} cannot be mergesd with ${other::class.qualifiedName} ${other.name}")
+}
+
+fun DClass.mergeWith(other: DClass): DClass = copy(
+ constructors = mergeExpectActual(
+ constructors + other.constructors,
+ DFunction::mergeWith
+ ),
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ generics = merge(generics + other.generics, DTypeParameter::mergeWith),
+ modifier = modifier + other.modifier,
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DEnum.mergeWith(other: DEnum): DEnum = copy(
+ entries = merge(entries + other.entries, DEnumEntry::mergeWith),
+ constructors = mergeExpectActual(
+ constructors + other.constructors,
+ DFunction::mergeWith
+ ),
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DEnumEntry.mergeWith(other: DEnumEntry): DEnumEntry = copy(
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DObject.mergeWith(other: DObject): DObject = copy(
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DInterface.mergeWith(other: DInterface): DInterface = copy(
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ generics = merge(generics + other.generics, DTypeParameter::mergeWith),
+ supertypes = supertypes + other.supertypes,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DAnnotation.mergeWith(other: DAnnotation): DAnnotation = copy(
+ constructors = mergeExpectActual(
+ constructors + other.constructors,
+ DFunction::mergeWith
+ ),
+ functions = mergeExpectActual(functions + other.functions, DFunction::mergeWith),
+ properties = mergeExpectActual(properties + other.properties, DProperty::mergeWith),
+ classlikes = mergeExpectActual(classlikes + other.classlikes, DClasslike::mergeWith),
+ companion = companion?.let { c -> other.companion?.let { c.mergeWith(it) } ?: c } ?: other.companion,
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sources = sources+ other.sources,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets,
+ generics = merge(generics + other.generics, DTypeParameter::mergeWith)
+).mergeExtras(this, other)
+
+fun DParameter.mergeWith(other: DParameter): DParameter = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DTypeParameter.mergeWith(other: DTypeParameter): DTypeParameter = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other)
+
+fun DTypeAlias.mergeWith(other: DTypeAlias): DTypeAlias = copy(
+ documentation = documentation + other.documentation,
+ expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet,
+ underlyingType = underlyingType + other.underlyingType,
+ visibility = visibility + other.visibility,
+ sourceSets = sourceSets + other.sourceSets
+).mergeExtras(this, other) \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt
new file mode 100644
index 00000000..109aa640
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt
@@ -0,0 +1,258 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
+
+class DeprecatedDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
+ override fun invoke(modules: List<DModule>) = modules.map { original ->
+ val sourceSet = original.sourceSets.single()
+ val packageOptions =
+ sourceSet.perPackageOptions
+ original.let {
+ DeprecatedDocumentableFilter(sourceSet, packageOptions).processModule(it)
+ }
+ }
+
+ private class DeprecatedDocumentableFilter(
+ val globalOptions: DokkaConfiguration.DokkaSourceSet,
+ val packageOptions: List<DokkaConfiguration.PackageOptions>
+ ) {
+
+ fun <T> T.isAllowedInPackage(): Boolean where T : WithExtraProperties<T>, T : Documentable {
+ val packageName = this.dri.packageName
+ val condition = packageName != null && packageOptions.firstOrNull {
+ packageName.startsWith(it.prefix)
+ }?.skipDeprecated
+ ?: globalOptions.skipDeprecated
+
+ fun T.isDeprecated() = extra[Annotations]?.let { annotations ->
+ annotations.content.values.flatten().any {
+ it.dri.toString() == "kotlin/Deprecated///PointingToDeclaration/"
+ }
+ } ?: false
+
+ return !(condition && this.isDeprecated())
+ }
+
+ fun processModule(original: DModule) =
+ filterPackages(original.packages).let { (modified, packages) ->
+ if (!modified) original
+ else
+ DModule(
+ original.name,
+ packages = packages,
+ documentation = original.documentation,
+ sourceSets = original.sourceSets,
+ extra = original.extra
+ )
+ }
+
+
+ private fun filterPackages(packages: List<DPackage>): Pair<Boolean, List<DPackage>> {
+ var packagesListChanged = false
+ val filteredPackages = packages.mapNotNull { pckg ->
+ var modified = false
+ val functions = filterFunctions(pckg.functions).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val properties = filterProperties(pckg.properties).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val classlikes = filterClasslikes(pckg.classlikes).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ when {
+ !modified -> pckg
+ else -> {
+ packagesListChanged = true
+ DPackage(
+ pckg.dri,
+ functions,
+ properties,
+ classlikes,
+ pckg.typealiases,
+ pckg.documentation,
+ pckg.expectPresentInSet,
+ pckg.sourceSets,
+ pckg.extra
+ )
+ }
+ }
+ }
+ return Pair(packagesListChanged, filteredPackages)
+ }
+
+ private fun filterFunctions(
+ functions: List<DFunction>
+ ) = functions.filter { it.isAllowedInPackage() }.let {
+ Pair(it.size != functions.size, it)
+ }
+
+ private fun filterProperties(
+ properties: List<DProperty>
+ ): Pair<Boolean, List<DProperty>> = properties.filter {
+ it.isAllowedInPackage()
+ }.let {
+ Pair(properties.size != it.size, it)
+ }
+
+ private fun filterEnumEntries(entries: List<DEnumEntry>) =
+ entries.filter { it.isAllowedInPackage() }.map { entry ->
+ DEnumEntry(
+ entry.dri,
+ entry.name,
+ entry.documentation,
+ entry.expectPresentInSet,
+ filterFunctions(entry.functions).second,
+ filterProperties(entry.properties).second,
+ filterClasslikes(entry.classlikes).second,
+ entry.sourceSets,
+ entry.extra
+ )
+ }
+
+ private fun filterClasslikes(
+ classlikeList: List<DClasslike>
+ ): Pair<Boolean, List<DClasslike>> {
+ var modified = false
+ return classlikeList.filter { classlike ->
+ when (classlike) {
+ is DClass -> classlike.isAllowedInPackage()
+ is DInterface -> classlike.isAllowedInPackage()
+ is DEnum -> classlike.isAllowedInPackage()
+ is DObject -> classlike.isAllowedInPackage()
+ is DAnnotation -> classlike.isAllowedInPackage()
+ }
+ }.map { classlike ->
+ fun helper(): DClasslike = when (classlike) {
+ is DClass -> DClass(
+ classlike.dri,
+ classlike.name,
+ filterFunctions(classlike.constructors).let {
+ modified = modified || it.first; it.second
+ },
+ filterFunctions(classlike.functions).let {
+ modified = modified || it.first; it.second
+ },
+ filterProperties(classlike.properties).let {
+ modified = modified || it.first; it.second
+ },
+ filterClasslikes(classlike.classlikes).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.sources,
+ classlike.visibility,
+ classlike.companion,
+ classlike.generics,
+ classlike.supertypes,
+ classlike.documentation,
+ classlike.expectPresentInSet,
+ classlike.modifier,
+ classlike.sourceSets,
+ classlike.extra
+ )
+ is DAnnotation -> DAnnotation(
+ classlike.name,
+ classlike.dri,
+ classlike.documentation,
+ classlike.expectPresentInSet,
+ classlike.sources,
+ filterFunctions(classlike.functions).let {
+ modified = modified || it.first; it.second
+ },
+ filterProperties(classlike.properties).let {
+ modified = modified || it.first; it.second
+ },
+ filterClasslikes(classlike.classlikes).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.visibility,
+ classlike.companion,
+ filterFunctions(classlike.constructors).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.generics,
+ classlike.sourceSets,
+ classlike.extra
+ )
+ is DEnum -> DEnum(
+ classlike.dri,
+ classlike.name,
+ filterEnumEntries(classlike.entries),
+ classlike.documentation,
+ classlike.expectPresentInSet,
+ classlike.sources,
+ filterFunctions(classlike.functions).let {
+ modified = modified || it.first; it.second
+ },
+ filterProperties(classlike.properties).let {
+ modified = modified || it.first; it.second
+ },
+ filterClasslikes(classlike.classlikes).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.visibility,
+ classlike.companion,
+ filterFunctions(classlike.constructors).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.supertypes,
+ classlike.sourceSets,
+ classlike.extra
+ )
+ is DInterface -> DInterface(
+ classlike.dri,
+ classlike.name,
+ classlike.documentation,
+ classlike.expectPresentInSet,
+ classlike.sources,
+ filterFunctions(classlike.functions).let {
+ modified = modified || it.first; it.second
+ },
+ filterProperties(classlike.properties).let {
+ modified = modified || it.first; it.second
+ },
+ filterClasslikes(classlike.classlikes).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.visibility,
+ classlike.companion,
+ classlike.generics,
+ classlike.supertypes,
+ classlike.sourceSets,
+ classlike.extra
+ )
+ is DObject -> DObject(
+ classlike.name,
+ classlike.dri,
+ classlike.documentation,
+ classlike.expectPresentInSet,
+ classlike.sources,
+ filterFunctions(classlike.functions).let {
+ modified = modified || it.first; it.second
+ },
+ filterProperties(classlike.properties).let {
+ modified = modified || it.first; it.second
+ },
+ filterClasslikes(classlike.classlikes).let {
+ modified = modified || it.first; it.second
+ },
+ classlike.visibility,
+ classlike.supertypes,
+ classlike.sourceSets,
+ classlike.extra
+ )
+ }
+ helper()
+ }.let {
+ Pair(it.size != classlikeList.size || modified, it)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt
new file mode 100644
index 00000000..ff05beed
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt
@@ -0,0 +1,327 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+
+class DocumentableVisibilityFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
+
+ override fun invoke(modules: List<DModule>) = modules.map { original ->
+ val sourceSet = original.sourceSets.single()
+ val packageOptions = sourceSet.perPackageOptions
+ DocumentableVisibilityFilter(packageOptions, sourceSet).processModule(original)
+ }
+
+ private class DocumentableVisibilityFilter(
+ val packageOptions: List<DokkaConfiguration.PackageOptions>,
+ val globalOptions: DokkaSourceSet
+ ) {
+ fun Visibility.isAllowedInPackage(packageName: String?) = when (this) {
+ is JavaVisibility.Public,
+ is JavaVisibility.Default,
+ is KotlinVisibility.Public -> true
+ else -> packageName != null
+ && packageOptions.firstOrNull { packageName.startsWith(it.prefix) }?.includeNonPublic
+ ?: globalOptions.includeNonPublic
+ }
+
+ fun processModule(original: DModule) =
+ filterPackages(original.packages).let { (modified, packages) ->
+ if (!modified) original
+ else
+ DModule(
+ original.name,
+ packages = packages,
+ documentation = original.documentation,
+ sourceSets = original.sourceSets,
+ extra = original.extra
+ )
+ }
+
+
+ private fun filterPackages(packages: List<DPackage>): Pair<Boolean, List<DPackage>> {
+ var packagesListChanged = false
+ val filteredPackages = packages.map {
+ var modified = false
+ val functions = filterFunctions(it.functions).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val properties = filterProperties(it.properties).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val classlikes = filterClasslikes(it.classlikes).let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ when {
+ !modified -> it
+ else -> {
+ packagesListChanged = true
+ DPackage(
+ it.dri,
+ functions,
+ properties,
+ classlikes,
+ it.typealiases,
+ it.documentation,
+ it.expectPresentInSet,
+ it.sourceSets,
+ it.extra
+ )
+ }
+ }
+ }
+ return Pair(packagesListChanged, filteredPackages)
+ }
+
+ private fun <T : WithVisibility> alwaysTrue(a: T, p: DokkaSourceSet) = true
+ private fun <T : WithVisibility> alwaysFalse(a: T, p: DokkaSourceSet) = false
+
+ private fun WithVisibility.visibilityForPlatform(data: DokkaSourceSet): Visibility? = visibility[data]
+
+ private fun <T> T.filterPlatforms(
+ additionalCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysTrue,
+ alternativeCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysFalse
+ ) where T : Documentable, T : WithVisibility =
+ sourceSets.filter { d ->
+ visibilityForPlatform(d)?.isAllowedInPackage(dri.packageName) == true &&
+ additionalCondition(this, d) ||
+ alternativeCondition(this, d)
+ }.toSet()
+
+ private fun <T> List<T>.transform(
+ additionalCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysTrue,
+ alternativeCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysFalse,
+ recreate: (T, Set<DokkaSourceSet>) -> T
+ ): Pair<Boolean, List<T>> where T : Documentable, T : WithVisibility {
+ var changed = false
+ val values = mapNotNull { t ->
+ val filteredPlatforms = t.filterPlatforms(additionalCondition, alternativeCondition)
+ when (filteredPlatforms.size) {
+ t.visibility.size -> t
+ 0 -> {
+ changed = true
+ null
+ }
+ else -> {
+ changed = true
+ recreate(t, filteredPlatforms)
+ }
+ }
+ }
+ return Pair(changed, values)
+ }
+
+ private fun filterFunctions(
+ functions: List<DFunction>,
+ additionalCondition: (DFunction, DokkaSourceSet) -> Boolean = ::alwaysTrue
+ ) =
+ functions.transform(additionalCondition) { original, filteredPlatforms ->
+ with(original) {
+ DFunction(
+ dri,
+ name,
+ isConstructor,
+ parameters,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ visibility.filtered(filteredPlatforms),
+ type,
+ generics.mapNotNull { it.filter(filteredPlatforms) },
+ receiver,
+ modifier,
+ filteredPlatforms,
+ extra
+ )
+ }
+ }
+
+ private fun hasVisibleAccessorsForPlatform(property: DProperty, data: DokkaSourceSet) =
+ property.getter?.visibilityForPlatform(data)?.isAllowedInPackage(property.dri.packageName) == true ||
+ property.setter?.visibilityForPlatform(data)?.isAllowedInPackage(property.dri.packageName) == true
+
+ private fun filterProperties(
+ properties: List<DProperty>,
+ additionalCondition: (DProperty, DokkaSourceSet) -> Boolean = ::alwaysTrue
+ ): Pair<Boolean, List<DProperty>> =
+ properties.transform(additionalCondition, ::hasVisibleAccessorsForPlatform) { original, filteredPlatforms ->
+ with(original) {
+ DProperty(
+ dri,
+ name,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ visibility.filtered(filteredPlatforms),
+ type,
+ receiver,
+ setter,
+ getter,
+ modifier,
+ filteredPlatforms,
+ generics.mapNotNull { it.filter(filteredPlatforms) },
+ extra
+ )
+ }
+ }
+
+ private fun filterEnumEntries(entries: List<DEnumEntry>, filteredPlatforms: Set<DokkaSourceSet>) =
+ entries.mapNotNull { entry ->
+ if (filteredPlatforms.containsAll(entry.sourceSets)) entry
+ else {
+ val intersection = filteredPlatforms.intersect(entry.sourceSets)
+ if (intersection.isEmpty()) null
+ else DEnumEntry(
+ entry.dri,
+ entry.name,
+ entry.documentation.filtered(intersection),
+ entry.expectPresentInSet.filtered(filteredPlatforms),
+ filterFunctions(entry.functions) { _, data -> data in intersection }.second,
+ filterProperties(entry.properties) { _, data -> data in intersection }.second,
+ filterClasslikes(entry.classlikes) { _, data -> data in intersection }.second,
+ intersection,
+ entry.extra
+ )
+ }
+ }
+
+ private fun filterClasslikes(
+ classlikeList: List<DClasslike>,
+ additionalCondition: (DClasslike, DokkaSourceSet) -> Boolean = ::alwaysTrue
+ ): Pair<Boolean, List<DClasslike>> {
+ var classlikesListChanged = false
+ val filteredClasslikes: List<DClasslike> = classlikeList.mapNotNull {
+ with(it) {
+ val filteredPlatforms = filterPlatforms(additionalCondition)
+ if (filteredPlatforms.isEmpty()) {
+ classlikesListChanged = true
+ null
+ } else {
+ var modified = sourceSets.size != filteredPlatforms.size
+ val functions =
+ filterFunctions(functions) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val properties =
+ filterProperties(properties) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val classlikes =
+ filterClasslikes(classlikes) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ }
+ val companion =
+ if (this is WithCompanion) filterClasslikes(listOfNotNull(companion)) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
+ modified = modified || listModified
+ list.firstOrNull() as DObject?
+ } else null
+ val constructors = if (this is WithConstructors)
+ filterFunctions(constructors) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
+ modified = modified || listModified
+ list
+ } else emptyList()
+ val generics =
+ if (this is WithGenerics) generics.mapNotNull { param -> param.filter(filteredPlatforms) } else emptyList()
+ val enumEntries =
+ if (this is DEnum) filterEnumEntries(entries, filteredPlatforms) else emptyList()
+ classlikesListChanged = classlikesListChanged || modified
+ when {
+ !modified -> this
+ this is DClass -> DClass(
+ dri,
+ name,
+ constructors,
+ functions,
+ properties,
+ classlikes,
+ sources.filtered(filteredPlatforms),
+ visibility.filtered(filteredPlatforms),
+ companion,
+ generics,
+ supertypes.filtered(filteredPlatforms),
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ modifier,
+ filteredPlatforms,
+ extra
+ )
+ this is DAnnotation -> DAnnotation(
+ name,
+ dri,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ functions,
+ properties,
+ classlikes,
+ visibility.filtered(filteredPlatforms),
+ companion,
+ constructors,
+ generics,
+ filteredPlatforms,
+ extra
+ )
+ this is DEnum -> DEnum(
+ dri,
+ name,
+ enumEntries,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ functions,
+ properties,
+ classlikes,
+ visibility.filtered(filteredPlatforms),
+ companion,
+ constructors,
+ supertypes.filtered(filteredPlatforms),
+ filteredPlatforms,
+ extra
+ )
+ this is DInterface -> DInterface(
+ dri,
+ name,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ functions,
+ properties,
+ classlikes,
+ visibility.filtered(filteredPlatforms),
+ companion,
+ generics,
+ supertypes.filtered(filteredPlatforms),
+ filteredPlatforms,
+ extra
+ )
+ this is DObject -> DObject(
+ name,
+ dri,
+ documentation.filtered(filteredPlatforms),
+ expectPresentInSet.filtered(filteredPlatforms),
+ sources.filtered(filteredPlatforms),
+ functions,
+ properties,
+ classlikes,
+ visibility,
+ supertypes.filtered(filteredPlatforms),
+ filteredPlatforms,
+ extra
+ )
+ else -> null
+ }
+ }
+ }
+ }
+ return Pair(classlikesListChanged, filteredClasslikes)
+ }
+ }
+}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt
new file mode 100644
index 00000000..61abfbd7
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt
@@ -0,0 +1,28 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.DPackage
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
+
+class EmptyPackagesFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
+ override fun invoke(modules: List<DModule>): List<DModule> = modules.map { original ->
+ original.let {
+ EmptyPackagesFilter(original.sourceSets.single()).processModule(it)
+ }
+ }
+
+ private class EmptyPackagesFilter(
+ val sourceSet: DokkaConfiguration.DokkaSourceSet
+ ) {
+ fun DPackage.shouldBeSkipped() = sourceSet.skipEmptyPackages &&
+ functions.isEmpty() &&
+ properties.isEmpty() &&
+ classlikes.isEmpty()
+
+ fun processModule(module: DModule) = module.copy(
+ packages = module.packages.filter { !it.shouldBeSkipped() }
+ )
+ }
+}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt
new file mode 100644
index 00000000..2da25d4b
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt
@@ -0,0 +1,127 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ClosedReceiveChannelException
+import kotlinx.coroutines.channels.ReceiveChannel
+import kotlinx.coroutines.channels.SendChannel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.toList
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.DriOfAny
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.model.properties.MergeStrategy
+import org.jetbrains.dokka.model.properties.plus
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+
+
+class ExtensionExtractorTransformer : DocumentableTransformer {
+ override fun invoke(original: DModule, context: DokkaContext): DModule = runBlocking(Dispatchers.Default) {
+ val channel = Channel<Pair<DRI, Callable>>(10)
+ launch {
+ coroutineScope {
+ original.packages.forEach { launch { collectExtensions(it, channel) } }
+ }
+ channel.close()
+ }
+ val extensionMap = channel.consumeAsFlow().toList().toMultiMap()
+
+ val newPackages = original.packages.map { async { it.addExtensionInformation(extensionMap) } }
+ original.copy(packages = newPackages.awaitAll())
+ }
+}
+
+private suspend fun <T : Documentable> T.addExtensionInformation(
+ extensionMap: Map<DRI, List<Callable>>
+): T = coroutineScope {
+ val newClasslikes = (this@addExtensionInformation as? WithScope)
+ ?.classlikes
+ ?.map { async { it.addExtensionInformation(extensionMap) } }
+ .orEmpty()
+
+ @Suppress("UNCHECKED_CAST")
+ when (this@addExtensionInformation) {
+ is DPackage -> {
+ val newTypealiases = typealiases.map { async { it.addExtensionInformation(extensionMap) } }
+ copy(classlikes = newClasslikes.awaitAll(), typealiases = newTypealiases.awaitAll())
+ }
+ is DClass -> copy(classlikes = newClasslikes.awaitAll(), extra = extra + extensionMap.find(dri))
+ is DEnum -> copy(classlikes = newClasslikes.awaitAll(), extra = extra + extensionMap.find(dri))
+ is DInterface -> copy(classlikes = newClasslikes.awaitAll(), extra = extra + extensionMap.find(dri))
+ is DObject -> copy(classlikes = newClasslikes.awaitAll(), extra = extra + extensionMap.find(dri))
+ is DAnnotation -> copy(classlikes = newClasslikes.awaitAll(), extra = extra + extensionMap.find(dri))
+ is DTypeAlias -> copy(extra = extra + extensionMap.find(dri))
+ else -> throw IllegalStateException(
+ "${this@addExtensionInformation::class.simpleName} is not expected to have extensions"
+ )
+ } as T
+}
+
+private fun Map<DRI, List<Callable>>.find(dri: DRI) = get(dri)?.toSet()?.let(::CallableExtensions)
+
+private suspend fun collectExtensions(
+ documentable: Documentable,
+ channel: SendChannel<Pair<DRI, Callable>>
+): Unit = coroutineScope {
+ if (documentable is WithScope) {
+ documentable.classlikes.forEach {
+ launch { collectExtensions(it, channel) }
+ }
+
+ if (documentable is DObject || documentable is DPackage) {
+ (documentable.properties.asSequence() + documentable.functions.asSequence())
+ .flatMap(Callable::asPairsWithReceiverDRIs)
+ .forEach { channel.send(it) }
+ }
+ }
+}
+
+
+private fun Callable.asPairsWithReceiverDRIs(): Sequence<Pair<DRI, Callable>> =
+ receiver?.type?.let(::findReceiverDRIs).orEmpty().map { it to this }
+
+// In normal cases we return at max one DRI, but sometimes receiver type can be bound by more than one type constructor
+// for example `fun <T> T.example() where T: A, T: B` is extension of both types A and B
+// Note: in some cases returning empty sequence doesn't mean that we cannot determine the DRI but only that we don't
+// care about it since there is nowhere to put documentation of given extension.
+private fun Callable.findReceiverDRIs(bound: Bound): Sequence<DRI> = when (bound) {
+ is Nullable -> findReceiverDRIs(bound.inner)
+ is OtherParameter ->
+ if (this is DFunction && bound.declarationDRI == this.dri)
+ generics.find { it.name == bound.name }?.bounds?.asSequence()?.flatMap(::findReceiverDRIs).orEmpty()
+ else
+ emptySequence()
+ is TypeConstructor -> sequenceOf(bound.dri)
+ is PrimitiveJavaType -> emptySequence()
+ is Void -> emptySequence()
+ is JavaObject -> sequenceOf(DriOfAny)
+ is Dynamic -> sequenceOf(DriOfAny)
+ is UnresolvedBound -> emptySequence()
+}
+
+private fun <T, U> Iterable<Pair<T, U>>.toMultiMap(): Map<T, List<U>> =
+ groupBy(Pair<T, *>::first, Pair<*, U>::second)
+
+data class CallableExtensions(val extensions: Set<Callable>) : ExtraProperty<Documentable> {
+ companion object Key : ExtraProperty.Key<Documentable, CallableExtensions> {
+ override fun mergeStrategyFor(left: CallableExtensions, right: CallableExtensions) =
+ MergeStrategy.Replace(CallableExtensions(left.extensions + right.extensions))
+ }
+
+ override val key = Key
+}
+
+//TODO IMPORTANT remove this terrible hack after updating to 1.4-M3
+fun <T : Any> ReceiveChannel<T>.consumeAsFlow(): Flow<T> = flow {
+ try {
+ while (true) {
+ emit(receive())
+ }
+ } catch (_: ClosedReceiveChannelException) {
+ // cool and good
+ }
+}.flowOn(Dispatchers.Default) \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt
new file mode 100644
index 00000000..85256d51
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt
@@ -0,0 +1,85 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.model.properties.MergeStrategy
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+
+class InheritorsExtractorTransformer : DocumentableTransformer {
+ override fun invoke(original: DModule, context: DokkaContext): DModule =
+ original.generateInheritanceMap().let { inheritanceMap -> original.appendInheritors(inheritanceMap) as DModule }
+
+ private fun <T : Documentable> T.appendInheritors(inheritanceMap: Map<DokkaSourceSet, Map<DRI, List<DRI>>>): Documentable =
+ InheritorsInfo(inheritanceMap.getForDRI(dri)).let { info ->
+ when (this) {
+ is DModule -> copy(packages = packages.map { it.appendInheritors(inheritanceMap) as DPackage })
+ is DPackage -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ is DClass -> if (info.isNotEmpty()) {
+ copy(
+ extra = extra + info,
+ classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ } else {
+ copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ }
+ is DEnum -> if (info.isNotEmpty()) {
+ copy(
+ extra = extra + info,
+ classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ } else {
+ copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ }
+ is DInterface -> if (info.isNotEmpty()) {
+ copy(
+ extra = extra + info,
+ classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ } else {
+ copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ }
+ is DObject -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ is DAnnotation -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
+ else -> this
+ }
+ }
+
+ private fun InheritorsInfo.isNotEmpty() = this.value.values.fold(0) { acc, list -> acc + list.size } > 0
+
+ private fun Map<DokkaSourceSet, Map<DRI, List<DRI>>>.getForDRI(dri: DRI) =
+ map { (v, k) ->
+ v to k[dri]
+ }.map { (k, v) -> k to v.orEmpty() }.toMap()
+
+ private fun DModule.generateInheritanceMap() =
+ getInheritanceEntriesRec().filterNot { it.second.isEmpty() }.groupBy({ it.first }) { it.second }
+ .map { (k, v) ->
+ k to v.flatMap { p -> p.groupBy({ it.first }) { it.second }.toList() }
+ .groupBy({ it.first }) { it.second }.map { (k2, v2) -> k2 to v2.flatten() }.toMap()
+ }.filter { it.second.values.isNotEmpty() }.toMap()
+
+ private fun <T : Documentable> T.getInheritanceEntriesRec(): List<Pair<DokkaSourceSet, List<Pair<DRI, DRI>>>> =
+ this.toInheritanceEntries() + children.flatMap { it.getInheritanceEntriesRec() }
+
+ private fun <T : Documentable> T.toInheritanceEntries() =
+ (this as? WithSupertypes)?.let {
+ it.supertypes.map { (k, v) -> k to v.map { it.dri to dri } }
+ }.orEmpty()
+
+}
+
+class InheritorsInfo(val value: SourceSetDependent<List<DRI>>) : ExtraProperty<Documentable> {
+ companion object : ExtraProperty.Key<Documentable, InheritorsInfo> {
+ override fun mergeStrategyFor(left: InheritorsInfo, right: InheritorsInfo): MergeStrategy<Documentable> =
+ MergeStrategy.Replace(
+ InheritorsInfo(
+ (left.value.entries.toList() + right.value.entries.toList())
+ .groupBy({ it.key }) { it.value }
+ .map { (k, v) -> k to v.flatten() }.toMap()
+ )
+ )
+ }
+
+ override val key: ExtraProperty.Key<Documentable, *> = InheritorsInfo
+}
+
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
new file mode 100644
index 00000000..4a98a5e0
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
@@ -0,0 +1,108 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.analysis.KotlinAnalysis
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.parsers.MarkdownParser
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import java.nio.file.Files
+import java.nio.file.Paths
+
+
+internal class ModuleAndPackageDocumentationTransformer(
+ private val context: DokkaContext,
+ private val kotlinAnalysis: KotlinAnalysis
+) : PreMergeDocumentableTransformer {
+
+ override fun invoke(modules: List<DModule>): List<DModule> {
+
+ val modulesAndPackagesDocumentation =
+ context.configuration.sourceSets
+ .map {
+ Pair(it.moduleDisplayName, it) to
+ it.includes.map { Paths.get(it) }
+ .also {
+ it.forEach {
+ if (Files.notExists(it))
+ context.logger.warn("Not found file under this path ${it.toAbsolutePath()}")
+ }
+ }
+ .filter { Files.exists(it) }
+ .flatMap {
+ it.toFile()
+ .readText()
+ .split(Regex("(\n|^)# (?=(Module|Package))")) // Matches heading with Module/Package to split by
+ .filter { it.isNotEmpty() }
+ .map {
+ it.split(
+ Regex(" "),
+ 2
+ )
+ } // Matches space between Module/Package and fully qualified name
+ }.groupBy({ it[0] }, {
+ it[1].split(Regex("\n"), 2) // Matches new line after fully qualified name
+ .let { it[0].trim() to it[1].trim() }
+ }).mapValues {
+ it.value.toMap()
+ }
+ }.toMap()
+
+ return modules.map { module ->
+
+ val moduleDocumentation =
+ module.sourceSets.mapNotNull { pd ->
+ val doc = modulesAndPackagesDocumentation[Pair(module.name, pd)]
+ val facade = kotlinAnalysis[pd].facade
+ try {
+ doc?.get("Module")?.get(module.name)?.run {
+ pd to MarkdownParser(
+ facade,
+ facade.moduleDescriptor.getPackage(FqName.topLevel(Name.identifier(""))),
+ context.logger
+ ).parse(this)
+ }
+ } catch (e: IllegalArgumentException) {
+ context.logger.error(e.message.orEmpty())
+ null
+ }
+ }.toMap()
+
+ val packagesDocumentation = module.packages.map {
+ it.name to it.sourceSets.mapNotNull { pd ->
+ val doc = modulesAndPackagesDocumentation[Pair(module.name, pd)]
+ val facade = kotlinAnalysis[pd].facade
+ val descriptor = facade.moduleDescriptor.getPackage(FqName(it.name.let { if(it == "[JS root]") "" else it }))
+ doc?.get("Package")?.get(it.name)?.run {
+ pd to MarkdownParser(
+ facade,
+ descriptor,
+ context.logger
+ ).parse(this)
+ }
+ }.toMap()
+ }.toMap()
+
+ module.copy(
+ documentation = mergeDocumentation(module.documentation, moduleDocumentation),
+ packages = module.packages.map {
+ val packageDocumentation = packagesDocumentation[it.name]
+ if (packageDocumentation != null && packageDocumentation.isNotEmpty())
+ it.copy(documentation = mergeDocumentation(it.documentation, packageDocumentation))
+ else
+ it
+ }
+ )
+ }
+ }
+
+ private fun mergeDocumentation(origin: Map<DokkaSourceSet, DocumentationNode>, new: Map<DokkaSourceSet, DocumentationNode>) =
+ (origin.asSequence() + new.asSequence())
+ .distinct()
+ .groupBy({ it.key }, { it.value })
+ .mapValues { (_, values) -> DocumentationNode(values.flatMap { it.children }) }
+
+}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
new file mode 100644
index 00000000..2ebd4c62
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
@@ -0,0 +1,165 @@
+package org.jetbrains.dokka.base.transformers.documentables
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+internal class ReportUndocumentedTransformer : DocumentableTransformer {
+
+ override fun invoke(original: DModule, context: DokkaContext): DModule = original.apply {
+ withDescendants().forEach { documentable -> invoke(documentable, context) }
+ }
+
+ private fun invoke(documentable: Documentable, context: DokkaContext) {
+ documentable.sourceSets.forEach { sourceSet ->
+ if (shouldBeReportedIfNotDocumented(documentable, sourceSet, context)) {
+ reportIfUndocumented(context, documentable, sourceSet)
+ }
+ }
+ }
+
+ private fun shouldBeReportedIfNotDocumented(
+ documentable: Documentable, sourceSet: DokkaSourceSet, context: DokkaContext
+ ): Boolean {
+ val packageOptionsOrNull = packageOptionsOrNull(sourceSet, documentable)
+
+ if (!(packageOptionsOrNull?.reportUndocumented ?: sourceSet.reportUndocumented)) {
+ return false
+ }
+
+ if (documentable is DParameter || documentable is DPackage || documentable is DModule) {
+ return false
+ }
+
+ if (isConstructor(documentable)) {
+ return false
+ }
+
+ if (isFakeOverride(documentable, sourceSet)) {
+ return false
+ }
+
+ if (isSynthesized(documentable, sourceSet)) {
+ return false
+ }
+
+ if (isPrivateOrInternalApi(documentable, sourceSet)) {
+ return false
+ }
+
+ return true
+ }
+
+ private fun reportIfUndocumented(
+ context: DokkaContext,
+ documentable: Documentable,
+ sourceSet: DokkaSourceSet
+ ) {
+ if (isUndocumented(documentable, sourceSet)) {
+ val documentableDescription = with(documentable) {
+ buildString {
+ dri.packageName?.run {
+ append(this)
+ append("/")
+ }
+
+ dri.classNames?.run {
+ append(this)
+ append("/")
+ }
+
+ dri.callable?.run {
+ append(name)
+ append("/")
+ append(signature())
+ append("/")
+ }
+
+ val sourceSetName = sourceSet.displayName
+ if (sourceSetName != null.toString()) {
+ append(" ($sourceSetName)")
+ }
+ }
+ }
+
+ context.logger.warn("Undocumented: $documentableDescription")
+ }
+ }
+
+ private fun isUndocumented(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
+ fun resolveDependentSourceSets(sourceSet: DokkaSourceSet): List<DokkaSourceSet> {
+ return sourceSet.dependentSourceSets.mapNotNull { sourceSetID ->
+ documentable.sourceSets.singleOrNull { it.sourceSetID == sourceSetID }
+ }
+ }
+
+ fun withAllDependentSourceSets(sourceSet: DokkaSourceSet): Sequence<DokkaSourceSet> {
+ return sequence {
+ yield(sourceSet)
+ for (dependentSourceSet in resolveDependentSourceSets(sourceSet)) {
+ yieldAll(withAllDependentSourceSets(dependentSourceSet))
+ }
+ }
+ }
+
+ return withAllDependentSourceSets(sourceSet).all { sourceSetOrDependentSourceSet ->
+ documentable.documentation[sourceSetOrDependentSourceSet]?.children?.isEmpty() ?: true
+ }
+ }
+
+ private fun isConstructor(documentable: Documentable): Boolean {
+ if (documentable !is DFunction) return false
+ return documentable.isConstructor
+ }
+
+ private fun isFakeOverride(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
+ return callableMemberDescriptorOrNull(documentable, sourceSet)?.kind == FAKE_OVERRIDE
+ }
+
+ private fun isSynthesized(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
+ return callableMemberDescriptorOrNull(documentable, sourceSet)?.kind == SYNTHESIZED
+ }
+
+ private fun callableMemberDescriptorOrNull(
+ documentable: Documentable, sourceSet: DokkaSourceSet
+ ): CallableMemberDescriptor? {
+ if (documentable is WithExpectActual) {
+ return documentable.sources[sourceSet]
+ .safeAs<DescriptorDocumentableSource>()?.descriptor
+ .safeAs()
+ }
+
+ return null
+ }
+
+ private fun isPrivateOrInternalApi(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
+ return when (documentable.safeAs<WithVisibility>()?.visibility?.get(sourceSet)) {
+ KotlinVisibility.Public -> false
+ KotlinVisibility.Private -> true
+ KotlinVisibility.Protected -> true
+ KotlinVisibility.Internal -> true
+ JavaVisibility.Public -> false
+ JavaVisibility.Private -> true
+ JavaVisibility.Protected -> true
+ JavaVisibility.Default -> true
+ null -> false
+ }
+ }
+
+ private fun packageOptionsOrNull(
+ dokkaSourceSet: DokkaSourceSet,
+ documentable: Documentable
+ ): DokkaConfiguration.PackageOptions? {
+ val packageName = documentable.dri.packageName ?: return null
+ return dokkaSourceSet.perPackageOptions
+ .filter { packageOptions -> packageName.startsWith(packageOptions.prefix) }
+ .maxBy { packageOptions -> packageOptions.prefix.length }
+ }
+}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
new file mode 100644
index 00000000..7914e88f
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
@@ -0,0 +1,82 @@
+package org.jetbrains.dokka.base.transformers.pages.annotations
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.doc.CustomTagWrapper
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+class SinceKotlinTransformer(val context: DokkaContext) : DocumentableTransformer {
+
+ override fun invoke(original: DModule, context: DokkaContext) = original.transform() as DModule
+
+ private fun <T : Documentable> T.transform(): Documentable =
+ when (this) {
+ is DModule -> copy(
+ packages = packages.map { it.transform() as DPackage }
+ )
+ is DPackage -> copy(
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DClass -> copy(
+ documentation = appendSinceKotlin(),
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DEnum -> copy(
+ documentation = appendSinceKotlin(),
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DInterface -> copy(
+ documentation = appendSinceKotlin(),
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DObject -> copy(
+ documentation = appendSinceKotlin(),
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DAnnotation -> copy(
+ documentation = appendSinceKotlin(),
+ classlikes = classlikes.map { it.transform() as DClasslike },
+ functions = functions.map { it.transform() as DFunction },
+ properties = properties.map { it.transform() as DProperty }
+ )
+ is DFunction -> copy(
+ documentation = appendSinceKotlin()
+ )
+ is DProperty -> copy(
+ documentation = appendSinceKotlin()
+ )
+ is DParameter -> copy(
+ documentation = appendSinceKotlin()
+ )
+ else -> this.also { context.logger.warn("Unrecognized documentable $this while SinceKotlin transformation") }
+ }
+
+ private fun Documentable.appendSinceKotlin() =
+ sourceSets.fold(documentation) { acc, sourceSet ->
+ safeAs<WithExtraProperties<Documentable>>()?.extra?.get(Annotations)?.content?.get(sourceSet)?.find {
+ it.dri == DRI("kotlin", "SinceKotlin")
+ }?.params?.get("version").safeAs<StringValue>()?.value?.let { version ->
+ acc.mapValues {
+ if (it.key == sourceSet) it.value.copy(
+ it.value.children + listOf(
+ CustomTagWrapper(Text(version.dropWhile { it == '"' }.dropLastWhile { it == '"' }), "Since Kotlin")
+ )
+ ) else it.value
+ }
+ } ?: acc
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt
new file mode 100644
index 00000000..fa9ce37e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt
@@ -0,0 +1,16 @@
+package org.jetbrains.dokka.base.transformers.pages.comments
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.model.doc.DocTag
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+
+interface CommentsToContentConverter {
+ fun buildContent(
+ docTag: DocTag,
+ dci: DCI,
+ sourceSets: Set<DokkaSourceSet>,
+ styles: Set<Style> = emptySet(),
+ extras: PropertyContainer<ContentNode> = PropertyContainer.empty()
+ ): List<ContentNode>
+}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
new file mode 100644
index 00000000..0f953e0f
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
@@ -0,0 +1,178 @@
+package org.jetbrains.dokka.base.transformers.pages.comments
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+
+object DocTagToContentConverter : CommentsToContentConverter {
+ override fun buildContent(
+ docTag: DocTag,
+ dci: DCI,
+ sourceSets: Set<DokkaSourceSet>,
+ styles: Set<Style>,
+ extra: PropertyContainer<ContentNode>
+ ): List<ContentNode> {
+
+ fun buildChildren(docTag: DocTag, newStyles: Set<Style> = emptySet(), newExtras: SimpleAttr? = null) =
+ docTag.children.flatMap {
+ buildContent(it, dci, sourceSets, styles + newStyles, newExtras?.let { extra + it } ?: extra)
+ }
+
+ fun buildTableRows(rows: List<DocTag>, newStyle: Style): List<ContentGroup> =
+ rows.flatMap {
+ buildContent(it, dci, sourceSets, styles + newStyle, extra) as List<ContentGroup>
+ }
+
+ fun buildHeader(level: Int) =
+ listOf(
+ ContentHeader(
+ buildChildren(docTag),
+ level,
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+
+ fun buildList(ordered: Boolean, start: Int = 1) =
+ listOf(
+ ContentList(
+ buildChildren(docTag),
+ ordered,
+ dci,
+ sourceSets,
+ styles,
+ ((PropertyContainer.empty<ContentNode>()) + SimpleAttr("start", start.toString()))
+ )
+ )
+
+ fun buildNewLine() = listOf(
+ ContentBreakLine(
+ sourceSets
+ )
+ )
+
+ return when (docTag) {
+ is H1 -> buildHeader(1)
+ is H2 -> buildHeader(2)
+ is H3 -> buildHeader(3)
+ is H4 -> buildHeader(4)
+ is H5 -> buildHeader(5)
+ is H6 -> buildHeader(6)
+ is Ul -> buildList(false)
+ is Ol -> buildList(true, docTag.params["start"]?.toInt() ?: 1)
+ is Li -> listOf(
+ ContentGroup(children = buildChildren(docTag), dci, sourceSets, styles, extra)
+ )
+ is Br -> buildNewLine()
+ is B -> buildChildren(docTag, setOf(TextStyle.Strong))
+ is I -> buildChildren(docTag, setOf(TextStyle.Italic))
+ is P -> buildChildren(docTag, newStyles = setOf(TextStyle.Paragraph))
+ is A -> listOf(
+ ContentResolvedLink(
+ buildChildren(docTag),
+ docTag.params.get("href")!!,
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is DocumentationLink -> listOf(
+ ContentDRILink(
+ buildChildren(docTag),
+ docTag.dri,
+ DCI(
+ setOf(docTag.dri),
+ ContentKind.Main
+ ),
+ sourceSets,
+ styles
+ )
+ )
+ is BlockQuote -> listOf(
+ ContentCodeBlock(
+ buildChildren(docTag),
+ "",
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is CodeInline -> listOf(
+ ContentCodeInline(
+ buildChildren(docTag),
+ "",
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is CodeBlock -> listOf(
+ ContentCodeBlock(
+ buildChildren(docTag),
+ "",
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is Img -> listOf(
+ ContentEmbeddedResource(
+ address = docTag.params["href"]!!,
+ altText = docTag.params["alt"],
+ dci = dci,
+ sourceSets = sourceSets,
+ style = styles,
+ extra = extra
+ )
+ )
+ is HorizontalRule -> listOf(
+ ContentText(
+ "",
+ dci,
+ sourceSets,
+ setOf()
+ )
+ )
+ is Text -> listOf(
+ ContentText(
+ docTag.body,
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is Strikethrough -> buildChildren(docTag, setOf(TextStyle.Strikethrough))
+ is Table -> listOf(
+ ContentTable(
+ buildTableRows(docTag.children.filterIsInstance<Th>(), CommentTable),
+ buildTableRows(docTag.children.filterIsInstance<Tr>(), CommentTable),
+ dci,
+ sourceSets,
+ styles + CommentTable
+ )
+ )
+ is Th,
+ is Tr -> listOf(
+ ContentGroup(
+ docTag.children.map {
+ ContentGroup(buildChildren(it), dci, sourceSets, styles, extra)
+ },
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ is Index -> listOf(
+ ContentGroup(
+ buildChildren(docTag, newStyles = styles + ContentStyle.InDocumentationAnchor),
+ dci,
+ sourceSets,
+ styles
+ )
+ )
+ else -> buildChildren(docTag)
+ }
+ }
+}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt
new file mode 100644
index 00000000..df0c27ee
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt
@@ -0,0 +1,12 @@
+package org.jetbrains.dokka.base.transformers.pages.merger
+
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+class FallbackPageMergerStrategy(private val logger: DokkaLogger) : PageMergerStrategy {
+ override fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode> {
+ val renderedPath = path.joinToString(separator = "/")
+ if (pages.size != 1) logger.warn("For $renderedPath: expected 1 page, but got ${pages.size}")
+ return listOf(pages.first())
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt
new file mode 100644
index 00000000..4faf3ad4
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt
@@ -0,0 +1,29 @@
+package org.jetbrains.dokka.base.transformers.pages.merger
+
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+
+class PageMerger(private val strategies: Iterable<PageMergerStrategy>) : PageTransformer {
+ override fun invoke(input: RootPageNode): RootPageNode =
+ input.modified(children = input.children.map { it.mergeChildren(emptyList()) })
+
+ private fun PageNode.mergeChildren(path: List<String>): PageNode = children.groupBy { it::class }.map {
+ it.value.groupBy { it.name }.map { (n, v) -> mergePageNodes(v, path + n) }.map { it.assertSingle(path) }
+ }.let { pages ->
+ modified(children = pages.flatten().map { it.mergeChildren(path + it.name) })
+ }
+
+ private fun mergePageNodes(pages: List<PageNode>, path: List<String>): List<PageNode> =
+ strategies.fold(pages) { acc, strategy -> tryMerge(strategy, acc, path) }
+
+ private fun tryMerge(strategy: PageMergerStrategy, pages: List<PageNode>, path: List<String>) =
+ if (pages.size > 1) strategy.tryMerge(pages, path) else pages
+}
+
+private fun <T> Iterable<T>.assertSingle(path: List<String>): T = try {
+ single()
+ } catch (e: Exception) {
+ val renderedPath = path.joinToString(separator = "/")
+ throw IllegalStateException("Page merger is misconfigured. Error for $renderedPath: ${e.message}")
+ } \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt
new file mode 100644
index 00000000..b73b17e0
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt
@@ -0,0 +1,9 @@
+package org.jetbrains.dokka.base.transformers.pages.merger
+
+import org.jetbrains.dokka.pages.PageNode
+
+interface PageMergerStrategy {
+
+ fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode>
+
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt
new file mode 100644
index 00000000..d81f131b
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt
@@ -0,0 +1,40 @@
+package org.jetbrains.dokka.base.transformers.pages.merger
+
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+class SameMethodNamePageMergerStrategy(val logger: DokkaLogger) : PageMergerStrategy {
+ override fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode> {
+ val members = pages.filterIsInstance<MemberPageNode>().takeIf { it.isNotEmpty() } ?: return pages
+ val name = pages.first().name.also {
+ if (pages.any { page -> page.name != it }) { // Is this even possible?
+ logger.error("Page names for $it do not match!")
+ }
+ }
+ val dri = members.flatMap { it.dri }.toSet()
+
+
+ val merged = MemberPageNode(
+ dri = dri,
+ name = name,
+ children = members.flatMap { it.children }.distinct(),
+ content = squashDivergentInstances(members),
+ embeddedResources = members.flatMap { it.embeddedResources }.distinct(),
+ documentable = null
+ )
+
+ return (pages - members) + listOf(merged)
+ }
+
+ private fun squashDivergentInstances(nodes: List<MemberPageNode>): ContentNode =
+ nodes.map { it.content }
+ .reduce { acc, node ->
+ acc.mapTransform<ContentDivergentGroup, ContentNode> { g ->
+ g.copy(children = (g.children +
+ (node.dfs { it is ContentDivergentGroup && it.groupID == g.groupID } as? ContentDivergentGroup)
+ ?.children?.single()
+ ).filterNotNull()
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/DefaultSamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/DefaultSamplesTransformer.kt
new file mode 100644
index 00000000..a391b534
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/samples/DefaultSamplesTransformer.kt
@@ -0,0 +1,38 @@
+package org.jetbrains.dokka.base.transformers.pages.samples
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.kotlin.idea.kdoc.resolveKDocSampleLink
+import org.jetbrains.kotlin.psi.KtBlockExpression
+import org.jetbrains.kotlin.psi.KtDeclarationWithBody
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+
+class DefaultSamplesTransformer(context: DokkaContext) : SamplesTransformer(context) {
+
+ override fun processBody(psiElement: PsiElement): String {
+ val text = processSampleBody(psiElement).trim { it == '\n' || it == '\r' }.trimEnd()
+ val lines = text.split("\n")
+ val indent = lines.filter(String::isNotBlank).map { it.takeWhile(Char::isWhitespace).count() }.min() ?: 0
+ return lines.joinToString("\n") { it.drop(indent) }
+ }
+
+ private fun processSampleBody(psiElement: PsiElement): String = when (psiElement) {
+ is KtDeclarationWithBody -> {
+ val bodyExpression = psiElement.bodyExpression
+ when (bodyExpression) {
+ is KtBlockExpression -> bodyExpression.text.removeSurrounding("{", "}")
+ else -> bodyExpression!!.text
+ }
+ }
+ else -> psiElement.text
+ }
+
+ override fun processImports(psiElement: PsiElement): String {
+ val psiFile = psiElement.containingFile
+ return when(val text = psiFile.safeAs<KtFile>()?.importList?.text) {
+ is String -> text
+ else -> ""
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/KotlinWebsiteSamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/KotlinWebsiteSamplesTransformer.kt
new file mode 100644
index 00000000..c099644f
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/samples/KotlinWebsiteSamplesTransformer.kt
@@ -0,0 +1,196 @@
+package org.jetbrains.dokka.base.transformers.pages.samples
+
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.impl.source.tree.LeafPsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.allChildren
+import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import org.jetbrains.kotlin.resolve.ImportPath
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import java.io.PrintWriter
+import java.io.StringWriter
+
+// TODO Inspect below class for any bugs. Big chunk of was ripped from 0.10.1
+class KotlinWebsiteSamplesTransformer(context: DokkaContext): SamplesTransformer(context) {
+
+ private class SampleBuilder : KtTreeVisitorVoid() {
+ val builder = StringBuilder()
+ val text: String
+ get() = builder.toString()
+
+ val errors = mutableListOf<ConvertError>()
+
+ data class ConvertError(val e: Exception, val text: String, val loc: String)
+
+ fun KtValueArgument.extractStringArgumentValue() =
+ (getArgumentExpression() as KtStringTemplateExpression)
+ .entries.joinToString("") { it.text }
+
+
+ fun convertAssertPrints(expression: KtCallExpression) {
+ val (argument, commentArgument) = expression.valueArguments
+ builder.apply {
+ append("println(")
+ append(argument.text)
+ append(") // ")
+ append(commentArgument.extractStringArgumentValue())
+ }
+ }
+
+ fun convertAssertTrueFalse(expression: KtCallExpression, expectedResult: Boolean) {
+ val (argument) = expression.valueArguments
+ builder.apply {
+ expression.valueArguments.getOrNull(1)?.let {
+ append("// ${it.extractStringArgumentValue()}")
+ val ws = expression.prevLeaf { it is PsiWhiteSpace }
+ append(ws?.text ?: "\n")
+ }
+ append("println(\"")
+ append(argument.text)
+ append(" is \${")
+ append(argument.text)
+ append("}\") // $expectedResult")
+ }
+ }
+
+ fun convertAssertFails(expression: KtCallExpression) {
+ val valueArguments = expression.valueArguments
+
+ val funcArgument: KtValueArgument
+ val message: KtValueArgument?
+
+ if (valueArguments.size == 1) {
+ message = null
+ funcArgument = valueArguments.first()
+ } else {
+ message = valueArguments.first()
+ funcArgument = valueArguments.last()
+ }
+
+ builder.apply {
+ val argument = funcArgument.extractFunctionalArgumentText()
+ append(argument.lines().joinToString(separator = "\n") { "// $it" })
+ append(" // ")
+ if (message != null) {
+ append(message.extractStringArgumentValue())
+ }
+ append(" will fail")
+ }
+ }
+
+ private fun KtValueArgument.extractFunctionalArgumentText(): String {
+ return if (getArgumentExpression() is KtLambdaExpression)
+ PsiTreeUtil.findChildOfType(this, KtBlockExpression::class.java)?.text ?: ""
+ else
+ text
+ }
+
+ fun convertAssertFailsWith(expression: KtCallExpression) {
+ val (funcArgument) = expression.valueArguments
+ val (exceptionType) = expression.typeArguments
+ builder.apply {
+ val argument = funcArgument.extractFunctionalArgumentText()
+ append(argument.lines().joinToString(separator = "\n") { "// $it" })
+ append(" // will fail with ")
+ append(exceptionType.text)
+ }
+ }
+
+ override fun visitCallExpression(expression: KtCallExpression) {
+ when (expression.calleeExpression?.text) {
+ "assertPrints" -> convertAssertPrints(expression)
+ "assertTrue" -> convertAssertTrueFalse(expression, expectedResult = true)
+ "assertFalse" -> convertAssertTrueFalse(expression, expectedResult = false)
+ "assertFails" -> convertAssertFails(expression)
+ "assertFailsWith" -> convertAssertFailsWith(expression)
+ else -> super.visitCallExpression(expression)
+ }
+ }
+
+ private fun reportProblemConvertingElement(element: PsiElement, e: Exception) {
+ val text = element.text
+ val document = PsiDocumentManager.getInstance(element.project).getDocument(element.containingFile)
+
+ val lineInfo = if (document != null) {
+ val lineNumber = document.getLineNumber(element.startOffset)
+ "$lineNumber, ${element.startOffset - document.getLineStartOffset(lineNumber)}"
+ } else {
+ "offset: ${element.startOffset}"
+ }
+ errors += ConvertError(e, text, lineInfo)
+ }
+
+ override fun visitElement(element: PsiElement) {
+ if (element is LeafPsiElement)
+ builder.append(element.text)
+
+ element.acceptChildren(object : PsiElementVisitor() {
+ override fun visitElement(element: PsiElement) {
+ try {
+ element.accept(this@SampleBuilder)
+ } catch (e: Exception) {
+ try {
+ reportProblemConvertingElement(element, e)
+ } finally {
+ builder.append(element.text) //recover
+ }
+ }
+ }
+ })
+ }
+
+ }
+
+ private fun PsiElement.buildSampleText(): String {
+ val sampleBuilder = SampleBuilder()
+ this.accept(sampleBuilder)
+
+ sampleBuilder.errors.forEach {
+ val sw = StringWriter()
+ val pw = PrintWriter(sw)
+ it.e.printStackTrace(pw)
+
+ this@KotlinWebsiteSamplesTransformer.context.logger.error("${containingFile.name}: (${it.loc}): Exception thrown while converting \n```\n${it.text}\n```\n$sw")
+ }
+ return sampleBuilder.text
+ }
+
+ val importsToIgnore = arrayOf("samples.*", "samples.Sample").map { ImportPath.fromString(it) }
+
+ override fun processImports(psiElement: PsiElement): String {
+ val psiFile = psiElement.containingFile
+ return when(val text = psiFile.safeAs<KtFile>()?.importList) {
+ is KtImportList -> text.let {
+ it.allChildren.filter {
+ it !is KtImportDirective || it.importPath !in importsToIgnore
+ }.joinToString(separator = "\n") { it.text }
+ }
+ else -> ""
+ }
+ }
+
+ override fun processBody(psiElement: PsiElement): String {
+ val text = processSampleBody(psiElement).trim { it == '\n' || it == '\r' }.trimEnd()
+ val lines = text.split("\n")
+ val indent = lines.filter(String::isNotBlank).map { it.takeWhile(Char::isWhitespace).count() }.min() ?: 0
+ return lines.joinToString("\n") { it.drop(indent) }
+ }
+
+ private fun processSampleBody(psiElement: PsiElement) = when (psiElement) {
+ is KtDeclarationWithBody -> {
+ val bodyExpression = psiElement.bodyExpression
+ val bodyExpressionText = bodyExpression!!.buildSampleText()
+ when (bodyExpression) {
+ is KtBlockExpression -> bodyExpressionText.removeSurrounding("{", "}")
+ else -> bodyExpressionText
+ }
+ }
+ else -> psiElement.buildSampleText()
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
new file mode 100644
index 00000000..695ef050
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt
@@ -0,0 +1,151 @@
+package org.jetbrains.dokka.base.transformers.pages.samples
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.analysis.AnalysisEnvironment
+import org.jetbrains.dokka.analysis.DokkaMessageCollector
+import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.EnvironmentAndFacade
+import org.jetbrains.dokka.base.renderers.sourceSets
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.doc.Sample
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+import org.jetbrains.kotlin.idea.kdoc.resolveKDocSampleLink
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
+import org.jetbrains.kotlin.utils.PathUtil
+import java.io.File
+
+abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer {
+
+ abstract fun processBody(psiElement: PsiElement): String
+ abstract fun processImports(psiElement: PsiElement): String
+
+ final override fun invoke(input: RootPageNode): RootPageNode {
+ val analysis = setUpAnalysis(context)
+ val kotlinPlaygroundScript =
+ "<script src=\"https://unpkg.com/kotlin-playground@1\" data-selector=\"code.runnablesample\"></script>"
+
+ return input.transformContentPagesTree { page ->
+ page.documentable?.documentation?.entries?.fold(page) { acc, entry ->
+ entry.value.children.filterIsInstance<Sample>().fold(acc) { acc, sample ->
+ acc.modified(
+ content = acc.content.addSample(page, entry.key, sample.name, analysis),
+ embeddedResources = acc.embeddedResources + kotlinPlaygroundScript
+ )
+ }
+ } ?: page
+ }
+ }
+
+ private fun setUpAnalysis(context: DokkaContext) = context.configuration.sourceSets.map {
+ it to AnalysisEnvironment(DokkaMessageCollector(context.logger), it.analysisPlatform).run {
+ if (analysisPlatform == Platform.jvm) {
+ addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
+ }
+ it.classpath.forEach { addClasspath(File(it)) }
+
+ addSources(it.samples.map { it })
+
+ loadLanguageVersionSettings(it.languageVersion, it.apiVersion)
+
+ val environment = createCoreEnvironment()
+ val (facade, _) = createResolutionFacade(environment)
+ EnvironmentAndFacade(environment, facade)
+ }
+ }.toMap()
+
+ private fun ContentNode.addSample(
+ contentPage: ContentPage,
+ platform: DokkaSourceSet,
+ fqName: String,
+ analysis: Map<DokkaSourceSet, EnvironmentAndFacade>
+ ): ContentNode {
+ val facade = analysis[platform]?.facade
+ ?: return this.also { context.logger.warn("Cannot resolve facade for platform ${platform.moduleDisplayName}") }
+ val psiElement = fqNameToPsiElement(facade, fqName)
+ ?: return this.also { context.logger.warn("Cannot find PsiElement corresponding to $fqName") }
+ val imports =
+ processImports(psiElement)
+ val body = processBody(psiElement)
+ val node = contentCode(contentPage.sourceSets(), contentPage.dri, createSampleBody(imports, body), "kotlin")
+
+ return dfs(fqName, node)
+ }
+
+ protected open fun createSampleBody(imports: String, body: String) =
+ """ |$imports
+ |fun main() {
+ | //sampleStart
+ | $body
+ | //sampleEnd
+ |}""".trimMargin()
+
+ private fun ContentNode.dfs(fqName: String, node: ContentCodeBlock): ContentNode {
+ return when (this) {
+ is ContentHeader -> copy(children.map { it.dfs(fqName, node) })
+ is ContentDivergentGroup -> @Suppress("UNCHECKED_CAST") copy(children.map {
+ it.dfs(fqName, node)
+ } as List<ContentDivergentInstance>)
+ is ContentDivergentInstance -> copy(
+ before.let { it?.dfs(fqName, node) },
+ divergent.dfs(fqName, node),
+ after.let { it?.dfs(fqName, node) })
+ is ContentCodeBlock -> copy(children.map { it.dfs(fqName, node) })
+ is ContentCodeInline -> copy(children.map { it.dfs(fqName, node) })
+ is ContentDRILink -> copy(children.map { it.dfs(fqName, node) })
+ is ContentResolvedLink -> copy(children.map { it.dfs(fqName, node) })
+ is ContentEmbeddedResource -> copy(children.map { it.dfs(fqName, node) })
+ is ContentTable -> copy(children = children.map { it.dfs(fqName, node) as ContentGroup })
+ is ContentList -> copy(children.map { it.dfs(fqName, node) })
+ is ContentGroup -> copy(children.map { it.dfs(fqName, node) })
+ is PlatformHintedContent -> copy(inner.dfs(fqName, node))
+ is ContentText -> if (text == fqName) node else this
+ is ContentBreakLine -> this
+ else -> this.also { context.logger.error("Could not recognize $this ContentNode in SamplesTransformer") }
+ }
+ }
+
+ private fun fqNameToPsiElement(resolutionFacade: DokkaResolutionFacade, functionName: String): PsiElement? {
+ val packageName = functionName.takeWhile { it != '.' }
+ val descriptor = resolutionFacade.resolveSession.getPackageFragment(FqName(packageName))
+ ?: return null.also { context.logger.warn("Cannot find descriptor for package $packageName") }
+ val symbol = resolveKDocSampleLink(
+ BindingContext.EMPTY,
+ resolutionFacade,
+ descriptor,
+ functionName.split(".")
+ ).firstOrNull() ?: return null.also { context.logger.warn("Unresolved function $functionName in @sample") }
+ return DescriptorToSourceUtils.descriptorToDeclaration(symbol)
+ }
+
+ private fun contentCode(
+ sourceSets: Set<DokkaSourceSet>,
+ dri: Set<DRI>,
+ content: String,
+ language: String,
+ styles: Set<Style> = emptySet(),
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty()
+ ) =
+ ContentCodeBlock(
+ children = listOf(
+ ContentText(
+ text = content,
+ dci = DCI(dri, ContentKind.Sample),
+ sourceSets = sourceSets,
+ style = emptySet(),
+ extra = PropertyContainer.empty()
+ )
+ ),
+ language = language,
+ dci = DCI(dri, ContentKind.Sample),
+ sourceSets = sourceSets,
+ style = styles + ContentStyle.RunnableSample + TextStyle.Monospace,
+ extra = extra
+ )
+}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
new file mode 100644
index 00000000..f0e62f11
--- /dev/null
+++ b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
@@ -0,0 +1,130 @@
+package org.jetbrains.dokka.base.transformers.pages.sourcelinks
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiDocumentManager
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.model.DocumentableSource
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
+import org.jetbrains.dokka.analysis.PsiDocumentableSource
+import org.jetbrains.dokka.model.WithExpectActual
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
+import org.jetbrains.kotlin.resolve.source.getPsi
+import org.jetbrains.kotlin.utils.addToStdlib.cast
+
+class SourceLinksTransformer(val context: DokkaContext, val builder: PageContentBuilder) : PageTransformer {
+
+ override fun invoke(input: RootPageNode) =
+ input.transformContentPagesTree { node ->
+ when (val documentable = node.documentable) {
+ is WithExpectActual -> resolveSources(documentable)
+ .takeIf { it.isNotEmpty() }
+ ?.let { node.addSourcesContent(it) }
+ ?: node
+ else -> node
+ }
+ }
+
+ private fun getSourceLinks() = context.configuration.sourceSets
+ .flatMap { it.sourceLinks.map { sl -> SourceLink(sl, it) } }
+
+ private fun resolveSources(documentable: WithExpectActual) = documentable.sources
+ .mapNotNull { entry ->
+ getSourceLinks().find { entry.value.path.contains(it.path) && it.sourceSetData == entry.key }?.let {
+ Pair(
+ entry.key,
+ entry.value.toLink(it)
+ )
+ }
+ }
+
+ private fun ContentPage.addSourcesContent(sources: List<Pair<DokkaSourceSet, String>>) = builder
+ .buildSourcesContent(this, sources)
+ .let {
+ this.modified(
+ content = this.content.addTable(it)
+ )
+ }
+
+ private fun PageContentBuilder.buildSourcesContent(
+ node: ContentPage,
+ sources: List<Pair<DokkaSourceSet, String>>
+ ) = contentFor(
+ node.dri.first(),
+ node.documentable!!.sourceSets.toSet()
+ ) {
+ header(2, "Sources", kind = ContentKind.Source)
+ +ContentTable(
+ emptyList(),
+ sources.map {
+ buildGroup(node.dri, setOf(it.first), kind = ContentKind.Source) {
+ link("(source)", it.second)
+ }
+ },
+ DCI(node.dri, ContentKind.Source),
+ node.documentable!!.sourceSets.toSet(),
+ style = emptySet(),
+ extra = mainExtra + SimpleAttr.header("Sources")
+ )
+ }
+
+ private fun DocumentableSource.toLink(sourceLink: SourceLink): String {
+ val lineNumber = when (this) {
+ is DescriptorDocumentableSource -> this.descriptor
+ .cast<DeclarationDescriptorWithSource>()
+ .source.getPsi()
+ ?.lineNumber()
+ is PsiDocumentableSource -> this.psi.lineNumber()
+ else -> null
+ }
+ return sourceLink.url +
+ this.path.split(sourceLink.path)[1] +
+ sourceLink.lineSuffix +
+ "${lineNumber ?: 1}"
+ }
+
+ private fun ContentNode.addTable(table: ContentGroup): ContentNode =
+ when (this) {
+ is ContentGroup -> {
+ if(hasTabbedContent()){
+ copy(
+ children = children.map {
+ if(it.hasStyle(ContentStyle.TabbedContent) && it is ContentGroup){
+ it.copy(children = it.children + table)
+ } else {
+ it
+ }
+ }
+ )
+ } else {
+ copy(children = children + table)
+ }
+
+ }
+ else -> ContentGroup(
+ children = listOf(this, table),
+ extra = this.extra,
+ sourceSets = this.sourceSets,
+ dci = this.dci,
+ style = this.style
+ )
+ }
+
+ private fun PsiElement.lineNumber(): Int? {
+ val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile)
+ // IJ uses 0-based line-numbers; external source browsers use 1-based
+ return doc?.getLineNumber(textRange.startOffset)?.plus(1)
+ }
+}
+
+data class SourceLink(val path: String, val url: String, val lineSuffix: String?, val sourceSetData: DokkaSourceSet) {
+ constructor(sourceLinkDefinition: DokkaConfiguration.SourceLinkDefinition, sourceSetData: DokkaSourceSet) : this(
+ sourceLinkDefinition.path, sourceLinkDefinition.url, sourceLinkDefinition.lineSuffix, sourceSetData
+ )
+}
+
+fun ContentGroup.hasTabbedContent(): Boolean = children.any { it.hasStyle(ContentStyle.TabbedContent) } \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
new file mode 100644
index 00000000..ffceaaa7
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -0,0 +1,782 @@
+package org.jetbrains.dokka.base.translators.descriptors
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
+import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.dokka.analysis.KotlinAnalysis
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.base.parsers.MarkdownParser
+import org.jetbrains.dokka.links.*
+import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.Nullable
+import org.jetbrains.dokka.model.TypeConstructor
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.builtins.isExtensionFunctionType
+import org.jetbrains.kotlin.builtins.isFunctionType
+import org.jetbrains.kotlin.codegen.isJvmStaticInObjectOrClassOrInterface
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.ClassKind
+import org.jetbrains.kotlin.descriptors.Visibility
+import org.jetbrains.kotlin.descriptors.annotations.Annotated
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
+import org.jetbrains.kotlin.idea.kdoc.findKDoc
+import org.jetbrains.kotlin.load.kotlin.toSourceElement
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
+import org.jetbrains.kotlin.resolve.calls.components.isVararg
+import org.jetbrains.kotlin.resolve.constants.ConstantValue
+import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.LocalClass
+import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.NormalClass
+import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
+import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
+import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
+import org.jetbrains.kotlin.resolve.scopes.MemberScope
+import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
+import org.jetbrains.kotlin.resolve.source.PsiSourceElement
+import org.jetbrains.kotlin.types.DynamicType
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.TypeProjection
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import java.nio.file.Paths
+import org.jetbrains.kotlin.resolve.constants.AnnotationValue as ConstantsAnnotationValue
+import org.jetbrains.kotlin.resolve.constants.ArrayValue as ConstantsArrayValue
+import org.jetbrains.kotlin.resolve.constants.EnumValue as ConstantsEnumValue
+import org.jetbrains.kotlin.resolve.constants.KClassValue as ConstantsKtClassValue
+
+class DefaultDescriptorToDocumentableTranslator(
+ private val kotlinAnalysis: KotlinAnalysis
+) : SourceToDocumentableTranslator {
+
+ override fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
+ val (environment, facade) = kotlinAnalysis[sourceSet]
+ val packageFragments = environment.getSourceFiles().asSequence()
+ .map { it.packageFqName }
+ .distinct()
+ .mapNotNull { facade.resolveSession.getPackageFragment(it) }
+ .toList()
+
+ return DokkaDescriptorVisitor(sourceSet, kotlinAnalysis[sourceSet].facade, context.logger).run {
+ packageFragments.mapNotNull { it.safeAs<PackageFragmentDescriptor>() }.map {
+ visitPackageFragmentDescriptor(
+ it,
+ DRIWithPlatformInfo(DRI.topLevel, emptyMap())
+ )
+ }
+ }.let { DModule(sourceSet.moduleDisplayName, it, emptyMap(), null, setOf(sourceSet)) }
+ }
+}
+
+data class DRIWithPlatformInfo(
+ val dri: DRI,
+ val actual: SourceSetDependent<DocumentableSource>
+)
+
+fun DRI.withEmptyInfo() = DRIWithPlatformInfo(this, emptyMap())
+
+private class DokkaDescriptorVisitor(
+ private val sourceSet: DokkaSourceSet,
+ private val resolutionFacade: DokkaResolutionFacade,
+ private val logger: DokkaLogger
+) : DeclarationDescriptorVisitorEmptyBodies<Documentable, DRIWithPlatformInfo>() {
+ override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor, parent: DRIWithPlatformInfo): Nothing {
+ throw IllegalStateException("${javaClass.simpleName} should never enter ${descriptor.javaClass.simpleName}")
+ }
+
+ private fun Collection<DeclarationDescriptor>.filterDescriptorsInSourceSet() = filter {
+ it.toSourceElement.containingFile.toString().let { path ->
+ path.isNotBlank() && sourceSet.sourceRoots.any { root ->
+ Paths.get(path).startsWith(Paths.get(root.path))
+ }
+ }
+ }
+
+ private fun <T> T.toSourceSetDependent() = mapOf(sourceSet to this)
+
+ override fun visitPackageFragmentDescriptor(
+ descriptor: PackageFragmentDescriptor,
+ parent: DRIWithPlatformInfo
+ ): DPackage {
+ val name = descriptor.fqName.asString().takeUnless { it.isBlank() } ?: fallbackPackageName()
+ val driWithPlatform = DRI(packageName = name).withEmptyInfo()
+ val scope = descriptor.getMemberScope()
+
+ return DPackage(
+ dri = driWithPlatform.dri,
+ functions = scope.functions(driWithPlatform, true),
+ properties = scope.properties(driWithPlatform, true),
+ classlikes = scope.classlikes(driWithPlatform, true),
+ typealiases = scope.typealiases(driWithPlatform, true),
+ documentation = descriptor.resolveDescriptorData(),
+ sourceSets = setOf(sourceSet)
+ )
+ }
+
+ override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClasslike =
+ when (descriptor.kind) {
+ ClassKind.ENUM_CLASS -> enumDescriptor(descriptor, parent)
+ ClassKind.OBJECT -> objectDescriptor(descriptor, parent)
+ ClassKind.INTERFACE -> interfaceDescriptor(descriptor, parent)
+ ClassKind.ANNOTATION_CLASS -> annotationDescriptor(descriptor, parent)
+ else -> classDescriptor(descriptor, parent)
+ }
+
+ private fun interfaceDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DInterface {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+ val info = descriptor.resolveClassDescriptionData()
+
+ return DInterface(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ classlikes = scope.classlikes(driWithPlatform),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() },
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
+ )
+ }
+
+ private fun objectDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DObject {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+ val info = descriptor.resolveClassDescriptionData()
+
+
+ return DObject(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ classlikes = scope.classlikes(driWithPlatform),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
+ )
+ }
+
+ private fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnum {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+ val info = descriptor.resolveClassDescriptionData()
+
+ return DEnum(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ entries = scope.enumEntries(driWithPlatform),
+ constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) },
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ classlikes = scope.classlikes(driWithPlatform),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
+ )
+ }
+
+ private fun enumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnumEntry {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+
+ return DEnumEntry(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ documentation = descriptor.resolveDescriptorData(),
+ classlikes = scope.classlikes(driWithPlatform),
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ConstructorValues(descriptor.getAppliedConstructorParameters().toSourceSetDependent())
+ )
+ )
+ }
+
+ fun annotationDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DAnnotation {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+
+ return DAnnotation(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ documentation = descriptor.resolveDescriptorData(),
+ classlikes = scope.classlikes(driWithPlatform),
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ expectPresentInSet = null,
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ ),
+ companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() },
+ constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) },
+ sources = descriptor.createSources()
+ )
+ }
+
+ private fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClass {
+ val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
+ val scope = descriptor.unsubstitutedMemberScope
+ val isExpect = descriptor.isExpect
+ val info = descriptor.resolveClassDescriptionData()
+ val actual = descriptor.createSources()
+
+ return DClass(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ constructors = descriptor.constructors.map {
+ visitConstructorDescriptor(
+ it,
+ if (it.isPrimary) DRIWithPlatformInfo(driWithPlatform.dri, actual)
+ else DRIWithPlatformInfo(driWithPlatform.dri, emptyMap())
+ )
+ },
+ functions = scope.functions(driWithPlatform),
+ properties = scope.properties(driWithPlatform),
+ classlikes = scope.classlikes(driWithPlatform),
+ sources = actual,
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() },
+ documentation = info.docs,
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
+ )
+ }
+
+ override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): DProperty {
+ val dri = parent.dri.copy(callable = Callable.from(descriptor))
+ val isExpect = descriptor.isExpect
+
+ val actual = descriptor.createSources()
+ return DProperty(
+ dri = dri,
+ name = descriptor.name.asString(),
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ sources = actual,
+ getter = descriptor.accessors.filterIsInstance<PropertyGetterDescriptor>().singleOrNull()?.let {
+ visitPropertyAccessorDescriptor(it, descriptor, dri)
+ },
+ setter = descriptor.accessors.filterIsInstance<PropertySetterDescriptor>().singleOrNull()?.let {
+ visitPropertyAccessorDescriptor(it, descriptor, dri)
+ },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ type = descriptor.returnType!!.toBound(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ sourceSets = setOf(sourceSet),
+ generics = descriptor.typeParameters.map { it.toTypeParameter() },
+ extra = PropertyContainer.withAll(
+ (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
+ .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations()
+ )
+ )
+ }
+
+ fun CallableMemberDescriptor.createDRI(wasOverridenBy: DRI? = null): Pair<DRI, DRI?> =
+ if (kind == CallableMemberDescriptor.Kind.DECLARATION || overriddenDescriptors.isEmpty())
+ Pair(DRI.from(this), wasOverridenBy)
+ else
+ overriddenDescriptors.first().createDRI(DRI.from(this))
+
+ override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): DFunction {
+ val (dri, inheritedFrom) = descriptor.createDRI()
+ val isExpect = descriptor.isExpect
+
+ val actual = descriptor.createSources()
+ return DFunction(
+ dri = dri,
+ name = descriptor.name.asString(),
+ isConstructor = false,
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ parameters = descriptor.valueParameters.mapIndexed { index, desc ->
+ parameter(index, desc, DRIWithPlatformInfo(dri, actual))
+ },
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ sources = actual,
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ generics = descriptor.typeParameters.map { it.toTypeParameter() },
+ documentation = descriptor.takeIf { it.kind != CallableMemberDescriptor.Kind.SYNTHESIZED }?.resolveDescriptorData() ?: emptyMap(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ type = descriptor.returnType!!.toBound(),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ InheritedFunction(inheritedFrom.toSourceSetDependent()),
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ )
+ )
+ }
+
+ override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): DFunction {
+ val dri = parent.dri.copy(callable = Callable.from(descriptor))
+ val actual = descriptor.createSources()
+ val isExpect = descriptor.isExpect
+
+ return DFunction(
+ dri = dri,
+ name = "<init>",
+ isConstructor = true,
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ parameters = descriptor.valueParameters.mapIndexed { index, desc ->
+ parameter(index, desc, DRIWithPlatformInfo(dri, actual))
+ },
+ sources = actual,
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData().let { sourceSetDependent ->
+ if (descriptor.isPrimary) {
+ sourceSetDependent.map { entry ->
+ Pair(
+ entry.key,
+ entry.value.copy(children = (entry.value.children.find { it is Constructor }?.root?.let { constructor ->
+ listOf(Description(constructor))
+ } ?: emptyList<TagWrapper>()) + entry.value.children.filterIsInstance<Param>()))
+ }.toMap()
+ } else {
+ sourceSetDependent
+ }
+ },
+ type = descriptor.returnType.toBound(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ generics = descriptor.typeParameters.map { it.toTypeParameter() },
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll<DFunction>(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ ).let {
+ if (descriptor.isPrimary) {
+ it + PrimaryConstructorExtra
+ } else it
+ }
+ )
+ }
+
+ override fun visitReceiverParameterDescriptor(
+ descriptor: ReceiverParameterDescriptor,
+ parent: DRIWithPlatformInfo
+ ) = DParameter(
+ dri = parent.dri.copy(target = PointingToDeclaration),
+ name = null,
+ type = descriptor.type.toBound(),
+ expectPresentInSet = null,
+ documentation = descriptor.resolveDescriptorData(),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(descriptor.getAnnotations().toSourceSetDependent().toAnnotations())
+ )
+
+ private fun visitPropertyAccessorDescriptor(
+ descriptor: PropertyAccessorDescriptor,
+ propertyDescriptor: PropertyDescriptor,
+ parent: DRI
+ ): DFunction {
+ val dri = parent.copy(callable = Callable.from(descriptor))
+ val isGetter = descriptor is PropertyGetterDescriptor
+ val isExpect = descriptor.isExpect
+
+ fun PropertyDescriptor.asParameter(parent: DRI) =
+ DParameter(
+ parent.copy(target = PointingToCallableParameters(parameterIndex = 1)),
+ this.name.asString(),
+ type = this.type.toBound(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ documentation = descriptor.resolveDescriptorData(),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations()
+ )
+ )
+
+ val name = run {
+ val modifier = if (isGetter) "get" else "set"
+ val rawName = propertyDescriptor.name.asString()
+ "$modifier${rawName[0].toUpperCase()}${rawName.drop(1)}"
+ }
+
+ val parameters =
+ if (isGetter) {
+ emptyList()
+ } else {
+ listOf(propertyDescriptor.asParameter(dri))
+ }
+
+ return DFunction(
+ dri,
+ name,
+ isConstructor = false,
+ parameters = parameters,
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData(),
+ type = descriptor.returnType!!.toBound(),
+ generics = descriptor.typeParameters.map { it.toTypeParameter() },
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(
+ it,
+ DRIWithPlatformInfo(dri, descriptor.createSources())
+ )
+ },
+ sources = descriptor.createSources(),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ )
+ )
+ }
+
+ override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, parent: DRIWithPlatformInfo?) =
+ with(descriptor) {
+ DTypeAlias(
+ dri = DRI.from(this),
+ name = name.asString(),
+ type = defaultType.toBound(),
+ expectPresentInSet = null,
+ underlyingType = underlyingType.toBound().toSourceSetDependent(),
+ visibility = visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = resolveDescriptorData(),
+ sourceSets = setOf(sourceSet)
+ )
+ }
+
+ private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) =
+ DParameter(
+ dri = parent.dri.copy(target = PointingToCallableParameters(index)),
+ name = descriptor.name.asString(),
+ type = descriptor.type.toBound(),
+ expectPresentInSet = null,
+ documentation = descriptor.resolveDescriptorData(),
+ sourceSets = setOf(sourceSet),
+ extra = PropertyContainer.withAll(listOfNotNull(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ descriptor.getDefaultValue()?.let { DefaultValue(it) }
+ ))
+ )
+
+ private fun MemberScope.getContributedDescriptors(kindFilter: DescriptorKindFilter, shouldFilter: Boolean) =
+ getContributedDescriptors(kindFilter) { true }.let {
+ if (shouldFilter) it.filterDescriptorsInSourceSet() else it
+ }
+
+ private fun MemberScope.functions(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DFunction> =
+ getContributedDescriptors(DescriptorKindFilter.FUNCTIONS, packageLevel)
+ .filterIsInstance<FunctionDescriptor>()
+ .map { visitFunctionDescriptor(it, parent) }
+
+ private fun MemberScope.properties(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DProperty> =
+ getContributedDescriptors(DescriptorKindFilter.VALUES, packageLevel)
+ .filterIsInstance<PropertyDescriptor>()
+ .map { visitPropertyDescriptor(it, parent) }
+
+ private fun MemberScope.classlikes(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DClasslike> =
+ getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, packageLevel)
+ .filter { it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY }
+ .map { visitClassDescriptor(it as ClassDescriptor, parent) }
+
+ private fun MemberScope.typealiases(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DTypeAlias> =
+ getContributedDescriptors(DescriptorKindFilter.TYPE_ALIASES, packageLevel)
+ .filterIsInstance<TypeAliasDescriptor>()
+ .map { visitTypeAliasDescriptor(it, parent) }
+
+ private fun MemberScope.enumEntries(parent: DRIWithPlatformInfo): List<DEnumEntry> =
+ this.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { true }
+ .filterIsInstance<ClassDescriptor>()
+ .filter { it.kind == ClassKind.ENUM_ENTRY }
+ .map { enumEntryDescriptor(it, parent) }
+
+
+ private fun DeclarationDescriptor.resolveDescriptorData(): SourceSetDependent<DocumentationNode> =
+ getDocumentation()?.toSourceSetDependent() ?: emptyMap()
+
+ private fun ClassDescriptor.resolveClassDescriptionData(): ClassInfo {
+ tailrec fun buildInheritanceInformation(
+ inheritorClass: ClassDescriptor?,
+ interfaces: List<ClassDescriptor>,
+ level: Int = 0,
+ inheritanceInformation: Set<InheritanceLevel> = emptySet()
+ ): Set<InheritanceLevel> {
+ if (inheritorClass == null && interfaces.isEmpty()) return inheritanceInformation
+
+ val updated = inheritanceInformation + InheritanceLevel(
+ level,
+ inheritorClass?.let { DRI.from(it) },
+ interfaces.map { DRI.from(it) })
+ val superInterfacesFromClass = inheritorClass?.getSuperInterfaces().orEmpty()
+ return buildInheritanceInformation(
+ inheritorClass = inheritorClass?.getSuperClassNotAny(),
+ interfaces = interfaces.flatMap { it.getSuperInterfaces() } + superInterfacesFromClass,
+ level = level + 1,
+ inheritanceInformation = updated
+ )
+ }
+ return ClassInfo(
+ buildInheritanceInformation(getSuperClassNotAny(), getSuperInterfaces()).sortedBy { it.level },
+ resolveDescriptorData()
+ )
+ }
+
+ private fun TypeParameterDescriptor.toTypeParameter() =
+ DTypeParameter(
+ DRI.from(this),
+ name.identifier,
+ resolveDescriptorData(),
+ null,
+ upperBounds.map { it.toBound() },
+ setOf(sourceSet),
+ extra = PropertyContainer.withAll(additionalExtras().toSourceSetDependent().toAdditionalModifiers())
+ )
+
+ private fun KotlinType.toBound(): Bound = when (this) {
+ is DynamicType -> Dynamic
+ else -> when (val ctor = constructor.declarationDescriptor) {
+ is TypeParameterDescriptor -> OtherParameter(
+ declarationDRI = DRI.from(ctor.containingDeclaration).withPackageFallbackTo(fallbackPackageName()),
+ name = ctor.name.asString()
+ )
+ else -> TypeConstructor(
+ DRI.from(constructor.declarationDescriptor!!), // TODO: remove '!!'
+ arguments.map { it.toProjection() },
+ if (isExtensionFunctionType) FunctionModifiers.EXTENSION
+ else if (isFunctionType) FunctionModifiers.FUNCTION
+ else FunctionModifiers.NONE
+ )
+ }.let {
+ if (isMarkedNullable) Nullable(it) else it
+ }
+ }
+
+ private fun TypeProjection.toProjection(): Projection =
+ if (isStarProjection) Star else formPossiblyVariant()
+
+ private fun TypeProjection.formPossiblyVariant(): Projection = type.fromPossiblyNullable().let {
+ when (projectionKind) {
+ org.jetbrains.kotlin.types.Variance.INVARIANT -> it
+ org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Variance(Variance.Kind.In, it)
+ org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Variance(Variance.Kind.Out, it)
+ }
+ }
+
+ private fun KotlinType.fromPossiblyNullable(): Bound =
+ toBound().let { if (isMarkedNullable) Nullable(it) else it }
+
+ private fun DeclarationDescriptor.getDocumentation() = findKDoc().let {
+ MarkdownParser(resolutionFacade, this, logger).parseFromKDocTag(it)
+ }.takeIf { it.children.isNotEmpty() }
+
+ private fun ClassDescriptor.companion(dri: DRIWithPlatformInfo): DObject? = companionObjectDescriptor?.let {
+ objectDescriptor(it, dri)
+ }
+
+ private fun MemberDescriptor.modifier() = when (modality) {
+ Modality.FINAL -> KotlinModifier.Final
+ Modality.SEALED -> KotlinModifier.Sealed
+ Modality.OPEN -> KotlinModifier.Open
+ Modality.ABSTRACT -> KotlinModifier.Abstract
+ else -> KotlinModifier.Empty
+ }
+
+ private fun MemberDescriptor.createSources(): SourceSetDependent<DocumentableSource> =
+ DescriptorDocumentableSource(this).toSourceSetDependent()
+
+ private fun FunctionDescriptor.additionalExtras() = listOfNotNull(
+ ExtraModifiers.KotlinOnlyModifiers.Infix.takeIf { isInfix },
+ ExtraModifiers.KotlinOnlyModifiers.Inline.takeIf { isInline },
+ ExtraModifiers.KotlinOnlyModifiers.Suspend.takeIf { isSuspend },
+ ExtraModifiers.KotlinOnlyModifiers.Operator.takeIf { isOperator },
+ ExtraModifiers.JavaOnlyModifiers.Static.takeIf { isJvmStaticInObjectOrClassOrInterface() },
+ ExtraModifiers.KotlinOnlyModifiers.TailRec.takeIf { isTailrec },
+ ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal },
+ ExtraModifiers.KotlinOnlyModifiers.Override.takeIf { DescriptorUtils.isOverride(this) }
+ ).toSet()
+
+ private fun ClassDescriptor.additionalExtras() = listOfNotNull(
+ ExtraModifiers.KotlinOnlyModifiers.Inline.takeIf { isInline },
+ ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal },
+ ExtraModifiers.KotlinOnlyModifiers.Inner.takeIf { isInner },
+ ExtraModifiers.KotlinOnlyModifiers.Data.takeIf { isData },
+ ExtraModifiers.KotlinOnlyModifiers.Fun.takeIf { isFun }
+ ).toSet()
+
+ private fun ValueParameterDescriptor.additionalExtras() = listOfNotNull(
+ ExtraModifiers.KotlinOnlyModifiers.NoInline.takeIf { isNoinline },
+ ExtraModifiers.KotlinOnlyModifiers.CrossInline.takeIf { isCrossinline },
+ ExtraModifiers.KotlinOnlyModifiers.Const.takeIf { isConst },
+ ExtraModifiers.KotlinOnlyModifiers.LateInit.takeIf { isLateInit },
+ ExtraModifiers.KotlinOnlyModifiers.VarArg.takeIf { isVararg }
+ ).toSet()
+
+ private fun TypeParameterDescriptor.additionalExtras() = listOfNotNull(
+ ExtraModifiers.KotlinOnlyModifiers.Reified.takeIf { isReified }
+ ).toSet()
+
+ private fun PropertyDescriptor.additionalExtras() = listOfNotNull(
+ ExtraModifiers.KotlinOnlyModifiers.Const.takeIf { isConst },
+ ExtraModifiers.KotlinOnlyModifiers.LateInit.takeIf { isLateInit },
+ ExtraModifiers.JavaOnlyModifiers.Static.takeIf { isJvmStaticInObjectOrClassOrInterface() },
+ ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal },
+ ExtraModifiers.KotlinOnlyModifiers.Override.takeIf { DescriptorUtils.isOverride(this) }
+ )
+
+ private fun Annotated.getAnnotations() = annotations.mapNotNull { it.toAnnotation() }
+
+ private fun ConstantValue<*>.toValue(): AnnotationParameterValue? = when (this) {
+ is ConstantsAnnotationValue -> value.toAnnotation()?.let { AnnotationValue(it) }
+ is ConstantsArrayValue -> ArrayValue(value.mapNotNull { it.toValue() })
+ is ConstantsEnumValue -> EnumValue(
+ fullEnumEntryName(),
+ DRI(enumClassId.packageFqName.asString(), fullEnumEntryName())
+ )
+ is ConstantsKtClassValue -> when (value) {
+ is NormalClass -> (value as NormalClass).value.classId.let {
+ ClassValue(
+ it.relativeClassName.asString(),
+ DRI(it.packageFqName.asString(), it.relativeClassName.asString())
+ )
+ }
+ is LocalClass -> (value as LocalClass).type.let {
+ ClassValue(
+ it.toString(),
+ DRI.from(it.constructor.declarationDescriptor as DeclarationDescriptor)
+ )
+ }
+ }
+ else -> StringValue(toString())
+ }
+
+ private fun AnnotationDescriptor.toAnnotation(): Annotations.Annotation {
+ return Annotations.Annotation(
+ DRI.from(annotationClass as DeclarationDescriptor),
+ allValueArguments.map { it.key.asString() to it.value.toValue() }.filter {
+ it.second != null
+ }.toMap() as Map<String, AnnotationParameterValue>,
+ annotationClass!!.annotations.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented"))
+ )
+ }
+
+ private fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> =
+ getAnnotations() + (backingField?.getAnnotations() ?: emptyList())
+
+ private fun List<Annotations.Annotation>.toAdditionalExtras() = mapNotNull {
+ try {
+ ExtraModifiers.valueOf(it.dri.classNames?.toLowerCase() ?: "")
+ } catch (e: IllegalArgumentException) {
+ null
+ }
+ }
+
+
+ private fun ValueParameterDescriptor.getDefaultValue(): String? =
+ (source as? KotlinSourceElement)?.psi?.children?.find { it is KtExpression }?.text
+
+ private fun ClassDescriptor.getAppliedConstructorParameters() =
+ (source as PsiSourceElement).psi?.children?.flatMap {
+ it.safeAs<KtInitializerList>()?.initializersAsText().orEmpty()
+ }.orEmpty()
+
+ private fun KtInitializerList.initializersAsText() =
+ initializers.firstIsInstanceOrNull<KtCallElement>()
+ ?.getValueArgumentsInParentheses()
+ ?.flatMap { it.childrenAsText() }
+ .orEmpty()
+
+ private fun ValueArgument.childrenAsText() = this.safeAs<KtValueArgument>()?.children?.map { it.text }.orEmpty()
+
+ private data class InheritanceLevel(val level: Int, val superclass: DRI?, val interfaces: List<DRI>)
+
+ private data class ClassInfo(val inheritance: List<InheritanceLevel>, val docs: SourceSetDependent<DocumentationNode>){
+ val supertypes: List<DriWithKind>
+ get() = inheritance.firstOrNull { it.level == 0 }?.let {
+ listOfNotNull(it.superclass?.let { DriWithKind(it, KotlinClassKindTypes.CLASS) }) + it.interfaces.map { DriWithKind(it, KotlinClassKindTypes.INTERFACE) }
+ }.orEmpty()
+
+ val allImplementedInterfaces: List<DRI>
+ get() = inheritance.flatMap { it.interfaces }.distinct()
+ }
+
+ private fun Visibility.toDokkaVisibility(): org.jetbrains.dokka.model.Visibility = when (this) {
+ Visibilities.PUBLIC -> KotlinVisibility.Public
+ Visibilities.PROTECTED -> KotlinVisibility.Protected
+ Visibilities.INTERNAL -> KotlinVisibility.Internal
+ Visibilities.PRIVATE -> KotlinVisibility.Private
+ else -> KotlinVisibility.Public
+ }
+
+ private fun ConstantsEnumValue.fullEnumEntryName() =
+ "${this.enumClassId.relativeClassName.asString()}.${this.enumEntryName.identifier}"
+
+ private fun fallbackPackageName(): String =
+ "[${sourceSet.displayName} root]"// TODO: error-prone, find a better way to do it
+}
+
+private fun DRI.withPackageFallbackTo(fallbackPackage: String): DRI {
+ return if (packageName.isNullOrBlank()) {
+ copy(packageName = fallbackPackage)
+ } else {
+ this
+ }
+}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt
new file mode 100644
index 00000000..04251947
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt
@@ -0,0 +1,17 @@
+package org.jetbrains.dokka.base.translators.documentables
+
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.pages.ModulePageNode
+import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+class DefaultDocumentableToPageTranslator(
+ private val commentsToContentConverter: CommentsToContentConverter,
+ private val signatureProvider: SignatureProvider,
+ private val logger: DokkaLogger
+) : DocumentableToPageTranslator {
+ override fun invoke(module: DModule): ModulePageNode =
+ DefaultPageCreator(commentsToContentConverter, signatureProvider, logger).pageForModule(module)
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
new file mode 100644
index 00000000..02f4b54e
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
@@ -0,0 +1,525 @@
+package org.jetbrains.dokka.base.translators.documentables
+
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions
+import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import kotlin.reflect.KClass
+import kotlin.reflect.full.isSubclassOf
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+
+private typealias GroupedTags = Map<KClass<out TagWrapper>, List<Pair<DokkaSourceSet?, TagWrapper>>>
+
+private val specialTags: Set<KClass<out TagWrapper>> =
+ setOf(Property::class, Description::class, Constructor::class, Receiver::class, Param::class, See::class)
+
+open class DefaultPageCreator(
+ commentsToContentConverter: CommentsToContentConverter,
+ signatureProvider: SignatureProvider,
+ val logger: DokkaLogger
+) {
+ protected open val contentBuilder = PageContentBuilder(commentsToContentConverter, signatureProvider, logger)
+
+ open fun pageForModule(m: DModule) =
+ ModulePageNode(m.name.ifEmpty { "<root>" }, contentForModule(m), m, m.packages.map(::pageForPackage))
+
+ open fun pageForPackage(p: DPackage): PackagePageNode = PackagePageNode(
+ p.name, contentForPackage(p), setOf(p.dri), p,
+ p.classlikes.map(::pageForClasslike) +
+ p.functions.map(::pageForFunction)
+ )
+
+ open fun pageForEnumEntry(e: DEnumEntry): ClasslikePageNode =
+ ClasslikePageNode(
+ e.name, contentForEnumEntry(e), setOf(e.dri), e,
+ e.classlikes.map(::pageForClasslike) +
+ e.filteredFunctions.map(::pageForFunction)
+ )
+
+ open fun pageForClasslike(c: DClasslike): ClasslikePageNode {
+ val constructors = if (c is WithConstructors) c.constructors else emptyList()
+
+ return ClasslikePageNode(
+ c.name.orEmpty(), contentForClasslike(c), setOf(c.dri), c,
+ constructors.map(::pageForFunction) +
+ c.classlikes.map(::pageForClasslike) +
+ c.filteredFunctions.map(::pageForFunction) +
+ if (c is DEnum) c.entries.map(::pageForEnumEntry) else emptyList()
+ )
+ }
+
+ open fun pageForFunction(f: DFunction) = MemberPageNode(f.name, contentForFunction(f), setOf(f.dri), f)
+
+ open fun pageForTypeAlias(t: DTypeAlias) = MemberPageNode(t.name, contentForTypeAlias(t), setOf(t.dri), t)
+
+ private val WithScope.filteredFunctions: List<DFunction>
+ get() = functions.mapNotNull { function ->
+ function.takeIf {
+ it.sourceSets.any { sourceSet -> it.extra[InheritedFunction]?.isInherited(sourceSet) != true }
+ }
+ }
+
+ protected open fun contentForModule(m: DModule) = contentBuilder.contentFor(m) {
+ group(kind = ContentKind.Cover) {
+ cover(m.name)
+ if (contentForDescription(m).isNotEmpty()) {
+ sourceSetDependentHint(
+ m.dri,
+ m.sourceSets.toSet(),
+ kind = ContentKind.SourceSetDependentHint,
+ styles = setOf(TextStyle.UnderCoverText)
+ ) {
+ +contentForDescription(m)
+ }
+ }
+ }
+ +contentForComments(m)
+ block("Packages", 2, ContentKind.Packages, m.packages, m.sourceSets.toSet()) {
+ link(it.name, it.dri)
+ }
+// text("Index\n") TODO
+// text("Link to allpage here")
+ }
+
+ protected open fun contentForPackage(p: DPackage) = contentBuilder.contentFor(p) {
+ group(kind = ContentKind.Cover) {
+ cover("Package ${p.name}")
+ if (contentForDescription(p).isNotEmpty()) {
+ sourceSetDependentHint(
+ p.dri,
+ p.sourceSets.toSet(),
+ kind = ContentKind.SourceSetDependentHint,
+ styles = setOf(TextStyle.UnderCoverText)
+ ) {
+ +contentForDescription(p)
+ }
+ }
+ }
+ group(styles = setOf(ContentStyle.TabbedContent)) {
+ +contentForComments(p)
+ +contentForScope(p, p.dri, p.sourceSets)
+ }
+ }
+
+ protected open fun contentForScope(
+ s: WithScope,
+ dri: DRI,
+ sourceSets: Set<DokkaSourceSet>
+ ) = contentBuilder.contentFor(s as Documentable) {
+ val types = listOf(
+ s.classlikes,
+ (s as? DPackage)?.typealiases ?: emptyList()
+ ).flatten()
+ divergentBlock("Types", types, ContentKind.Classlikes, extra = mainExtra + SimpleAttr.header("Types"))
+ divergentBlock(
+ "Functions",
+ s.functions,
+ ContentKind.Functions,
+ extra = mainExtra + SimpleAttr.header("Functions")
+ )
+ block(
+ "Properties",
+ 2,
+ ContentKind.Properties,
+ s.properties,
+ sourceSets.toSet(),
+ needsAnchors = true,
+ extra = mainExtra + SimpleAttr.header("Properties")
+ ) {
+ link(it.name, it.dri, kind = ContentKind.Main)
+ sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependentHint) {
+ contentForBrief(it)
+ +buildSignature(it)
+ }
+ }
+ s.safeAs<WithExtraProperties<Documentable>>()?.let { it.extra[InheritorsInfo] }?.let { inheritors ->
+ val map = inheritors.value.filter { it.value.isNotEmpty() }
+ if (map.values.any()) {
+ header(2, "Inheritors") { }
+ +ContentTable(
+ listOf(contentBuilder.contentFor(mainDRI, mainSourcesetData){
+ text("Name")
+ }),
+ map.entries.flatMap { entry -> entry.value.map { Pair(entry.key, it) } }
+ .groupBy({ it.second }, { it.first }).map { (classlike, platforms) ->
+ buildGroup(setOf(dri), platforms.toSet(), ContentKind.Inheritors) {
+ link(
+ classlike.classNames?.substringBeforeLast(".") ?: classlike.toString()
+ .also { logger.warn("No class name found for DRI $classlike") }, classlike
+ )
+ }
+ },
+ DCI(setOf(dri), ContentKind.Inheritors),
+ sourceSets.toSet(),
+ style = emptySet(),
+ extra = mainExtra + SimpleAttr.header("Inheritors")
+ )
+ }
+ }
+ }
+
+ protected open fun contentForEnumEntry(e: DEnumEntry) = contentBuilder.contentFor(e) {
+ group(kind = ContentKind.Cover) {
+ cover(e.name)
+ sourceSetDependentHint(e.dri, e.sourceSets.toSet()) {
+ +contentForDescription(e)
+ +buildSignature(e)
+ }
+ }
+ group(styles = setOf(ContentStyle.TabbedContent)) {
+ +contentForComments(e)
+ +contentForScope(e, e.dri, e.sourceSets)
+ }
+ }
+
+ protected open fun contentForClasslike(c: DClasslike) = contentBuilder.contentFor(c) {
+ @Suppress("UNCHECKED_CAST")
+ val extensions = (c as WithExtraProperties<DClasslike>)
+ .extra[CallableExtensions]?.extensions
+ ?.filterIsInstance<Documentable>().orEmpty()
+ // Extensions are added to sourceSets since they can be placed outside the sourceSets from classlike
+ // Example would be an Interface in common and extension function in jvm
+ group(kind = ContentKind.Cover, sourceSets = mainSourcesetData + extensions.sourceSets) {
+ cover(c.name.orEmpty())
+ sourceSetDependentHint(c.dri, c.sourceSets) {
+ +contentForDescription(c)
+ +buildSignature(c)
+ }
+ }
+
+ group(styles = setOf(ContentStyle.TabbedContent), sourceSets = mainSourcesetData + extensions.sourceSets) {
+ +contentForComments(c)
+ if (c is WithConstructors) {
+ block(
+ "Constructors",
+ 2,
+ ContentKind.Constructors,
+ c.constructors.filter { it.extra[PrimaryConstructorExtra] == null || it.documentation.isNotEmpty() },
+ c.sourceSets,
+ extra = PropertyContainer.empty<ContentNode>() + SimpleAttr.header("Constructors")
+ ) {
+ link(it.name, it.dri, kind = ContentKind.Main)
+ sourceSetDependentHint(
+ it.dri,
+ it.sourceSets.toSet(),
+ kind = ContentKind.SourceSetDependentHint,
+ styles = emptySet()
+ ) {
+ contentForBrief(it)
+ +buildSignature(it)
+ }
+ }
+ }
+ if (c is DEnum) {
+ block(
+ "Entries",
+ 2,
+ ContentKind.Classlikes,
+ c.entries,
+ c.sourceSets.toSet(),
+ needsSorting = false,
+ extra = mainExtra + SimpleAttr.header("Entries"),
+ styles = emptySet()
+ ) {
+ link(it.name, it.dri)
+ sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependentHint) {
+ contentForBrief(it)
+ +buildSignature(it)
+ }
+ }
+ }
+ +contentForScope(c, c.dri, c.sourceSets)
+
+ divergentBlock("Extensions", extensions, ContentKind.Extensions, extra = mainExtra + SimpleAttr.header("Extensions"))
+ }
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ private inline fun <reified T : TagWrapper> GroupedTags.withTypeUnnamed(): SourceSetDependent<T> =
+ (this[T::class] as List<Pair<DokkaSourceSet, T>>?)?.toMap().orEmpty()
+
+ @Suppress("UNCHECKED_CAST")
+ private inline fun <reified T : NamedTagWrapper> GroupedTags.withTypeNamed(): Map<String, SourceSetDependent<T>> =
+ (this[T::class] as List<Pair<DokkaSourceSet, T>>?)
+ ?.groupBy { it.second.name }
+ ?.mapValues { (_, v) -> v.toMap() }
+ ?.toSortedMap(String.CASE_INSENSITIVE_ORDER)
+ .orEmpty()
+
+ private inline fun <reified T : TagWrapper> GroupedTags.isNotEmptyForTag(): Boolean =
+ this[T::class]?.isNotEmpty() ?: false
+
+ protected open fun contentForDescription(
+ d: Documentable
+ ): List<ContentNode> {
+ val tags: GroupedTags = d.documentation.flatMap { (pd, doc) ->
+ doc.children.asSequence().map { pd to it }.toList()
+ }.groupBy { it.second::class }
+
+ val platforms = d.sourceSets.toSet()
+
+ return contentBuilder.contentFor(d, styles = setOf(TextStyle.Block)) {
+ val description = tags.withTypeUnnamed<Description>()
+ if (description.any { it.value.root.children.isNotEmpty() }) {
+ platforms.forEach { platform ->
+ description[platform]?.also {
+ group(sourceSets = setOf(platform)) {
+ comment(it.root)
+ }
+ }
+ }
+ }
+
+ val unnamedTags: List<SourceSetDependent<TagWrapper>> =
+ tags.filterNot { (k, _) -> k.isSubclassOf(NamedTagWrapper::class) || k in specialTags }
+ .map { (_, v) -> v.mapNotNull { (k, v) -> k?.let { it to v } }.toMap() }
+ if (unnamedTags.isNotEmpty()) {
+ platforms.forEach { platform ->
+ unnamedTags.forEach { pdTag ->
+ pdTag[platform]?.also { tag ->
+ group(sourceSets = setOf(platform)) {
+ header(4, tag.toHeaderString())
+ comment(tag.root)
+ }
+ }
+ }
+ }
+ }
+
+ contentForSinceKotlin(d)
+ }.children
+ }
+
+ private fun Documentable.getPossibleFallbackSourcesets(sourceSet: DokkaSourceSet) =
+ this.sourceSets.filter { it.sourceSetID in sourceSet.dependentSourceSets }
+
+ private fun <V> Map<DokkaSourceSet, V>.fallback(sourceSets: List<DokkaSourceSet>): V? =
+ sourceSets.firstOrNull { it in this.keys }.let { this[it] }
+
+ protected open fun contentForComments(
+ d: Documentable
+ ): List<ContentNode> {
+ val tags: GroupedTags = d.documentation.flatMap { (pd, doc) ->
+ doc.children.asSequence().map { pd to it }.toList()
+ }.groupBy { it.second::class }
+
+ val platforms = d.sourceSets
+
+ fun DocumentableContentBuilder.contentForParams() {
+ if (tags.isNotEmptyForTag<Param>()) {
+ header(2, "Parameters", kind = ContentKind.Parameters)
+ group(
+ extra = mainExtra + SimpleAttr.header("Parameters"),
+ styles = setOf(ContentStyle.WithExtraAttributes)
+ ) {
+ sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependentHint) {
+ val receiver = tags.withTypeUnnamed<Receiver>()
+ val params = tags.withTypeNamed<Param>()
+ table(kind = ContentKind.Parameters) {
+ platforms.flatMap { platform ->
+ val possibleFallbacks = d.getPossibleFallbackSourcesets(platform)
+ val receiverRow = (receiver[platform] ?: receiver.fallback(possibleFallbacks))?.let {
+ buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) {
+ text("<receiver>", styles = mainStyles + ContentStyle.RowTitle)
+ comment(it.root)
+ }
+ }
+
+ val paramRows = params.mapNotNull { (_, param) ->
+ (param[platform] ?: param.fallback(possibleFallbacks))?.let {
+ buildGroup(sourceSets = setOf(platform), kind = ContentKind.Parameters) {
+ text(
+ it.name,
+ kind = ContentKind.Parameters,
+ styles = mainStyles + ContentStyle.RowTitle
+ )
+ comment(it.root)
+ }
+ }
+ }
+
+ listOfNotNull(receiverRow) + paramRows
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun DocumentableContentBuilder.contentForSeeAlso() {
+ if (tags.isNotEmptyForTag<See>()) {
+ header(2, "See also", kind = ContentKind.Comment)
+ group(
+ extra = mainExtra + SimpleAttr.header("See also"),
+ styles = setOf(ContentStyle.WithExtraAttributes)
+ ) {
+ sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependentHint) {
+ val seeAlsoTags = tags.withTypeNamed<See>()
+ table(kind = ContentKind.Sample) {
+ platforms.flatMap { platform ->
+ val possibleFallbacks = d.getPossibleFallbackSourcesets(platform)
+ seeAlsoTags.mapNotNull { (_, see) ->
+ (see[platform] ?: see.fallback(possibleFallbacks))?.let {
+ buildGroup(
+ sourceSets = setOf(platform),
+ kind = ContentKind.Comment,
+ styles = mainStyles + ContentStyle.RowTitle
+ ) {
+ if (it.address != null) link(
+ it.name,
+ it.address!!,
+ kind = ContentKind.Comment
+ )
+ else text(it.name, kind = ContentKind.Comment)
+ comment(it.root)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun DocumentableContentBuilder.contentForSamples() {
+ val samples = tags.withTypeNamed<Sample>()
+ if (samples.isNotEmpty()) {
+ header(2, "Samples", kind = ContentKind.Sample)
+ group(
+ extra = mainExtra + SimpleAttr.header("Samples"),
+ styles = emptySet()
+ ) {
+ sourceSetDependentHint(sourceSets = platforms.toSet(), kind = ContentKind.SourceSetDependentHint) {
+ platforms.map { platformData ->
+ val content = samples.filter { it.value.isEmpty() || platformData in it.value }
+ group(
+ sourceSets = setOf(platformData),
+ kind = ContentKind.Sample,
+ styles = setOf(TextStyle.Monospace, ContentStyle.RunnableSample)
+ ) {
+ content.forEach {
+ text(it.key)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return contentBuilder.contentFor(d) {
+ if (tags.isNotEmpty()) {
+ contentForSamples()
+ contentForSeeAlso()
+ contentForParams()
+ }
+ }.children
+ }
+
+ protected open fun DocumentableContentBuilder.contentForBrief(documentable: Documentable) {
+ documentable.sourceSets.forEach { sourceSet ->
+ documentable.documentation[sourceSet]?.children?.firstOrNull()?.root?.let {
+ group(sourceSets = setOf(sourceSet), kind = ContentKind.BriefComment) {
+ comment(it)
+ }
+ }
+ }
+ }
+
+ protected open fun DocumentableContentBuilder.contentForSinceKotlin(documentable: Documentable) {
+ documentable.documentation.mapValues {
+ it.value.children.find { it is CustomTagWrapper && it.name == "Since Kotlin" } as CustomTagWrapper?
+ }.run {
+ documentable.sourceSets.forEach { sourceSet ->
+ this[sourceSet]?.also { tag ->
+ group(sourceSets = setOf(sourceSet), kind = ContentKind.Comment, styles = setOf(TextStyle.Block)) {
+ header(4, tag.name)
+ comment(tag.root)
+ }
+ }
+ }
+ }
+ }
+
+ protected open fun contentForFunction(f: DFunction) = contentForMember(f)
+ protected open fun contentForTypeAlias(t: DTypeAlias) = contentForMember(t)
+ protected open fun contentForMember(d: Documentable) = contentBuilder.contentFor(d) {
+ group(kind = ContentKind.Cover) {
+ cover(d.name.orEmpty())
+ }
+ divergentGroup(ContentDivergentGroup.GroupID("member")) {
+ instance(setOf(d.dri), d.sourceSets.toSet()) {
+ before {
+ +contentForDescription(d)
+ +contentForComments(d)
+ }
+ divergent(kind = ContentKind.Symbol) {
+ +buildSignature(d)
+ }
+ }
+ }
+ }
+
+ protected open fun DocumentableContentBuilder.divergentBlock(
+ name: String,
+ collection: Collection<Documentable>,
+ kind: ContentKind,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) {
+ if (collection.any()) {
+ header(2, name, kind = kind)
+ table(kind, extra = extra, styles = emptySet()) {
+ collection
+ .groupBy { it.name }
+ // This hacks displaying actual typealias signatures along classlike ones
+ .mapValues { if (it.value.any { it is DClasslike }) it.value.filter { it !is DTypeAlias } else it.value }
+ .toSortedMap(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)){it})
+ .map { (elementName, elements) -> // This groupBy should probably use LocationProvider
+ buildGroup(
+ dri = elements.map { it.dri }.toSet(),
+ sourceSets = elements.flatMap { it.sourceSets }.toSet(),
+ kind = kind,
+ styles = emptySet()
+ ) {
+ link(elementName.orEmpty(), elements.first().dri, kind = kind)
+ divergentGroup(
+ ContentDivergentGroup.GroupID(name),
+ elements.map { it.dri }.toSet(),
+ kind = kind
+ ) {
+ elements.map {
+ instance(setOf(it.dri), it.sourceSets.toSet()) {
+ before {
+ contentForBrief(it)
+ contentForSinceKotlin(it)
+ }
+ divergent {
+ group {
+ +buildSignature(it)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ protected open fun TagWrapper.toHeaderString() = this.javaClass.toGenericString().split('.').last()
+
+ private val List<Documentable>.sourceSets: Set<DokkaSourceSet>
+ get() = flatMap { it.sourceSets }.toSet()
+}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
new file mode 100644
index 00000000..b7927076
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
@@ -0,0 +1,474 @@
+package org.jetbrains.dokka.base.translators.documentables
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
+import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.Documentable
+import org.jetbrains.dokka.model.SourceSetDependent
+import org.jetbrains.dokka.model.doc.DocTag
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+@DslMarker
+annotation class ContentBuilderMarker
+
+open class PageContentBuilder(
+ val commentsConverter: CommentsToContentConverter,
+ val signatureProvider: SignatureProvider,
+ val logger: DokkaLogger
+) {
+ fun contentFor(
+ dri: DRI,
+ sourceSets: Set<DokkaSourceSet>,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = emptySet(),
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
+ block: DocumentableContentBuilder.() -> Unit
+ ): ContentGroup =
+ DocumentableContentBuilder(setOf(dri), sourceSets, styles, extra)
+ .apply(block)
+ .build(sourceSets, kind, styles, extra)
+
+ fun contentFor(
+ dri: Set<DRI>,
+ sourceSets: Set<DokkaSourceSet>,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = emptySet(),
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
+ block: DocumentableContentBuilder.() -> Unit
+ ): ContentGroup =
+ DocumentableContentBuilder(dri, sourceSets, styles, extra)
+ .apply(block)
+ .build(sourceSets, kind, styles, extra)
+
+ fun contentFor(
+ d: Documentable,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = emptySet(),
+ extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
+ sourceSets: Set<DokkaSourceSet> = d.sourceSets.toSet(),
+ block: DocumentableContentBuilder.() -> Unit = {}
+ ): ContentGroup =
+ DocumentableContentBuilder(setOf(d.dri), sourceSets, styles, extra)
+ .apply(block)
+ .build(sourceSets, kind, styles, extra)
+
+ @ContentBuilderMarker
+ open inner class DocumentableContentBuilder(
+ val mainDRI: Set<DRI>,
+ val mainSourcesetData: Set<DokkaSourceSet>,
+ val mainStyles: Set<Style>,
+ val mainExtra: PropertyContainer<ContentNode>
+ ) {
+ protected val contents = mutableListOf<ContentNode>()
+
+ fun build(
+ sourceSets: Set<DokkaSourceSet>,
+ kind: Kind,
+ styles: Set<Style>,
+ extra: PropertyContainer<ContentNode>
+ ) = ContentGroup(
+ contents.toList(),
+ DCI(mainDRI, kind),
+ sourceSets,
+ styles,
+ extra
+ )
+
+ operator fun ContentNode.unaryPlus() {
+ contents += this
+ }
+
+ operator fun Collection<ContentNode>.unaryPlus() {
+ contents += this
+ }
+
+ private val defaultHeaders
+ get() = listOf(
+ contentFor(mainDRI, mainSourcesetData){
+ text("Name")
+ },
+ contentFor(mainDRI, mainSourcesetData){
+ text("Summary")
+ }
+ )
+
+ fun header(
+ level: Int,
+ text: String,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit = {}
+ ) {
+ contents += ContentHeader(
+ level,
+ contentFor(
+ mainDRI,
+ sourceSets,
+ kind,
+ styles,
+ extra + SimpleAttr("anchor", text.replace("\\s".toRegex(), "").toLowerCase())
+ ) {
+ text(text, kind = kind)
+ block()
+ }
+ )
+ }
+
+ fun cover(
+ text: String,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles + TextStyle.Cover,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit = {}
+ ) {
+ header(1, text, sourceSets = sourceSets, styles = styles, extra = extra, block = block)
+ }
+
+ fun text(
+ text: String,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) {
+ contents += createText(text, kind, sourceSets, styles, extra)
+ }
+
+ fun buildSignature(d: Documentable) = signatureProvider.signature(d)
+
+ fun table(
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ operation: DocumentableContentBuilder.() -> List<ContentGroup>
+ ) {
+ contents += ContentTable(
+ defaultHeaders,
+ operation(),
+ DCI(mainDRI, kind),
+ sourceSets, styles, extra
+ )
+ }
+
+ fun <T : Documentable> block(
+ name: String,
+ level: Int,
+ kind: Kind = ContentKind.Main,
+ elements: Iterable<T>,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ renderWhenEmpty: Boolean = false,
+ needsSorting: Boolean = true,
+ headers: List<ContentGroup>? = null,
+ needsAnchors: Boolean = false,
+ operation: DocumentableContentBuilder.(T) -> Unit
+ ) {
+ if (renderWhenEmpty || elements.any()) {
+ header(level, name, kind = kind) { }
+ contents += ContentTable(
+ headers ?: defaultHeaders,
+ elements
+ .let {
+ if (needsSorting)
+ it.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.name })
+ else it
+ }
+ .map {
+ val newExtra = if (needsAnchors) extra + SymbolAnchorHint else extra
+ buildGroup(setOf(it.dri), it.sourceSets.toSet(), kind, styles, newExtra) {
+ operation(it)
+ }
+ },
+ DCI(mainDRI, kind),
+ sourceSets, styles, extra
+ )
+ }
+ }
+
+ fun <T> list(
+ elements: List<T>,
+ prefix: String = "",
+ suffix: String = "",
+ separator: String = ", ",
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData, // TODO: children should be aware of this platform data
+ operation: DocumentableContentBuilder.(T) -> Unit
+ ) {
+ if (elements.isNotEmpty()) {
+ if (prefix.isNotEmpty()) text(prefix, sourceSets = sourceSets)
+ elements.dropLast(1).forEach {
+ operation(it)
+ text(separator, sourceSets = sourceSets)
+ }
+ operation(elements.last())
+ if (suffix.isNotEmpty()) text(suffix, sourceSets = sourceSets)
+ }
+ }
+
+ fun link(
+ text: String,
+ address: DRI,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) {
+ contents += linkNode(text, address, kind, sourceSets, styles, extra)
+ }
+
+ fun linkNode(
+ text: String,
+ address: DRI,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) = ContentDRILink(
+ listOf(createText(text, kind, sourceSets, styles, extra)),
+ address,
+ DCI(mainDRI, kind),
+ sourceSets
+ )
+
+ fun link(
+ text: String,
+ address: String,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) {
+ contents += ContentResolvedLink(
+ children = listOf(createText(text, kind, sourceSets, styles, extra)),
+ address = address,
+ extra = PropertyContainer.empty(),
+ dci = DCI(mainDRI, kind),
+ sourceSets = sourceSets,
+ style = emptySet()
+ )
+ }
+
+ fun link(
+ address: DRI,
+ kind: Kind = ContentKind.Main,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contents += ContentDRILink(
+ contentFor(mainDRI, sourceSets, kind, styles, extra, block).children,
+ address,
+ DCI(mainDRI, kind),
+ sourceSets
+ )
+ }
+
+ fun comment(
+ docTag: DocTag,
+ kind: Kind = ContentKind.Comment,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) {
+ val content = commentsConverter.buildContent(
+ docTag,
+ DCI(mainDRI, kind),
+ sourceSets
+ )
+ contents += ContentGroup(content, DCI(mainDRI, kind), sourceSets, styles, extra)
+ }
+
+ fun group(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contents += buildGroup(dri, sourceSets, kind, styles, extra, block)
+ }
+
+ fun divergentGroup(
+ groupID: ContentDivergentGroup.GroupID,
+ dri: Set<DRI> = mainDRI,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ implicitlySourceSetHinted: Boolean = true,
+ block: DivergentBuilder.() -> Unit
+ ) {
+ contents +=
+ DivergentBuilder(dri, kind, styles, extra)
+ .apply(block)
+ .build(groupID = groupID, implicitlySourceSetHinted = implicitlySourceSetHinted)
+ }
+
+ fun buildGroup(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ): ContentGroup = contentFor(dri, sourceSets, kind, styles, extra, block)
+
+ fun sourceSetDependentHint(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contents += PlatformHintedContent(
+ buildGroup(dri, sourceSets, kind, styles, extra, block),
+ sourceSets
+ )
+ }
+
+ fun sourceSetDependentHint(
+ dri: DRI,
+ sourcesetData: Set<DokkaSourceSet> = mainSourcesetData,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contents += PlatformHintedContent(
+ buildGroup(setOf(dri), sourcesetData, kind, styles, extra, block),
+ sourcesetData
+ )
+ }
+
+ protected fun createText(
+ text: String,
+ kind: Kind,
+ sourceSets: Set<DokkaSourceSet>,
+ styles: Set<Style>,
+ extra: PropertyContainer<ContentNode>
+ ) =
+ ContentText(text, DCI(mainDRI, kind), sourceSets, styles, extra)
+
+ fun <T> sourceSetDependentText(
+ value: SourceSetDependent<T>,
+ sourceSets: Set<DokkaSourceSet> = value.keys,
+ transform: (T) -> String
+ ) = value.entries.filter { it.key in sourceSets }.mapNotNull { (p, v) ->
+ transform(v).takeIf { it.isNotBlank() }?.let { it to p }
+ }.groupBy({ it.first }) { it.second }.forEach {
+ text(it.key, sourceSets = it.value.toSet())
+ }
+ }
+
+ @ContentBuilderMarker
+ open inner class DivergentBuilder(
+ private val mainDRI: Set<DRI>,
+ private val mainKind: Kind,
+ private val mainStyles: Set<Style>,
+ private val mainExtra: PropertyContainer<ContentNode>
+ ) {
+ private val instances: MutableList<ContentDivergentInstance> = mutableListOf()
+ fun instance(
+ dri: Set<DRI>,
+ sourceSets: Set<DokkaSourceSet>, // Having correct sourcesetData is crucial here, that's why there's no default
+ kind: Kind = mainKind,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DivergentInstanceBuilder.() -> Unit
+ ) {
+ instances += DivergentInstanceBuilder(dri, sourceSets, styles, extra)
+ .apply(block)
+ .build(kind)
+ }
+
+ fun build(
+ groupID: ContentDivergentGroup.GroupID,
+ implicitlySourceSetHinted: Boolean,
+ kind: Kind = mainKind,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) = ContentDivergentGroup(
+ instances.toList(),
+ DCI(mainDRI, kind),
+ styles,
+ extra,
+ groupID,
+ implicitlySourceSetHinted
+ )
+ }
+
+ @ContentBuilderMarker
+ open inner class DivergentInstanceBuilder(
+ private val mainDRI: Set<DRI>,
+ private val mainSourceSets: Set<DokkaSourceSet>,
+ private val mainStyles: Set<Style>,
+ private val mainExtra: PropertyContainer<ContentNode>
+ ) {
+ private var before: ContentNode? = null
+ private var divergent: ContentNode? = null
+ private var after: ContentNode? = null
+
+ fun before(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourceSets,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contentFor(dri, sourceSets, kind, styles, extra, block)
+ .takeIf { it.hasAnyContent() }
+ .also { before = it }
+ }
+
+ fun divergent(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourceSets,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ divergent = contentFor(dri, sourceSets, kind, styles, extra, block)
+ }
+
+ fun after(
+ dri: Set<DRI> = mainDRI,
+ sourceSets: Set<DokkaSourceSet> = mainSourceSets,
+ kind: Kind = ContentKind.Main,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra,
+ block: DocumentableContentBuilder.() -> Unit
+ ) {
+ contentFor(dri, sourceSets, kind, styles, extra, block)
+ .takeIf { it.hasAnyContent() }
+ .also { after = it }
+ }
+
+
+ fun build(
+ kind: Kind,
+ sourceSets: Set<DokkaSourceSet> = mainSourceSets,
+ styles: Set<Style> = mainStyles,
+ extra: PropertyContainer<ContentNode> = mainExtra
+ ) =
+ ContentDivergentInstance(
+ before,
+ divergent ?: throw IllegalStateException("Divergent block needs divergent part"),
+ after,
+ DCI(mainDRI, kind),
+ sourceSets,
+ styles,
+ extra
+ )
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
new file mode 100644
index 00000000..6f980383
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -0,0 +1,480 @@
+package org.jetbrains.dokka.base.translators.psi
+
+import com.intellij.lang.jvm.JvmModifier
+import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute
+import com.intellij.lang.jvm.types.JvmReferenceType
+import com.intellij.openapi.vfs.VirtualFileManager
+import com.intellij.psi.*
+import com.intellij.psi.impl.source.PsiClassReferenceType
+import com.intellij.psi.impl.source.PsiImmediateClassType
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.analysis.KotlinAnalysis
+import org.jetbrains.dokka.analysis.PsiDocumentableSource
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.DriWithKind
+import org.jetbrains.dokka.links.nextTarget
+import org.jetbrains.dokka.links.withClass
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.doc.DocumentationLink
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.model.doc.Param
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
+import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
+import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
+import org.jetbrains.kotlin.descriptors.Visibilities
+import org.jetbrains.kotlin.load.java.JvmAbi
+import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName
+import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import java.io.File
+
+class DefaultPsiToDocumentableTranslator(
+ private val kotlinAnalysis: KotlinAnalysis
+) : SourceToDocumentableTranslator {
+
+ override fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
+
+ fun isFileInSourceRoots(file: File) : Boolean {
+ return sourceSet.sourceRoots.any { root -> file.path.startsWith(File(root.path).absolutePath) }
+ }
+
+ val (environment, _) = kotlinAnalysis[sourceSet]
+
+ val sourceRoots = environment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
+ ?.filterIsInstance<JavaSourceRoot>()
+ ?.mapNotNull { it.file.takeIf(::isFileInSourceRoots) }
+ ?: listOf()
+ val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file")
+
+ val psiFiles = sourceRoots.map { sourceRoot ->
+ sourceRoot.absoluteFile.walkTopDown().mapNotNull {
+ localFileSystem.findFileByPath(it.path)?.let { vFile ->
+ PsiManager.getInstance(environment.project).findFile(vFile) as? PsiJavaFile
+ }
+ }.toList()
+ }.flatten()
+
+ val docParser =
+ DokkaPsiParser(
+ sourceSet,
+ context.logger
+ )
+ return DModule(
+ sourceSet.moduleDisplayName,
+ psiFiles.mapNotNull { it.safeAs<PsiJavaFile>() }.groupBy { it.packageName }.map { (packageName, psiFiles) ->
+ val dri = DRI(packageName = packageName)
+ DPackage(
+ dri,
+ emptyList(),
+ emptyList(),
+ psiFiles.flatMap { psiFile ->
+ psiFile.classes.map { docParser.parseClasslike(it, dri) }
+ },
+ emptyList(),
+ emptyMap(),
+ null,
+ setOf(sourceSet)
+ )
+ },
+ emptyMap(),
+ null,
+ setOf(sourceSet)
+ )
+ }
+
+ class DokkaPsiParser(
+ private val sourceSetData: DokkaSourceSet,
+ private val logger: DokkaLogger
+ ) {
+
+ private val javadocParser: JavaDocumentationParser = JavadocParser(logger)
+
+ private val cachedBounds = hashMapOf<String, Bound>()
+
+ private fun PsiModifierListOwner.getVisibility() = modifierList?.children?.toList()?.let { ml ->
+ when {
+ ml.any { it.text == PsiKeyword.PUBLIC } -> JavaVisibility.Public
+ ml.any { it.text == PsiKeyword.PROTECTED } -> JavaVisibility.Protected
+ ml.any { it.text == PsiKeyword.PRIVATE } -> JavaVisibility.Private
+ else -> JavaVisibility.Default
+ }
+ } ?: JavaVisibility.Default
+
+ private val PsiMethod.hash: Int
+ get() = "$returnType $name$parameterList".hashCode()
+
+ private val PsiClassType.shouldBeIgnored: Boolean
+ get() = isClass("java.lang.Enum") || isClass("java.lang.Object")
+
+ private fun PsiClassType.isClass(qName: String): Boolean {
+ val shortName = qName.substringAfterLast('.')
+ if (className == shortName) {
+ val psiClass = resolve()
+ return psiClass?.qualifiedName == qName
+ }
+ return false
+ }
+
+ private fun <T> T.toSourceSetDependent() = mapOf(sourceSetData to this)
+
+ fun parseClasslike(psi: PsiClass, parent: DRI): DClasslike = with(psi) {
+ val dri = parent.withClass(name.toString())
+ val inheritanceTree = mutableListOf<AncestorLevel>()
+ val superMethodsKeys = hashSetOf<Int>()
+ val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
+ methods.forEach { superMethodsKeys.add(it.hash) }
+ fun parseSupertypes(superTypes: Array<PsiClassType>, level: Int = 0) {
+ if(superTypes.isEmpty()) return
+ val parsedClasses = superTypes.filter { !it.shouldBeIgnored }.mapNotNull {
+ it.resolve()?.let {
+ when {
+ it.isInterface -> DRI.from(it) to JavaClassKindTypes.INTERFACE
+ else -> DRI.from(it) to JavaClassKindTypes.CLASS
+ }
+ }
+ }
+ val (classes, interfaces) = parsedClasses.partition { it.second == JavaClassKindTypes.CLASS }
+ inheritanceTree.add(AncestorLevel(level, classes.firstOrNull()?.first, interfaces.map { it.first }))
+
+ superTypes.forEach { type ->
+ (type as? PsiClassType)?.takeUnless { type.shouldBeIgnored }?.resolve()?.let {
+ val definedAt = DRI.from(it)
+ it.methods.forEach { method ->
+ val hash = method.hash
+ if (!method.isConstructor && !superMethodsKeys.contains(hash) &&
+ method.getVisibility() != Visibilities.PRIVATE
+ ) {
+ superMethodsKeys.add(hash)
+ superMethods.add(Pair(method, definedAt))
+ }
+ }
+ parseSupertypes(it.superTypes, level + 1)
+ }
+ }
+ }
+ parseSupertypes(superTypes)
+ val (regularFunctions, accessors) = splitFunctionsAndAccessors()
+ val documentation = javadocParser.parseDocumentation(this).toSourceSetDependent()
+ val allFunctions = regularFunctions.mapNotNull { if (!it.isConstructor) parseFunction(it) else null } +
+ superMethods.map { parseFunction(it.first, inheritedFrom = it.second) }
+ val source = PsiDocumentableSource(this).toSourceSetDependent()
+ val classlikes = innerClasses.map { parseClasslike(it, dri) }
+ val visibility = getVisibility().toSourceSetDependent()
+ val ancestors = inheritanceTree.filter { it.level == 0 }.flatMap {
+ listOfNotNull(it.superclass?.let {
+ DriWithKind(
+ dri = it,
+ kind = JavaClassKindTypes.CLASS
+ )
+ }) + it.interfaces.map { DriWithKind(dri = it, kind = JavaClassKindTypes.INTERFACE) }
+ }.toSourceSetDependent()
+ val modifiers = getModifier().toSourceSetDependent()
+ val implementedInterfacesExtra = ImplementedInterfaces(inheritanceTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
+ return when {
+ isAnnotationType ->
+ DAnnotation(
+ name.orEmpty(),
+ dri,
+ documentation,
+ null,
+ source,
+ allFunctions,
+ fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
+ classlikes,
+ visibility,
+ null,
+ constructors.map { parseFunction(it, true) },
+ mapTypeParameters(dri),
+ setOf(sourceSetData),
+ PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations())
+ )
+ isEnum -> DEnum(
+ dri,
+ name.orEmpty(),
+ fields.filterIsInstance<PsiEnumConstant>().map { entry ->
+ DEnumEntry(
+ dri.withClass("${entry.name}"),
+ entry.name,
+ javadocParser.parseDocumentation(entry).toSourceSetDependent(),
+ null,
+ emptyList(),
+ emptyList(),
+ emptyList(),
+ setOf(sourceSetData),
+ PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations())
+ )
+ },
+ documentation,
+ null,
+ source,
+ allFunctions,
+ fields.filter { it !is PsiEnumConstant }.map { parseField(it, accessors[it].orEmpty()) },
+ classlikes,
+ visibility,
+ null,
+ constructors.map { parseFunction(it, true) },
+ ancestors,
+ setOf(sourceSetData),
+ PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations())
+ )
+ isInterface -> DInterface(
+ dri,
+ name.orEmpty(),
+ documentation,
+ null,
+ source,
+ allFunctions,
+ fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
+ classlikes,
+ visibility,
+ null,
+ mapTypeParameters(dri),
+ ancestors,
+ setOf(sourceSetData),
+ PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations())
+ )
+ else -> DClass(
+ dri,
+ name.orEmpty(),
+ constructors.map { parseFunction(it, true) },
+ allFunctions,
+ fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
+ classlikes,
+ source,
+ visibility,
+ null,
+ mapTypeParameters(dri),
+ ancestors,
+ documentation,
+ null,
+ modifiers,
+ setOf(sourceSetData),
+ PropertyContainer.withAll(implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations())
+ )
+ }
+ }
+
+ private fun parseFunction(
+ psi: PsiMethod,
+ isConstructor: Boolean = false,
+ inheritedFrom: DRI? = null
+ ): DFunction {
+ val dri = DRI.from(psi)
+ val docs = javadocParser.parseDocumentation(psi)
+ return DFunction(
+ dri,
+ if (isConstructor) "<init>" else psi.name,
+ isConstructor,
+ psi.parameterList.parameters.map { psiParameter ->
+ DParameter(
+ dri.copy(target = dri.target.nextTarget()),
+ psiParameter.name,
+ DocumentationNode(
+ listOfNotNull(docs.firstChildOfTypeOrNull<Param> {
+ it.firstChildOfTypeOrNull<DocumentationLink>()
+ ?.firstChildOfTypeOrNull<Text>()?.body == psiParameter.name
+ })).toSourceSetDependent(),
+ null,
+ getBound(psiParameter.type),
+ setOf(sourceSetData)
+ )
+ },
+ docs.toSourceSetDependent(),
+ null,
+ PsiDocumentableSource(psi).toSourceSetDependent(),
+ psi.getVisibility().toSourceSetDependent(),
+ psi.returnType?.let { getBound(type = it) } ?: Void,
+ psi.mapTypeParameters(dri),
+ null,
+ psi.getModifier().toSourceSetDependent(),
+ setOf(sourceSetData),
+ psi.additionalExtras().let {
+ PropertyContainer.withAll(
+ InheritedFunction(inheritedFrom.toSourceSetDependent()),
+ it.toSourceSetDependent().toAdditionalModifiers(),
+ (psi.annotations.toList().toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
+ .toAnnotations()
+ )
+ }
+ )
+ }
+
+ private fun PsiModifierListOwner.additionalExtras() = listOfNotNull(
+ ExtraModifiers.JavaOnlyModifiers.Static.takeIf { hasModifier(JvmModifier.STATIC) },
+ ExtraModifiers.JavaOnlyModifiers.Native.takeIf { hasModifier(JvmModifier.NATIVE) },
+ ExtraModifiers.JavaOnlyModifiers.Synchronized.takeIf { hasModifier(JvmModifier.SYNCHRONIZED) },
+ ExtraModifiers.JavaOnlyModifiers.StrictFP.takeIf { hasModifier(JvmModifier.STRICTFP) },
+ ExtraModifiers.JavaOnlyModifiers.Transient.takeIf { hasModifier(JvmModifier.TRANSIENT) },
+ ExtraModifiers.JavaOnlyModifiers.Volatile.takeIf { hasModifier(JvmModifier.VOLATILE) },
+ ExtraModifiers.JavaOnlyModifiers.Transitive.takeIf { hasModifier(JvmModifier.TRANSITIVE) }
+ ).toSet()
+
+ private fun Set<ExtraModifiers>.toListOfAnnotations() = map {
+ if (it !is ExtraModifiers.JavaOnlyModifiers.Static)
+ Annotations.Annotation(DRI("kotlin.jvm", it.name.toLowerCase().capitalize()), emptyMap())
+ else
+ Annotations.Annotation(DRI("kotlin.jvm", "JvmStatic"), emptyMap())
+ }
+
+ private fun getBound(type: PsiType): Bound =
+ cachedBounds.getOrPut(type.canonicalText) {
+ when (type) {
+ is PsiClassReferenceType -> {
+ val resolved: PsiClass = type.resolve()
+ ?: return UnresolvedBound(type.presentableText)
+ when {
+ resolved.qualifiedName == "java.lang.Object" -> JavaObject
+ resolved is PsiTypeParameter && resolved.owner != null ->
+ OtherParameter(
+ declarationDRI = DRI.from(resolved.owner!!),
+ name = resolved.name.orEmpty()
+ )
+ else ->
+ TypeConstructor(DRI.from(resolved), type.parameters.map { getProjection(it) })
+ }
+ }
+ is PsiArrayType -> TypeConstructor(
+ DRI("kotlin", "Array"),
+ listOf(getProjection(type.componentType))
+ )
+ is PsiPrimitiveType -> if (type.name == "void") Void else PrimitiveJavaType(type.name)
+ is PsiImmediateClassType -> JavaObject
+ else -> throw IllegalStateException("${type.presentableText} is not supported by PSI parser")
+ }
+ }
+
+ private fun getVariance(type: PsiWildcardType): Projection = when {
+ type.extendsBound != PsiType.NULL -> Variance(Variance.Kind.Out, getBound(type.extendsBound))
+ type.superBound != PsiType.NULL -> Variance(Variance.Kind.In, getBound(type.superBound))
+ else -> throw IllegalStateException("${type.presentableText} has incorrect bounds")
+ }
+
+ private fun getProjection(type: PsiType): Projection = when (type) {
+ is PsiEllipsisType -> Star
+ is PsiWildcardType -> getVariance(type)
+ else -> getBound(type)
+ }
+
+ private fun PsiModifierListOwner.getModifier() = when {
+ hasModifier(JvmModifier.ABSTRACT) -> JavaModifier.Abstract
+ hasModifier(JvmModifier.FINAL) -> JavaModifier.Final
+ else -> JavaModifier.Empty
+ }
+
+ private fun PsiTypeParameterListOwner.mapTypeParameters(dri: DRI): List<DTypeParameter> {
+ fun mapBounds(bounds: Array<JvmReferenceType>): List<Bound> =
+ if (bounds.isEmpty()) emptyList() else bounds.mapNotNull {
+ (it as? PsiClassType)?.let { classType -> Nullable(getBound(classType)) }
+ }
+ return typeParameters.map { type ->
+ DTypeParameter(
+ dri.copy(target = dri.target.nextTarget()),
+ type.name.orEmpty(),
+ javadocParser.parseDocumentation(type).toSourceSetDependent(),
+ null,
+ mapBounds(type.bounds),
+ setOf(sourceSetData)
+ )
+ }
+ }
+
+ private fun PsiMethod.getPropertyNameForFunction() =
+ getAnnotation(DescriptorUtils.JVM_NAME.asString())?.findAttributeValue("name")?.text
+ ?: when {
+ JvmAbi.isGetterName(name) -> propertyNameByGetMethodName(Name.identifier(name))?.asString()
+ JvmAbi.isSetterName(name) -> propertyNamesBySetMethodName(Name.identifier(name)).firstOrNull()
+ ?.asString()
+ else -> null
+ }
+
+ private fun PsiClass.splitFunctionsAndAccessors(): Pair<MutableList<PsiMethod>, MutableMap<PsiField, MutableList<PsiMethod>>> {
+ val fieldNames = fields.map { it.name to it }.toMap()
+ val accessors = mutableMapOf<PsiField, MutableList<PsiMethod>>()
+ val regularMethods = mutableListOf<PsiMethod>()
+ methods.forEach { method ->
+ val field = method.getPropertyNameForFunction()?.let { name -> fieldNames[name] }
+ if (field != null) {
+ accessors.getOrPut(field, ::mutableListOf).add(method)
+ } else {
+ regularMethods.add(method)
+ }
+ }
+ return regularMethods to accessors
+ }
+
+ private fun parseField(psi: PsiField, accessors: List<PsiMethod>): DProperty {
+ val dri = DRI.from(psi)
+ return DProperty(
+ dri,
+ psi.name,
+ javadocParser.parseDocumentation(psi).toSourceSetDependent(),
+ null,
+ PsiDocumentableSource(psi).toSourceSetDependent(),
+ psi.getVisibility().toSourceSetDependent(),
+ getBound(psi.type),
+ null,
+ accessors.firstOrNull { it.hasParameters() }?.let { parseFunction(it) },
+ accessors.firstOrNull { it.returnType == psi.type }?.let { parseFunction(it) },
+ psi.getModifier().toSourceSetDependent(),
+ setOf(sourceSetData),
+ emptyList(),
+ psi.additionalExtras().let {
+ PropertyContainer.withAll<DProperty>(
+ it.toSourceSetDependent().toAdditionalModifiers(),
+ (psi.annotations.toList().toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
+ .toAnnotations()
+ )
+ }
+ )
+ }
+
+ private fun Collection<PsiAnnotation>.toListOfAnnotations() =
+ filter { it !is KtLightAbstractAnnotation }.mapNotNull { it.toAnnotation() }
+
+ private fun JvmAnnotationAttribute.toValue(): AnnotationParameterValue = when (this) {
+ is PsiNameValuePair -> value?.toValue() ?: StringValue("")
+ else -> StringValue(this.attributeName)
+ }
+
+ private fun PsiAnnotationMemberValue.toValue(): AnnotationParameterValue? = when (this) {
+ is PsiAnnotation -> toAnnotation()?.let { AnnotationValue(it) }
+ is PsiArrayInitializerMemberValue -> ArrayValue(initializers.mapNotNull { it.toValue() })
+ is PsiReferenceExpression -> psiReference?.let { EnumValue(text ?: "", DRI.from(it)) }
+ is PsiClassObjectAccessExpression -> {
+ val psiClass = ((type as PsiImmediateClassType).parameters.single() as PsiClassReferenceType).resolve()
+ psiClass?.let { ClassValue(text ?: "", DRI.from(psiClass)) }
+ }
+ else -> StringValue(text ?: "")
+ }
+
+ private fun PsiAnnotation.toAnnotation() = psiReference?.let { psiElement ->
+ Annotations.Annotation(
+ DRI.from(psiElement),
+ attributes.filter { it !is KtLightAbstractAnnotation }.mapNotNull { it.attributeName to it.toValue() }
+ .toMap(),
+ (psiElement as PsiClass).annotations.any {
+ it.hasQualifiedName("java.lang.annotation.Documented")
+ }
+ )
+ }
+
+ private val PsiElement.psiReference
+ get() = getChildOfType<PsiJavaCodeReferenceElement>()?.resolve()
+ }
+
+ private data class AncestorLevel(val level: Int, val superclass: DRI?, val interfaces: List<DRI>)
+}
diff --git a/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
new file mode 100644
index 00000000..81955fde
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/psi/JavadocParser.kt
@@ -0,0 +1,216 @@
+package org.jetbrains.dokka.base.translators.psi
+
+import com.intellij.psi.*
+import com.intellij.psi.impl.source.javadoc.PsiDocParamRef
+import com.intellij.psi.impl.source.tree.JavaDocElementType
+import com.intellij.psi.impl.source.tree.LeafPsiElement
+import com.intellij.psi.javadoc.*
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.doc.Deprecated
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
+import org.jsoup.nodes.TextNode
+
+interface JavaDocumentationParser {
+ fun parseDocumentation(element: PsiNamedElement): DocumentationNode
+}
+
+class JavadocParser(
+ private val logger: DokkaLogger // TODO: Add logging
+) : JavaDocumentationParser {
+
+ override fun parseDocumentation(element: PsiNamedElement): DocumentationNode {
+ val docComment = findClosestDocComment(element) ?: return DocumentationNode(emptyList())
+ val nodes = mutableListOf<TagWrapper>()
+ docComment.getDescription()?.let { nodes.add(it) }
+ nodes.addAll(docComment.tags.mapNotNull { tag ->
+ when (tag.name) {
+ "param" -> Param(P(convertJavadocElements(tag.dataElements.toList())), tag.text)
+ "throws" -> Throws(P(convertJavadocElements(tag.dataElements.toList())), tag.text)
+ "return" -> Return(P(convertJavadocElements(tag.dataElements.toList())))
+ "author" -> Author(P(convertJavadocElements(tag.dataElements.toList())))
+ "see" -> See(P(getSeeTagElementContent(tag)), tag.referenceElement()?.text.orEmpty(), null)
+ "deprecated" -> Deprecated(P(convertJavadocElements(tag.dataElements.toList())))
+ else -> null
+ }
+ })
+ return DocumentationNode(nodes)
+ }
+
+ private fun findClosestDocComment(element: PsiNamedElement): PsiDocComment? {
+ (element as? PsiDocCommentOwner)?.docComment?.run { return this }
+ if (element is PsiMethod) {
+ val superMethods = element.findSuperMethodsOrEmptyArray()
+ if (superMethods.isEmpty()) return null
+
+ if (superMethods.size == 1) {
+ return findClosestDocComment(superMethods.single())
+ }
+
+ val superMethodDocumentation = superMethods.map(::findClosestDocComment)
+ if (superMethodDocumentation.size == 1) {
+ return superMethodDocumentation.single()
+ }
+
+ logger.warn(
+ "Conflicting documentation for ${DRI.from(element)}" +
+ "${superMethods.map { DRI.from(it) }}"
+ )
+
+ /* Prioritize super class over interface */
+ val indexOfSuperClass = superMethods.indexOfFirst { method ->
+ val parent = method.parent
+ if (parent is PsiClass) !parent.isInterface
+ else false
+ }
+
+ return if (indexOfSuperClass >= 0) superMethodDocumentation[indexOfSuperClass]
+ else superMethodDocumentation.first()
+ }
+
+ return null
+ }
+
+ /**
+ * Workaround for failing [PsiMethod.findSuperMethods].
+ * This might be resolved once ultra light classes are enabled for dokka
+ * See [KT-39518](https://youtrack.jetbrains.com/issue/KT-39518)
+ */
+ private fun PsiMethod.findSuperMethodsOrEmptyArray(): Array<PsiMethod> {
+ return try {
+ /*
+ We are not even attempting to call "findSuperMethods" on all methods called "getGetter" or "getSetter"
+ on any object implementing "kotlin.reflect.KProperty", since we know that those methods will fail
+ (KT-39518). Just catching the exception is not good enough, since "findSuperMethods" will
+ print the whole exception to stderr internally and then spoil the console.
+ */
+ val kPropertyFqName = FqName("kotlin.reflect.KProperty")
+ if (
+ this.parent?.safeAs<PsiClass>()?.implementsInterface(kPropertyFqName) == true &&
+ (this.name == "getSetter" || this.name == "getGetter")
+ ) {
+ logger.warn("Skipped lookup of super methods for ${getKotlinFqName()} (KT-39518)")
+ return emptyArray()
+ }
+ findSuperMethods()
+ } catch (exception: Throwable) {
+ logger.warn("Failed to lookup of super methods for ${getKotlinFqName()} (KT-39518)")
+ emptyArray()
+ }
+ }
+
+ private fun PsiClass.implementsInterface(fqName: FqName): Boolean {
+ return allInterfaces().any { it.getKotlinFqName() == fqName }
+ }
+
+ private fun PsiClass.allInterfaces(): Sequence<PsiClass> {
+ return sequence {
+ this.yieldAll(interfaces.toList())
+ interfaces.forEach { yieldAll(it.allInterfaces()) }
+ }
+ }
+
+ private fun getSeeTagElementContent(tag: PsiDocTag): List<DocTag> =
+ listOfNotNull(tag.referenceElement()?.toDocumentationLink())
+
+ private fun PsiDocComment.getDescription(): Description? {
+ val nonEmptyDescriptionElements = descriptionElements.filter { it.text.trim().isNotEmpty() }
+ val convertedDescriptionElements = convertJavadocElements(nonEmptyDescriptionElements)
+ if (convertedDescriptionElements.isNotEmpty()) {
+ return Description(P(convertedDescriptionElements))
+ }
+
+ return null
+ }
+
+ private fun convertJavadocElements(elements: Iterable<PsiElement>): List<DocTag> =
+ elements.mapNotNull {
+ when (it) {
+ is PsiReference -> convertJavadocElements(it.children.toList())
+ is PsiInlineDocTag -> listOfNotNull(convertInlineDocTag(it))
+ is PsiDocParamRef -> listOfNotNull(it.toDocumentationLink())
+ is PsiDocTagValue,
+ is LeafPsiElement -> Jsoup.parse(it.text.trim()).body().childNodes().mapNotNull(::convertHtmlNode)
+ else -> null
+ }
+ }.flatten()
+
+ private fun convertHtmlNode(node: Node, insidePre: Boolean = false): DocTag? = when (node) {
+ is TextNode -> Text(body = if (insidePre) node.wholeText else node.text())
+ is Element -> createBlock(node)
+ else -> null
+ }
+
+ private fun createBlock(element: Element): DocTag {
+ val children = element.childNodes().mapNotNull { convertHtmlNode(it) }
+ return when (element.tagName()) {
+ "p" -> P(listOf(Br, Br) + children)
+ "b" -> B(children)
+ "strong" -> Strong(children)
+ "i" -> I(children)
+ "em" -> Em(children)
+ "code" -> CodeBlock(children)
+ "pre" -> Pre(children)
+ "ul" -> Ul(children)
+ "ol" -> Ol(children)
+ "li" -> Li(children)
+ "a" -> createLink(element, children)
+ else -> Text(body = element.ownText())
+ }
+ }
+
+ private fun createLink(element: Element, children: List<DocTag>): DocTag {
+ return when {
+ element.hasAttr("docref") -> {
+ A(children, params = mapOf("docref" to element.attr("docref")))
+ }
+ element.hasAttr("href") -> {
+ A(children, params = mapOf("href" to element.attr("href")))
+ }
+ else -> Text(children = children)
+ }
+ }
+
+ private fun PsiDocToken.isSharpToken() = tokenType.toString() == "DOC_TAG_VALUE_SHARP_TOKEN"
+
+ private fun PsiElement.toDocumentationLink(labelElement: PsiElement? = null) =
+ reference?.resolve()?.let {
+ val dri = DRI.from(it)
+ val label = labelElement ?: children.firstOrNull {
+ it is PsiDocToken && it.text.isNotBlank() && !it.isSharpToken()
+ } ?: this
+ DocumentationLink(dri, convertJavadocElements(listOfNotNull(label)))
+ }
+
+ private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) {
+ "link", "linkplain" -> {
+ tag.referenceElement()?.toDocumentationLink(tag.dataElements.firstIsInstanceOrNull<PsiDocToken>())
+ }
+ "code", "literal" -> {
+ CodeInline(listOf(Text(tag.text)))
+ }
+ "index" -> Index(tag.children.filterIsInstance<PsiDocTagValue>().map { Text(it.text) })
+ else -> Text(tag.text)
+ }
+
+ private fun PsiDocTag.referenceElement(): PsiElement? =
+ linkElement()?.let {
+ if (it.node.elementType == JavaDocElementType.DOC_REFERENCE_HOLDER) {
+ PsiTreeUtil.findChildOfType(it, PsiJavaCodeReferenceElement::class.java)
+ } else {
+ it
+ }
+ }
+
+ private fun PsiDocTag.linkElement(): PsiElement? =
+ valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace }
+}
diff --git a/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
new file mode 100644
index 00000000..bc8de448
--- /dev/null
+++ b/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
@@ -0,0 +1 @@
+org.jetbrains.dokka.base.DokkaBase
diff --git a/plugins/base/src/main/resources/dokka/format/gfm.properties b/plugins/base/src/main/resources/dokka/format/gfm.properties
new file mode 100644
index 00000000..5e8f7aa8
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/gfm.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.GFMFormatDescriptor
+description=Produces documentation in GitHub-flavored markdown format
diff --git a/plugins/base/src/main/resources/dokka/format/html-as-java.properties b/plugins/base/src/main/resources/dokka/format/html-as-java.properties
new file mode 100644
index 00000000..f598f377
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/html-as-java.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.HtmlAsJavaFormatDescriptor
+description=Produces output in HTML format using Java syntax \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/format/html.properties b/plugins/base/src/main/resources/dokka/format/html.properties
new file mode 100644
index 00000000..7881dfae
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/html.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.HtmlFormatDescriptor
+description=Produces output in HTML format \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/format/java-layout-html.properties b/plugins/base/src/main/resources/dokka/format/java-layout-html.properties
new file mode 100644
index 00000000..fbb2bbed
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/java-layout-html.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.JavaLayoutHtmlFormatDescriptor
+description=Produces Kotlin Style Docs with Javadoc like layout \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/format/jekyll.properties b/plugins/base/src/main/resources/dokka/format/jekyll.properties
new file mode 100644
index 00000000..b11401a4
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/jekyll.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.JekyllFormatDescriptor
+description=Produces documentation in Jekyll format \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties b/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties
new file mode 100644
index 00000000..f4c320b9
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.KotlinWebsiteHtmlFormatDescriptor
+description=Generates Kotlin website documentation \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/format/markdown.properties b/plugins/base/src/main/resources/dokka/format/markdown.properties
new file mode 100644
index 00000000..6217a6df
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/format/markdown.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.MarkdownFormatDescriptor
+description=Produces documentation in markdown format \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/images/arrow_down.svg b/plugins/base/src/main/resources/dokka/images/arrow_down.svg
new file mode 100755
index 00000000..89e7df47
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/images/arrow_down.svg
@@ -0,0 +1,3 @@
+<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.71824 1.66658L9.01113 0.959473L5.00497 4.96447L1.00008 0.959473L0.292969 1.66658L5.01113 6.38474L9.71824 1.66658Z" fill="#A1AAB4"/>
+</svg>
diff --git a/plugins/base/src/main/resources/dokka/images/docs_logo.svg b/plugins/base/src/main/resources/dokka/images/docs_logo.svg
new file mode 100644
index 00000000..7c1e3ae8
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/images/docs_logo.svg
@@ -0,0 +1,7 @@
+<svg width="125" height="27" viewBox="0 0 125 27" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M89.1611 7.6297V25.6345V25.6867H103.843V21.8039H93.3589V10.3852H103.843V6.50244H89.1611V7.6297Z" fill="#27282C"/>
+<path d="M124.989 21.8039L114.778 10.3852H124.905V6.50244H109.059V10.3852L119.459 21.8039H109.059V25.6867H125V21.8039H124.989Z" fill="#27282C"/>
+<path d="M58.2978 7.76556C56.5872 6.46086 54.4463 5.67804 52.1271 5.67804C46.5336 5.67804 42 10.1871 42 15.7503C42 21.3135 46.5336 25.8226 52.1271 25.8226C54.4463 25.8226 56.5872 25.0502 58.2978 23.735V25.7182H62.4955V0H58.2978V7.76556ZM52.1271 21.8041C48.7584 21.8041 46.0298 19.0903 46.0298 15.7399C46.0298 12.3894 48.7584 9.67563 52.1271 9.67563C55.4958 9.67563 58.2243 12.3894 58.2243 15.7399C58.2138 19.0903 55.4853 21.8041 52.1271 21.8041Z" fill="#27282C"/>
+<path d="M75.9698 5.8656C70.3763 5.8656 65.8428 10.3746 65.8428 15.9379C65.8428 21.5011 70.3763 26.0101 75.9698 26.0101C81.5633 26.0101 86.0969 21.5011 86.0969 15.9379C86.0969 10.3746 81.5633 5.8656 75.9698 5.8656ZM75.9698 21.9916C72.6012 21.9916 69.8726 19.2779 69.8726 15.9274C69.8726 12.577 72.6012 9.86319 75.9698 9.86319C79.3385 9.86319 82.0671 12.577 82.0671 15.9274C82.0671 19.2779 79.3385 21.9916 75.9698 21.9916Z" fill="#27282C"/>
+<path d="M26 26H0V0H26L12.9243 12.9747L26 26Z" fill="#F8873C"/>
+</svg>
diff --git a/plugins/base/src/main/resources/dokka/images/logo-icon.svg b/plugins/base/src/main/resources/dokka/images/logo-icon.svg
new file mode 100755
index 00000000..1b3b3670
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/images/logo-icon.svg
@@ -0,0 +1,3 @@
+<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M26 26H0V0H26L12.9243 12.9747L26 26Z" fill="#F8873C"/>
+</svg>
diff --git a/plugins/base/src/main/resources/dokka/images/logo-text.svg b/plugins/base/src/main/resources/dokka/images/logo-text.svg
new file mode 100755
index 00000000..7bf3e6c5
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/images/logo-text.svg
@@ -0,0 +1,6 @@
+<svg width="83" height="27" viewBox="0 0 83 27" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M47.1611 7.6297V25.6345V25.6867H61.8428V21.8039H51.3589V10.3852H61.8428V6.50244H47.1611V7.6297Z" fill="#27282C"/>
+<path d="M82.9891 21.8039L72.778 10.3852H82.9051V6.50244H67.0586V10.3852L77.4585 21.8039H67.0586V25.6867H82.9996V21.8039H82.9891Z" fill="#27282C"/>
+<path d="M16.2978 7.76556C14.5872 6.46086 12.4463 5.67804 10.1271 5.67804C4.53357 5.67804 0 10.1871 0 15.7503C0 21.3135 4.53357 25.8226 10.1271 25.8226C12.4463 25.8226 14.5872 25.0502 16.2978 23.735V25.7182H20.4955V0H16.2978V7.76556ZM10.1271 21.8041C6.75838 21.8041 4.02984 19.0903 4.02984 15.7399C4.02984 12.3894 6.75838 9.67563 10.1271 9.67563C13.4958 9.67563 16.2243 12.3894 16.2243 15.7399C16.2138 19.0903 13.4853 21.8041 10.1271 21.8041Z" fill="#27282C"/>
+<path d="M33.9703 5.86566C28.3768 5.86566 23.8433 10.3747 23.8433 15.9379C23.8433 21.5011 28.3768 26.0102 33.9703 26.0102C39.5638 26.0102 44.0974 21.5011 44.0974 15.9379C44.0974 10.3747 39.5638 5.86566 33.9703 5.86566ZM33.9703 21.9917C30.6016 21.9917 27.8731 19.2779 27.8731 15.9275C27.8731 12.577 30.6016 9.86325 33.9703 9.86325C37.339 9.86325 40.0676 12.577 40.0676 15.9275C40.0676 19.2779 37.339 21.9917 33.9703 21.9917Z" fill="#27282C"/>
+</svg>
diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties
new file mode 100644
index 00000000..c484a920
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Dokka
+description=Uses Dokka Default resolver \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties
new file mode 100644
index 00000000..3b61eabe
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.Formats.JavaLayoutHtmlInboundLinkResolutionService
+description=Resolver for JavaLayoutHtml \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties
new file mode 100644
index 00000000..0d5d7d17
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties
@@ -0,0 +1,2 @@
+class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Javadoc
+description=Uses Javadoc Default resolver \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/scripts/clipboard.js b/plugins/base/src/main/resources/dokka/scripts/clipboard.js
new file mode 100644
index 00000000..b00ce246
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/scripts/clipboard.js
@@ -0,0 +1,52 @@
+window.addEventListener('load', () => {
+ document.querySelectorAll('span.copy-icon').forEach(element => {
+ element.addEventListener('click', (el) => copyElementsContentToClipboard(element));
+ })
+
+ document.querySelectorAll('span.anchor-icon').forEach(element => {
+ element.addEventListener('click', (el) => {
+ if(element.hasAttribute('pointing-to')){
+ const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to')
+ copyTextToClipboard(element, location)
+ }
+ });
+ })
+})
+
+const copyElementsContentToClipboard = (element) => {
+ const selection = window.getSelection();
+ const range = document.createRange();
+ range.selectNodeContents(element.parentNode.parentNode);
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ copyAndShowPopup(element, () => selection.removeAllRanges())
+}
+
+const copyTextToClipboard = (element, text) => {
+ var textarea = document.createElement("textarea");
+ textarea.textContent = text;
+ textarea.style.position = "fixed";
+ document.body.appendChild(textarea);
+ textarea.select();
+
+ copyAndShowPopup(element, () => document.body.removeChild(textarea))
+}
+
+const copyAndShowPopup = (element, after) => {
+ try {
+ document.execCommand('copy');
+ element.nextElementSibling.classList.add('active-popup');
+ setTimeout(() => {
+ element.nextElementSibling.classList.remove('active-popup');
+ }, 1200);
+ } catch (e) {
+ console.error('Failed to write to clipboard:', e)
+ }
+ finally {
+ if(after) after()
+ }
+}
+
+const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0]
+
diff --git a/plugins/base/src/main/resources/dokka/scripts/navigationLoader.js b/plugins/base/src/main/resources/dokka/scripts/navigationLoader.js
new file mode 100644
index 00000000..c2f60ec5
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/scripts/navigationLoader.js
@@ -0,0 +1,54 @@
+window.addEventListener('load', () => {
+ fetch(pathToRoot + "navigation.html")
+ .then(response => response.text())
+ .then(data => {
+ document.getElementById("sideMenu").innerHTML = data;
+ }).then(() => {
+ document.querySelectorAll(".overview > a").forEach(link => {
+ link.setAttribute("href", pathToRoot + link.getAttribute("href"));
+ })
+ }).then(() => {
+ document.querySelectorAll(".sideMenuPart").forEach(nav => {
+ if (!nav.classList.contains("hidden")) nav.classList.add("hidden")
+ })
+ }).then(() => {
+ revealNavigationForCurrentPage()
+ })
+
+ /* Smooth scrolling support for going to the top of the page */
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
+ anchor.addEventListener('click', function (e) {
+ e.preventDefault();
+
+ document.querySelector(this.getAttribute('href')).scrollIntoView({
+ behavior: 'smooth'
+ });
+ });
+ });
+})
+
+revealNavigationForCurrentPage = () => {
+ let pageId = document.getElementById("content").attributes["pageIds"].value.toString();
+ let parts = document.querySelectorAll(".sideMenuPart");
+ let found = 0;
+ do {
+ parts.forEach(part => {
+ if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) {
+ found = 1;
+ if (part.classList.contains("hidden")){
+ part.classList.remove("hidden");
+ part.setAttribute('data-active',"");
+ }
+ revealParents(part)
+ }
+ });
+ pageId = pageId.substring(0, pageId.lastIndexOf("/"))
+ } while (pageId.indexOf("/") !== -1 && found === 0)
+};
+
+revealParents = (part) => {
+ if (part.classList.contains("sideMenuPart")) {
+ if (part.classList.contains("hidden")) part.classList.remove("hidden");
+ revealParents(part.parentNode)
+ }
+}; \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js b/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js
new file mode 100644
index 00000000..6f10b08a
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/scripts/platformContentHandler.js
@@ -0,0 +1,226 @@
+filteringContext = {
+ dependencies: {},
+ restrictedDependencies: [],
+ activeFilters: []
+}
+window.addEventListener('load', () => {
+ document.querySelectorAll("div[data-platform-hinted]")
+ .forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event,elem)))
+ document.querySelectorAll("div[tabs-section]")
+ .forEach(elem => elem.addEventListener('click', (event) => toggleSectionsEventHandler(event)))
+ const filterSection = document.getElementById('filter-section')
+ if (filterSection) {
+ filterSection.addEventListener('click', (event) => filterButtonHandler(event))
+ initializeFiltering()
+ }
+ initTabs()
+ handleAnchor()
+})
+
+function handleAnchor() {
+ let searchForTab = function(element) {
+ if(element && element.hasAttribute) {
+ if(element.hasAttribute("data-togglable")) return element;
+ else return searchForTab(element.parentNode)
+ } else return null
+ }
+ let anchor = window.location.hash
+ if (anchor != "") {
+ anchor = anchor.substring(1)
+ let element = document.querySelector('a[data-name="' + anchor+'"]')
+ if (element) {
+ let tab = searchForTab(element)
+ if (tab) {
+ let found = document.querySelector('.tabs-section > .section-tab[data-togglable="' + tab.getAttribute("data-togglable") + '"]')
+ toggleSections(tab)
+ element.scrollIntoView({behavior: "smooth"})
+ }
+ }
+ }
+}
+
+function initTabs(){
+ document.querySelectorAll("div[tabs-section]")
+ .forEach(element => {
+ showCorrespondingTabBody(element)
+ element.addEventListener('click', (event) => toggleSectionsEventHandler(event))
+ })
+ let cached = localStorage.getItem("active-tab")
+ if (cached) {
+ let parsed = JSON.parse(cached)
+ let tab = document.querySelector('div[tabs-section] > button[data-togglable="' + parsed + '"]')
+ if(tab) {
+ toggleSections(tab)
+ }
+ }
+}
+
+function showCorrespondingTabBody(element){
+ const key = element.querySelector("button[data-active]").getAttribute("data-togglable")
+ document.querySelector(".tabs-section-body")
+ .querySelector("div[data-togglable='" + key + "']")
+ .setAttribute("data-active", "")
+}
+
+function filterButtonHandler(event) {
+ if(event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) {
+ let sourceset = event.target.getAttribute("data-filter")
+ if(filteringContext.activeFilters.indexOf(sourceset) != -1) {
+ filterSourceset(sourceset)
+ } else {
+ unfilterSourceset(sourceset)
+ }
+ }
+}
+
+function initializeFiltering() {
+ filteringContext.dependencies = JSON.parse(sourceset_dependencies)
+ document.querySelectorAll("#filter-section > button")
+ .forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter")))
+ Object.keys(filteringContext.dependencies).forEach(p => {
+ filteringContext.dependencies[p] = filteringContext.dependencies[p]
+ .filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q))
+ })
+ let cached = window.localStorage.getItem('inactive-filters')
+ if (cached) {
+ let parsed = JSON.parse(cached)
+ filteringContext.activeFilters = filteringContext.restrictedDependencies
+ .filter(q => parsed.indexOf(q) == -1 )
+ } else {
+ filteringContext.activeFilters = filteringContext.restrictedDependencies
+ }
+ refreshFiltering()
+}
+
+function filterSourceset(sourceset) {
+ filteringContext.activeFilters = filteringContext.activeFilters.filter(p => p != sourceset)
+ refreshFiltering()
+ addSourcesetFilterToCache(sourceset)
+}
+
+function unfilterSourceset(sourceset) {
+ if(filteringContext.activeFilters.length == 0) {
+ filteringContext.activeFilters = filteringContext.dependencies[sourceset].concat([sourceset])
+ refreshFiltering()
+ filteringContext.dependencies[sourceset].concat([sourceset]).forEach(p => removeSourcesetFilterFromCache(p))
+ } else {
+ filteringContext.activeFilters.push(sourceset)
+ refreshFiltering()
+ removeSourcesetFilterFromCache(sourceset)
+ }
+
+}
+
+function addSourcesetFilterToCache(sourceset) {
+ let cached = localStorage.getItem('inactive-filters')
+ if (cached) {
+ let parsed = JSON.parse(cached)
+ localStorage.setItem('inactive-filters', JSON.stringify(parsed.concat([sourceset])))
+ } else {
+ localStorage.setItem('inactive-filters', JSON.stringify([sourceset]))
+ }
+}
+
+function removeSourcesetFilterFromCache(sourceset) {
+ let cached = localStorage.getItem('inactive-filters')
+ if (cached) {
+ let parsed = JSON.parse(cached)
+ localStorage.setItem('inactive-filters', JSON.stringify(parsed.filter(p => p != sourceset)))
+ }
+}
+
+function toggleSections(target) {
+ localStorage.setItem('active-tab', JSON.stringify(target.getAttribute("data-togglable")))
+ const activateTabs = (containerClass) => {
+ for(const element of document.getElementsByClassName(containerClass)){
+ for(const child of element.children){
+ if(child.getAttribute("data-togglable") === target.getAttribute("data-togglable")){
+ child.setAttribute("data-active", "")
+ } else {
+ child.removeAttribute("data-active")
+ }
+ }
+ }
+ }
+
+ activateTabs("tabs-section")
+ activateTabs("tabs-section-body")
+}
+
+function toggleSectionsEventHandler(evt){
+ if(!evt.target.getAttribute("data-togglable")) return
+ toggleSections(evt.target)
+}
+
+function togglePlatformDependent(e, container) {
+ let target = e.target
+ if (target.tagName != 'BUTTON') return;
+ let index = target.getAttribute('data-toggle')
+
+ for(let child of container.children){
+ if(child.hasAttribute('data-toggle-list')){
+ for(let bm of child.children){
+ if(bm == target){
+ bm.setAttribute('data-active',"")
+ } else if(bm != target) {
+ bm.removeAttribute('data-active')
+ }
+ }
+ }
+ else if(child.getAttribute('data-togglable') == index) {
+ child.setAttribute('data-active',"")
+ }
+ else {
+ child.removeAttribute('data-active')
+ }
+ }
+}
+
+function refreshFiltering() {
+ let sourcesetList = filteringContext.activeFilters
+ document.querySelectorAll("[data-filterable-set]")
+ .forEach(
+ elem => {
+ let platformList = elem.getAttribute("data-filterable-set").split(' ').filter(v => -1 !== sourcesetList.indexOf(v))
+ elem.setAttribute("data-filterable-current", platformList.join(' '))
+ }
+ )
+ refreshFilterButtons()
+ refreshPlatformTabs()
+}
+
+function refreshPlatformTabs() {
+ document.querySelectorAll(".platform-hinted > .platform-bookmarks-row").forEach(
+ p => {
+ let active = false;
+ let firstAvailable = null
+ p.childNodes.forEach(
+ element => {
+ if(element.getAttribute("data-filterable-current") != ''){
+ if( firstAvailable == null) {
+ firstAvailable = element
+ }
+ if(element.hasAttribute("data-active")) {
+ active = true;
+ }
+ }
+ }
+ )
+ if( active == false && firstAvailable) {
+ firstAvailable.click()
+ }
+ }
+ )
+}
+
+function refreshFilterButtons() {
+ document.querySelectorAll("#filter-section > button")
+ .forEach(f => {
+ if(filteringContext.activeFilters.indexOf(f.getAttribute("data-filter")) != -1){
+ f.setAttribute("data-active","")
+ } else {
+ f.removeAttribute("data-active")
+ }
+ })
+}
+
diff --git a/plugins/base/src/main/resources/dokka/scripts/scripts.js b/plugins/base/src/main/resources/dokka/scripts/scripts.js
new file mode 100644
index 00000000..c2e29b9f
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/scripts/scripts.js
@@ -0,0 +1,11 @@
+document.getElementById("navigationFilter").oninput = function (e) {
+ var input = e.target.value;
+ var menuParts = document.getElementsByClassName("sideMenuPart")
+ for (let part of menuParts) {
+ if(part.querySelector("a").textContent.startsWith(input)) {
+ part.classList.remove("filtered");
+ } else {
+ part.classList.add("filtered");
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/scripts/search.js b/plugins/base/src/main/resources/dokka/scripts/search.js
new file mode 100644
index 00000000..04d88ab5
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/scripts/search.js
@@ -0,0 +1,7 @@
+let query = new URLSearchParams(window.location.search).get("query");
+document.getElementById("searchTitle").innerHTML += '"' + query + '":';
+document.getElementById("searchTable").innerHTML = pages
+ .filter(el => el.name.toLowerCase().startsWith(query.toLowerCase()))
+ .reduce((acc, element) => {
+ return acc + '<tr><td><a href="' + element.location + '">' + element.name + '</a></td></tr>'
+ }, ""); \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/styles/jetbrains-mono.css b/plugins/base/src/main/resources/dokka/styles/jetbrains-mono.css
new file mode 100644
index 00000000..2af32a92
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/styles/jetbrains-mono.css
@@ -0,0 +1,13 @@
+@font-face{
+ font-family: 'JetBrains Mono';
+ src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/web/woff2/JetBrainsMono-Regular.woff2') format('woff2');
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face{
+ font-family: 'JetBrains Mono';
+ src: url('https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/web/woff2/JetBrainsMono-Bold.woff2') format('woff2');
+ font-weight: bold;
+ font-style: normal;
+} \ No newline at end of file
diff --git a/plugins/base/src/main/resources/dokka/styles/style.css b/plugins/base/src/main/resources/dokka/styles/style.css
new file mode 100644
index 00000000..57ffb8a5
--- /dev/null
+++ b/plugins/base/src/main/resources/dokka/styles/style.css
@@ -0,0 +1,1048 @@
+@import url(https://fonts.googleapis.com/css?family=Open+Sans:300i,400,700);
+@import url('https://rsms.me/inter/inter.css');
+@import url('jetbrains-mono.css');
+
+:root {
+ --breadcrumb-font-color: #A6AFBA;
+ --hover-link-color: #5B5DEF;
+ --footer-height: 64px;
+ --footer-padding-top: 48px;
+ --horizontal-spacing-for-content: 42px;
+}
+
+#content {
+ padding: 0 var(--horizontal-spacing-for-content);
+ height: calc(100% - var(--footer-height) - var(--footer-padding-top));
+}
+
+.breadcrumbs {
+ padding: 24px 0;
+ color: var(--breadcrumb-font-color);
+}
+
+.breadcrumbs a {
+ color: var(--breadcrumb-font-color)
+}
+
+.breadcrumbs a:hover {
+ color: var(--hover-link-color)
+}
+
+.tabs-section > .section-tab:first-child {
+ margin-left: 0;
+}
+
+.section-tab {
+ border: 0;
+ cursor: pointer;
+ background-color: transparent;
+ border-bottom: 1px solid #DADFE6;
+ padding: 11px 3px;
+ font-size: 14px;
+ color: #637282;
+ outline: none;
+ margin: 0 8px;
+}
+
+.section-tab:hover {
+ color: #282E34;
+ border-bottom: 2px solid var(--hover-link-color);
+}
+
+.section-tab[data-active=''] {
+ color: #282E34;
+ border-bottom: 2px solid var(--hover-link-color);
+}
+
+.tabs-section-body {
+ margin: 12px 0;
+ background-color: white;
+}
+
+.tabs-section-body > .table {
+ margin: 12px 0;
+}
+
+.tabs-section-body .with-platform-tabs > div {
+ margin: 0 12px;
+}
+
+.tabs-section-body .table .with-platform-tabs > div {
+ margin: 0;
+}
+
+.tabs-section-body .with-platform-tabs {
+ padding-top: 12px;
+ padding-bottom: 12px;
+}
+
+.tabs-section-body .with-platform-tabs .sourceset-depenent-content .table-row {
+ background-color: #f4f4f4;
+ border-bottom: 2px solid white;
+}
+
+.cover > .platform-hinted {
+ padding-top: 24px;
+ margin-top: 24px;
+ padding-bottom: 16px;
+}
+
+.cover {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ padding-bottom: 48px;
+}
+
+.tabbedcontent {
+ padding: 14px 0;
+}
+
+.cover .platform-hinted .sourceset-depenent-content > .symbol,
+.cover > .symbol {
+ background-color: white;
+}
+
+.cover .platform-hinted.with-platform-tabs .sourceset-depenent-content > .symbol {
+ background-color: #f4f4f4;
+}
+
+.cover .platform-hinted.with-platform-tabs .sourceset-depenent-content > .block ~ .symbol {
+ padding-top: 16px;
+ padding-left: 0;
+}
+
+.cover .sourceset-depenent-content > .block {
+ padding: 16px 0;
+ font-size: 18px;
+ line-height: 28px;
+}
+
+.cover .platform-hinted.with-platform-tabs .sourceset-depenent-content > .block {
+ padding: 0;
+ font-size: 14px;
+}
+
+.cover ~ .divergent-group {
+ margin-top: 24px;
+ padding: 24px 8px 8px 8px;
+}
+
+.cover ~ .divergent-group .main-subrow .symbol {
+ width: 100%;
+}
+
+.divergent-group {
+ background-color: white;
+ padding: 16px 8px;
+ margin-bottom: 2px;
+}
+
+.divergent-group .table-row {
+ background-color: #F4F4F4;
+ border-bottom: 2px solid white;
+}
+
+.title > .divergent-group:first-of-type {
+ padding-top: 0;
+}
+
+#container {
+ display: flex;
+ flex-direction: row;
+ min-height: 100%;
+}
+
+#main {
+ width: 100%;
+ max-width: calc(100% - 280px);
+}
+
+#leftColumn {
+ width: 280px;
+ min-height: 100%;
+ border-right: 1px solid #DADFE6;
+ flex: 0 0 auto;
+}
+
+@media screen and (max-width: 600px) {
+ #container {
+ flex-direction: column;
+ }
+
+ #leftColumn {
+ border-right: none;
+ }
+}
+
+#sideMenu {
+ max-height: calc(100% - 90px);
+ padding-top: 16px;
+ position: relative;
+}
+
+#sideMenu img {
+ margin: 1em 0.25em;
+}
+
+#sideMenu hr {
+ background: #DADFE6;
+}
+
+#searchBar {
+ float: right;
+}
+
+#logo {
+ background-size: 125px 26px;
+ border-bottom: 1px solid #DADFE6;
+ background-repeat: no-repeat;
+ background-image: url(../images/docs_logo.svg);
+ background-origin: content-box;
+ padding-left: 24px;
+ padding-top: 24px;
+ height: 48px;
+}
+
+.monospace,
+.code {
+ font-family: monospace;
+}
+
+.sample-container, .code-area {
+ display: flex;
+ flex-direction: column;
+}
+
+code.paragraph {
+ display: block;
+}
+
+.overview > .navButton {
+ height: 100%;
+ align-items: center;
+ display: flex;
+ justify-content: flex-end;
+ padding-right: 24px;
+}
+
+.strikethrough {
+ text-decoration: line-through;
+}
+
+.symbol:empty {
+ padding: 0;
+}
+
+.symbol {
+ background-color: #F4F4F4;
+ align-items: center;
+ display: block;
+ padding: 8px 8px 8px 16px;
+ box-sizing: border-box;
+ white-space: pre-wrap;
+ font-weight: bold;
+ position: relative;
+ line-height: 24px;
+}
+
+.symbol span.copy-icon path {
+ fill: #637282;
+}
+
+.symbol span.copy-icon:hover path {
+ fill: black;
+}
+
+.copy-popup-wrapper {
+ display: none;
+ align-items: center;
+ position: absolute;
+ z-index: 1000;
+ background: white;
+ font-weight: normal;
+ font-family: 'Inter', "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ width: max-content;
+ font-size: 14px;
+ cursor: default;
+ border: 1px solid #D8DCE1;
+ box-sizing: border-box;
+ box-shadow: 0px 5px 10px var(--ring-popup-shadow-color);
+ border-radius: 3px;
+}
+
+.copy-popup-wrapper.popup-to-left {
+ /* since it is in position absolute we can just move it to the left to make it always appear on the left side of the icon */
+ left: -15em;
+}
+
+.copy-popup-wrapper.active-popup {
+ display: flex !important;
+}
+
+.copy-popup-wrapper:hover {
+ font-weight: normal;
+}
+
+.copy-popup-wrapper svg {
+ padding: 8px;
+}
+
+.copy-popup-wrapper > span:last-child {
+ padding-right: 14px;
+}
+
+.symbol .top-right-position {
+ /* it is important for a parent to have a position: relative */
+ position: absolute;
+ top: 8px;
+ right: 8px;
+}
+
+.sideMenuPart > .overview {
+ height: 40px;
+ display: flex;
+ align-items: center;
+ position: relative;
+ user-select: none; /* there's a weird bug with text selection */
+}
+
+.sideMenuPart a {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ height: 100%;
+ color: #637282;
+ overflow: hidden;
+}
+
+.sideMenuPart > .overview:before {
+ box-sizing: border-box;
+ content: '';
+ top: 0;
+ width: 280px;
+ right: 0;
+ bottom: 0;
+ position: absolute;
+ z-index: -1;
+}
+
+.overview:hover:before {
+ background-color: #DADFE5;
+}
+
+#nav-submenu {
+ padding-left: 24px;
+}
+
+.sideMenuPart {
+ padding-left: 12px;
+ box-sizing: border-box;
+}
+
+.sideMenuPart .hidden > .overview .navButtonContent::before {
+ transform: rotate(0deg);
+}
+
+.sideMenuPart > .overview .navButtonContent::before {
+ content: url("../images/arrow_down.svg");
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ transform: rotate(180deg);
+}
+
+.sideMenuPart.hidden > .navButton .navButtonContent::after {
+ content: '\02192';
+}
+
+.sideMenuPart.hidden > .sideMenuPart {
+ height: 0;
+ visibility: hidden;
+}
+
+.filtered > a, .filtered > .navButton {
+ display: none;
+}
+
+body, table {
+ font-family: 'Inter', "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ background: #F4F4F4;
+ font-style: normal;
+ font-weight: normal;
+ font-size: 14px;
+ line-height: 24px;
+ margin: 0;
+ height: 100%;
+ /*max-width: 1440px; TODO: This results in worse experience on ultrawide, but on 16:9/16:10 looks better.*/
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+ background-color: #ffffff;
+ padding: 5px;
+}
+
+tbody > tr {
+ border-bottom: 2px solid #F4F4F4;
+ min-height: 56px;
+}
+
+td:first-child {
+ width: 20vw;
+}
+
+.keyword {
+ color: black;
+ font-family: JetBrains Mono, Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
+ font-size: 12px;
+}
+
+.symbol {
+ font-family: JetBrains Mono, Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
+ font-size: 12px;
+ min-height: 43px;
+}
+
+.symbol > a {
+ color: var(--hover-link-color);
+}
+
+.identifier {
+ color: darkblue;
+ font-size: 12px;
+ font-family: JetBrains Mono, Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
+}
+
+.brief {
+ white-space: pre-wrap;
+ overflow: hidden;
+ padding-top: 8px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #222;
+ font-weight: bold;
+}
+
+p, ul, ol, table, pre, dl {
+ margin: 0 0 20px;
+}
+
+h1 {
+ font-weight: bold;
+ font-size: 40px;
+ line-height: 48px;
+ letter-spacing: -1px;
+}
+
+
+h1.cover {
+ font-size: 60px;
+ line-height: 64px;
+ letter-spacing: -1.5px;
+
+ margin-left: calc(-1 * var(--horizontal-spacing-for-content));
+ margin-right: calc(-1 * var(--horizontal-spacing-for-content));
+ padding-left: var(--horizontal-spacing-for-content);
+ padding-right: var(--horizontal-spacing-for-content);
+ border-bottom: 1px solid #DADFE6;
+
+ margin-bottom: 0;
+ padding-bottom: 32px;
+}
+
+h2 {
+ color: #393939;
+ font-size: 31px;
+ line-height: 40px;
+ letter-spacing: -0.5px;
+}
+
+h3 {
+ font-size: 20px;
+ line-height: 28px;
+ letter-spacing: -0.2px;
+}
+
+h4 {
+ margin: 0;
+}
+
+h3, h4, h5, h6 {
+ color: #494949;
+}
+
+.UnderCoverText {
+ font-size: 18px;
+ line-height: 28px;
+}
+
+a {
+ color: #5B5DEF;
+ font-weight: 400;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #5B5DEF;
+ text-decoration: underline;
+}
+
+a small {
+ font-size: 11px;
+ color: #555;
+ margin-top: -0.6em;
+ display: block;
+}
+
+.wrapper {
+ width: 860px;
+ margin: 0 auto;
+}
+
+blockquote {
+ border-left: 1px solid #e5e5e5;
+ margin: 0;
+ padding: 0 0 0 20px;
+ font-style: italic;
+}
+
+code, pre {
+ font-family: Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
+ color: #333;
+ font-size: 12px;
+}
+
+pre {
+ display: block;
+ overflow-x: auto;
+}
+
+th, td {
+ text-align: left;
+ vertical-align: top;
+ padding: 5px 10px;
+}
+
+dt {
+ color: #444;
+ font-weight: 700;
+}
+
+th {
+ color: #444;
+}
+
+img {
+ max-width: 100%;
+}
+
+header {
+ width: 270px;
+ float: left;
+ position: fixed;
+}
+
+header ul {
+ list-style: none;
+ height: 40px;
+
+ padding: 0;
+
+ background: #eee;
+ background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8f8f8), color-stop(100%, #dddddd));
+ background: -webkit-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+ background: -o-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+ background: -ms-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+ background: linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+
+ border-radius: 5px;
+ border: 1px solid #d2d2d2;
+ box-shadow: inset #fff 0 1px 0, inset rgba(0, 0, 0, 0.03) 0 -1px 0;
+ width: 270px;
+}
+
+header li {
+ width: 89px;
+ float: left;
+ border-right: 1px solid #d2d2d2;
+ height: 40px;
+}
+
+header ul a {
+ line-height: 1;
+ font-size: 11px;
+ color: #999;
+ display: block;
+ text-align: center;
+ padding-top: 6px;
+ height: 40px;
+}
+
+strong {
+ color: #222;
+ font-weight: 700;
+}
+
+header ul li + li {
+ width: 88px;
+ border-left: 1px solid #fff;
+}
+
+header ul li + li + li {
+ border-right: none;
+ width: 89px;
+}
+
+header ul a strong {
+ font-size: 14px;
+ display: block;
+ color: #222;
+}
+
+section {
+ width: 500px;
+ float: right;
+ padding-bottom: 50px;
+}
+
+small {
+ font-size: 11px;
+}
+
+hr {
+ border: 0;
+ background: #e5e5e5;
+ height: 1px;
+ margin: 0 0 20px;
+}
+
+footer {
+ width: 270px;
+ float: left;
+ position: fixed;
+ bottom: 50px;
+}
+
+.platform-tag {
+ display: flex;
+ flex-direction: row;
+ padding: 4px 8px;
+ height: 24px;
+ border-radius: 100px;
+ box-sizing: border-box;
+ border: 1px solid transparent;
+ margin: 2px;
+ font-family: Inter, Arial, sans-serif;
+ font-size: 12px;
+ font-weight: 400;
+ font-style: normal;
+ font-stretch: normal;
+ line-height: normal;
+ letter-spacing: normal;
+ text-align: center;
+ outline: none;
+
+ color: #fff
+
+}
+
+.platform-tags {
+ flex: 0 0 auto;
+ display: flex;
+}
+
+.platform-tags > .platform-tag {
+ align-self: center;
+}
+
+.platform-tag.jvm-like {
+ background-color: #4DBB5F;
+ color: white;
+}
+
+.platform-tag.js-like {
+ background-color: #FED236;
+ color: white;
+}
+
+.platform-tag.native-like {
+ background-color: #CD74F6;
+ color: white;
+}
+
+.platform-tag.common-like {
+ background-color: #A6AFBA;
+ color: white;
+}
+
+.filter-section {
+ display: flex;
+ flex-direction: row;
+ align-self: flex-end;
+ min-height: 30px;
+ position: absolute;
+ top: 20px;
+ right: 88px;
+ z-index: 0;
+}
+
+.platform-selector:hover {
+ border: 1px solid #A6AFBA !important;
+}
+
+[data-filterable-current=''] {
+ display: none !important;
+}
+
+.platform-selector:not([data-active]) {
+ border: 1px solid #DADFE6;
+ background-color: transparent;
+ color: #637282;
+}
+
+td.content {
+ padding-left: 24px;
+ padding-top: 16px;
+ display: flex;
+ flex-direction: column;
+}
+
+.main-subrow {
+ display: flex;
+ flex-direction: row;
+ padding: 0;
+ justify-content: space-between;
+}
+
+.main-subrow > span {
+ display: flex;
+ position: relative;
+}
+
+.main-subrow > span > a {
+ text-decoration: none;
+ font-style: normal;
+ font-weight: 600;
+ font-size: 14px;
+ color: #282E34;
+}
+
+.main-subrow > span > a:hover {
+ color: var(--hover-link-color);
+}
+
+.main-subrow:hover .anchor-icon {
+ opacity: 1;
+ transition: 0.2s;
+}
+
+.main-subrow .anchor-icon {
+ padding: 0 8px;
+ opacity: 0;
+ transition: 0.2s 0.5s;
+}
+
+.main-subrow .anchor-icon > svg path {
+ fill: #637282;
+}
+
+.main-subrow .anchor-icon:hover {
+ cursor: pointer;
+}
+
+.main-subrow .anchor-icon:hover > svg path {
+ fill: var(--hover-link-color);
+}
+
+.main-subrow .anchor-wrapper {
+ position: relative;
+}
+
+.platform-hinted {
+ flex: auto;
+ display: block;
+ margin-bottom: 5px;
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark {
+ min-width: 64px;
+ height: 36px;
+ border: 2px solid white;
+ background: white;
+ outline: none;
+ flex: none;
+ order: 5;
+ align-self: flex-start;
+ margin: 0;
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.jvm-like:hover {
+ border-top: 2px solid rgba(77, 187, 95, 0.3);
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.js-like:hover {
+ border-top: 2px solid rgba(254, 175, 54, 0.3);
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.native-like:hover {
+ border-top: 2px solid rgba(105, 118, 249, 0.3);
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.common-like:hover {
+ border-top: 2px solid rgba(161, 170, 180, 0.3);
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.jvm-like[data-active=''] {
+ border: 2px solid #F4F4F4;
+ border-top: 2px solid #4DBB5F;
+
+ background: #F4F4F4;
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.js-like[data-active=''] {
+ border: 2px solid #F4F4F4;
+ border-top: 2px solid #FED236;
+
+ background: #F4F4F4;
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.native-like[data-active=''] {
+ border: 2px solid #F4F4F4;
+ border-top: 2px solid #CD74F6;
+
+ background: #F4F4F4;
+}
+
+.platform-hinted > .platform-bookmarks-row > .platform-bookmark.common-like[data-active=''] {
+ border: 2px solid #F4F4F4;
+ border-top: 2px solid #A6AFBA;
+
+ background: #F4F4F4;
+}
+
+.platform-hinted > .content:not([data-active]),
+.tabs-section-body > *:not([data-active]) {
+ visibility: hidden;
+ height: 0;
+ position: fixed;
+ top: 0;
+}
+
+.inner-brief-with-platform-tags {
+ display: block;
+ width: 100%
+}
+
+.brief-with-platform-tags {
+ display: flex;
+}
+
+.brief-with-platform-tags ~ .main-subrow {
+ padding-top: 16px;
+}
+
+.cover .with-platform-tabs {
+ background-color: white;
+}
+
+.cover > .with-platform-tabs .platform-bookmarks-row {
+ margin: 0 16px;
+}
+
+.cover > .with-platform-tabs > .content {
+ margin: 0 16px;
+ background-color: #f4f4f4;
+ padding: 8px 16px;
+}
+
+.cover > .block {
+ padding-top: 48px;
+ padding-bottom: 24px;
+ font-size: 18px;
+ line-height: 28px;
+}
+
+.cover > .block:empty {
+ padding-bottom: 0;
+}
+
+.table-row .with-platform-tabs .sourceset-depenent-content .brief {
+ padding: 16px;
+ background-color: #f4f4f4;
+}
+
+.sideMenuPart[data-active] > .overview:before {
+ border-left: 4px solid var(--hover-link-color);
+ background: rgba(91, 93, 239, 0.15);
+}
+
+.table {
+ display: flex;
+ flex-direction: column;
+}
+
+.table-row {
+ display: flex;
+ flex-direction: column;
+ background: white;
+ border-bottom: 2px solid #f4f4f4;
+ padding: 16px 24px 16px 24px;
+}
+
+.platform-dependent-row {
+ display: grid;
+ padding-top: 8px;
+}
+
+.title-row {
+ display: grid;
+ grid-template-columns: auto auto 7em;
+ width: 100%;
+}
+
+.keyValue {
+ display: grid;
+}
+
+@media print, screen and (min-width: 960px) {
+ .keyValue {
+ grid-template-columns: 20% 80%;
+ }
+
+ .title-row {
+ grid-template-columns: 20% auto 7em;
+ }
+}
+
+@media print, screen and (max-width: 960px) {
+
+ div.wrapper {
+ width: auto;
+ margin: 0;
+ }
+
+ header, section, footer {
+ float: none;
+ position: static;
+ width: auto;
+ }
+
+ header {
+ padding-right: 320px;
+ }
+
+ section {
+ border: 1px solid #e5e5e5;
+ border-width: 1px 0;
+ padding: 20px 0;
+ margin: 0 0 20px;
+ }
+
+ header a small {
+ display: inline;
+ }
+
+ header ul {
+ position: absolute;
+ right: 50px;
+ top: 52px;
+ }
+}
+
+@media print, screen and (max-width: 720px) {
+ body {
+ word-wrap: break-word;
+ }
+
+ header {
+ padding: 0;
+ }
+
+ header ul, header p.view {
+ position: static;
+ }
+
+ pre, code {
+ word-wrap: normal;
+ }
+}
+
+@media print, screen and (max-width: 480px) {
+ body {
+ padding-right: 15px;
+ }
+
+ header ul {
+ display: none;
+ }
+}
+
+@media print {
+ body {
+ padding: 0.4in;
+ font-size: 12pt;
+ color: #444;
+ }
+}
+
+.footer {
+ clear: both;
+ display: flex;
+ align-items: center;
+ position: relative;
+ height: var(--footer-height);
+ border-top: 1px solid #DADFE6;
+ font-size: 12px;
+ line-height: 16px;
+ letter-spacing: 0.2px;
+ color: var(--breadcrumb-font-color);
+ margin-top: var(--footer-padding-top);
+}
+
+.footer span.go-to-top-icon {
+ border-radius: 2em;
+ padding: 11px 10px !important;
+ background-color: white;
+}
+
+.footer span.go-to-top-icon path {
+ fill: #637282;
+}
+
+.footer > span:first-child {
+ margin-left: var(--horizontal-spacing-for-content);
+ padding-left: 0;
+}
+
+.footer > span:last-child {
+ margin-right: var(--horizontal-spacing-for-content);
+ padding-right: 0;
+}
+
+.footer > span {
+ padding: 0 16px;
+}
+
+.footer .padded-icon {
+ padding-left: 0.5em;
+}
+
+/*For svg*/
+.footer path {
+ fill: var(--breadcrumb-font-color);
+}
+
+.pull-right {
+ float: right;
+ margin-left: auto
+}
+
+div.runnablesample {
+ height: fit-content;
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/basic/DRITest.kt b/plugins/base/src/test/kotlin/basic/DRITest.kt
new file mode 100644
index 00000000..559a2dbf
--- /dev/null
+++ b/plugins/base/src/test/kotlin/basic/DRITest.kt
@@ -0,0 +1,317 @@
+package basic
+
+import org.jetbrains.dokka.links.*
+import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.links.Nullable
+import org.jetbrains.dokka.links.TypeConstructor
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.pages.ClasslikePageNode
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.pages.MemberPageNode
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+
+class DRITest : AbstractCoreTest() {
+ @Test
+ fun issue634() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package toplevel
+ |
+ |inline fun <T, R : Comparable<R>> Array<out T>.mySortBy(
+ | crossinline selector: (T) -> R?): Array<out T> = TODO()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val expected = TypeConstructor(
+ "kotlin.Function1", listOf(
+ TypeParam(listOf(Nullable(TypeConstructor("kotlin.Any", emptyList())))),
+ Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(SelfType)))))
+ )
+ )
+ val actual = module.packages.single()
+ .functions.single()
+ .dri.callable?.params?.single()
+ assertEquals(expected, actual)
+ }
+ }
+ }
+
+ @Test
+ fun issue634WithImmediateNullableSelf() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package toplevel
+ |
+ |fun <T : Comparable<T>> Array<T>.doSomething(t: T?): Array<T> = TODO()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val expected = Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(SelfType)))))
+ val actual = module.packages.single()
+ .functions.single()
+ .dri.callable?.params?.single()
+ assertEquals(expected, actual)
+ }
+ }
+ }
+
+ @Test
+ fun issue634WithGenericNullableReceiver() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package toplevel
+ |
+ |fun <T : Comparable<T>> T?.doSomethingWithNullable() = TODO()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val expected = Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(SelfType)))))
+ val actual = module.packages.single()
+ .functions.single()
+ .dri.callable?.receiver
+ assertEquals(expected, actual)
+ }
+ }
+ }
+
+ @Test
+ fun issue642WithStarAndAny() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ analysisPlatform = "js"
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |
+ |open class Bar<Z>
+ |class ReBarBar : Bar<StringBuilder>()
+ |class Foo<out T : Comparable<*>, R : List<Bar<*>>>
+ |
+ |fun <T : Comparable<Any?>> Foo<T, *>.qux(): String = TODO()
+ |fun <T : Comparable<*>> Foo<T, *>.qux(): String = TODO()
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = { module ->
+ // DRI(//qux/Foo[TypeParam(bounds=[kotlin.Comparable[kotlin.Any?]]),*]#/PointingToFunctionOrClasslike/)
+ val expectedDRI = DRI(
+ "",
+ null,
+ Callable(
+ "qux", TypeConstructor(
+ "Foo", listOf(
+ TypeParam(
+ listOf(
+ TypeConstructor(
+ "kotlin.Comparable", listOf(
+ Nullable(TypeConstructor("kotlin.Any", emptyList()))
+ )
+ )
+ )
+ ),
+ StarProjection
+ )
+ ),
+ emptyList()
+ )
+ )
+
+ val driCount = module
+ .withDescendants()
+ .filterIsInstance<ContentPage>()
+ .sumBy { it.dri.count { dri -> dri == expectedDRI } }
+
+ assertEquals(1, driCount)
+ }
+ }
+ }
+
+ @Test
+ fun driForGenericClass(){
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package example
+ |
+ |class Sample<S>(first: S){ }
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = { module ->
+ val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode
+ val classDocumentable = sampleClass.documentable as DClass
+
+ assertEquals( "example/Sample///PointingToDeclaration/", sampleClass.dri.first().toString())
+ assertEquals("example/Sample///PointingToGenericParameters(0)/", classDocumentable.generics.first().dri.toString())
+ }
+ }
+ }
+
+ @Test
+ fun driForGenericFunction(){
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package example
+ |
+ |class Sample<S>(first: S){
+ | fun <T> genericFun(param1: String): Tuple<S,T> = TODO()
+ |}
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = { module ->
+ val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode
+ val functionNode = sampleClass.children.first { it.name == "genericFun" } as MemberPageNode
+ val functionDocumentable = functionNode.documentable as DFunction
+ val parameter = functionDocumentable.parameters.first()
+
+ assertEquals("example/Sample/genericFun/#kotlin.String/PointingToDeclaration/", functionNode.dri.first().toString())
+
+ assertEquals(1, functionDocumentable.parameters.size)
+ assertEquals("example/Sample/genericFun/#kotlin.String/PointingToCallableParameters(0)/", parameter.dri.toString())
+ //1 since from the function's perspective there is only 1 new generic declared
+ //The other one is 'inherited' from class
+ assertEquals( 1, functionDocumentable.generics.size)
+ assertEquals( "T", functionDocumentable.generics.first().name)
+ assertEquals( "example/Sample/genericFun/#kotlin.String/PointingToGenericParameters(0)/", functionDocumentable.generics.first().dri.toString())
+ }
+ }
+ }
+
+ @Test
+ fun driForFunctionNestedInsideInnerClass() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package example
+ |
+ |class Sample<S>(first: S){
+ | inner class SampleInner {
+ | fun foo(): S = TODO()
+ | }
+ |}
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = { module ->
+ val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode
+ val sampleInner = sampleClass.children.first { it.name == "SampleInner" } as ClasslikePageNode
+ val foo = sampleInner.children.first { it.name == "foo" } as MemberPageNode
+ val documentable = foo.documentable as DFunction
+
+ assertEquals(sampleClass.dri.first().toString(), (documentable.type as OtherParameter).declarationDRI.toString())
+ assertEquals(0, documentable.generics.size)
+ }
+ }
+ }
+
+ @Test
+ fun driForGenericExtensionFunction(){
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package example
+ |
+ | fun <T> List<T>.extensionFunction(): String = ""
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = { module ->
+ val extensionFunction = module.dfs { it.name == "extensionFunction" } as MemberPageNode
+ val documentable = extensionFunction.documentable as DFunction
+
+ assertEquals(
+ "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/",
+ extensionFunction.dri.first().toString()
+ )
+ assertEquals(1, documentable.generics.size)
+ assertEquals("T", documentable.generics.first().name)
+ assertEquals(
+ "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToGenericParameters(0)/",
+ documentable.generics.first().dri.toString()
+ )
+
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt b/plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt
new file mode 100644
index 00000000..bceb79ae
--- /dev/null
+++ b/plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt
@@ -0,0 +1,42 @@
+package basic
+
+import org.jetbrains.dokka.pages.ClasslikePageNode
+import org.jetbrains.dokka.pages.ModulePageNode
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+
+class DokkaBasicTests : AbstractCoreTest() {
+
+ @Test
+ fun basic1() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package basic
+ |
+ |class Test {
+ | val tI = 1
+ | fun tF() = 2
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = {
+ val root = it as ModulePageNode
+ assertTrue(root.getClasslikeToMemberMap().filterKeys { it.name == "Test" }.entries.firstOrNull()?.value?.size == 2)
+ }
+ }
+ }
+
+ private fun ModulePageNode.getClasslikeToMemberMap() =
+ this.parentMap.filterValues { it is ClasslikePageNode }.entries.groupBy({ it.value }) { it.key }
+}
diff --git a/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt b/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt
new file mode 100644
index 00000000..9d2c5825
--- /dev/null
+++ b/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt
@@ -0,0 +1,118 @@
+package basic
+
+import org.jetbrains.dokka.DokkaException
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.dokka.utilities.DokkaConsoleLogger
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import testApi.logger.TestLogger
+
+class FailOnWarningTest : AbstractCoreTest() {
+
+ @Test
+ fun `throws exception if one or more warnings were emitted`() {
+ val configuration = dokkaConfiguration {
+ failOnWarning = true
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ assertThrows<DokkaException> {
+ testInline(
+ """
+ |/src/main/kotlin
+ |package sample
+ """.trimIndent(), configuration
+ ) {
+ pluginsSetupStage = {
+ logger.warn("Warning!")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `throws exception if one or more error were emitted`() {
+ val configuration = dokkaConfiguration {
+ failOnWarning = true
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ assertThrows<DokkaException> {
+ testInline(
+ """
+ |/src/main/kotlin
+ |package sample
+ """.trimIndent(), configuration
+ ) {
+ pluginsSetupStage = {
+ logger.error("Error!")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `does not throw if now warning or error was emitted`() {
+ logger = TestLogger(ZeroErrorOrWarningCountDokkaLogger())
+
+ val configuration = dokkaConfiguration {
+ failOnWarning = true
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+
+ testInline(
+ """
+ |/src/main/kotlin
+ |package sample
+ """.trimIndent(), configuration
+ ) {
+ /* We expect no Exception */
+ }
+ }
+
+ @Test
+ fun `does not throw if disabled`() {
+ val configuration = dokkaConfiguration {
+ failOnWarning = false
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+
+ testInline(
+ """
+ |/src/main/kotlin
+ |package sample
+ """.trimIndent(), configuration
+ ) {
+ pluginsSetupStage = {
+ logger.warn("Error!")
+ logger.error("Error!")
+ }
+ }
+ }
+}
+
+private class ZeroErrorOrWarningCountDokkaLogger(
+ logger: DokkaLogger = DokkaConsoleLogger
+) : DokkaLogger by logger {
+ override var warningsCount: Int = 0
+ override var errorsCount: Int = 0
+}
diff --git a/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt b/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt
new file mode 100644
index 00000000..bf78b847
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt
@@ -0,0 +1,221 @@
+package content.annotations
+
+import matchers.content.*
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.pages.PackagePageNode
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Test
+import utils.ParamAttributes
+import utils.bareSignature
+import utils.propertySignature
+
+
+class ContentForAnnotationsTest : AbstractCoreTest() {
+
+
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+
+ @Test
+ fun `function with documented annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
+ | AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD
+ |)
+ |@Retention(AnnotationRetention.SOURCE)
+ |@MustBeDocumented
+ |annotation class Fancy
+ |
+ |
+ |@Fancy
+ |fun function(@Fancy abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ mapOf("Fancy" to emptySet()),
+ "",
+ "",
+ emptySet(),
+ "function",
+ "String",
+ "abc" to ParamAttributes(mapOf("Fancy" to emptySet()), emptySet(), "String")
+ )
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with undocumented annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
+ | AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD
+ |)
+ |@Retention(AnnotationRetention.SOURCE)
+ |annotation class Fancy
+ |
+ |@Fancy
+ |fun function(@Fancy abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `property with undocumented annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@Suppress
+ |val property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(emptyMap(), "", "", emptySet(), "val", "property", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `property with documented annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@MustBeDocumented
+ |annotation class Fancy
+ |
+ |@Fancy
+ |val property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(mapOf("Fancy" to emptySet()), "", "", emptySet(), "val", "property", "Int")
+ }
+ }
+ }
+ }
+
+
+ @Test
+ fun `rich documented annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@MustBeDocumented
+ |@Retention(AnnotationRetention.SOURCE)
+ |@Target(AnnotationTarget.FIELD)
+ |annotation class BugReport(
+ | val assignedTo: String = "[none]",
+ | val testCase: KClass<ABC> = ABC::class,
+ | val status: Status = Status.UNCONFIRMED,
+ | val ref: Reference = Reference(value = 1),
+ | val reportedBy: Array<Reference>,
+ | val showStopper: Boolean = false
+ |) {
+ | enum class Status {
+ | UNCONFIRMED, CONFIRMED, FIXED, NOTABUG
+ | }
+ | class ABC
+ |}
+ |annotation class Reference(val value: Int)
+ |
+ |
+ |@BugReport(
+ | assignedTo = "me",
+ | testCase = BugReport.ABC::class,
+ | status = BugReport.Status.FIXED,
+ | ref = Reference(value = 2),
+ | reportedBy = [Reference(value = 2), Reference(value = 4)],
+ | showStopper = true
+ |)
+ |val ltint: Int = 5
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(
+ mapOf(
+ "BugReport" to setOf(
+ "assignedTo",
+ "testCase",
+ "status",
+ "ref",
+ "reportedBy",
+ "showStopper"
+ )
+ ), "", "", emptySet(), "val", "ltint", "Int"
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/content/annotations/DepredatedAndSinceKotlinTest.kt b/plugins/base/src/test/kotlin/content/annotations/DepredatedAndSinceKotlinTest.kt
new file mode 100644
index 00000000..69de1bcd
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/annotations/DepredatedAndSinceKotlinTest.kt
@@ -0,0 +1,103 @@
+package content.annotations
+
+
+import matchers.content.*
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Test
+import utils.ParamAttributes
+import utils.bareSignature
+
+
+class DepredatedAndSinceKotlinTest : AbstractCoreTest() {
+
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+
+ @Test
+ fun `function with deprecated annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@Deprecated("And some things that should not have been forgotten were lost. History became legend. Legend became myth.")
+ |fun ring(abc: String): String {
+ | return "My precious " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "ring" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"ring" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "ring",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with since kotlin annotation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |@SinceKotlin("1.3")
+ |fun ring(abc: String): String {
+ | return "My precious " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "ring" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"ring" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "ring",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
new file mode 100644
index 00000000..a9689bc5
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt
@@ -0,0 +1,611 @@
+package content.params
+
+import matchers.content.*
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.model.DFunction
+import org.jetbrains.dokka.model.dfs
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.model.doc.Param
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.pages.MemberPageNode
+import org.jetbrains.dokka.pages.dfs
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+import org.junit.jupiter.api.Test
+import utils.*
+
+class ContentForParamsTest : AbstractCoreTest() {
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(), "", "", emptySet(), "function", null, "abc" to ParamAttributes(
+ emptyMap(),
+ emptySet(),
+ "String"
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented parameter`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented parameter and other tags without function comment`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @author Kordyjan
+ | * @since 0.11
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented parameter and other tags`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @author Kordyjan
+ | * @since 0.11
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `single parameter`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @param abc comment to param
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ header(2) { +"Parameters" }
+ group {
+ platformHinted {
+ table {
+ group {
+ +"abc"
+ group { +"comment to param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `multiple parameters`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @param first comment to first param
+ | * @param second comment to second param
+ | * @param[third] comment to third param
+ | */
+ |fun function(first: String, second: Int, third: Double) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ header(2) { +"Parameters" }
+ group {
+ platformHinted {
+ table {
+ group {
+ +"first"
+ group { +"comment to first param" }
+ }
+ group {
+ +"second"
+ group { +"comment to second param" }
+ }
+ group {
+ +"third"
+ group { +"comment to third param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(), "", "", emptySet(), "function", null,
+ "first" to ParamAttributes(emptyMap(), emptySet(), "String"),
+ "second" to ParamAttributes(emptyMap(), emptySet(), "Int"),
+ "third" to ParamAttributes(emptyMap(), emptySet(), "Double")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `multiple parameters without function description`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @param first comment to first param
+ | * @param second comment to second param
+ | * @param[third] comment to third param
+ | */
+ |fun function(first: String, second: Int, third: Double) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"Parameters" }
+ group {
+ platformHinted {
+ table {
+ group {
+ +"first"
+ group { +"comment to first param" }
+ }
+ group {
+ +"second"
+ group { +"comment to second param" }
+ }
+ group {
+ +"third"
+ group { +"comment to third param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(), "", "", emptySet(), "function", null,
+ "first" to ParamAttributes(emptyMap(), emptySet(), "String"),
+ "second" to ParamAttributes(emptyMap(), emptySet(), "Int"),
+ "third" to ParamAttributes(emptyMap(), emptySet(), "Double")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with receiver`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @param abc comment to param
+ | * @receiver comment to receiver
+ | */
+ |fun String.function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ header(2) { +"Parameters" }
+ group {
+ platformHinted {
+ table {
+ group {
+ +"<receiver>"
+ group { +"comment to receiver" }
+ }
+ group {
+ +"abc"
+ group { +"comment to param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignatureWithReceiver(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "String",
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `missing parameter documentation`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @param first comment to first param
+ | * @param[third] comment to third param
+ | */
+ |fun function(first: String, second: Int, third: Double) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ header(2) { +"Parameters" }
+ group {
+ platformHinted {
+ table {
+ group {
+ +"first"
+ group { +"comment to first param" }
+ }
+ group {
+ +"third"
+ group { +"comment to third param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(), "", "", emptySet(), "function", null,
+ "first" to ParamAttributes(emptyMap(), emptySet(), "String"),
+ "second" to ParamAttributes(emptyMap(), emptySet(), "Int"),
+ "third" to ParamAttributes(emptyMap(), emptySet(), "Double")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `parameters mixed with other tags`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * comment to function
+ | * @param first comment to first param
+ | * @author Kordyjan
+ | * @param second comment to second param
+ | * @since 0.11
+ | * @param[third] comment to third param
+ | */
+ |fun function(first: String, second: Int, third: Double) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("comment to function")
+ unnamedTag("Author") { +"Kordyjan" }
+ unnamedTag("Since") { +"0.11" }
+ header(2) { +"Parameters" }
+
+ group {
+ platformHinted {
+ table {
+ group {
+ +"first"
+ group { +"comment to first param" }
+ }
+ group {
+ +"second"
+ group { +"comment to second param" }
+ }
+ group {
+ +"third"
+ group { +"comment to third param" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(), "", "", emptySet(), "function", null,
+ "first" to ParamAttributes(emptyMap(), emptySet(), "String"),
+ "second" to ParamAttributes(emptyMap(), emptySet(), "Int"),
+ "third" to ParamAttributes(emptyMap(), emptySet(), "Double")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun javaDocCommentWithDocumentedParameters() {
+ testInline(
+ """
+ |/src/main/java/test/Main.java
+ |package test
+ | public class Main {
+ |
+ | /**
+ | * comment to function
+ | * @param first comment to first param
+ | * @param second comment to second param
+ | */
+ | public void sample(String first, String second) {
+ |
+ | }
+ | }
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val sampleFunction = module.dfs {
+ it is MemberPageNode && it.dri.first()
+ .toString() == "test/Main/sample/#java.lang.String#java.lang.String/PointingToDeclaration/"
+ } as MemberPageNode
+ val forJvm = (sampleFunction.documentable as DFunction).parameters.mapNotNull {
+ val jvm = it.documentation.keys.first { it.analysisPlatform == Platform.jvm }
+ it.documentation[jvm]
+ }
+
+ assert(forJvm.size == 2)
+ val (first, second) = forJvm.map { it.paramsDescription() }
+ assert(first == "comment to first param")
+ assert(second == "comment to second param")
+ }
+ }
+ }
+
+ private fun DocumentationNode.paramsDescription(): String =
+ children.firstIsInstanceOrNull<Param>()?.root?.children?.firstIsInstanceOrNull<Text>()?.body.orEmpty()
+
+}
diff --git a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt
new file mode 100644
index 00000000..24970660
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt
@@ -0,0 +1,459 @@
+package content.seealso
+
+import matchers.content.*
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Test
+import utils.ParamAttributes
+import utils.bareSignature
+import utils.pWrapped
+import utils.unnamedTag
+
+class ContentForSeeAlsoTest : AbstractCoreTest() {
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented seealso`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see abc
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"abc" }
+ group { }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `documented seealso`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see abc Comment to abc
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"abc" }
+ group { +"Comment to abc" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented seealso with stdlib link`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see Collection
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "kotlin.collections/Collection////"
+ link { +"Collection" }
+ group { }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `documented seealso with stdlib link`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see Collection Comment to stdliblink
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"Collection" }
+ group { +"Comment to stdliblink" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `documented seealso with stdlib link with other tags`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * random comment
+ | * @see Collection Comment to stdliblink
+ | * @author pikinier20
+ | * @since 0.11
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ pWrapped("random comment")
+ unnamedTag("Author") { +"pikinier20" }
+ unnamedTag("Since") { +"0.11" }
+
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"Collection" }
+ group { +"Comment to stdliblink" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `documented multiple see also`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see abc Comment to abc1
+ | * @see abc Comment to abc2
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"abc" }
+ group { +"Comment to abc2" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `documented multiple see also mixed source`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ | /**
+ | * @see abc Comment to abc1
+ | * @see[Collection] Comment to collection
+ | */
+ |fun function(abc: String) {
+ | println(abc)
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ before {
+ header(2) { +"See also" }
+ group {
+ platformHinted {
+ table {
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"abc" }
+ group { +"Comment to abc1" }
+ }
+ group {
+ //DRI should be "test//abc/#/-1/"
+ link { +"Collection" }
+ group { +"Comment to collection" }
+ }
+ }
+ }
+ }
+ }
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ null,
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt b/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt
new file mode 100644
index 00000000..cabe822d
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt
@@ -0,0 +1,456 @@
+package content.signatures
+
+import matchers.content.*
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Test
+import utils.ParamAttributes
+import utils.bareSignature
+import utils.propertySignature
+import utils.typealiasSignature
+
+class ContentForSignaturesTest : AbstractCoreTest() {
+
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ includeNonPublic = true
+ }
+ }
+ }
+
+ @Test
+ fun `function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ emptySet(),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `private function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |private fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "private",
+ "",
+ emptySet(),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `open function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |open fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "open",
+ emptySet(),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function without parameters`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |fun function(): String {
+ | return "Hello"
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ annotations = emptyMap(),
+ visibility = "",
+ modifier = "",
+ keywords = emptySet(),
+ name = "function",
+ returnType = "String",
+ )
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+
+ @Test
+ fun `suspend function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |suspend fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "",
+ "",
+ setOf("suspend"),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `protected open suspend function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |protected open suspend fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "protected",
+ "open",
+ setOf("suspend"),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `protected open suspend inline function`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |protected open suspend inline fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "function" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"function" }
+ }
+ divergentGroup {
+ divergentInstance {
+ divergent {
+ bareSignature(
+ emptyMap(),
+ "protected",
+ "open",
+ setOf("inline", "suspend"),
+ "function",
+ "String",
+ "abc" to ParamAttributes(emptyMap(), emptySet(), "String")
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `property`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |val property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(emptyMap(), "", "", emptySet(), "val", "property", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `const property`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |const val property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(emptyMap(), "", "", setOf("const"), "val", "property", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `protected property`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |protected val property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(emptyMap(), "protected", "", emptySet(), "val", "property", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `protected lateinit property`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |protected lateinit var property: Int = 6
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ propertySignature(emptyMap(), "protected", "", setOf("lateinit"), "var", "property", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `typealias to String`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |typealias Alias = String
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ typealiasSignature("Alias", "String")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `typealias to Int`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |typealias Alias = Int
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ typealiasSignature("Alias", "Int")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `typealias to type in same package`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |typealias Alias = X
+ |class X
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ typealiasSignature("Alias", "X")
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `typealias to type in different package`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |import other.X
+ |typealias Alias = X
+ |
+ |/src/main/kotlin/test/source2.kt
+ |package other
+ |class X
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" } as PackagePageNode
+ page.content.assertNode {
+ typealiasSignature("Alias", "other.X")
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt
new file mode 100644
index 00000000..7de48664
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt
@@ -0,0 +1,254 @@
+package content.signatures
+
+import matchers.content.*
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Test
+import utils.functionSignature
+
+class ConstructorsSignaturesTest : AbstractCoreTest() {
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ }
+ }
+ }
+
+ @Test
+ fun `class name without parenthesis`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class SomeClass
+ |
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ group {
+ +"class"
+ link { +"SomeClass" }
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `class name with empty parenthesis`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class SomeClass()
+ |
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ group {
+ +"class"
+ link { +"SomeClass" }
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `class with a parameter`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class SomeClass(a: String)
+ |
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ group {
+ +"class"
+ link { +"SomeClass" }
+ +"(a:"
+ group { link { +"String" } }
+ +")"
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `class with a val parameter`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class SomeClass(val a: String)
+ |
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ group {
+ +"class"
+ link { +"SomeClass" }
+ +"(a:" // TODO: Make sure if we still do not want to have "val" here
+ group { link { +"String" } }
+ +")"
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `class with a parameterless secondary constructor`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class SomeClass(a: String) {
+ | constructor()
+ |}
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ group {
+ +"class"
+ link { +"SomeClass" }
+ +"(a:"
+ group { link { +"String" } }
+ +")"
+ }
+ }
+ }
+ group {
+ header { +"Constructors" }
+ table {
+ group {
+ link { +"<init>" }
+ functionSignature(
+ annotations = emptyMap(),
+ visibility = "",
+ modifier = "",
+ keywords = emptySet(),
+ name = "<init>"
+ )
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `class with explicitly documented constructor`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ | /**
+ | * some comment
+ | * @constructor ctor comment
+ | **/
+ |class SomeClass(a: String)
+ """.trimIndent(), testConfiguration
+ ) {
+ pagesTransformationStage = { module ->
+ val page = module.children.single { it.name == "test" }
+ .children.single { it.name == "SomeClass" } as ContentPage
+ page.content.assertNode {
+ group {
+ header(1) { +"SomeClass" }
+ platformHinted {
+ skipAllNotMatching()
+ group {
+ +"class"
+ link { +"SomeClass" }
+ +"(a:"
+ group { link { +"String" } }
+ +")"
+ }
+ }
+ }
+ group {
+ header { +"Constructors" }
+ table {
+ group {
+ link { +"<init>" }
+ platformHinted {
+ group {
+ group {
+ +"ctor comment"
+ }
+ }
+ group {
+ +"fun"
+ link { +"<init>" }
+ +"(a:"
+ group {
+ link { +"String" }
+ }
+ +")"
+ }
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/enums/EnumsTest.kt b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
new file mode 100644
index 00000000..6a973f8e
--- /dev/null
+++ b/plugins/base/src/test/kotlin/enums/EnumsTest.kt
@@ -0,0 +1,234 @@
+package enums
+
+import matchers.content.*
+import org.jetbrains.dokka.model.ConstructorValues
+import org.jetbrains.dokka.model.DEnum
+import org.jetbrains.dokka.model.dfs
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+
+class EnumsTest : AbstractCoreTest() {
+
+ @Test
+ fun basicEnum() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package enums
+ |
+ |enum class Test {
+ | E1,
+ | E2
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = {
+ val map = it.getClasslikeToMemberMap()
+ val test = map.filterKeys { it.name == "Test" }.values.firstOrNull()
+ assertTrue(test != null) { "Test not found" }
+ assertTrue(test!!.any { it.name == "E1" } && test.any { it.name == "E2" }) { "Enum entries missing in parent" }
+ }
+ }
+ }
+
+ @Test
+ fun enumWithCompanion() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package enums
+ |
+ |enum class Test {
+ | E1,
+ | E2;
+ | companion object {}
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesTransformationStage = { m ->
+ m.packages.let { p ->
+ assertTrue(p.isNotEmpty(), "Package list cannot be empty")
+ p.first().classlikes.let { c ->
+ assertTrue(c.isNotEmpty(), "Classlikes list cannot be empty")
+
+ val enum = c.first() as DEnum
+ assertEquals(enum.name, "Test")
+ assertEquals(enum.entries.count(), 2)
+ assertNotNull(enum.companion)
+ }
+ }
+ }
+ pagesGenerationStage = { module ->
+ val map = module.getClasslikeToMemberMap()
+ val test = map.filterKeys { it.name == "Test" }.values.firstOrNull()
+ assertNotNull(test, "Test not found")
+ assertTrue(test!!.any { it.name == "E1" } && test.any { it.name == "E2" }) { "Enum entries missing in parent" }
+ }
+ }
+ }
+
+ @Test
+ fun enumWithConstructor() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package enums
+ |
+ |
+ |enum class Test(name: String, index: Int, excluded: Boolean) {
+ | E1("e1", 1, true),
+ | E2("e2", 2, false);
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesTransformationStage = { m ->
+ m.packages.let { p ->
+ p.first().classlikes.let { c ->
+ val enum = c.first() as DEnum
+ val (first, second) = enum.entries
+
+ assertEquals(1, first.extra.allOfType<ConstructorValues>().size)
+ assertEquals(1, second.extra.allOfType<ConstructorValues>().size)
+ assertEquals(listOf("\"e1\"", "1", "true"), first.extra.allOfType<ConstructorValues>().first().values.values.first())
+ assertEquals(listOf("\"e2\"", "2", "false"), second.extra.allOfType<ConstructorValues>().first().values.values.first())
+ }
+ }
+ }
+ pagesGenerationStage = { module ->
+ val entryPage = module.dfs { it.name == "E1" } as ClasslikePageNode
+ val signaturePart = (entryPage.content.dfs {
+ it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/][Symbol]"
+ } as ContentGroup)
+ assertEquals("(\"e1\", 1, true)", signaturePart.constructorSignature())
+ }
+ }
+ }
+
+ @Test
+ fun enumWithMethods() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package enums
+ |
+ |
+ |interface Sample {
+ | fun toBeImplemented(): String
+ |}
+ |
+ |enum class Test: Sample {
+ | E1 {
+ | override fun toBeImplemented(): String = "e1"
+ | }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesTransformationStage = { m ->
+ m.packages.let { p ->
+ p.first().classlikes.let { c ->
+ val enum = c.first { it is DEnum } as DEnum
+ val first = enum.entries.first()
+
+ assertEquals(1, first.extra.allOfType<ConstructorValues>().size)
+ assertEquals(emptyList<String>(), first.extra.allOfType<ConstructorValues>().first().values.values.first())
+ assertNotNull(first.functions.find { it.name == "toBeImplemented" })
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun enumWithAnnotationsOnEntries(){
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package enums
+ |
+ |enum class Test {
+ | /**
+ | Sample docs for E1
+ | **/
+ | @SinceKotlin("1.3") // This annotation is transparent due to lack of @MustBeDocumented annotation
+ | E1
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = { m ->
+ val entryNode = m.children.first { it.name == "enums" }.children.first { it.name == "Test" }.children.first() as ClasslikePageNode
+ val signature = (entryNode.content as ContentGroup).dfs { it is ContentGroup && it.dci.toString() == "[enums/Test.E1///PointingToDeclaration/][Cover]" } as ContentGroup
+
+ signature.assertNode {
+ header(1) { +"E1" }
+ platformHinted {
+ group {
+ group {
+ + "Sample docs for E1"
+ }
+ }
+ group {
+ group {
+ link { +"E1" }
+ +"()"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ fun RootPageNode.getClasslikeToMemberMap() =
+ this.parentMap.filterValues { it is ClasslikePageNode }.entries.groupBy({ it.value }) { it.key }
+
+ private fun ContentGroup.constructorSignature(): String =
+ (children.single() as ContentGroup).children.drop(1).joinToString(separator = "") { (it as ContentText).text }
+}
diff --git a/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt b/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
new file mode 100644
index 00000000..4dfdc410
--- /dev/null
+++ b/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt
@@ -0,0 +1,104 @@
+package expect
+
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertTrue
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.util.concurrent.TimeUnit
+
+abstract class AbstractExpectTest(
+ val testDir: Path? = Paths.get("src/test", "resources", "expect"),
+ val formats: List<String> = listOf("html")
+) : AbstractCoreTest() {
+
+ protected fun generateOutput(path: Path, outFormat: String): Path? {
+ val config = dokkaConfiguration {
+ format = outFormat
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf(path.toAbsolutePath().asString())
+ }
+ }
+ }
+
+ var result: Path? = null
+ testFromData(config, cleanupOutput = false) {
+ renderingStage = { _, context -> result = Paths.get(context.configuration.outputDir) }
+ }
+ return result
+ }
+
+ protected fun compareOutput(expected: Path, obtained: Path?, gitTimeout: Long = 500) {
+ obtained?.let { path ->
+ val gitCompare = ProcessBuilder(
+ "git",
+ "--no-pager",
+ "diff",
+ expected.asString(),
+ path.asString()
+ ).also { logger.info("git diff command: ${it.command().joinToString(" ")}") }
+ .also { it.redirectErrorStream() }.start()
+
+ assertTrue(gitCompare.waitFor(gitTimeout, TimeUnit.MILLISECONDS)) { "Git timed out after $gitTimeout" }
+ gitCompare.inputStream.bufferedReader().lines().forEach { logger.info(it) }
+ assertTrue(gitCompare.exitValue() == 0) { "${path.fileName}: outputs don't match" }
+ } ?: throw AssertionError("obtained path is null")
+ }
+
+ protected fun compareOutputWithExcludes(
+ expected: Path,
+ obtained: Path?,
+ excludes: List<String>,
+ timeout: Long = 500
+ ) {
+ obtained?.let { path ->
+ val (res, out, err) = runDiff(expected, obtained, excludes, timeout)
+ assertTrue(res == 0, "Outputs differ:\nstdout - $out\n\nstderr - ${err ?: ""}")
+ } ?: throw AssertionError("obtained path is null")
+ }
+
+ protected fun runDiff(exp: Path, obt: Path, excludes: List<String>, timeout: Long): ProcessResult =
+ ProcessBuilder().command(
+ listOf("diff", "-ru") + excludes.flatMap { listOf("-x", it) } + listOf("--", exp.asString(), obt.asString())
+ ).also {
+ it.redirectErrorStream()
+ }.start().also { assertTrue(it.waitFor(timeout, TimeUnit.MILLISECONDS), "diff timed out") }.let {
+ ProcessResult(it.exitValue(), it.inputStream.bufferResult())
+ }
+
+
+ protected fun testOutput(p: Path, outFormat: String) {
+ val expectOut = p.resolve("out/$outFormat")
+ val testOut = generateOutput(p.resolve("src"), outFormat)
+ .also { logger.info("Test out: ${it?.asString()}") }
+
+ compareOutput(expectOut.toAbsolutePath(), testOut?.toAbsolutePath())
+ testOut?.deleteRecursively()
+ }
+
+ protected fun testOutputWithExcludes(
+ p: Path,
+ outFormat: String,
+ ignores: List<String> = emptyList(),
+ timeout: Long = 500
+ ) {
+ val expected = p.resolve("out/$outFormat")
+ generateOutput(p.resolve("src"), outFormat)
+ ?.let { obtained ->
+ compareOutputWithExcludes(expected, obtained, ignores, timeout)
+
+ obtained.deleteRecursively()
+ } ?: throw AssertionError("Output not generated for ${p.fileName}")
+ }
+
+ protected fun generateExpect(p: Path, outFormat: String) {
+ val out = p.resolve("out/$outFormat/")
+ Files.createDirectories(out)
+
+ val ret = generateOutput(p.resolve("src"), outFormat)
+ Files.list(out).forEach { it.deleteRecursively() }
+ ret?.let { Files.list(it).forEach { f -> f.copyRecursively(out.resolve(f.fileName)) } }
+ }
+
+}
diff --git a/plugins/base/src/test/kotlin/expect/ExpectGenerator.kt b/plugins/base/src/test/kotlin/expect/ExpectGenerator.kt
new file mode 100644
index 00000000..cb3313f9
--- /dev/null
+++ b/plugins/base/src/test/kotlin/expect/ExpectGenerator.kt
@@ -0,0 +1,13 @@
+package expect
+
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+
+class ExpectGenerator : AbstractExpectTest() {
+
+ @Disabled
+ @Test
+ fun generateAll() = testDir?.dirsWithFormats(formats).orEmpty().forEach { (p, f) ->
+ generateExpect(p, f)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/expect/ExpectTest.kt b/plugins/base/src/test/kotlin/expect/ExpectTest.kt
new file mode 100644
index 00000000..bed841a6
--- /dev/null
+++ b/plugins/base/src/test/kotlin/expect/ExpectTest.kt
@@ -0,0 +1,24 @@
+package expect
+
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.DynamicTest.dynamicTest
+import org.junit.jupiter.api.TestFactory
+
+class ExpectTest : AbstractExpectTest() {
+ private val ignores: List<String> = listOf(
+ "images",
+ "scripts",
+ "images",
+ "styles",
+ "*.js",
+ "*.css",
+ "*.svg",
+ "*.map"
+ )
+
+ @Disabled
+ @TestFactory
+ fun expectTest() = testDir?.dirsWithFormats(formats).orEmpty().map { (p, f) ->
+ dynamicTest("${p.fileName}-$f") { testOutputWithExcludes(p, f, ignores) }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/expect/ExpectUtils.kt b/plugins/base/src/test/kotlin/expect/ExpectUtils.kt
new file mode 100644
index 00000000..1f54c20e
--- /dev/null
+++ b/plugins/base/src/test/kotlin/expect/ExpectUtils.kt
@@ -0,0 +1,28 @@
+package expect
+
+import java.io.InputStream
+import java.nio.file.Files
+import java.nio.file.Path
+import kotlin.streams.toList
+
+data class ProcessResult(val code: Int, val out: String, val err: String? = null)
+
+internal fun Path.dirsWithFormats(formats: List<String>): List<Pair<Path, String>> =
+ Files.list(this).toList().filter { Files.isDirectory(it) }.flatMap { p -> formats.map { p to it } }
+
+internal fun Path.asString() = normalize().toString()
+internal fun Path.deleteRecursively() = toFile().deleteRecursively()
+
+internal fun Path.copyRecursively(target: Path) = toFile().copyRecursively(target.toFile())
+
+internal fun Path.listRecursively(filter: (Path) -> Boolean): List<Path> = when {
+ Files.isDirectory(this) -> listOfNotNull(takeIf(filter)) + Files.list(this).toList().flatMap {
+ it.listRecursively(
+ filter
+ )
+ }
+ Files.isRegularFile(this) -> listOfNotNull(this.takeIf(filter))
+ else -> emptyList()
+ }
+
+internal fun InputStream.bufferResult(): String = this.bufferedReader().lines().toList().joinToString("\n") \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt b/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt
new file mode 100644
index 00000000..c8b9f2d4
--- /dev/null
+++ b/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt
@@ -0,0 +1,173 @@
+package filter
+
+import org.jetbrains.dokka.PackageOptionsImpl
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+
+class DeprecationFilterTest : AbstractCoreTest() {
+ @Test
+ fun `function with false global skipDeprecated`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ skipDeprecated = false
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+ @Test
+ fun `deprecated function with false global skipDeprecated`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ skipDeprecated = false
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |@Deprecated("dep")
+ |fun testFunction() { }
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+ @Test
+ fun `deprecated function with true global skipDeprecated`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ skipDeprecated = true
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |@Deprecated("dep")
+ |fun testFunction() { }
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 0
+ )
+ }
+ }
+ }
+ @Test
+ fun `deprecated function with false global true package skipDeprecated`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ skipDeprecated = false
+ perPackageOptions = mutableListOf(
+ PackageOptionsImpl("example",
+ true,
+ false,
+ true,
+ false)
+ )
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |@Deprecated("dep")
+ |fun testFunction() { }
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 0
+ )
+ }
+ }
+ }
+ @Test
+ fun `deprecated function with true global false package skipDeprecated`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ skipDeprecated = true
+ perPackageOptions = mutableListOf(
+ PackageOptionsImpl("example",
+ false,
+ false,
+ false,
+ false)
+ )
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |@Deprecated("dep")
+ |fun testFunction() { }
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt b/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt
new file mode 100644
index 00000000..e5b9e9c2
--- /dev/null
+++ b/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt
@@ -0,0 +1,63 @@
+package filter
+
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+
+class EmptyPackagesFilterTest : AbstractCoreTest() {
+ @Test
+ fun `empty package with false skipEmptyPackages`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ skipEmptyPackages = false
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.isNotEmpty()
+ )
+ }
+ }
+ }
+ @Test
+ fun `empty package with true skipEmptyPackages`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ skipEmptyPackages = true
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.isEmpty()
+ )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt b/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt
new file mode 100644
index 00000000..192de449
--- /dev/null
+++ b/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt
@@ -0,0 +1,173 @@
+package filter
+
+import org.jetbrains.dokka.PackageOptionsImpl
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+
+class VisibilityFilterTest : AbstractCoreTest() {
+ @Test
+ fun `public function with false global includeNonPublic`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ includeNonPublic = false
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+ @Test
+ fun `private function with false global includeNonPublic`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ includeNonPublic = false
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |private fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 0
+ )
+ }
+ }
+ }
+ @Test
+ fun `private function with true global includeNonPublic`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ includeNonPublic = true
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |private fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+ @Test
+ fun `private function with false global true package includeNonPublic`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ includeNonPublic = false
+ perPackageOptions = mutableListOf(
+ PackageOptionsImpl("example",
+ true,
+ false,
+ false,
+ false)
+ )
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |private fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 1
+ )
+ }
+ }
+ }
+ @Test
+ fun `private function with true global false package includeNonPublic`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/basic/Test.kt")
+ includeNonPublic = true
+ perPackageOptions = mutableListOf(
+ PackageOptionsImpl("example",
+ false,
+ false,
+ false,
+ false)
+ )
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |package example
+ |
+ |private fun testFunction() { }
+ |
+ |
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesFirstTransformationStep = {
+ Assertions.assertTrue(
+ it.component2().packages.first().functions.size == 0
+ )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/issues/IssuesTest.kt b/plugins/base/src/test/kotlin/issues/IssuesTest.kt
new file mode 100644
index 00000000..7b065349
--- /dev/null
+++ b/plugins/base/src/test/kotlin/issues/IssuesTest.kt
@@ -0,0 +1,73 @@
+package issues
+
+import org.jetbrains.dokka.model.DClass
+import org.jetbrains.dokka.model.DFunction
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.name
+
+class IssuesTest : AbstractModelTest("/src/main/kotlin/issues/Test.kt", "issues") {
+
+ @Test
+ fun errorClasses() {
+ inlineModelTest(
+ """
+ |class Test(var value: String) {
+ | fun test(): List<String> = emptyList()
+ | fun brokenApply(v: String) = apply { value = v }
+ |
+ | fun brokenRun(v: String) = run {
+ | value = v
+ | this
+ | }
+ |
+ | fun brokenLet(v: String) = let {
+ | it.value = v
+ | it
+ | }
+ |
+ | fun brokenGenerics() = listOf("a", "b", "c")
+ |
+ | fun working(v: String) = doSomething()
+ |
+ | fun doSomething(): String = "Hello"
+ |}
+ """,
+ configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+ ) {
+ with((this / "issues" / "Test").cast<DClass>()) {
+ (this / "working").cast<DFunction>().type.name equals "String"
+ (this / "doSomething").cast<DFunction>().type.name equals "String"
+ (this / "brokenGenerics").cast<DFunction>().type.name equals "List"
+ (this / "brokenApply").cast<DFunction>().type.name equals "Test"
+ (this / "brokenRun").cast<DFunction>().type.name equals "Test"
+ (this / "brokenLet").cast<DFunction>().type.name equals "Test"
+ }
+ }
+ }
+
+ //@Test
+ // fun errorClasses() {
+ // checkSourceExistsAndVerifyModel("testdata/issues/errorClasses.kt",
+ // modelConfig = ModelConfig(analysisPlatform = analysisPlatform, withJdk = true, withKotlinRuntime = true)) { model ->
+ // val cls = model.members.single().members.single()
+ //
+ // fun DocumentationNode.returnType() = this.details.find { it.kind == NodeKind.Type }?.name
+ // assertEquals("Test", cls.members[1].returnType())
+ // assertEquals("Test", cls.members[2].returnType())
+ // assertEquals("Test", cls.members[3].returnType())
+ // assertEquals("List", cls.members[4].returnType())
+ // assertEquals("String", cls.members[5].returnType())
+ // assertEquals("String", cls.members[6].returnType())
+ // assertEquals("String", cls.members[7].returnType())
+ // }
+ // }
+
+}
diff --git a/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt b/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt
new file mode 100644
index 00000000..a8fc9f6d
--- /dev/null
+++ b/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt
@@ -0,0 +1,225 @@
+package linkableContent
+
+import org.jetbrains.dokka.SourceLinkDefinitionImpl
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.transformers.pages.samples.DefaultSamplesTransformer
+import org.jetbrains.dokka.base.transformers.pages.sourcelinks.SourceLinksTransformer
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.kotlin.utils.addToStdlib.cast
+import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import java.nio.file.Paths
+
+class LinkableContentTest : AbstractCoreTest() {
+
+ @Test
+ fun `Include module and package documentation`() {
+
+ val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+ val includesDir = getTestDataDir("linkable/includes").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "js"
+ sourceRoots = listOf("jsMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ name = "js"
+ includes = listOf(Paths.get("$includesDir/include2.md").toString())
+ }
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("jvmMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ name = "jvm"
+ includes = listOf(Paths.get("$includesDir/include1.md").toString())
+ }
+ }
+ }
+
+ testFromData(configuration) {
+ documentablesMergingStage = {
+ Assertions.assertEquals(2, it.documentation.size)
+ Assertions.assertEquals(2, it.packages.size)
+ Assertions.assertEquals(1, it.packages.first().documentation.size)
+ Assertions.assertEquals(1, it.packages.last().documentation.size)
+ }
+ }
+
+ }
+
+ @Test
+ fun `Sources multiplatform class documentation`() {
+
+ val testDataDir = getTestDataDir("linkable/sources").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "js"
+ sourceRoots = listOf("$testDataDir/jsMain/kotlin")
+ sourceLinks = listOf(
+ SourceLinkDefinitionImpl(
+ path = "jsMain/kotlin",
+ url = "https://github.com/user/repo/tree/master/src/jsMain/kotlin",
+ lineSuffix = "#L"
+ )
+ )
+ name = "js"
+ }
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("$testDataDir/jvmMain/kotlin")
+ sourceLinks = listOf(
+ SourceLinkDefinitionImpl(
+ path = "jvmMain/kotlin",
+ url = "https://github.com/user/repo/tree/master/src/jvmMain/kotlin",
+ lineSuffix = "#L"
+ )
+ )
+ name = "jvm"
+ }
+ }
+ }
+
+ testFromData(configuration) {
+ renderingStage = { rootPageNode, dokkaContext ->
+ val newRoot = SourceLinksTransformer(
+ dokkaContext,
+ PageContentBuilder(
+ dokkaContext.single(dokkaContext.plugin<DokkaBase>().commentsToContentConverter),
+ dokkaContext.single(dokkaContext.plugin<DokkaBase>().signatureProvider),
+ dokkaContext.logger
+ )
+ ).invoke(rootPageNode)
+ val moduleChildren = newRoot.children
+ Assertions.assertEquals(1, moduleChildren.size)
+ val packageChildren = moduleChildren.first().children
+ Assertions.assertEquals(2, packageChildren.size)
+ packageChildren.forEach {
+ val name = it.name.substringBefore("Class")
+ val crl = it.safeAs<ClasslikePageNode>()?.content?.safeAs<ContentGroup>()?.children?.last()
+ ?.safeAs<ContentGroup>()?.children?.last()?.safeAs<ContentGroup>()?.children?.lastOrNull()
+ ?.safeAs<ContentTable>()?.children?.singleOrNull()
+ ?.safeAs<ContentGroup>()?.children?.singleOrNull().safeAs<ContentResolvedLink>()
+ Assertions.assertEquals(
+ "https://github.com/user/repo/tree/master/src/${name.toLowerCase()}Main/kotlin/${name}Class.kt#L3",
+ crl?.address
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `Samples multiplatform documentation`() {
+
+ val testDataDir = getTestDataDir("linkable/samples").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "js"
+ sourceRoots = listOf("$testDataDir/jsMain/kotlin")
+ name = "js"
+ samples = listOf("$testDataDir/jsMain/resources/Samples.kt")
+ }
+ sourceSet {
+ moduleName = "example"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("$testDataDir/jvmMain/kotlin")
+ name = "jvm"
+ samples = listOf("$testDataDir/jvmMain/resources/Samples.kt")
+ }
+ }
+ }
+
+ testFromData(configuration) {
+ renderingStage = { rootPageNode, dokkaContext ->
+ val newRoot = DefaultSamplesTransformer(dokkaContext).invoke(rootPageNode)
+
+ val moduleChildren = newRoot.children
+ Assertions.assertEquals(1, moduleChildren.size)
+ val packageChildren = moduleChildren.first().children
+ Assertions.assertEquals(2, packageChildren.size)
+ packageChildren.forEach {
+ val name = it.name.substringBefore("Class")
+ val classChildren = it.children
+ Assertions.assertEquals(2, classChildren.size)
+ val function = classChildren.find { it.name == "printWithExclamation" }
+ val text = function.cast<MemberPageNode>().content.cast<ContentGroup>().children.last()
+ .cast<ContentDivergentGroup>().children.single()
+ .cast<ContentDivergentInstance>().before
+ .cast<ContentGroup>().children.last()
+ .cast<ContentGroup>().children.last()
+ .cast<PlatformHintedContent>().children.single()
+ .cast<ContentGroup>().children.single()
+ .cast<ContentGroup>().children.single()
+ .cast<ContentCodeBlock>().children.single().cast<ContentText>().text
+ Assertions.assertEquals(
+ """|import p2.${name}Class
+ |fun main() {
+ | //sampleStart
+ | ${name}Class().printWithExclamation("Hi, $name")
+ | //sampleEnd
+ |}""".trimMargin(),
+ text
+ )
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `Documenting return type for a function in inner class with generic parent`() {
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |
+ |class Sample<S>(first: S){
+ | inner class SampleInner {
+ | fun foo(): S = TODO()
+ | }
+ |}
+ |
+ """.trimIndent(),
+ dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ name = "js"
+ }
+ }
+ }
+ ) {
+ renderingStage = { module, _ ->
+ val sample = module.children.single { it.name == "test" }
+ .children.single { it.name == "Sample" }.cast<ClasslikePageNode>()
+ val foo = sample
+ .children.single { it.name == "SampleInner" }.cast<ClasslikePageNode>()
+ .children.single { it.name == "foo" }.cast<MemberPageNode>()
+
+ val returnTypeNode = foo.content.dfs {
+ val link = it.safeAs<ContentDRILink>()?.children
+ val child = link?.first().safeAs<ContentText>()
+ child?.text == "S"
+ }?.safeAs<ContentDRILink>()
+
+ Assertions.assertEquals(sample.dri.first(), returnTypeNode?.address)
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/locationProvider/DefaultLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/DefaultLocationProviderTest.kt
new file mode 100644
index 00000000..a219fb04
--- /dev/null
+++ b/plugins/base/src/test/kotlin/locationProvider/DefaultLocationProviderTest.kt
@@ -0,0 +1,41 @@
+package locationProvider
+
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProvider
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertNotEquals
+import org.junit.jupiter.api.Test
+
+class DefaultLocationProviderTest: AbstractCoreTest() {
+ @Test
+ fun `#644 same directory for module and package`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/basic/Test.kt
+ |
+ |class Test {
+ | val x = 1
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ var context: DokkaContext? = null
+ pluginsSetupStage = {
+ context = it
+ }
+
+ pagesGenerationStage = { module ->
+ val lp = DefaultLocationProvider(module, context!!)
+ assertNotEquals(lp.resolve(module.children.single()).removePrefix("/"), lp.resolve(module))
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/markdown/KDocTest.kt b/plugins/base/src/test/kotlin/markdown/KDocTest.kt
new file mode 100644
index 00000000..f5b29322
--- /dev/null
+++ b/plugins/base/src/test/kotlin/markdown/KDocTest.kt
@@ -0,0 +1,47 @@
+package markdown
+
+import org.jetbrains.dokka.model.DPackage
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.pages.ModulePageNode
+import org.junit.jupiter.api.Assertions.*
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+
+abstract class KDocTest : AbstractCoreTest() {
+
+ private val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/example/Test.kt")
+ }
+ }
+ }
+
+ private fun interpolateKdoc(kdoc: String) = """
+ |/src/main/kotlin/example/Test.kt
+ |package example
+ | /**
+ ${kdoc.split("\n").joinToString("") { "| *$it\n" } }
+ | */
+ |class Test
+ """.trimMargin()
+
+ private fun actualDocumentationNode(modulePageNode: ModulePageNode) =
+ (modulePageNode.documentable?.children?.first() as DPackage)
+ .classlikes.single()
+ .documentation.values.single()
+
+
+ protected fun executeTest(kdoc: String, expectedDocumentationNode: DocumentationNode) {
+ testInline(
+ interpolateKdoc(kdoc),
+ configuration
+ ) {
+ pagesGenerationStage = {
+ assertEquals(
+ expectedDocumentationNode,
+ actualDocumentationNode(it as ModulePageNode)
+ )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/markdown/LinkTest.kt b/plugins/base/src/test/kotlin/markdown/LinkTest.kt
new file mode 100644
index 00000000..a6333c5a
--- /dev/null
+++ b/plugins/base/src/test/kotlin/markdown/LinkTest.kt
@@ -0,0 +1,79 @@
+package markdown
+
+import org.jetbrains.dokka.pages.ClasslikePageNode
+import org.jetbrains.dokka.pages.ContentDRILink
+import org.jetbrains.dokka.pages.MemberPageNode
+import org.jetbrains.dokka.pages.dfs
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertNotNull
+import org.junit.jupiter.api.Test
+
+class LinkTest : AbstractCoreTest() {
+ @Test
+ fun linkToClassLoader() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/parser")
+ }
+ }
+ }
+ testInline(
+ """
+ |/src/main/kotlin/parser/Test.kt
+ |package parser
+ |
+ | /**
+ | * Some docs that link to [ClassLoader.clearAssertionStatus]
+ | */
+ |fun test(x: ClassLoader) = x.clearAssertionStatus()
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ renderingStage = { rootPageNode, _ ->
+ assertNotNull((rootPageNode.children.single().children.single() as MemberPageNode)
+ .content
+ .dfs { node ->
+ node is ContentDRILink &&
+ node.address.toString() == "parser//test/#java.lang.ClassLoader/PointingToDeclaration/"}
+ )
+ }
+ }
+ }
+
+ @Test
+ fun returnTypeShouldHaveLinkToOuterClassFromInner() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ displayName = "JVM"
+ }
+ }
+ }
+ //This does not contain a package to check for situation when the package has to be artificially generated
+ testInline(
+ """
+ |/src/main/kotlin/parser/Test.kt
+ |
+ |class Outer<OUTER> {
+ | inner class Inner<INNER> {
+ | fun foo(): OUTER = TODO()
+ | }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ renderingStage = { rootPageNode, _ ->
+ val root = rootPageNode.children.single().children.single() as ClasslikePageNode
+ val innerClass = root.children.first { it is ClasslikePageNode }
+ val foo = innerClass.children.first { it.name == "foo" } as MemberPageNode
+
+ assertEquals(root.dri.first().toString(), "[JVM root]/Outer///PointingToDeclaration/")
+ assertNotNull(foo.content.dfs { it is ContentDRILink && it.address.toString() == root.dri.first().toString() } )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/markdown/ParserTest.kt b/plugins/base/src/test/kotlin/markdown/ParserTest.kt
new file mode 100644
index 00000000..ee6170c2
--- /dev/null
+++ b/plugins/base/src/test/kotlin/markdown/ParserTest.kt
@@ -0,0 +1,1123 @@
+package org.jetbrains.dokka.tests
+
+import markdown.KDocTest
+import org.jetbrains.dokka.model.doc.*
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+
+
+class ParserTest : KDocTest() {
+
+ @Test
+ fun `Simple text`() {
+ val kdoc = """
+ | This is simple test of string
+ | Next line
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(Text("This is simple test of string Next line")))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Simple text with new line`() {
+ val kdoc = """
+ | This is simple test of string\
+ | Next line
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Text("This is simple test of string"),
+ Br,
+ Text("Next line")
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Text with Bold and Emphasis decorators`() {
+ val kdoc = """
+ | This is **simple** test of _string_
+ | Next **_line_**
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Text("This is "),
+ B(listOf(Text("simple"))),
+ Text(" test of "),
+ I(listOf(Text("string"))),
+ Text(" Next "),
+ B(listOf(I(listOf(Text("line")))))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Text with Colon`() {
+ val kdoc = """
+ | This is simple text with: colon!
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(Text("This is simple text with: colon!")))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Multilined text`() {
+ val kdoc = """
+ | Text
+ | and
+ | String
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(Text("Text and String")))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Paragraphs`() {
+ val kdoc = """
+ | Paragraph number
+ | one
+ |
+ | Paragraph\
+ | number two
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ P(listOf(Text("Paragraph number one"))),
+ P(listOf(Text("Paragraph"), Br, Text("number two")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Emphasis with star`() {
+ val kdoc = " *text*"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(I(listOf(Text("text")))))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Underscores that are not Emphasis`() {
+ val kdoc = "text_with_underscores"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(Text("text_with_underscores")))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Emphasis with underscores`() {
+ val kdoc = "_text_"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(I(listOf(Text("text")))))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Embedded star`() {
+ val kdoc = "Embedded*Star"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(listOf(Text("Embedded*Star")))
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+
+ @Test
+ fun `Unordered list`() {
+ val kdoc = """
+ | * list item 1
+ | * list item 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1"))))),
+ Li(listOf(P(listOf(Text("list item 2")))))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Unordered list with multilines`() {
+ val kdoc = """
+ | * list item 1
+ | continue 1
+ | * list item 2\
+ | continue 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1 continue 1"))))),
+ Li(listOf(P(listOf(Text("list item 2"), Br, Text("continue 2")))))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Unordered list with Bold`() {
+ val kdoc = """
+ | * list **item** 1
+ | continue 1
+ | * list __item__ 2
+ | continue 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ul(
+ listOf(
+ Li(
+ listOf(
+ P(
+ listOf(
+ Text("list "),
+ B(listOf(Text("item"))),
+ Text(" 1 continue 1")
+ )
+ )
+ )
+ ),
+ Li(
+ listOf(
+ P(
+ listOf(
+ Text("list "),
+ B(listOf(Text("item"))),
+ Text(" 2 continue 2")
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Unordered list with nested bullets`() {
+ val kdoc = """
+ | * Outer first
+ | Outer next line
+ | * Outer second
+ | - Middle first
+ | Middle next line
+ | - Middle second
+ | + Inner first
+ | Inner next line
+ | - Middle third
+ | * Outer third
+ |
+ | New paragraph""".trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Outer first Outer next line"))))),
+ Li(listOf(P(listOf(Text("Outer second"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Middle first Middle next line"))))),
+ Li(listOf(P(listOf(Text("Middle second"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Inner first Inner next line")))))
+ )
+ ),
+ Li(listOf(P(listOf(Text("Middle third")))))
+ )
+ ),
+ Li(listOf(P(listOf(Text("Outer third")))))
+ )
+ ),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Ordered list`() {
+ val kdoc = """
+ | 1. list item 1
+ | 2. list item 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1"))))),
+ Li(listOf(P(listOf(Text("list item 2")))))
+ ),
+ mapOf("start" to "1")
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+
+ @Test
+ fun `Ordered list beginning from other number`() {
+ val kdoc = """
+ | 9. list item 1
+ | 12. list item 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1"))))),
+ Li(listOf(P(listOf(Text("list item 2")))))
+ ),
+ mapOf("start" to "9")
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Ordered list with multilines`() {
+ val kdoc = """
+ | 2. list item 1
+ | continue 1
+ | 3. list item 2
+ | continue 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1 continue 1"))))),
+ Li(listOf(P(listOf(Text("list item 2 continue 2")))))
+ ),
+ mapOf("start" to "2")
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Ordered list with Bold`() {
+ val kdoc = """
+ | 1. list **item** 1
+ | continue 1
+ | 2. list __item__ 2
+ | continue 2
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ Ol(
+ listOf(
+ Li(
+ listOf(
+ P(
+ listOf(
+ Text("list "),
+ B(listOf(Text("item"))),
+ Text(" 1 continue 1")
+ )
+ )
+ )
+ ),
+ Li(
+ listOf(
+ P(
+ listOf(
+ Text("list "),
+ B(listOf(Text("item"))),
+ Text(" 2 continue 2")
+ )
+ )
+ )
+ )
+ ),
+ mapOf("start" to "1")
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Ordered list with nested bullets`() {
+ val kdoc = """
+ | 1. Outer first
+ | Outer next line
+ | 2. Outer second
+ | 1. Middle first
+ | Middle next line
+ | 2. Middle second
+ | 1. Inner first
+ | Inner next line
+ | 5. Middle third
+ | 4. Outer third
+ |
+ | New paragraph""".trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Outer first Outer next line"))))),
+ Li(listOf(P(listOf(Text("Outer second"))))),
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Middle first Middle next line"))))),
+ Li(listOf(P(listOf(Text("Middle second"))))),
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Inner first Inner next line")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ Li(listOf(P(listOf(Text("Middle third")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ Li(listOf(P(listOf(Text("Outer third")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Ordered nested in Unordered nested in Ordered list`() {
+ val kdoc = """
+ | 1. Outer first
+ | Outer next line
+ | 2. Outer second
+ | + Middle first
+ | Middle next line
+ | + Middle second
+ | 1. Inner first
+ | Inner next line
+ | + Middle third
+ | 4. Outer third
+ |
+ | New paragraph""".trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Outer first Outer next line"))))),
+ Li(listOf(P(listOf(Text("Outer second"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Middle first Middle next line"))))),
+ Li(listOf(P(listOf(Text("Middle second"))))),
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Inner first Inner next line")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ Li(listOf(P(listOf(Text("Middle third")))))
+ )
+ ),
+ Li(listOf(P(listOf(Text("Outer third")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Header and two paragraphs`() {
+ val kdoc = """
+ | # Header 1
+ | Following text
+ |
+ | New paragraph
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ H1(listOf(Text("Header 1"))),
+ P(listOf(Text("Following text"))),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Disabled //TODO: ATX_2 to ATX_6 and sometimes ATX_1 from jetbrains parser consumes white space. Need to handle it in their library
+ @Test
+ fun `All headers`() {
+ val kdoc = """
+ | # Header 1
+ | Text 1
+ | ## Header 2
+ | Text 2
+ | ### Header 3
+ | Text 3
+ | #### Header 4
+ | Text 4
+ | ##### Header 5
+ | Text 5
+ | ###### Header 6
+ | Text 6
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ H1(listOf(Text("Header 1"))),
+ P(listOf(Text("Text 1"))),
+ H2(listOf(Text("Header 2"))),
+ P(listOf(Text("Text 2"))),
+ H3(listOf(Text("Header 3"))),
+ P(listOf(Text("Text 3"))),
+ H4(listOf(Text("Header 4"))),
+ P(listOf(Text("Text 4"))),
+ H5(listOf(Text("Header 5"))),
+ P(listOf(Text("Text 5"))),
+ H6(listOf(Text("Header 6"))),
+ P(listOf(Text("Text 6")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Bold New Line Bold`() {
+ val kdoc = """
+ | **line 1**\
+ | **line 2**
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ B(listOf(Text("line 1"))),
+ Br,
+ B(listOf(Text("line 2")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Horizontal rule`() {
+ val kdoc = """
+ | ***
+ | text 1
+ | ___
+ | text 2
+ | ***
+ | text 3
+ | ___
+ | text 4
+ | ***
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ HorizontalRule,
+ P(listOf(Text("text 1"))),
+ HorizontalRule,
+ P(listOf(Text("text 2"))),
+ HorizontalRule,
+ P(listOf(Text("text 3"))),
+ HorizontalRule,
+ P(listOf(Text("text 4"))),
+ HorizontalRule
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Blockquote`() {
+ val kdoc = """
+ | > Blockquotes are very handy in email to emulate reply text.
+ | > This line is part of the same quote.
+ |
+ | Quote break.
+ |
+ | > Quote
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ BlockQuote(
+ listOf(
+ P(
+ listOf(
+ Text("Blockquotes are very handy in email to emulate reply text. This line is part of the same quote.")
+ )
+ )
+ )
+ ),
+ P(listOf(Text("Quote break."))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("Quote")))
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+
+ @Test
+ fun `Blockquote nested`() {
+ val kdoc = """
+ | > text 1
+ | > text 2
+ | >> text 3
+ | >> text 4
+ | >
+ | > text 5
+ |
+ | Quote break.
+ |
+ | > Quote
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ BlockQuote(
+ listOf(
+ P(listOf(Text("text 1 text 2"))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("text 3 text 4")))
+ )
+ ),
+ P(listOf(Text("text 5")))
+ )
+ ),
+ P(listOf(Text("Quote break."))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("Quote")))
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Disabled //TODO: Again ATX_1 consumes white space
+ @Test
+ fun `Blockquote nested with fancy text enhancement`() {
+ val kdoc = """
+ | > text **1**
+ | > text 2
+ | >> # text 3
+ | >> * text 4
+ | >> * text 5
+ | >
+ | > text 6
+ |
+ | Quote break.
+ |
+ | > Quote
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ BlockQuote(
+ listOf(
+ P(
+ listOf(
+ Text("text "),
+ B(listOf(Text("1"))),
+ Text("\ntext 2")
+ )
+ ),
+ BlockQuote(
+ listOf(
+ H1(listOf(Text("text 3"))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("text 4"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("text 5")))))
+ )
+ )
+ )
+ )
+ )
+ ),
+ P(listOf(Text("text 6")))
+ )
+ ),
+ P(listOf(Text("Quote break."))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("Quote")))
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Simple Code Block`() {
+ val kdoc = """
+ | `Some code`
+ | Sample text
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ CodeInline(listOf(Text("Some code"))),
+ Text(" Sample text")
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Multilined Code Block`() {
+ val kdoc = """
+ | ```kotlin
+ | val x: Int = 0
+ | val y: String = "Text"
+ |
+ | val z: Boolean = true
+ | for(i in 0..10) {
+ | println(i)
+ | }
+ | ```
+ | Sample text
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ CodeBlock(
+ listOf(
+ Text("val x: Int = 0"), Br,
+ Text("val y: String = \"Text\""), Br, Br,
+ Text(" val z: Boolean = true"), Br,
+ Text("for(i in 0..10) {"), Br,
+ Text(" println(i)"), Br,
+ Text("}")
+ ),
+ mapOf("lang" to "kotlin")
+ ),
+ P(listOf(Text("Sample text")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+
+ @Test
+ fun `Inline link`() {
+ val kdoc = """
+ | [I'm an inline-style link](https://www.google.com)
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm an inline-style link")),
+ mapOf("href" to "https://www.google.com")
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Inline link with title`() {
+ val kdoc = """
+ | [I'm an inline-style link with title](https://www.google.com "Google's Homepage")
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm an inline-style link with title")),
+ mapOf("href" to "https://www.google.com", "title" to "Google's Homepage")
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Full reference link`() {
+ val kdoc = """
+ | [I'm a reference-style link][Arbitrary case-insensitive reference text]
+ |
+ | [arbitrary case-insensitive reference text]: https://www.mozilla.org
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm a reference-style link")),
+ mapOf("href" to "https://www.mozilla.org")
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Full reference link with number`() {
+ val kdoc = """
+ | [You can use numbers for reference-style link definitions][1]
+ |
+ | [1]: http://slashdot.org
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ P(
+ listOf(
+ A(
+ listOf(Text("You can use numbers for reference-style link definitions")),
+ mapOf("href" to "http://slashdot.org")
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Short reference link`() {
+ val kdoc = """
+ | Or leave it empty and use the [link text itself].
+ |
+ | [link text itself]: http://www.reddit.com
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ P(
+ listOf(
+ Text("Or leave it empty and use the "),
+ A(
+ listOf(Text("link text itself")),
+ mapOf("href" to "http://www.reddit.com")
+ ),
+ Text(".")
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Autolink`() {
+ val kdoc = """
+ | URLs and URLs in angle brackets will automatically get turned into links.
+ | http://www.example.com or <http://www.example.com> and sometimes
+ | example.com (but not on Github, for example).
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Text("URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com or "),
+ A(
+ listOf(Text("http://www.example.com")),
+ mapOf("href" to "http://www.example.com")
+ ),
+ Text(" and sometimes example.com (but not on Github, for example).")
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Various links`() {
+ val kdoc = """
+ | [I'm an inline-style link](https://www.google.com)
+ |
+ | [I'm an inline-style link with title](https://www.google.com "Google's Homepage")
+ |
+ | [I'm a reference-style link][Arbitrary case-insensitive reference text]
+ |
+ | [You can use numbers for reference-style link definitions][1]
+ |
+ | Or leave it empty and use the [link text itself].
+ |
+ | URLs and URLs in angle brackets will automatically get turned into links.
+ | http://www.example.com or <http://www.example.com> and sometimes
+ | example.com (but not on Github, for example).
+ |
+ | Some text to show that the reference links can follow later.
+ |
+ | [arbitrary case-insensitive reference text]: https://www.mozilla.org
+ | [1]: http://slashdot.org
+ | [link text itself]: http://www.reddit.com
+ """.trimMargin()
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm an inline-style link")),
+ mapOf("href" to "https://www.google.com")
+ )
+ )
+ ),
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm an inline-style link with title")),
+ mapOf("href" to "https://www.google.com", "title" to "Google's Homepage")
+ )
+ )
+ ),
+ P(
+ listOf(
+ A(
+ listOf(Text("I'm a reference-style link")),
+ mapOf("href" to "https://www.mozilla.org")
+ )
+ )
+ ),
+ P(
+ listOf(
+ A(
+ listOf(Text("You can use numbers for reference-style link definitions")),
+ mapOf("href" to "http://slashdot.org")
+ )
+ )
+ ),
+ P(
+ listOf(
+ Text("Or leave it empty and use the "),
+ A(
+ listOf(Text("link text itself")),
+ mapOf("href" to "http://www.reddit.com")
+ ),
+ Text(".")
+ )
+ ),
+ P(
+ listOf(
+ Text("URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com or "),
+ A(
+ listOf(Text("http://www.example.com")),
+ mapOf("href" to "http://www.example.com")
+ ),
+ Text(" and sometimes example.com (but not on Github, for example).")
+ )
+ ),
+ P(listOf(Text("Some text to show that the reference links can follow later.")))
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+
+ @Test
+ fun `Windows Carriage Return Line Feed`() {
+ val kdoc = "text\r\ntext"
+ val expectedDocumentationNode = DocumentationNode(
+ listOf(
+ Description(
+ P(
+ listOf(
+ Text("text text")
+ )
+ )
+ )
+ )
+ )
+ executeTest(kdoc, expectedDocumentationNode)
+ }
+}
+
diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt
new file mode 100644
index 00000000..5dc8812e
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/ClassesTest.kt
@@ -0,0 +1,533 @@
+package model
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.sureClassNames
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.KotlinModifier.*
+import org.junit.jupiter.api.Assertions.assertNull
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.assertNotNull
+import utils.name
+import utils.supers
+
+
+class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") {
+
+ @Test
+ fun emptyClass() {
+ inlineModelTest(
+ """
+ |class Klass {}"""
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 4
+ }
+ }
+ }
+
+ @Test
+ fun emptyObject() {
+ inlineModelTest(
+ """
+ |object Obj {}
+ """
+ ) {
+ with((this / "classes" / "Obj").cast<DObject>()) {
+ name equals "Obj"
+ children counts 3
+ }
+ }
+ }
+
+ @Test
+ fun classWithConstructor() {
+ inlineModelTest(
+ """
+ |class Klass(name: String)
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 4
+
+ with(constructors.firstOrNull().assertNotNull("Constructor")) {
+ visibility.values allEquals KotlinVisibility.Public
+ parameters counts 1
+ with(parameters.firstOrNull().assertNotNull("Constructor parameter")) {
+ name equals "name"
+ type.name equals "String"
+ }
+ }
+
+ }
+ }
+ }
+
+ @Test
+ fun classWithFunction() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | fun fn() {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "fn").cast<DFunction>()) {
+ type.name equals "Unit"
+ parameters counts 0
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+ }
+
+ @Test
+ fun classWithProperty() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | val name: String = ""
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "name").cast<DProperty>()) {
+ name equals "name"
+ // TODO property name
+ }
+ }
+ }
+ }
+
+ @Test
+ fun classWithCompanionObject() {
+ inlineModelTest(
+ """
+ |class Klass() {
+ | companion object {
+ | val x = 1
+ | fun foo() {}
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ children counts 5
+
+ with((this / "Companion").cast<DObject>()) {
+ name equals "Companion"
+ children counts 5
+
+ with((this / "x").cast<DProperty>()) {
+ name equals "x"
+ }
+
+ with((this / "foo").cast<DFunction>()) {
+ name equals "foo"
+ parameters counts 0
+ type.name equals "Unit"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun dataClass() {
+ inlineModelTest(
+ """
+ |data class Klass() {}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ visibility.values allEquals KotlinVisibility.Public
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("Extras")) {
+ this counts 1
+ first() equals ExtraModifiers.KotlinOnlyModifiers.Data
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sealedClass() {
+ inlineModelTest(
+ """
+ |sealed class Klass() {}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ modifier.values.forEach { it equals Sealed }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedClassWithAnnotationParameters() {
+ inlineModelTest(
+ """
+ |@Deprecated("should no longer be used") class Foo() {}
+ """
+ ) {
+ with((this / "classes" / "Foo").cast<DClass>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Deprecated"
+ params.entries counts 1
+ (params["message"].assertNotNull("message") as StringValue).value equals "\"should no longer be used\""
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun notOpenClass() {
+ inlineModelTest(
+ """
+ |open class C() {
+ | open fun f() {}
+ |}
+ |
+ |class D() : C() {
+ | override fun f() {}
+ |}
+ """
+ ) {
+ val C = (this / "classes" / "C").cast<DClass>()
+ val D = (this / "classes" / "D").cast<DClass>()
+
+ with(C) {
+ modifier.values.forEach { it equals Open }
+ with((this / "f").cast<DFunction>()) {
+ modifier.values.forEach { it equals Open }
+ }
+ }
+ with(D) {
+ modifier.values.forEach { it equals Final }
+ with((this / "f").cast<DFunction>()) {
+ modifier.values.forEach { it equals Open }
+ }
+ D.supertypes.flatMap { it.component2() }.firstOrNull()?.dri equals C.dri
+ }
+ }
+ }
+
+ @Test
+ fun indirectOverride() {
+ inlineModelTest(
+ """
+ |abstract class C() {
+ | abstract fun foo()
+ |}
+ |
+ |abstract class D(): C()
+ |
+ |class E(): D() {
+ | override fun foo() {}
+ |}
+ """
+ ) {
+ val C = (this / "classes" / "C").cast<DClass>()
+ val D = (this / "classes" / "D").cast<DClass>()
+ val E = (this / "classes" / "E").cast<DClass>()
+
+ with(C) {
+ modifier.values.forEach { it equals Abstract }
+ ((this / "foo").cast<DFunction>()).modifier.values.forEach { it equals Abstract }
+ }
+
+ with(D) {
+ modifier.values.forEach { it equals Abstract }
+ }
+
+ with(E) {
+ modifier.values.forEach { it equals Final }
+
+ }
+ D.supers.single().dri equals C.dri
+ E.supers.single().dri equals D.dri
+ }
+ }
+
+ @Test
+ fun innerClass() {
+ inlineModelTest(
+ """
+ |class C {
+ | inner class D {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+
+ with((this / "D").cast<DClass>()) {
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) {
+ this counts 1
+ first() equals ExtraModifiers.KotlinOnlyModifiers.Inner
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun companionObjectExtension() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | companion object Default {}
+ |}
+ |
+ |/**
+ | * The def
+ | */
+ |val Klass.Default.x: Int get() = 1
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+
+ with((this / "Default").cast<DObject>()) {
+ name equals "Default"
+ // TODO extensions
+ }
+ }
+ }
+ }
+
+// @Test fun companionObjectExtension() {
+// checkSourceExistsAndVerifyModel("testdata/classes/companionObjectExtension.kt", defaultModelConfig) { model ->
+// val pkg = model.members.single()
+// val cls = pkg.members.single { it.name == "Foo" }
+// val extensions = cls.extensions.filter { it.kind == NodeKind.CompanionObjectProperty }
+// assertEquals(1, extensions.size)
+// }
+// }
+
+ @Test
+ fun secondaryConstructor() {
+ inlineModelTest(
+ """
+ |class C() {
+ | /** This is a secondary constructor. */
+ | constructor(s: String): this() {}
+ |}
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+ name equals "C"
+ constructors counts 2
+
+ constructors.map { it.name } allEquals "<init>"
+
+ with(constructors.find { it.parameters.isNullOrEmpty() } notNull "C()") {
+ parameters counts 0
+ }
+
+ with(constructors.find { it.parameters.isNotEmpty() } notNull "C(String)") {
+ parameters counts 1
+ with(parameters.firstOrNull() notNull "Constructor parameter") {
+ name equals "s"
+ type.name equals "String"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sinceKotlin() {
+ inlineModelTest(
+ """
+ |/**
+ | * Useful
+ | */
+ |@SinceKotlin("1.1")
+ |class C
+ """
+ ) {
+ with((this / "classes" / "C").cast<DClass>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "SinceKotlin"
+ params.entries counts 1
+ (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun privateCompanionObject() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | private companion object {
+ | fun fn() {}
+ | val a = 0
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ assertNull(companion, "Companion should not be visible by default")
+ }
+ }
+ }
+
+ @Test
+ fun companionObject() {
+ inlineModelTest(
+ """
+ |class Klass {
+ | companion object {
+ | fun fn() {}
+ | val a = 0
+ | }
+ |}
+ """
+ ) {
+ with((this / "classes" / "Klass").cast<DClass>()) {
+ name equals "Klass"
+ with((this / "Companion").cast<DObject>()) {
+ name equals "Companion"
+ visibility.values allEquals KotlinVisibility.Public
+
+ with((this / "fn").cast<DFunction>()) {
+ name equals "fn"
+ parameters counts 0
+ receiver equals null
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedClass() {
+ inlineModelTest(
+ """@Suppress("abc") class Foo() {}"""
+ ) {
+ with((this / "classes" / "Foo").cast<DClass>()) {
+ with(extra[Annotations]?.content?.values?.firstOrNull()?.firstOrNull().assertNotNull("annotations")) {
+ dri.toString() equals "kotlin/Suppress///PointingToDeclaration/"
+ (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("\"abc\""))
+ }
+ }
+ }
+ }
+
+ @Test
+ fun javaAnnotationClass() {
+ inlineModelTest(
+ """
+ |import java.lang.annotation.Retention
+ |import java.lang.annotation.RetentionPolicy
+ |
+ |@Retention(RetentionPolicy.SOURCE)
+ |public annotation class throws()
+ """
+ ) {
+ with((this / "classes" / "throws").cast<DAnnotation>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Retention"
+ params["value"].assertNotNull("value") equals EnumValue(
+ "RetentionPolicy.SOURCE",
+ DRI("java.lang.annotation", "RetentionPolicy.SOURCE")
+ )
+ }
+ }
+ }
+ }
+ }
+
+ @Test fun genericAnnotationClass() {
+ inlineModelTest(
+ """annotation class Foo<A,B,C,D:Number>() {}"""
+ ) {
+ with((this / "classes" / "Foo").cast<DAnnotation>()){
+ generics.map { it.name to it.bounds.first().name } equals listOf("A" to "Any", "B" to "Any", "C" to "Any", "D" to "Number")
+ }
+ }
+ }
+
+ @Test fun nestedGenericClasses(){
+ inlineModelTest(
+ """
+ |class Outer<OUTER> {
+ | inner class Inner<INNER, T : OUTER> { }
+ |}
+ """.trimMargin()
+ ){
+ with((this / "classes" / "Outer").cast<DClass>()){
+ val inner = classlikes.single().cast<DClass>()
+ inner.generics.map { it.name to it.bounds.first().name } equals listOf("INNER" to "Any", "T" to "OUTER")
+ }
+ }
+ }
+
+ @Test fun allImplementedInterfaces() {
+ inlineModelTest(
+ """
+ | interface Highest { }
+ | open class HighestImpl: Highest { }
+ | interface Lower { }
+ | interface LowerImplInterface: Lower { }
+ | class Tested : HighestImpl(), LowerImplInterface { }
+ """.trimIndent()
+ ){
+ with((this / "classes" / "Tested").cast<DClass>()){
+ extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.sureClassNames }?.sorted() equals listOf("Highest", "Lower", "LowerImplInterface").sorted()
+ }
+ }
+ }
+
+ @Test fun multipleClassInheritance() {
+ inlineModelTest(
+ """
+ | open class A { }
+ | open class B: A() { }
+ | class Tested : B() { }
+ """.trimIndent()
+ ) {
+ with((this / "classes" / "Tested").cast<DClass>()) {
+ supertypes.entries.single().value.map { it.dri.sureClassNames }.single() equals "B"
+ }
+ }
+ }
+
+ @Test fun multipleClassInheritanceWithInterface(){
+ inlineModelTest(
+ """
+ | open class A { }
+ | open class B: A() { }
+ | interface X { }
+ | interface Y : X { }
+ | class Tested : B(), Y { }
+ """.trimIndent()
+ ){
+ with((this / "classes" / "Tested").cast<DClass>()) {
+ supertypes.entries.single().value.map { it.dri.sureClassNames to it.kind }.sortedBy { it.first } equals listOf("B" to KotlinClassKindTypes.CLASS, "Y" to KotlinClassKindTypes.INTERFACE)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/CommentTest.kt b/plugins/base/src/test/kotlin/model/CommentTest.kt
new file mode 100644
index 00000000..c1da8ee0
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/CommentTest.kt
@@ -0,0 +1,332 @@
+package model
+
+import org.jetbrains.dokka.model.DProperty
+import org.jetbrains.dokka.model.doc.CustomTagWrapper
+import org.jetbrains.dokka.model.doc.Text
+import org.junit.jupiter.api.Test
+import utils.*
+
+class CommentTest : AbstractModelTest("/src/main/kotlin/comment/Test.kt", "comment") {
+
+ @Test
+ fun codeBlockComment() {
+ inlineModelTest(
+ """
+ |/**
+ | * ```brainfuck
+ | * ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
+ | * ```
+ | */
+ |val prop1 = ""
+ |
+ |
+ |/**
+ | * ```
+ | * a + b - c
+ | * ```
+ | */
+ |val prop2 = ""
+ """
+ ) {
+ with((this / "comment" / "prop1").cast<DProperty>()) {
+ name equals "prop1"
+ with(this.docs().firstOrNull()?.root.assertNotNull("Code")) {
+ (children.firstOrNull() as? Text)
+ ?.body equals "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
+
+ params["lang"] equals "brainfuck"
+ }
+ }
+ with((this / "comment" / "prop2").cast<DProperty>()) {
+ name equals "prop2"
+ comments() equals "a + b - c"
+ }
+ }
+ }
+
+ @Test
+ fun emptyDoc() {
+ inlineModelTest(
+ """
+ val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ name equals "property"
+ comments() equals ""
+ }
+ }
+ }
+
+ @Test
+ fun emptyDocButComment() {
+ inlineModelTest(
+ """
+ |/* comment */
+ |val property = "test"
+ |fun tst() = property
+ """
+ ) {
+ val p = this
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals ""
+ }
+ }
+ }
+
+ @Test
+ fun multilineDoc() {
+ inlineModelTest(
+ """
+ |/**
+ | * doc1
+ | *
+ | * doc2
+ | * doc3
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc1\ndoc2 doc3"
+ }
+ }
+ }
+
+ @Test
+ fun multilineDocWithComment() {
+ inlineModelTest(
+ """
+ |/**
+ | * doc1
+ | *
+ | * doc2
+ | * doc3
+ | */
+ |// comment
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc1\ndoc2 doc3"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDoc() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDocWithComment() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |// comment
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc"
+ }
+ }
+ }
+
+ @Test
+ fun oneLineDocWithEmptyLine() {
+ inlineModelTest(
+ """
+ |/** doc */
+ |
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "doc"
+ }
+ }
+ }
+
+ @Test
+ fun emptySection() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\none: []"
+ docs().find { it is CustomTagWrapper && it.name == "one" }.let {
+ with(it.assertNotNull("'one' entry")) {
+ root.children counts 0
+ root.params.keys counts 0
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun quotes() {
+ inlineModelTest(
+ """
+ |/** it's "useful" */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals """it's "useful""""
+ }
+ }
+ }
+
+ @Test
+ fun section1() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one section one
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\none: [section one]"
+ }
+ }
+ }
+
+
+ @Test
+ fun section2() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one section one
+ | * @two section two
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\none: [section one]\ntwo: [section two]"
+ }
+ }
+ }
+
+ @Test
+ fun multilineSection() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | * @one
+ | * line one
+ | * line two
+ | */
+ |val property = "test"
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ comments() equals "Summary\none: [line one line two]"
+ }
+ }
+ }
+
+// @Test todo
+ fun directive() {
+ inlineModelTest(
+ """
+ |/**
+ | * Summary
+ | *
+ | * @sample example1
+ | * @sample example2
+ | * @sample X.example3
+ | * @sample X.Y.example4
+ | */
+ |val property = "test"
+ |
+ |fun example1(node: String) = if (true) {
+ | println(property)
+ |}
+ |
+ |fun example2(node: String) {
+ | if (true) {
+ | println(property)
+ | }
+ |}
+ |
+ |class X {
+ | fun example3(node: String) {
+ | if (true) {
+ | println(property)
+ | }
+ | }
+ |
+ | class Y {
+ | fun example4(node: String) {
+ | if (true) {
+ | println(property)
+ | }
+ | }
+ | }
+ |}
+ """
+ ) {
+ with((this / "comment" / "property").cast<DProperty>()) {
+ this
+ }
+ }
+ }
+
+
+// @Test fun directive() {
+// checkSourceExistsAndVerifyModel("testdata/comments/directive.kt", defaultModelConfig) { model ->
+// with(model.members.single().members.first()) {
+// assertEquals("Summary", content.summary.toTestString())
+// with (content.description) {
+// assertEqualsIgnoringSeparators("""
+// |[code lang=kotlin]
+// |if (true) {
+// | println(property)
+// |}
+// |[/code]
+// |[code lang=kotlin]
+// |if (true) {
+// | println(property)
+// |}
+// |[/code]
+// |[code lang=kotlin]
+// |if (true) {
+// | println(property)
+// |}
+// |[/code]
+// |[code lang=kotlin]
+// |if (true) {
+// | println(property)
+// |}
+// |[/code]
+// |""".trimMargin(), toTestString())
+// }
+// }
+// }
+// }
+
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/FunctionsTest.kt b/plugins/base/src/test/kotlin/model/FunctionsTest.kt
new file mode 100644
index 00000000..c96e7df6
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/FunctionsTest.kt
@@ -0,0 +1,396 @@
+package model
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.*
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.assertNotNull
+import utils.comments
+import utils.name
+
+class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "function") {
+
+ @Test
+ fun function() {
+ inlineModelTest(
+ """
+ |/**
+ | * Function fn
+ | */
+ |fun fn() {}
+ """
+ ) {
+ with((this / "function" / "fn").cast<DFunction>()) {
+ name equals "fn"
+ type.name equals "Unit"
+ this.children.assertCount(0, "Function children: ")
+ }
+ }
+ }
+
+ @Test
+ fun overloads() {
+ inlineModelTest(
+ """
+ |/**
+ | * Function fn
+ | */
+ |fun fn() {}
+ | /**
+ | * Function fn(Int)
+ | */
+ |fun fn(i: Int) {}
+ """
+ ) {
+ with((this / "function").cast<DPackage>()) {
+ val fn1 = functions.find {
+ it.name == "fn" && it.parameters.isNullOrEmpty()
+ }.assertNotNull("fn()")
+ val fn2 = functions.find {
+ it.name == "fn" && it.parameters.isNotEmpty()
+ }.assertNotNull("fn(Int)")
+
+ with(fn1) {
+ name equals "fn"
+ parameters.assertCount(0)
+ }
+
+ with(fn2) {
+ name equals "fn"
+ parameters.assertCount(1)
+ parameters.first().type.name equals "Int"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithReceiver() {
+ inlineModelTest(
+ """
+ |/**
+ | * Function with receiver
+ | */
+ |fun String.fn() {}
+ |
+ |/**
+ | * Function with receiver
+ | */
+ |fun String.fn(x: Int) {}
+ """
+ ) {
+ with((this / "function").cast<DPackage>()) {
+ val fn1 = functions.find {
+ it.name == "fn" && it.parameters.isNullOrEmpty()
+ }.assertNotNull("fn()")
+ val fn2 = functions.find {
+ it.name == "fn" && it.parameters.count() == 1
+ }.assertNotNull("fn(Int)")
+
+ with(fn1) {
+ name equals "fn"
+ parameters counts 0
+ receiver.assertNotNull("fn() receiver")
+ }
+
+ with(fn2) {
+ name equals "fn"
+ parameters counts 1
+ receiver.assertNotNull("fn(Int) receiver")
+ parameters.first().type.name equals "Int"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithParams() {
+ inlineModelTest(
+ """
+ |/**
+ | * Multiline
+ | *
+ | * Function
+ | * Documentation
+ | */
+ |fun function(/** parameter */ x: Int) {
+ |}
+ """
+ ) {
+ with((this / "function" / "function").cast<DFunction>()) {
+ comments() equals "Multiline\nFunction Documentation"
+
+ name equals "function"
+ parameters counts 1
+ parameters.firstOrNull().assertNotNull("Parameter: ").also {
+ it.name equals "x"
+ it.type.name equals "Int"
+ it.comments() equals "parameter"
+ }
+
+ type.assertNotNull("Return type: ").name equals "Unit"
+ }
+ }
+ }
+
+ @Test
+ fun functionWithNotDocumentedAnnotation() {
+ inlineModelTest(
+ """
+ |@Suppress("FOO") fun f() {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Suppress"
+ params.entries counts 1
+ (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("\"FOO\""))
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun inlineFunction() {
+ inlineModelTest(
+ """
+ |inline fun f(a: () -> String) {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ extra[AdditionalModifiers]!!.content.entries.single().value counts 1
+ extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Inline
+ }
+ }
+ }
+
+ @Test
+ fun suspendFunction() {
+ inlineModelTest(
+ """
+ |suspend fun f() {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ extra[AdditionalModifiers]!!.content.entries.single().value counts 1
+ extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Suspend
+ }
+ }
+ }
+
+ @Test
+ fun suspendInlineFunctionOrder() {
+ inlineModelTest(
+ """
+ |suspend inline fun f(a: () -> String) {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ extra[AdditionalModifiers]!!.content.entries.single().value counts 2
+ extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Suspend
+ extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Inline
+ }
+ }
+ }
+
+ @Test
+ fun inlineSuspendFunctionOrderChanged() {
+ inlineModelTest(
+ """
+ |inline suspend fun f(a: () -> String) {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) {
+ this counts 2
+ this exists ExtraModifiers.KotlinOnlyModifiers.Suspend
+ this exists ExtraModifiers.KotlinOnlyModifiers.Inline
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithAnnotatedParam() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.VALUE_PARAMETER)
+ |@Retention(AnnotationRetention.SOURCE)
+ |@MustBeDocumented
+ |public annotation class Fancy
+ |
+ |fun function(@Fancy notInlined: () -> Unit) {}
+ """
+ ) {
+ with((this / "function" / "Fancy").cast<DAnnotation>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 3
+ with(map { it.dri.classNames to it }.toMap()) {
+ with(this["Target"].assertNotNull("Target")) {
+ (params["allowedTargets"].assertNotNull("allowedTargets") as ArrayValue).value equals listOf(
+ EnumValue(
+ "AnnotationTarget.VALUE_PARAMETER",
+ DRI("kotlin.annotation", "AnnotationTarget.VALUE_PARAMETER")
+ )
+ )
+ }
+ with(this["Retention"].assertNotNull("Retention")) {
+ (params["value"].assertNotNull("value") as EnumValue) equals EnumValue(
+ "AnnotationRetention.SOURCE",
+ DRI("kotlin.annotation", "AnnotationRetention.SOURCE")
+ )
+ }
+ this["MustBeDocumented"].assertNotNull("MustBeDocumented").params.entries counts 0
+ }
+ }
+
+ }
+ with((this / "function" / "function" / "notInlined").cast<DParameter>()) {
+ with(this.extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Fancy"
+ params.entries counts 0
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithNoinlineParam() {
+ inlineModelTest(
+ """
+ |fun f(noinline notInlined: () -> Unit) {}
+ """
+ ) {
+ with((this / "function" / "f" / "notInlined").cast<DParameter>()) {
+ extra[AdditionalModifiers]!!.content.entries.single().value counts 1
+ extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.NoInline
+ }
+ }
+ }
+
+ @Test
+ fun annotatedFunctionWithAnnotationParameters() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.VALUE_PARAMETER)
+ |@Retention(AnnotationRetention.SOURCE)
+ |@MustBeDocumented
+ |public annotation class Fancy(val size: Int)
+ |
+ |@Fancy(1) fun f() {}
+ """
+ ) {
+ with((this / "function" / "Fancy").cast<DAnnotation>()) {
+ constructors counts 1
+ with(constructors.first()) {
+ parameters counts 1
+ with(parameters.first()) {
+ type.name equals "Int"
+ name equals "size"
+ }
+ }
+
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 3
+ with(map { it.dri.classNames to it }.toMap()) {
+ with(this["Target"].assertNotNull("Target")) {
+ (params["allowedTargets"].assertNotNull("allowedTargets") as ArrayValue).value equals listOf(
+ EnumValue(
+ "AnnotationTarget.VALUE_PARAMETER",
+ DRI("kotlin.annotation", "AnnotationTarget.VALUE_PARAMETER")
+ )
+ )
+ }
+ with(this["Retention"].assertNotNull("Retention")) {
+ (params["value"].assertNotNull("value") as EnumValue) equals EnumValue(
+ "AnnotationRetention.SOURCE",
+ DRI("kotlin.annotation", "AnnotationRetention.SOURCE")
+ )
+ }
+ this["MustBeDocumented"].assertNotNull("MustBeDocumented").params.entries counts 0
+ }
+ }
+
+ }
+ with((this / "function" / "f").cast<DFunction>()) {
+ with(this.extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(this.first()) {
+ dri.classNames equals "Fancy"
+ params.entries counts 1
+ (params["size"] as StringValue).value equals "1"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithDefaultStringParameter() {
+ inlineModelTest(
+ """
+ |/src/main/kotlin/function/Test.kt
+ |package function
+ |fun f(x: String = "") {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ parameters.forEach { p ->
+ p.name equals "x"
+ p.type.name.assertNotNull("Parameter type: ") equals "String"
+ p.extra[DefaultValue]?.value equals "\"\""
+ }
+ }
+ }
+ }
+
+ @Test
+ fun functionWithDefaultFloatParameter() {
+ inlineModelTest(
+ """
+ |/src/main/kotlin/function/Test.kt
+ |package function
+ |fun f(x: Float = 3.14f) {}
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ parameters.forEach { p ->
+ p.name equals "x"
+ p.type.name.assertNotNull("Parameter type: ") equals "Float"
+ p.extra[DefaultValue]?.value equals "3.14f"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sinceKotlin() {
+ inlineModelTest(
+ """
+ |/**
+ | * Quite useful [String]
+ | */
+ |@SinceKotlin("1.1")
+ |fun f(): String = "1.1 rulezz"
+ """
+ ) {
+ with((this / "function" / "f").cast<DFunction>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "SinceKotlin"
+ params.entries counts 1
+ (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ }
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/InheritorsTest.kt b/plugins/base/src/test/kotlin/model/InheritorsTest.kt
new file mode 100644
index 00000000..503cf50c
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/InheritorsTest.kt
@@ -0,0 +1,95 @@
+package model
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.base.transformers.documentables.InheritorsExtractorTransformer
+import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo
+import org.jetbrains.dokka.model.DInterface
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.assertNotNull
+
+class InheritorsTest : AbstractModelTest("/src/main/kotlin/inheritors/Test.kt", "inheritors") {
+
+ object InheritorsPlugin : DokkaPlugin() {
+ val inheritors by extending {
+ CoreExtensions.documentableTransformer with InheritorsExtractorTransformer()
+ }
+ }
+
+ @Disabled("reenable after fixing subtypes")
+ @Test
+ fun simple() {
+ inlineModelTest(
+ """|interface A{}
+ |class B() : A {}
+ """.trimMargin(),
+ pluginsOverrides = listOf(InheritorsPlugin)
+ ) {
+ with((this / "inheritors" / "A").cast<DInterface>()) {
+ val map = extra[InheritorsInfo].assertNotNull("InheritorsInfo").value
+ with(map.keys.also { it counts 1 }.find { it.analysisPlatform == Platform.jvm }.assertNotNull("jvm key").let { map[it]!! }
+ ) {
+ this counts 1
+ first().classNames equals "B"
+ }
+ }
+ }
+ }
+
+ @Disabled("reenable after fixing subtypes")
+ @Test
+ fun multiplatform() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("common/src/", "jvm/src/")
+ analysisPlatform = "jvm"
+ }
+ sourceSet {
+ sourceRoots = listOf("common/src/", "js/src/")
+ analysisPlatform = "js"
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/common/src/main/kotlin/inheritors/Test.kt
+ |package inheritors
+ |interface A{}
+ |/jvm/src/main/kotlin/inheritors/Test.kt
+ |package inheritors
+ |class B() : A {}
+ |/js/src/main/kotlin/inheritors/Test.kt
+ |package inheritors
+ |class B() : A {}
+ |class C() : A {}
+ """.trimMargin(),
+ configuration,
+ cleanupOutput = false,
+ pluginOverrides = listOf(InheritorsPlugin)
+ ) {
+ documentablesTransformationStage = { m ->
+ with((m / "inheritors" / "A").cast<DInterface>()) {
+ val map = extra[InheritorsInfo].assertNotNull("InheritorsInfo").value
+ with(map.keys.also { it counts 2 }) {
+ with(find { it.analysisPlatform == Platform.jvm }.assertNotNull("jvm key").let { map[it]!! }) {
+ this counts 1
+ first().classNames equals "B"
+ }
+ with(find { it.analysisPlatform == Platform.js }.assertNotNull("js key").let { map[it]!! }) {
+ this counts 2
+ val classes = listOf("B", "C")
+ assertTrue(all { classes.contains(it.classNames) }, "One of subclasses missing in js" )
+ }
+ }
+
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt
new file mode 100644
index 00000000..1f042304
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/JavaTest.kt
@@ -0,0 +1,346 @@
+package model
+
+import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.sureClassNames
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.doc.Param
+import org.jetbrains.dokka.model.doc.Text
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.assertNotNull
+import utils.name
+
+class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
+
+ @Test
+ fun function() {
+ inlineModelTest(
+ """
+ |class Test {
+ | /**
+ | * Summary for Function
+ | * @param name is String parameter
+ | * @param value is int parameter
+ | */
+ | public void fn(String name, int value) {}
+ |}
+ """
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ name equals "Test"
+ children counts 1
+ with((this / "fn").cast<DFunction>()) {
+ name equals "fn"
+ val params = parameters.map { it.documentation.values.first().children.first() as Param }
+ params.mapNotNull { it.firstChildOfTypeOrNull<Text>()?.body } equals listOf("is String parameter", "is int parameter")
+ }
+ }
+ }
+ }
+
+ @Test fun allImplementedInterfacesInJava() {
+ inlineModelTest(
+ """
+ |interface Highest { }
+ |interface Lower extends Highest { }
+ |class Extendable { }
+ |class Tested extends Extendable implements Lower { }
+ """){
+ with((this / "java" / "Tested").cast<DClass>()){
+ extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.sureClassNames }?.sorted() equals listOf("Highest", "Lower").sorted()
+ }
+ }
+ }
+
+ @Test fun multipleClassInheritanceWithInterface() {
+ inlineModelTest(
+ """
+ |interface Highest { }
+ |interface Lower extends Highest { }
+ |class Extendable { }
+ |class Tested extends Extendable implements Lower { }
+ """){
+ with((this / "java" / "Tested").cast<DClass>()) {
+ supertypes.entries.single().value.map { it.dri.sureClassNames to it.kind }.sortedBy { it.first } equals listOf("Extendable" to JavaClassKindTypes.CLASS, "Lower" to JavaClassKindTypes.INTERFACE)
+ }
+ }
+ }
+
+ @Test // todo
+ fun memberWithModifiers() {
+ inlineModelTest(
+ """
+ |class Test {
+ | /**
+ | * Summary for Function
+ | * @param name is String parameter
+ | * @param value is int parameter
+ | */
+ | public void fn(String name, int value) {}
+ |}
+ """
+ ) {
+ with((this / "java" / "Test" / "fn").cast<DFunction>()) {
+ this
+ }
+ }
+ }
+
+ @Test
+ fun superClass() {
+ inlineModelTest(
+ """
+ |public class Foo extends Exception implements Cloneable {}
+ """
+ ) {
+ with((this / "java" / "Foo").cast<DClass>()) {
+ val sups = listOf("Exception", "Cloneable")
+ assertTrue(
+ sups.all { s -> supertypes.values.flatten().any { it.dri.classNames == s } })
+ "Foo must extend ${sups.joinToString(", ")}"
+ }
+ }
+ }
+
+ @Test
+ fun arrayType() {
+ inlineModelTest(
+ """
+ |class Test {
+ | public String[] arrayToString(int[] data) {
+ | return null;
+ | }
+ |}
+ """
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ name equals "Test"
+ children counts 1
+
+ with((this / "arrayToString").cast<DFunction>()) {
+ name equals "arrayToString"
+ type.name equals "Array"
+ with(parameters.firstOrNull().assertNotNull("parameters")) {
+ name equals "data"
+ type.name equals "Array"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun typeParameter() {
+ inlineModelTest(
+ """
+ |class Foo<T extends Comparable<T>> {
+ | public <E> E foo();
+ |}
+ """
+ ) {
+ with((this / "java" / "Foo").cast<DClass>()) {
+ generics counts 1
+ }
+ }
+ }
+
+ @Test
+ fun constructors() {
+ inlineModelTest(
+ """
+ |class Test {
+ | public Test() {}
+ |
+ | public Test(String s) {}
+ |}
+ """
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ name equals "Test"
+
+ constructors counts 2
+ constructors.find { it.parameters.isNullOrEmpty() }.assertNotNull("Test()")
+
+ with(constructors.find { it.parameters.isNotEmpty() }.assertNotNull("Test(String)")) {
+ parameters.firstOrNull()?.type?.name equals "String"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun innerClass() {
+ inlineModelTest(
+ """
+ |class InnerClass {
+ | public class D {}
+ |}
+ """
+ ) {
+ with((this / "java" / "InnerClass").cast<DClass>()) {
+ children counts 1
+ with((this / "D").cast<DClass>()) {
+ name equals "D"
+ children counts 0
+ }
+ }
+ }
+ }
+
+ @Test
+ fun varargs() {
+ inlineModelTest(
+ """
+ |class Foo {
+ | public void bar(String... x);
+ |}
+ """
+ ) {
+ with((this / "java" / "Foo").cast<DClass>()) {
+ name equals "Foo"
+ children counts 1
+
+ with((this / "bar").cast<DFunction>()) {
+ name equals "bar"
+ with(parameters.firstOrNull().assertNotNull("parameter")) {
+ name equals "x"
+ type.name equals "Array"
+ }
+ }
+ }
+ }
+ }
+
+ @Test // todo
+ fun fields() {
+ inlineModelTest(
+ """
+ |class Test {
+ | public int i;
+ | public static final String s;
+ |}
+ """
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ children counts 2
+
+ with((this / "i").cast<DProperty>()) {
+ getter equals null
+ setter equals null
+ }
+
+ with((this / "s").cast<DProperty>()) {
+ getter equals null
+ setter equals null
+ }
+ }
+ }
+ }
+
+ @Test
+ fun staticMethod() {
+ inlineModelTest(
+ """
+ |class C {
+ | public static void foo() {}
+ |}
+ """
+ ) {
+ with((this / "java" / "C" / "foo").cast<DFunction>()) {
+ with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) {
+ this counts 1
+ first() equals ExtraModifiers.JavaOnlyModifiers.Static
+ }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedAnnotation() {
+ inlineModelTest(
+ """
+ |import java.lang.annotation.*;
+ |
+ |@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
+ |public @interface Attribute {
+ | String value() default "";
+ |}
+ """
+ ) {
+ with((this / "java" / "Attribute").cast<DAnnotation>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(single()) {
+ dri.classNames equals "Target"
+ (params["value"].assertNotNull("value") as ArrayValue).value equals listOf(
+ EnumValue("ElementType.FIELD", DRI("java.lang.annotation", "ElementType")),
+ EnumValue("ElementType.TYPE", DRI("java.lang.annotation", "ElementType")),
+ EnumValue("ElementType.METHOD", DRI("java.lang.annotation", "ElementType"))
+ )
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun javaLangObject() {
+ inlineModelTest(
+ """
+ |class Test {
+ | public Object fn() { return null; }
+ |}
+ """
+ ) {
+ with((this / "java" / "Test" / "fn").cast<DFunction>()) {
+ assertTrue(type is JavaObject)
+ }
+ }
+ }
+
+ @Test
+ fun enumValues() {
+ inlineModelTest(
+ """
+ |enum E {
+ | Foo
+ |}
+ """
+ ) {
+ with((this / "java" / "E").cast<DEnum>()) {
+ name equals "E"
+ entries counts 1
+
+ with((this / "Foo").cast<DEnumEntry>()) {
+ name equals "Foo"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun inheritorLinks() {
+ inlineModelTest(
+ """
+ |public class InheritorLinks {
+ | public static class Foo {}
+ |
+ | public static class Bar extends Foo {}
+ |}
+ """
+ ) {
+ with((this / "java" / "InheritorLinks").cast<DClass>()) {
+ val dri = (this / "Bar").assertNotNull("Foo dri").dri
+ with((this / "Foo").cast<DClass>()) {
+ with(extra[InheritorsInfo].assertNotNull("InheritorsInfo")) {
+ with(value.values.flatten().distinct()) {
+ this counts 1
+ first() equals dri
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/model/PackagesTest.kt b/plugins/base/src/test/kotlin/model/PackagesTest.kt
new file mode 100644
index 00000000..86222d95
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/PackagesTest.kt
@@ -0,0 +1,134 @@
+package model
+
+import org.jetbrains.dokka.model.DPackage
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+
+class PackagesTest : AbstractModelTest("/src/main/kotlin/packages/Test.kt", "packages") {
+
+ @Test
+ fun rootPackage() {
+ inlineModelTest(
+ """
+ |
+ """.trimIndent(),
+ prependPackage = false,
+ configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ displayName = "JVM"
+ }
+ }
+ }
+ ) {
+ with((this / "[JVM root]").cast<DPackage>()) {
+ name equals "[JVM root]"
+ children counts 0
+ }
+ }
+ }
+
+ @Test
+ fun simpleNamePackage() {
+ inlineModelTest(
+ """
+ |package simple
+ """.trimIndent(),
+ prependPackage = false
+ ) {
+ with((this / "simple").cast<DPackage>()) {
+ name equals "simple"
+ children counts 0
+ }
+ }
+ }
+
+ @Test
+ fun dottedNamePackage() {
+ inlineModelTest(
+ """
+ |package dot.name
+ """.trimIndent(),
+ prependPackage = false
+ ) {
+ with((this / "dot.name").cast<DPackage>()) {
+ name equals "dot.name"
+ children counts 0
+ }
+ }
+
+ }
+
+ @Test
+ fun multipleFiles() {
+ inlineModelTest(
+ """
+ |package dot.name
+ |/src/main/kotlin/packages/Test2.kt
+ |package simple
+ """.trimIndent(),
+ prependPackage = false
+ ) {
+ children counts 2
+ with((this / "dot.name").cast<DPackage>()) {
+ name equals "dot.name"
+ children counts 0
+ }
+ with((this / "simple").cast<DPackage>()) {
+ name equals "simple"
+ children counts 0
+ }
+ }
+ }
+
+ @Test
+ fun multipleFilesSamePackage() {
+ inlineModelTest(
+ """
+ |package simple
+ |/src/main/kotlin/packages/Test2.kt
+ |package simple
+ """.trimIndent(),
+ prependPackage = false
+ ) {
+ children counts 1
+ with((this / "simple").cast<DPackage>()) {
+ name equals "simple"
+ children counts 0
+ }
+ }
+ }
+
+ @Test
+ fun classAtPackageLevel() {
+ inlineModelTest(
+ """
+ |package simple.name
+ |
+ |class Foo {}
+ """.trimIndent(),
+ prependPackage = false
+ ) {
+ with((this / "simple.name").cast<DPackage>()) {
+ name equals "simple.name"
+ children counts 1
+ }
+ }
+ }
+
+ // todo
+// @Test fun suppressAtPackageLevel() {
+// verifyModel(
+// ModelConfig(
+// roots = arrayOf(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)),
+// perPackageOptions = listOf(
+// PackageOptionsImpl(prefix = "simple.name", suppress = true)
+// ),
+// analysisPlatform = analysisPlatform
+// )
+// ) { model ->
+// assertEquals(0, model.members.count())
+// }
+// }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/PropertyTest.kt b/plugins/base/src/test/kotlin/model/PropertyTest.kt
new file mode 100644
index 00000000..af952b43
--- /dev/null
+++ b/plugins/base/src/test/kotlin/model/PropertyTest.kt
@@ -0,0 +1,265 @@
+package model
+
+import org.jetbrains.dokka.model.*
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+import utils.assertNotNull
+import utils.name
+
+class PropertyTest : AbstractModelTest("/src/main/kotlin/property/Test.kt", "property") {
+
+ @Test
+ fun valueProperty() {
+ inlineModelTest(
+ """
+ |val property = "test""""
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "String"
+ }
+ type.name equals "String"
+ }
+ }
+ }
+
+ @Test
+ fun variableProperty() {
+ inlineModelTest(
+ """
+ |var property = "test"
+ """
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ setter.assertNotNull("Setter")
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "String"
+ }
+ type.name equals "String"
+ }
+ }
+ }
+
+ @Test
+ fun valuePropertyWithGetter() {
+ inlineModelTest(
+ """
+ |val property: String
+ | get() = "test"
+ """
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "String"
+ }
+ type.name equals "String"
+ }
+ }
+ }
+
+ @Test
+ fun variablePropertyWithAccessors() {
+ inlineModelTest(
+ """
+ |var property: String
+ | get() = "test"
+ | set(value) {}
+ """
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ setter.assertNotNull("Setter")
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "String"
+ }
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+
+ @Test
+ fun propertyWithReceiver() {
+ inlineModelTest(
+ """
+ |val String.property: Int
+ | get() = size() * 2
+ """
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ with(receiver.assertNotNull("property receiver")) {
+ name equals null
+ type.name equals "String"
+ }
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "Int"
+ }
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+
+ @Test
+ fun propertyOverride() {
+ inlineModelTest(
+ """
+ |open class Foo() {
+ | open val property: Int get() = 0
+ |}
+ |class Bar(): Foo() {
+ | override val property: Int get() = 1
+ |}
+ """
+ ) {
+ with((this / "property").cast<DPackage>()) {
+ with((this / "Foo" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "Int"
+ }
+ }
+ with((this / "Bar" / "property").cast<DProperty>()) {
+ name equals "property"
+ children counts 0
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "Int"
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun sinceKotlin() {
+ inlineModelTest(
+ """
+ |/**
+ | * Quite useful [String]
+ | */
+ |@SinceKotlin("1.1")
+ |val prop: String = "1.1 rulezz"
+ """
+ ) {
+ with((this / "property" / "prop").cast<DProperty>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "SinceKotlin"
+ params.entries counts 1
+ (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun annotatedProperty() {
+ inlineModelTest(
+ """
+ |@Strictfp var property = "test"
+ """,
+ configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath = listOfNotNull(jvmStdlibPath)
+ }
+ }
+ }
+ ) {
+ with((this / "property" / "property").cast<DProperty>()) {
+ with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ this counts 1
+ with(first()) {
+ dri.classNames equals "Strictfp"
+ params.entries counts 0
+ }
+ }
+ }
+ }
+ }
+
+ @Test fun genericTopLevelExtensionProperty(){
+ inlineModelTest(
+ """ | val <T : Number> List<T>.sampleProperty: T
+ | get() { TODO() }
+ """.trimIndent()
+ ){
+ with((this / "property" / "sampleProperty").cast<DProperty>()) {
+ name equals "sampleProperty"
+ with(receiver.assertNotNull("Property receiver")) {
+ type.name equals "List"
+ }
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "T"
+ }
+ setter equals null
+ generics counts 1
+ generics.forEach {
+ it.name equals "T"
+ it.bounds.first().name equals "Number"
+ }
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+
+ @Test fun genericExtensionPropertyInClass(){
+ inlineModelTest(
+ """ | package test
+ | class XD<T> {
+ | var List<T>.sampleProperty: T
+ | get() { TODO() }
+ | set(value) { TODO() }
+ | }
+ """.trimIndent()
+ ){
+ with((this / "property" / "XD" / "sampleProperty").cast<DProperty>()) {
+ name equals "sampleProperty"
+ children counts 0
+ with(receiver.assertNotNull("Property receiver")) {
+ type.name equals "List"
+ }
+ with(getter.assertNotNull("Getter")) {
+ type.name equals "T"
+ }
+ with(setter.assertNotNull("Setter")){
+ type.name equals "Unit"
+ }
+ generics counts 0
+ visibility.values allEquals KotlinVisibility.Public
+ }
+ }
+ }
+// @Test
+// fun annotatedProperty() {
+// checkSourceExistsAndVerifyModel(
+// "testdata/properties/annotatedProperty.kt",
+// modelConfig = ModelConfig(
+// analysisPlatform = analysisPlatform,
+// withKotlinRuntime = true
+// )
+// ) { model ->
+// with(model.members.single().members.single()) {
+// Assert.assertEquals(1, annotations.count())
+// with(annotations[0]) {
+// Assert.assertEquals("Strictfp", name)
+// Assert.assertEquals(Content.Empty, content)
+// Assert.assertEquals(NodeKind.Annotation, kind)
+// }
+// }
+// }
+// }
+//
+//}
+}
diff --git a/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt b/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt
new file mode 100644
index 00000000..b3ac7b07
--- /dev/null
+++ b/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt
@@ -0,0 +1,54 @@
+package multiplatform
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+
+class BasicMultiplatformTest : AbstractCoreTest() {
+
+ @Test
+ fun dataTestExample() {
+ val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("$testDataDir/jvmMain/")
+ }
+ }
+ }
+
+ testFromData(configuration) {
+ pagesTransformationStage = {
+ assertEquals(6, it.children.firstOrNull()?.children?.count() ?: 0)
+ }
+ }
+ }
+
+ @Test
+ fun inlineTestExample() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/multiplatform/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/multiplatform/Test.kt
+ |package multiplatform
+ |
+ |object Test {
+ | fun test2(str: String): Unit {println(str)}
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesGenerationStage = {
+ assertEquals(3, it.parentMap.size)
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt b/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt
new file mode 100644
index 00000000..935b9377
--- /dev/null
+++ b/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt
@@ -0,0 +1,126 @@
+package pageMerger
+
+import org.jetbrains.dokka.pages.ContentPage
+import org.jetbrains.dokka.pages.PageNode
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+
+class PageNodeMergerTest : AbstractCoreTest() {
+
+ /* object SameNameStrategy : DokkaPlugin() {
+ val strategy by extending { CoreExtensions.pageMergerStrategy with SameMethodNamePageMergerStrategy }
+ }
+
+ class DefaultStrategy(val strList: MutableList<String> = mutableListOf()) : DokkaPlugin(), DokkaLogger {
+ val strategy by extending { CoreExtensions.pageMergerStrategy with DefaultPageMergerStrategy(this@DefaultStrategy) }
+
+ override var warningsCount: Int = 0
+ override var errorsCount: Int = 0
+
+ override fun debug(message: String) = TODO()
+
+ override fun info(message: String) = TODO()
+
+ override fun progress(message: String) = TODO()
+
+ override fun warn(message: String) {
+ strList += message
+ }
+
+ override fun error(message: String) = TODO()
+
+ override fun report() = TODO()
+ }
+ */
+
+ @Test
+ fun sameNameStrategyTest() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/pageMerger/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/pageMerger/Test.kt
+ |package pageMerger
+ |
+ |fun testT(): Int = 1
+ |fun testT(i: Int): Int = i
+ |
+ |object Test {
+ | fun test(): String = ""
+ | fun test(str: String): String = str
+ |}
+ """.trimMargin(),
+ configuration/*,
+ pluginOverrides = listOf(SameNameStrategy)*/
+ ) {
+ pagesTransformationStage = {
+ val allChildren = it.childrenRec().filterIsInstance<ContentPage>()
+ val testT = allChildren.filter { it.name == "testT" }
+ val test = allChildren.filter { it.name == "test" }
+
+ assertTrue(testT.size == 1) { "There can be only one testT page" }
+ assertTrue(testT.first().dri.size == 2) { "testT page should have 2 DRI, but has ${testT.first().dri.size}" }
+
+ assertTrue(test.size == 1) { "There can be only one test page" }
+ assertTrue(test.first().dri.size == 2) { "test page should have 2 DRI, but has ${test.first().dri.size}" }
+ }
+ }
+ }
+
+ @Disabled("TODO: reenable when we have infrastructure for turning off extensions")
+ @Test
+ fun defaultStrategyTest() {
+ val strList: MutableList<String> = mutableListOf()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/pageMerger/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/pageMerger/Test.kt
+ |package pageMerger
+ |
+ |fun testT(): Int = 1
+ |fun testT(i: Int): Int = i
+ |
+ |object Test {
+ | fun test(): String = ""
+ | fun test(str: String): String = str
+ |}
+ """.trimMargin(),
+ configuration/*,
+ pluginOverrides = listOf(DefaultStrategy(strList)) */
+ ) {
+ pagesTransformationStage = { root ->
+ val allChildren = root.childrenRec().filterIsInstance<ContentPage>()
+ val testT = allChildren.filter { it.name == "testT" }
+ val test = allChildren.filter { it.name == "test" }
+
+ assertTrue(testT.size == 1) { "There can be only one testT page" }
+ assertTrue(testT.first().dri.size == 1) { "testT page should have single DRI, but has ${testT.first().dri.size}" }
+
+ assertTrue(test.size == 1) { "There can be only one test page" }
+ assertTrue(test.first().dri.size == 1) { "test page should have single DRI, but has ${test.first().dri.size}" }
+
+ assertTrue(strList.count() == 2) { "Expected 2 warnings, got ${strList.count()}" }
+ }
+ }
+ }
+
+ fun PageNode.childrenRec(): List<PageNode> = listOf(this) + children.flatMap { it.childrenRec() }
+
+}
diff --git a/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt b/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt
new file mode 100644
index 00000000..8ab277f1
--- /dev/null
+++ b/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt
@@ -0,0 +1,328 @@
+package renderers.html
+
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.SourceRootImpl
+import org.jetbrains.dokka.base.renderers.html.HtmlRenderer
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.pages.ContentDivergentGroup
+import org.junit.jupiter.api.Test
+import renderers.*
+import utils.Div
+import utils.Span
+import utils.match
+
+class DivergentTest : HtmlRenderingOnlyTestBase() {
+
+ @Test
+ fun simpleWrappingCase() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("a")
+ }
+ }
+ }
+ }
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div(Div("a")))))
+ }
+
+ @Test
+ fun noPlatformHintCase() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test"), implicitlySourceSetHinted = false) {
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("a")
+ }
+ }
+ }
+ }
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div("a")))
+ }
+
+ @Test
+ fun divergentBetweenSourceSets() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("a")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(jvm)) {
+ divergent {
+ text("b")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ divergent {
+ text("c")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div(Div("a"), Div("b"), Div("c")))))
+ }
+
+ @Test
+ fun divergentInOneSourceSet() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("a")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(js)) {
+ divergent {
+ text("b")
+ }
+ }
+ instance(setOf(DRI("test", "Test3")), setOf(js)) {
+ divergent {
+ text("c")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div((Div(Div("abc"))))))
+ }
+
+ @Test
+ fun divergentInAndBetweenSourceSets() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ divergent {
+ text("a")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("b")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(jvm)) {
+ divergent {
+ text("c")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(js)) {
+ divergent {
+ text("d")
+ }
+ }
+ instance(setOf(DRI("test", "Test3")), setOf(native)) {
+ divergent {
+ text("e")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div(Div("ae"), Div("bd"), Div("c")))))
+ }
+
+ @Test
+ fun divergentInAndBetweenSourceSetsWithGrouping() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ divergent {
+ text("a")
+ }
+ after {
+ text("a+")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(js)) {
+ divergent {
+ text("b")
+ }
+ after {
+ text("bd+")
+ }
+ }
+ instance(setOf(DRI("test", "Test")), setOf(jvm)) {
+ divergent {
+ text("c")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(js)) {
+ divergent {
+ text("d")
+ }
+ after {
+ text("bd+")
+ }
+ }
+ instance(setOf(DRI("test", "Test3")), setOf(native)) {
+ divergent {
+ text("e")
+ }
+ after {
+ text("e+")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(
+ Div(Div(Span(Div(Div("NATIVE")))), Div(Div(Div("a"))), "a+"),
+ Div(Div(Span(Div(Div("JS")))), Div(Div(Div("bd"))), "bd+"),
+ Div(Div(Span(Div(Div("JVM")))), Div(Div(Div("c")))),
+ Div(Div(Span(Div(Div("NATIVE")))), Div(Div(Div("e"))), "e+"),
+ )
+ }
+
+ @Test
+ fun divergentSameBefore() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ before {
+ text("ab-")
+ }
+ divergent {
+ text("a")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(native)) {
+ before {
+ text("ab-")
+ }
+ divergent {
+ text("b")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(
+ Div(
+ Div(
+ Div("ab-"),
+ Span()
+ ),
+ Div(Div(Div("ab")))
+ )
+ )
+ }
+
+ @Test
+ fun divergentSameAfter() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ divergent {
+ text("a")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(native)) {
+ divergent {
+ text("b")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(
+ Div(
+ Div(Div(Div("ab"))),
+ "ab+"
+ )
+ )
+ }
+
+ @Test
+ fun divergentGroupedByBeforeAndAfter() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ before {
+ text("ab-")
+ }
+ divergent {
+ text("a")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(native)) {
+ before {
+ text("ab-")
+ }
+ divergent {
+ text("b")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(
+ Div(
+ Div(Div("ab-"), Span()),
+ Div(Div(Div("ab"))),
+ "ab+"
+ )
+ )
+ }
+
+ @Test
+ fun divergentDifferentBeforeAndAfter() {
+ val page = TestPage {
+ divergentGroup(ContentDivergentGroup.GroupID("test")) {
+ instance(setOf(DRI("test", "Test")), setOf(native)) {
+ before {
+ text("a-")
+ }
+ divergent {
+ text("a")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ instance(setOf(DRI("test", "Test2")), setOf(native)) {
+ before {
+ text("b-")
+ }
+ divergent {
+ text("b")
+ }
+ after {
+ text("ab+")
+ }
+ }
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(
+ Div(Div(Div("a-"), Span()), Div(Div(Div("a"))), "ab+"),
+ Div(Div(Div("b-"), Span()), Div(Div(Div(("b")))), "ab+")
+ )
+ }
+}
diff --git a/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt b/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt
new file mode 100644
index 00000000..c0c03998
--- /dev/null
+++ b/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt
@@ -0,0 +1,78 @@
+package renderers.html
+
+import org.jetbrains.dokka.base.renderers.html.HtmlRenderer
+import org.jetbrains.dokka.pages.TextStyle
+import org.junit.jupiter.api.Test
+import renderers.*
+import utils.Div
+import utils.P
+import utils.match
+
+class GroupWrappingTest : HtmlRenderingOnlyTestBase() {
+
+ @Test
+ fun notWrapped() {
+ val page = TestPage {
+ group {
+ text("a")
+ text("b")
+ }
+ text("c")
+ }
+
+ HtmlRenderer(context).render(page)
+
+ renderedContent.match("abc")
+ }
+
+ @Test
+ fun paragraphWrapped() {
+ val page = TestPage {
+ group(styles = setOf(TextStyle.Paragraph)) {
+ text("a")
+ text("b")
+ }
+ text("c")
+ }
+
+ HtmlRenderer(context).render(page)
+
+ renderedContent.match(P("ab"), "c")
+ }
+
+ @Test
+ fun blockWrapped() {
+ val page = TestPage {
+ group(styles = setOf(TextStyle.Block)) {
+ text("a")
+ text("b")
+ }
+ text("c")
+ }
+
+ HtmlRenderer(context).render(page)
+
+ renderedContent.match(Div("ab"), "c")
+ }
+
+ @Test
+ fun nested() {
+ val page = TestPage {
+ group(styles = setOf(TextStyle.Block)) {
+ text("a")
+ group(styles = setOf(TextStyle.Block)) {
+ group(styles = setOf(TextStyle.Block)) {
+ text("b")
+ text("c")
+ }
+ }
+ text("d")
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+
+ renderedContent.match(Div("a", Div(Div("bc")), "d"))
+ }
+
+}
diff --git a/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt b/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt
new file mode 100644
index 00000000..b6765fda
--- /dev/null
+++ b/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt
@@ -0,0 +1,90 @@
+package renderers.html
+
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.SourceRootImpl
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.renderers.DefaultTabSortingStrategy
+import org.jetbrains.dokka.base.renderers.RootCreator
+import org.jetbrains.dokka.base.resolvers.external.DokkaExternalLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.external.JavadocExternalLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProviderFactory
+import org.jetbrains.dokka.testApi.context.MockContext
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
+import org.jsoup.nodes.TextNode
+import renderers.RenderingOnlyTestBase
+import utils.TestOutputWriter
+import renderers.defaultSourceSet
+
+abstract class HtmlRenderingOnlyTestBase : RenderingOnlyTestBase<Element>() {
+
+ protected val js = defaultSourceSet.copy(
+ "root",
+ "JS",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "js"),
+ analysisPlatform = Platform.js,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+ protected val jvm = defaultSourceSet.copy(
+ "root",
+ "JVM",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "jvm"),
+
+ analysisPlatform = Platform.jvm,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+ protected val native = defaultSourceSet.copy(
+ "root",
+ "NATIVE",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "native"),
+ analysisPlatform = Platform.native,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+
+ val files = TestOutputWriter()
+ override val context = MockContext(
+ DokkaBase().outputWriter to { _ -> files },
+ DokkaBase().locationProviderFactory to ::DefaultLocationProviderFactory,
+ DokkaBase().htmlPreprocessors to { _ -> RootCreator },
+ DokkaBase().externalLocationProviderFactory to { ::JavadocExternalLocationProviderFactory },
+ DokkaBase().externalLocationProviderFactory to { ::DokkaExternalLocationProviderFactory },
+ DokkaBase().tabSortingStrategy to { DefaultTabSortingStrategy() },
+ testConfiguration = DokkaConfigurationImpl(
+ "", null, false, listOf(js, jvm, native), emptyList(), emptyMap(), emptyList(), false
+ )
+ )
+
+ override val renderedContent: Element by lazy {
+ files.contents.getValue("test-page.html").let { Jsoup.parse(it) }.select("#content").single()
+ }
+
+ protected fun linesAfterContentTag() =
+ files.contents.getValue("test-page.html").lines()
+ .dropWhile { !it.contains("""<div id="content">""") }
+ .joinToString(separator = "") { it.trim() }
+}
+
+fun Element.match(vararg matchers: Any): Unit =
+ childNodes()
+ .filter { it !is TextNode || it.text().isNotBlank() }
+ .let { it.drop(it.size - matchers.size) }
+ .zip(matchers)
+ .forEach { (n, m) -> m.accepts(n) }
+
+open class Tag(val name: String, vararg val matchers: Any)
+class Div(vararg matchers: Any) : Tag("div", *matchers)
+class P(vararg matchers: Any) : Tag("p", *matchers)
+class Span(vararg matchers: Any) : Tag("span", *matchers)
+
+private fun Any.accepts(n: Node) {
+ when (this) {
+ is String -> assert(n is TextNode && n.text().trim() == this.trim()) { "\"$this\" expected but found: $n" }
+ is Tag -> {
+ assert(n is Element && n.tagName() == name) { "Tag $name expected but found: $n" }
+ if (n is Element && matchers.isNotEmpty()) n.match(*matchers)
+ }
+ else -> throw IllegalArgumentException("$this is not proper matcher")
+ }
+}
diff --git a/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt b/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt
new file mode 100644
index 00000000..cf7f47e6
--- /dev/null
+++ b/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt
@@ -0,0 +1,139 @@
+package renderers.html
+
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.SourceRootImpl
+import org.jetbrains.dokka.base.renderers.html.HtmlRenderer
+import org.jetbrains.dokka.pages.TextStyle
+import org.junit.jupiter.api.Test
+import renderers.TestPage
+import renderers.defaultSourceSet
+import renderers.RenderingOnlyTestBase
+import utils.Div
+import utils.match
+
+class SourceSetDependentHintTest : HtmlRenderingOnlyTestBase() {
+
+ private val pl1 = defaultSourceSet.copy(
+ "root",
+ "pl1",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "pl1"),
+ analysisPlatform = Platform.js,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+ private val pl2 = defaultSourceSet.copy(
+ "root",
+ "pl2",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "pl2"),
+ analysisPlatform = Platform.jvm,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+ private val pl3 = defaultSourceSet.copy(
+ "root",
+ "pl3",
+ defaultSourceSet.sourceSetID.copy(sourceSetName = "pl3"),
+ analysisPlatform = Platform.native,
+ sourceRoots = listOf(SourceRootImpl("pl1"))
+ )
+
+ @Test
+ fun platformIndependentCase() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) {
+ text("a")
+ text("b")
+ text("c")
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div("abc"))))
+ }
+
+ @Test
+ fun completelyDivergentCase() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) {
+ text("a", sourceSets = setOf(pl1))
+ text("b", sourceSets = setOf(pl2))
+ text("c", sourceSets = setOf(pl3))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div("a")), Div(Div("b")), Div(Div("c"))))
+ }
+
+ @Test
+ fun overlappingCase() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) {
+ text("a", sourceSets = setOf(pl1))
+ text("b", sourceSets = setOf(pl1, pl2))
+ text("c", sourceSets = setOf(pl2))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div("ab")), Div(Div("bc"))))
+ }
+
+ @Test
+ fun caseThatCanBeSimplified() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) {
+ text("a", sourceSets = setOf(pl1, pl2))
+ text("b", sourceSets = setOf(pl1))
+ text("b", sourceSets = setOf(pl2))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div("ab"))))
+ }
+
+ @Test
+ fun caseWithGroupBreakingSimplification() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) {
+ group(styles = setOf(TextStyle.Block)) {
+ text("a", sourceSets = setOf(pl1, pl2))
+ text("b", sourceSets = setOf(pl1))
+ }
+ text("b", sourceSets = setOf(pl2))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div(Div("ab"))), Div(Div(Div("a"), "b"))))
+ }
+
+ @Test
+ fun caseWithGroupNotBreakingSimplification() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2)) {
+ group {
+ text("a", sourceSets = setOf(pl1, pl2))
+ text("b", sourceSets = setOf(pl1))
+ }
+ text("b", sourceSets = setOf(pl2))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div("ab")))
+ }
+
+ @Test
+ fun partiallyUnifiedCase() {
+ val page = TestPage {
+ sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) {
+ text("a", sourceSets = setOf(pl1))
+ text("a", sourceSets = setOf(pl2))
+ text("b", sourceSets = setOf(pl3))
+ }
+ }
+
+ HtmlRenderer(context).render(page)
+ renderedContent.match(Div(Div(Div("a")), Div(Div("b"))))
+ }
+}
diff --git a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
new file mode 100644
index 00000000..4f8a834b
--- /dev/null
+++ b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt
@@ -0,0 +1,71 @@
+package resourceLinks
+
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+import org.jsoup.Jsoup
+import org.junit.jupiter.api.Test
+import utils.TestOutputWriterPlugin
+
+class ResourceLinksTest : AbstractCoreTest() {
+ class TestResourcesAppenderPlugin(val resources: List<String>) : DokkaPlugin() {
+ class TestResourcesAppender(val resources: List<String>) : PageTransformer {
+ override fun invoke(input: RootPageNode) = input.transformContentPagesTree {
+ it.modified(
+ embeddedResources = it.embeddedResources + resources
+ )
+ }
+ }
+
+ val appender by extending {
+ plugin<DokkaBase>().htmlPreprocessors with TestResourcesAppender(resources)
+ }
+ }
+ @Test
+ fun resourceLinksTest() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+ val absoluteResources = listOf(
+ "https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css",
+ "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"
+ )
+ val relativeResources = listOf(
+ "test/relativePath.js",
+ "test/relativePath.css"
+ )
+
+ val source =
+ """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(TestResourcesAppenderPlugin(absoluteResources + relativeResources), writerPlugin)
+ ) {
+ renderingStage = {
+ root, context -> Jsoup
+ .parse(writerPlugin.writer.contents["root/example.html"])
+ .head()
+ .select("link, script")
+ .let {
+ absoluteResources.forEach {
+ r -> assert(it.`is`("[href=$r], [src=$r]"))
+ }
+ relativeResources.forEach {
+ r -> assert(it.`is`("[href=../$r] , [src=../$r]"))
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt
new file mode 100644
index 00000000..7635ab05
--- /dev/null
+++ b/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt
@@ -0,0 +1,175 @@
+package signatures
+
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
+import org.junit.jupiter.api.Test
+import java.nio.file.Paths
+import utils.TestOutputWriterPlugin
+
+class DivergentSignatureTest : AbstractCoreTest() {
+
+ @Test
+ fun `group { common + jvm + js }`() {
+
+ val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ displayName = "js"
+ name = "js"
+ analysisPlatform = "js"
+ sourceRoots = listOf("jsMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "jvm"
+ name = "jvm"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("jvmMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "common"
+ name = "common"
+ analysisPlatform = "common"
+ sourceRoots = listOf("commonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ }
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedContent("example/example/-clock/get-time.html")
+
+ assert(content.count() == 1)
+ assert(content.select("[data-filterable-current=example/js example/jvm example/common]").single().brief == "")
+ }
+ }
+ }
+
+ @Test
+ fun `group { common + jvm }, group { js }`() {
+
+ val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ displayName = "js"
+ name = "js"
+ analysisPlatform = "js"
+ sourceRoots = listOf("jsMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "jvm"
+ name = "jvm"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("jvmMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "common"
+ name = "common"
+ analysisPlatform = "common"
+ sourceRoots = listOf("commonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ }
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedContent("example/example/-clock/get-times-in-millis.html")
+ assert(content.count() == 2)
+ assert(content.select("[data-filterable-current=example/jvm example/common]").single().brief == "Time in minis")
+ assert(content.select("[data-filterable-current=example/js]").single().brief == "JS implementation of getTimeInMillis js" )
+ }
+ }
+ }
+
+ @Test
+ fun `group { js }, group { jvm }, group { js }`() {
+
+ val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath()
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ moduleName = "example"
+ displayName = "js"
+ name = "js"
+ analysisPlatform = "js"
+ sourceRoots = listOf("jsMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "jvm"
+ name = "jvm"
+ analysisPlatform = "jvm"
+ sourceRoots = listOf("jvmMain", "commonMain", "jvmAndJsSecondCommonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ sourceSet {
+ moduleName = "example"
+ displayName = "common"
+ name = "common"
+ analysisPlatform = "common"
+ sourceRoots = listOf("commonMain").map {
+ Paths.get("$testDataDir/$it/kotlin").toString()
+ }
+ }
+ }
+ }
+
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testFromData(
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ val content = writerPlugin.renderedContent("example/example/-clock/get-year.html")
+ assert(content.count() == 3)
+ assert(content.select("[data-filterable-current=example/jvm]").single().brief == "JVM custom kdoc jvm")
+ assert(content.select("[data-filterable-current=example/js]").single().brief == "JS custom kdoc js")
+ assert(content.select("[data-filterable-current=example/common]").single().brief == "common")
+ }
+ }
+ }
+
+ private fun TestOutputWriterPlugin.renderedContent(path: String) = writer.contents.getValue(path)
+ .let { Jsoup.parse(it) }.select("#content").single().select("div.divergent-group")
+
+ private val Element.brief: String
+ get() = children().select(".brief-with-platform-tags").text()
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt
new file mode 100644
index 00000000..9f2ae435
--- /dev/null
+++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt
@@ -0,0 +1,379 @@
+package signatures
+
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jsoup.Jsoup
+import org.junit.jupiter.api.Test
+import utils.*
+
+class SignatureTest : AbstractCoreTest() {
+
+ fun source(signature: String) =
+ """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ |
+ | $signature
+ """.trimIndent()
+
+ @Test
+ fun `fun`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("fun simpleFun(): String = \"Celebrimbor\"")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "fun ", A("simpleFun"), "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `open fun`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("open fun simpleFun(): String = \"Celebrimbor\"")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "open fun ", A("simpleFun"), "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `open suspend fun`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("open suspend fun simpleFun(): String = \"Celebrimbor\"")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "open suspend fun ", A("simpleFun"), "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with params`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("fun simpleFun(a: Int, b: Boolean, c: Any): String = \"Celebrimbor\"")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "fun ", A("simpleFun"), "(a: ", A("Int"),
+ ", b: ", A("Boolean"), ", c: ", A("Any"),
+ "): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with function param`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("fun simpleFun(a: (Int) -> String): String = \"Celebrimbor\"")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "fun ", A("simpleFun"), "(a: (", A("Int"),
+ ") -> ", A("String"), "): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with generic param`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("fun <T> simpleFun(): T = \"Celebrimbor\" as T")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "fun <", A("T"), " : ", A("Any"), "?> ", A("simpleFun"), "(): ",
+ A("T"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with generic bounded param`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("fun <T : String> simpleFun(): T = \"Celebrimbor\" as T")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"),
+ "(): ", A("T"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with keywords, params and generic bound`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = source("inline suspend fun <T : String> simpleFun(a: Int, b: String): T = \"Celebrimbor\" as T")
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ "inline suspend fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"),
+ "(a: ", A("Int"), ", b: ", A("String"), "): ", A("T"), Span()
+ )
+ }
+ }
+ }
+
+
+ @Test
+ fun `fun with annotation`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ |
+ | @MustBeDocumented()
+ | @Target(AnnotationTarget.FUNCTION)
+ | annotation class Marking
+ |
+ | @Marking()
+ | fun simpleFun(): String = "Celebrimbor"
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ Div(
+ Div("@", A("Marking"), "()")
+ ),
+ "fun ", A("simpleFun"),
+ "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with two annotations`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ |
+ | @MustBeDocumented()
+ | @Target(AnnotationTarget.FUNCTION)
+ | annotation class Marking(val msg: String)
+ |
+ | @MustBeDocumented()
+ | @Target(AnnotationTarget.FUNCTION)
+ | annotation class Marking2(val int: Int)
+ |
+ | @Marking("Nenya")
+ | @Marking2(1)
+ | fun simpleFun(): String = "Celebrimbor"
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html")
+ .match(
+ Div(
+ Div("@", A("Marking"), "(", Span("msg = ", Span("\"Nenya\"")), Wbr, ")"),
+ Div("@", A("Marking2"), "(", Span("int = ", Span("1")), Wbr, ")")
+ ),
+ "fun ", A("simpleFun"),
+ "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `fun with annotation with array`() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/test/Test.kt")
+ }
+ }
+ }
+
+ val source = """
+ |/src/main/kotlin/test/Test.kt
+ |package example
+ |
+ | @MustBeDocumented()
+ | @Target(AnnotationTarget.FUNCTION)
+ | annotation class Marking(val msg: Array<String>)
+ |
+ | @Marking(["Nenya", "Vilya", "Narya"])
+ | @Marking2(1)
+ | fun simpleFun(): String = "Celebrimbor"
+ """.trimIndent()
+ val writerPlugin = TestOutputWriterPlugin()
+
+ testInline(
+ source,
+ configuration,
+ pluginOverrides = listOf(writerPlugin)
+ ) {
+ renderingStage = { _, _ ->
+ writerPlugin.writer.renderedContent("root/example/simple-fun.html").match(
+ Div(
+ Div("@", A("Marking"), "(", Span("msg = [",
+ Span(Span("\"Nenya\""), ", "), Wbr,
+ Span(Span("\"Vilya\""), ", "), Wbr,
+ Span(Span("\"Narya\"")), Wbr, "]"), Wbr, ")"
+ )
+ ),
+ "fun ", A("simpleFun"),
+ "(): ", A("String"), Span()
+ )
+ }
+ }
+ }
+
+ private fun TestOutputWriter.renderedContent(path: String = "root/example.html") =
+ contents.getValue(path).let { Jsoup.parse(it) }.select("#content")
+ .single().select("div.symbol div.monospace").first()
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt b/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt
new file mode 100644
index 00000000..d8e057da
--- /dev/null
+++ b/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt
@@ -0,0 +1,150 @@
+package transformerBuilders;
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.pages.PageNode
+import org.jetbrains.dokka.pages.RendererSpecificResourcePage
+import org.jetbrains.dokka.pages.RenderingStrategy
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.jetbrains.dokka.transformers.pages.PageTransformer
+import org.jetbrains.dokka.transformers.pages.pageMapper
+import org.jetbrains.dokka.transformers.pages.pageScanner
+import org.jetbrains.dokka.transformers.pages.pageStructureTransformer
+import org.junit.jupiter.api.Test
+
+class PageTransformerBuilderTest : AbstractCoreTest() {
+
+ class ProxyPlugin(transformer: PageTransformer) : DokkaPlugin() {
+ val pageTransformer by extending { CoreExtensions.pageTransformer with transformer }
+ }
+
+ @Test
+ fun scannerTest() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt")
+ }
+ }
+ }
+ val list = mutableListOf<String>()
+
+ var orig: PageNode? = null
+
+ testInline(
+ """
+ |/src/main/kotlin/transformerBuilder/Test.kt
+ |package transformerBuilder
+ |
+ |object Test {
+ | fun test2(str: String): Unit {println(str)}
+ |}
+ """.trimMargin(),
+ configuration,
+ pluginOverrides = listOf(ProxyPlugin(pageScanner {
+ list += name
+ }))
+ ) {
+ pagesGenerationStage = {
+ orig = it
+ }
+ pagesTransformationStage = { root ->
+ list.assertCount(4, "Page list: ")
+ orig?.let { root.assertTransform(it) }
+ }
+ }
+ }
+
+ @Test
+ fun mapperTest() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt")
+ }
+ }
+ }
+
+ var orig: PageNode? = null
+
+ testInline(
+ """
+ |/src/main/kotlin/transformerBuilder/Test.kt
+ |package transformerBuilder
+ |
+ |object Test {
+ | fun test2(str: String): Unit {println(str)}
+ |}
+ """.trimMargin(),
+ configuration,
+ pluginOverrides = listOf(ProxyPlugin(pageMapper {
+ modified(name = name + "2")
+ }))
+ ) {
+ pagesGenerationStage = {
+ orig = it
+ }
+ pagesTransformationStage = {
+ it.let { root ->
+ root.name.assertEqual("root2", "Root name: ")
+ orig?.let {
+ root.assertTransform(it) { node -> node.modified(name = node.name + "2") }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun structureTransformerTest() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/transformerBuilder/Test.kt
+ |package transformerBuilder
+ |
+ |object Test {
+ | fun test2(str: String): Unit {println(str)}
+ |}
+ """.trimMargin(),
+ configuration,
+ pluginOverrides = listOf(ProxyPlugin(pageStructureTransformer {
+ val ch = children.first()
+ modified(
+ children = listOf(
+ ch,
+ RendererSpecificResourcePage("test", emptyList(), RenderingStrategy.DoNothing)
+ )
+ )
+ }))
+ ) {
+ pagesTransformationStage = { root ->
+ root.children.assertCount(2, "Root children: ")
+ root.children.first().name.assertEqual("transformerBuilder")
+ root.children[1].name.assertEqual("test")
+ }
+ }
+ }
+
+ private fun <T> Collection<T>.assertCount(n: Int, prefix: String = "") =
+ assert(count() == n) { "${prefix}Expected $n, got ${count()}" }
+
+ private fun <T> T.assertEqual(expected: T, prefix: String = "") = assert(this == expected) {
+ "${prefix}Expected $expected, got $this"
+ }
+
+ private fun PageNode.assertTransform(expected: PageNode, block: (PageNode) -> PageNode = { it }): Unit = this.let {
+ it.name.assertEqual(block(expected).name)
+ it.children.zip(expected.children).forEach { (g, e) ->
+ g.name.assertEqual(block(e).name)
+ g.assertTransform(e, block)
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt
new file mode 100644
index 00000000..5197afc6
--- /dev/null
+++ b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt
@@ -0,0 +1,403 @@
+package transformers
+
+import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.doc.*
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Test
+import matchers.content.*
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
+
+class CommentsToContentConverterTest {
+ private val converter = DocTagToContentConverter
+
+ private fun executeTest(
+ docTag:DocTag,
+ match: ContentMatcherBuilder<ContentComposite>.() -> Unit
+ ) {
+ val dci = DCI(
+ setOf(
+ DRI("kotlin", "Any")
+ ),
+ ContentKind.Comment
+ )
+ converter.buildContent(
+ Li(
+ listOf(
+ docTag
+ )
+ ),
+ dci,
+ emptySet()
+ ).single().assertNode(match)
+ }
+
+ @Test
+ fun `simple text`() {
+ val docTag = P(listOf(Text("This is simple test of string Next line")))
+ executeTest(docTag) {
+ +"This is simple test of string Next line"
+ }
+ }
+
+ @Test
+ fun `simple text with new line`() {
+ val docTag = P(
+ listOf(
+ Text("This is simple test of string"),
+ Br,
+ Text("Next line")
+ )
+ )
+ executeTest(docTag) {
+ +"This is simple test of string"
+ node<ContentBreakLine>()
+ +"Next line"
+ }
+ }
+
+ @Test
+ fun `paragraphs`() {
+ val docTag = P(
+ listOf(
+ P(listOf(Text("Paragraph number one"))),
+ P(listOf(Text("Paragraph"), Br, Text("number two")))
+ )
+ )
+ executeTest(docTag) {
+ +"Paragraph number one"
+ +"Paragraph"
+ node<ContentBreakLine>()
+ +"number two"
+ }
+ }
+
+ @Test
+ fun `unordered list with empty lines`() {
+ val docTag = Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("list item 1 continue 1"))))),
+ Li(listOf(P(listOf(Text("list item 2"), Br, Text("continue 2")))))
+ )
+ )
+ executeTest(docTag) {
+ node<ContentList> {
+ group {
+ +"list item 1 continue 1"
+ }
+ group {
+ +"list item 2"
+ node<ContentBreakLine>()
+ +"continue 2"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `nested list`() {
+ val docTag = P(
+ listOf(
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Outer first Outer next line"))))),
+ Li(listOf(P(listOf(Text("Outer second"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Middle first Middle next line"))))),
+ Li(listOf(P(listOf(Text("Middle second"))))),
+ Ul(
+ listOf(
+ Li(listOf(P(listOf(Text("Inner first Inner next line")))))
+ )
+ ),
+ Li(listOf(P(listOf(Text("Middle third")))))
+ )
+ ),
+ Li(listOf(P(listOf(Text("Outer third")))))
+ )
+ ),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ executeTest(docTag) {
+ node<ContentList> {
+ group { +"Outer first Outer next line" }
+ group { +"Outer second" }
+ node<ContentList> {
+ group { +"Middle first Middle next line" }
+ group { +"Middle second" }
+ node<ContentList> {
+ group { +"Inner first Inner next line" }
+ }
+ group { +"Middle third" }
+ }
+ group { +"Outer third" }
+ }
+ +"New paragraph"
+ }
+ }
+
+ @Test
+ fun `header and paragraphs`() {
+ val docTag = P(
+ listOf(
+ H1(listOf(Text("Header 1"))),
+ P(listOf(Text("Following text"))),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ executeTest(docTag) {
+ header(1) { +"Header 1" }
+ +"Following text"
+ +"New paragraph"
+ }
+ }
+
+ @Test
+ fun `header levels`() {
+ val docTag = P(
+ listOf(
+ H1(listOf(Text("Header 1"))),
+ P(listOf(Text("Text 1"))),
+ H2(listOf(Text("Header 2"))),
+ P(listOf(Text("Text 2"))),
+ H3(listOf(Text("Header 3"))),
+ P(listOf(Text("Text 3"))),
+ H4(listOf(Text("Header 4"))),
+ P(listOf(Text("Text 4"))),
+ H5(listOf(Text("Header 5"))),
+ P(listOf(Text("Text 5"))),
+ H6(listOf(Text("Header 6"))),
+ P(listOf(Text("Text 6")))
+ )
+ )
+ executeTest(docTag) {
+ header(1) {+"Header 1"}
+ +"Text 1"
+ header(2) {+"Header 2"}
+ +"Text 2"
+ header(3) {+"Header 3"}
+ +"Text 3"
+ header(4) {+"Header 4"}
+ +"Text 4"
+ header(5) {+"Header 5"}
+ +"Text 5"
+ header(6) {+"Header 6"}
+ +"Text 6"
+ }
+ }
+
+ @Test
+ fun `block quotes`() {
+ val docTag = P(
+ listOf(
+ BlockQuote(
+ listOf(
+ P(
+ listOf(
+ Text("Blockquotes are very handy in email to emulate reply text. This line is part of the same quote.")
+ )
+ )
+ )
+ ),
+ P(listOf(Text("Quote break."))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("Quote")))
+ )
+ )
+ )
+ )
+ executeTest(docTag) {
+ node<ContentCodeBlock> {
+ +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote."
+ }
+ +"Quote break."
+ node<ContentCodeBlock> {
+ +"Quote"
+ }
+ }
+ }
+
+ @Test
+ fun `nested block quotes`() {
+ val docTag = P(
+ listOf(
+ BlockQuote(
+ listOf(
+ P(listOf(Text("text 1 text 2"))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("text 3 text 4")))
+ )
+ ),
+ P(listOf(Text("text 5")))
+ )
+ ),
+ P(listOf(Text("Quote break."))),
+ BlockQuote(
+ listOf(
+ P(listOf(Text("Quote")))
+ )
+ )
+ )
+ )
+ executeTest(docTag) {
+ node<ContentCodeBlock> {
+ +"text 1 text 2"
+ node<ContentCodeBlock> {
+ +"text 3 text 4"
+ }
+ +"text 5"
+ }
+ +"Quote break."
+ node<ContentCodeBlock> {
+ +"Quote"
+ }
+ }
+ }
+
+ @Test
+ fun `multiline code`() {
+ val docTag = P(
+ listOf(
+ CodeBlock(
+ listOf(
+ Text("val x: Int = 0"), Br,
+ Text("val y: String = \"Text\""), Br, Br,
+ Text(" val z: Boolean = true"), Br,
+ Text("for(i in 0..10) {"), Br,
+ Text(" println(i)"), Br,
+ Text("}")
+ ),
+ mapOf("lang" to "kotlin")
+ ),
+ P(listOf(Text("Sample text")))
+ )
+ )
+ executeTest(docTag) {
+ node<ContentCodeBlock> {
+ +"val x: Int = 0"
+ node<ContentBreakLine>()
+ +"val y: String = \"Text\""
+ node<ContentBreakLine>()
+ node<ContentBreakLine>()
+ +" val z: Boolean = true"
+ node<ContentBreakLine>()
+ +"for(i in 0..10) {"
+ node<ContentBreakLine>()
+ +" println(i)"
+ node<ContentBreakLine>()
+ +"}"
+ }
+ +"Sample text"
+ }
+ }
+
+ @Test
+ fun `inline link`() {
+ val docTag = P(
+ listOf(
+ A(
+ listOf(Text("I'm an inline-style link")),
+ mapOf("href" to "https://www.google.com")
+ )
+ )
+ )
+ executeTest(docTag) {
+ link {
+ +"I'm an inline-style link"
+ check {
+ assertEquals(
+ assertedCast<ContentResolvedLink> { "Link should be resolved" }.address,
+ "https://www.google.com"
+ )
+ }
+ }
+ }
+ }
+
+
+
+ @Test
+ fun `ordered list`() {
+ val docTag =
+ Ol(
+ listOf(
+ Li(
+ listOf(
+ P(listOf(Text("test1"))),
+ P(listOf(Text("test2"))),
+ )
+ ),
+ Li(
+ listOf(
+ P(listOf(Text("test3"))),
+ P(listOf(Text("test4"))),
+ )
+ )
+ )
+ )
+ executeTest(docTag) {
+ node<ContentList> {
+ group {
+ +"test1"
+ +"test2"
+ }
+ group {
+ +"test3"
+ +"test4"
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `nested ordered list`() {
+ val docTag = P(
+ listOf(
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Outer first Outer next line"))))),
+ Li(listOf(P(listOf(Text("Outer second"))))),
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Middle first Middle next line"))))),
+ Li(listOf(P(listOf(Text("Middle second"))))),
+ Ol(
+ listOf(
+ Li(listOf(P(listOf(Text("Inner first Inner next line")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ Li(listOf(P(listOf(Text("Middle third")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ Li(listOf(P(listOf(Text("Outer third")))))
+ ),
+ mapOf("start" to "1")
+ ),
+ P(listOf(Text("New paragraph")))
+ )
+ )
+ executeTest(docTag) {
+ node<ContentList> {
+ group { +"Outer first Outer next line" }
+ group { +"Outer second" }
+ node<ContentList> {
+ group { +"Middle first Middle next line" }
+ group { +"Middle second" }
+ node<ContentList> {
+ +"Inner first Inner next line"
+ }
+ group { +"Middle third" }
+ }
+ group { +"Outer third" }
+ }
+ +"New paragraph"
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt b/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt
new file mode 100644
index 00000000..72948372
--- /dev/null
+++ b/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt
@@ -0,0 +1,919 @@
+package transformers
+
+import org.jetbrains.dokka.PackageOptionsImpl
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.*
+import org.junit.jupiter.api.Disabled
+import org.junit.jupiter.api.Test
+
+
+class ReportUndocumentedTransformerTest : AbstractCoreTest() {
+ @Test
+ fun `undocumented class gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport(Regex("init"))
+ assertSingleUndocumentedReport(Regex("""sample/X/"""))
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented non-public class does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |internal class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented function gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |class X {
+ | fun x()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X/x"))
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented property gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |class X {
+ | val x: Int = 0
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X/x"))
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented primary constructor does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |class X(private val x: Int) {
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `data class component functions do not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |data class X(val x: Int) {
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport(Regex("component"))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Disabled
+ @Test
+ fun `undocumented secondary constructor gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |class X {
+ | constructor(unit: Unit) : this()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X.*init.*Unit"))
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented inherited function does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |open class A {
+ | fun a() = Unit
+ |}
+ |
+ |/** Documented */
+ |class B : A()
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport(Regex("B"))
+ assertSingleUndocumentedReport(Regex("A.*a"))
+ }
+ }
+ }
+
+ @Test
+ fun `undocumented inherited property does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |/** Documented */
+ |open class A {
+ | val a = Unit
+ |}
+ |
+ |/** Documented */
+ |class B : A()
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport(Regex("B"))
+ assertSingleUndocumentedReport(Regex("A.*a"))
+ }
+ }
+ }
+
+ @Test
+ fun `overridden function does not get reported when super is documented`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |import kotlin.Exception
+ |
+ |/** Documented */
+ |open class A {
+ | /** Documented */
+ | fun a() = Unit
+ |}
+ |
+ |/** Documented */
+ |class B : A() {
+ | override fun a() = throw Exception()
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `overridden property does not get reported when super is documented`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |import kotlin.Exception
+ |
+ |/** Documented */
+ |open class A {
+ | /** Documented */
+ | open val a = 0
+ |}
+ |
+ |/** Documented */
+ |class B : A() {
+ | override val a = 1
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `report disabled by source set`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = false
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `report enabled by package configuration`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ perPackageOptions += packageOptions(
+ prefix = "sample",
+ reportUndocumented = true,
+ )
+ reportUndocumented = false
+ sourceRoots = listOf("src/main/kotlin/Test.kt")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/Test.kt
+ |package sample
+ |
+ |class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ }
+ }
+ }
+
+ @Test
+ fun `report enabled by more specific package configuration`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ perPackageOptions += packageOptions(
+ prefix = "sample",
+ reportUndocumented = false,
+ )
+ perPackageOptions += packageOptions(
+ prefix = "sample.enabled",
+ reportUndocumented = true,
+ )
+ reportUndocumented = false
+ sourceRoots = listOf("src/main/kotlin/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/sample/disabled/Disabled.kt
+ |package sample.disabled
+ |class Disabled
+ |
+ |/src/main/kotlin/sample/enabled/Enabled.kt
+ |package sample.enabled
+ |class Enabled
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("Enabled"))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Test
+ fun `report disabled by more specific package configuration`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ perPackageOptions += packageOptions(
+ prefix = "sample",
+ reportUndocumented = true,
+ )
+ perPackageOptions += packageOptions(
+ prefix = "sample.disabled",
+ reportUndocumented = false,
+ )
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/kotlin/")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/sample/disabled/Disabled.kt
+ |package sample.disabled
+ |class Disabled
+ |
+ |/src/main/kotlin/sample/enabled/Enabled.kt
+ |package sample.enabled
+ |class Enabled
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("Enabled"))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Test
+ fun `multiplatform undocumented class gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ val commonMain = sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.common.toString()
+ name = "commonMain"
+ displayName = "commonMain"
+ sourceRoots = listOf("src/commonMain/kotlin")
+ }
+
+ sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.jvm.toString()
+ name = "jvmMain"
+ displayName = "jvmMain"
+ sourceRoots = listOf("src/jvmMain/kotlin")
+ dependentSourceSets = setOf(commonMain.sourceSetID)
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/commonMain/kotlin/sample/Common.kt
+ |package sample
+ |expect class X
+ |
+ |/src/jvmMain/kotlin/sample/JvmMain.kt
+ |package sample
+ |actual class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNumberOfUndocumentedReports(2, Regex("X"))
+ assertSingleUndocumentedReport(Regex("X.*jvmMain"))
+ assertSingleUndocumentedReport(Regex("X.*commonMain"))
+ }
+ }
+ }
+
+ @Test
+ fun `multiplatform undocumented class does not get reported if expect is documented`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ val commonMain = sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.common.toString()
+ name = "commonMain"
+ displayName = "commonMain"
+ sourceRoots = listOf("src/commonMain/kotlin")
+ }
+
+ sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.jvm.toString()
+ name = "jvmMain"
+ displayName = "jvmMain"
+ sourceRoots = listOf("src/jvmMain/kotlin")
+ dependentSourceSets = setOf(commonMain.sourceSetID)
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/commonMain/kotlin/sample/Common.kt
+ |package sample
+ |/** Documented */
+ |expect class X
+ |
+ |/src/jvmMain/kotlin/sample/JvmMain.kt
+ |package sample
+ |actual class X
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNumberOfUndocumentedReports(0)
+ }
+ }
+ }
+
+ @Test
+ fun `multiplatform undocumented function gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ val commonMain = sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.common.toString()
+ name = "commonMain"
+ displayName = "commonMain"
+ sourceRoots = listOf("src/commonMain/kotlin")
+ }
+
+ sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.jvm.toString()
+ name = "jvmMain"
+ displayName = "jvmMain"
+ sourceRoots = listOf("src/jvmMain/kotlin")
+ dependentSourceSets = setOf(commonMain.sourceSetID)
+ }
+
+ sourceSet {
+ reportUndocumented = true
+ analysisPlatform = Platform.native.toString()
+ name = "macosMain"
+ displayName = "macosMain"
+ sourceRoots = listOf("src/macosMain/kotlin")
+ dependentSourceSets = setOf(commonMain.sourceSetID)
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/commonMain/kotlin/sample/Common.kt
+ |package sample
+ |expect fun x()
+ |
+ |/src/macosMain/kotlin/sample/MacosMain.kt
+ |package sample
+ |/** Documented */
+ |actual fun x() = Unit
+ |
+ |/src/jvmMain/kotlin/sample/JvmMain.kt
+ |package sample
+ |actual fun x() = Unit
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNumberOfUndocumentedReports(2)
+ assertSingleUndocumentedReport(Regex("x.*commonMain"))
+ assertSingleUndocumentedReport(Regex("x.*jvmMain"))
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented class gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Test.java
+ |package sample
+ |public class Test { }
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport(Regex("init"))
+ assertSingleUndocumentedReport(Regex("""Test"""))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented non-public class does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Test.java
+ |package sample
+ |class Test { }
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented constructor does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Test.java
+ |package sample
+ |/** Documented */
+ |public class Test {
+ | public Test() {
+ | }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented method gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/X.java
+ |package sample
+ |/** Documented */
+ |public class X {
+ | public void x { }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X.*x"))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented property gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/X.java
+ |package sample
+ |/** Documented */
+ |public class X {
+ | public int x = 0;
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X.*x"))
+ assertNumberOfUndocumentedReports(1)
+ }
+ }
+ }
+
+ @Test
+ fun `java undocumented inherited method gets reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Super.java
+ |package sample
+ |/** Documented */
+ |public class Super {
+ | public void x() {}
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |/** Documented */
+ |public class X extends Super {
+ | public void x() {}
+ |}
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertSingleUndocumentedReport(Regex("X"))
+ assertSingleUndocumentedReport(Regex("X.*x"))
+ assertSingleUndocumentedReport(Regex("Super.*x"))
+ assertNumberOfUndocumentedReports(2)
+ }
+ }
+ }
+
+ @Test
+ fun `java documented inherited method does not get reported`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Super.java
+ |package sample
+ |/** Documented */
+ |public class Super {
+ | /** Documented */
+ | public void x() {}
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |/** Documented */
+ |public class X extends Super {
+ |
+ |}
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ @Test
+ fun `java overridden function does not get reported when super is documented`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ reportUndocumented = true
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/Super.java
+ |package sample
+ |/** Documented */
+ |public class Super {
+ | /** Documented */
+ | public void x() {}
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |/** Documented */
+ |public class X extends Super {
+ | @Override
+ | public void x() {}
+ |}
+ |
+ """.trimMargin(),
+ configuration
+ ) {
+ pagesTransformationStage = {
+ assertNoUndocumentedReport()
+ }
+ }
+ }
+
+ private fun assertNumberOfUndocumentedReports(expectedReports: Int, regex: Regex = Regex(".")) {
+ val reports = logger.warnMessages
+ .filter { it.startsWith("Undocumented:") }
+ val matchingReports = reports
+ .filter { it.contains(regex) }
+
+ assertEquals(
+ expectedReports, matchingReports.size,
+ "Expected $expectedReports report of documented code ($regex).\n" +
+ "Found matching reports: $matchingReports\n" +
+ "Found reports: $reports"
+ )
+ }
+
+ private fun assertSingleUndocumentedReport(regex: Regex) {
+ assertNumberOfUndocumentedReports(1, regex)
+ }
+
+ private fun assertNoUndocumentedReport(regex: Regex) {
+ assertNumberOfUndocumentedReports(0, regex)
+ }
+
+ private fun assertNoUndocumentedReport() {
+ assertNoUndocumentedReport(Regex("."))
+ }
+
+ private fun packageOptions(
+ prefix: String,
+ reportUndocumented: Boolean?,
+ includeNonPublic: Boolean = true,
+ skipDeprecated: Boolean = false,
+ suppress: Boolean = false
+ ) = PackageOptionsImpl(
+ prefix = prefix,
+ reportUndocumented = reportUndocumented,
+ includeNonPublic = includeNonPublic,
+ skipDeprecated = skipDeprecated,
+ suppress = suppress
+ )
+}
diff --git a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt
new file mode 100644
index 00000000..b0754429
--- /dev/null
+++ b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt
@@ -0,0 +1,87 @@
+package translators
+
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+
+class DefaultDescriptorToDocumentableTranslatorTest : AbstractCoreTest() {
+
+ @Test
+ fun `data class kdocs over generated methods`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/sample/XD.kt
+ |package sample
+ |/**
+ | * But the fat Hobbit, he knows. Eyes always watching.
+ | */
+ |data class XD(val xd: String) {
+ | /**
+ | * But the fat Hobbit, he knows. Eyes always watching.
+ | */
+ | fun custom(): String = ""
+ |
+ | /**
+ | * Memory is not what the heart desires. That is only a mirror.
+ | */
+ | override fun equals(other: Any?): Boolean = true
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ assert(module.documentationOf("XD", "copy") == "")
+ assert(module.documentationOf("XD", "equals") == "Memory is not what the heart desires. That is only a mirror.")
+ assert(module.documentationOf("XD", "hashCode") == "")
+ assert(module.documentationOf("XD", "toString") == "")
+ assert(module.documentationOf("XD", "custom") == "But the fat Hobbit, he knows. Eyes always watching.")
+ }
+ }
+ }
+
+ @Test
+ fun `simple class kdocs`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/kotlin")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/kotlin/sample/XD.kt
+ |package sample
+ |/**
+ | * But the fat Hobbit, he knows. Eyes always watching.
+ | */
+ |class XD(val xd: String) {
+ | /**
+ | * But the fat Hobbit, he knows. Eyes always watching.
+ | */
+ | fun custom(): String = ""
+ |
+ | /**
+ | * Memory is not what the heart desires. That is only a mirror.
+ | */
+ | override fun equals(other: Any?): Boolean = true
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ assert(module.documentationOf("XD", "custom") == "But the fat Hobbit, he knows. Eyes always watching.")
+ assert(module.documentationOf("XD", "equals") == "Memory is not what the heart desires. That is only a mirror.")
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt
new file mode 100644
index 00000000..eb682b14
--- /dev/null
+++ b/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt
@@ -0,0 +1,144 @@
+package translators
+
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.doc.Description
+import org.jetbrains.dokka.model.doc.Text
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+
+class DefaultPsiToDocumentableTranslatorTest : AbstractCoreTest() {
+
+ @Test
+ fun `method overriding two documented classes picks closest class documentation`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/BaseClass1.java
+ |package sample
+ |public class BaseClass1 {
+ | /** B1 */
+ | void x() { }
+ |}
+ |
+ |/src/main/java/sample/BaseClass2.java
+ |package sample
+ |public class BaseClass2 extends BaseClass1 {
+ | /** B2 */
+ | void x() { }
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |public class X extends BaseClass2 {
+ | void x() { }
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val documentationOfFunctionX = module.documentationOf("X", "x")
+ assertTrue(
+ "B2" in documentationOfFunctionX,
+ "Expected nearest super method documentation to be parsed as documentation. " +
+ "Documentation: $documentationOfFunctionX"
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `method overriding class and interface picks class documentation`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/BaseClass1.java
+ |package sample
+ |public class BaseClass1 {
+ | /** B1 */
+ | void x() { }
+ |}
+ |
+ |/src/main/java/sample/Interface1.java
+ |package sample
+ |public interface Interface1 {
+ | /** I1 */
+ | void x() {}
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |public class X extends BaseClass1 implements Interface1 {
+ | void x() { }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val documentationOfFunctionX = module.documentationOf("X", "x")
+ assertTrue(
+ "B1" in documentationOfFunctionX,
+ "Expected documentation of superclass being prioritized over interface " +
+ "Documentation: $documentationOfFunctionX"
+ )
+ }
+ }
+ }
+
+ @Test
+ fun `method overriding two classes picks closest documented class documentation`() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ testInline(
+ """
+ |/src/main/java/sample/BaseClass1.java
+ |package sample
+ |public class BaseClass1 {
+ | /** B1 */
+ | void x() { }
+ |}
+ |
+ |/src/main/java/sample/BaseClass2.java
+ |package sample
+ |public class BaseClass2 extends BaseClass1 {
+ | void x() {}
+ |}
+ |
+ |/src/main/java/sample/X.java
+ |package sample
+ |public class X extends BaseClass2 {
+ | void x() { }
+ |}
+ """.trimMargin(),
+ configuration
+ ) {
+ documentablesMergingStage = { module ->
+ val documentationOfFunctionX = module.documentationOf("X", "x")
+ assertTrue(
+ "B1" in documentationOfFunctionX,
+ "Expected Documentation \"B1\", found: \"$documentationOfFunctionX\""
+ )
+ }
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/translators/utils.kt b/plugins/base/src/test/kotlin/translators/utils.kt
new file mode 100644
index 00000000..96d3035a
--- /dev/null
+++ b/plugins/base/src/test/kotlin/translators/utils.kt
@@ -0,0 +1,16 @@
+package translators
+
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.model.doc.Description
+import org.jetbrains.dokka.model.doc.Text
+
+fun DModule.documentationOf(className: String, functionName: String): String {
+ return (packages.single()
+ .classlikes.single { it.name == className }
+ .functions.single { it.name == functionName }
+ .documentation.values.singleOrNull()
+ ?.children?.singleOrNull()
+ .run { this as? Description }
+ ?.root?.children?.single() as? Text)
+ ?.body.orEmpty()
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/utils/JsoupUtils.kt b/plugins/base/src/test/kotlin/utils/JsoupUtils.kt
new file mode 100644
index 00000000..e8c7838d
--- /dev/null
+++ b/plugins/base/src/test/kotlin/utils/JsoupUtils.kt
@@ -0,0 +1,29 @@
+package utils
+
+import org.jsoup.nodes.Element
+import org.jsoup.nodes.Node
+import org.jsoup.nodes.TextNode
+
+fun Element.match(vararg matchers: Any): Unit =
+ childNodes()
+ .filter { it !is TextNode || it.text().isNotBlank() }
+ .let { it.drop(it.size - matchers.size) }
+ .zip(matchers)
+ .forEach { (n, m) -> m.accepts(n) }
+
+open class Tag(val name: String, vararg val matchers: Any)
+class Div(vararg matchers: Any) : Tag("div", *matchers)
+class P(vararg matchers: Any) : Tag("p", *matchers)
+class Span(vararg matchers: Any) : Tag("span", *matchers)
+class A(vararg matchers: Any) : Tag("a", *matchers)
+object Wbr : Tag("wbr")
+private fun Any.accepts(n: Node) {
+ when (this) {
+ is String -> assert(n is TextNode && n.text().trim() == this.trim()) { "\"$this\" expected but found: $n" }
+ is Tag -> {
+ assert(n is Element && n.tagName() == name) { "Tag $name expected but found: $n" }
+ if (n is Element && matchers.isNotEmpty()) n.match(*matchers)
+ }
+ else -> throw IllegalArgumentException("$this is not proper matcher")
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/utils/ModelUtils.kt b/plugins/base/src/test/kotlin/utils/ModelUtils.kt
new file mode 100644
index 00000000..87a9c802
--- /dev/null
+++ b/plugins/base/src/test/kotlin/utils/ModelUtils.kt
@@ -0,0 +1,37 @@
+package utils
+
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.model.DModule
+import org.jetbrains.dokka.plugability.DokkaPlugin
+
+abstract class AbstractModelTest(val path: String? = null, val pkg: String) : ModelDSL(), AssertDSL {
+
+ fun inlineModelTest(
+ query: String,
+ platform: String = "jvm",
+ prependPackage: Boolean = true,
+ cleanupOutput: Boolean = true,
+ pluginsOverrides: List<DokkaPlugin> = emptyList(),
+ configuration: DokkaConfigurationImpl? = null,
+ block: DModule.() -> Unit
+ ) {
+ val testConfiguration = configuration ?: dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = platform
+ }
+ }
+ }
+ val prepend = path.let { p -> p?.let { "|$it\n" } ?: "" } + if (prependPackage) "|package $pkg" else ""
+
+ testInline(
+ query = ("$prepend\n$query").trim().trimIndent(),
+ configuration = testConfiguration,
+ cleanupOutput = cleanupOutput,
+ pluginOverrides = pluginsOverrides
+ ) {
+ documentablesTransformationStage = block
+ }
+ }
+}
diff --git a/plugins/base/src/test/kotlin/utils/TestUtils.kt b/plugins/base/src/test/kotlin/utils/TestUtils.kt
new file mode 100644
index 00000000..bd0e1fe2
--- /dev/null
+++ b/plugins/base/src/test/kotlin/utils/TestUtils.kt
@@ -0,0 +1,79 @@
+package utils
+
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.doc.*
+import org.jetbrains.dokka.model.doc.P
+import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest
+import org.junit.jupiter.api.Assertions.assertTrue
+import kotlin.collections.orEmpty
+
+@DslMarker
+annotation class TestDSL
+
+@TestDSL
+abstract class ModelDSL : AbstractCoreTest() {
+ operator fun Documentable?.div(name: String): Documentable? =
+ this?.children?.find { it.name == name }
+
+ inline fun <reified T : Documentable> Documentable?.cast(): T =
+ (this as? T).assertNotNull()
+}
+
+@TestDSL
+interface AssertDSL {
+ infix fun Any?.equals(other: Any?) = this.assertEqual(other)
+ infix fun Collection<Any>?.allEquals(other: Any?) =
+ this?.also { c -> c.forEach { it equals other } } ?: run { assert(false) { "Collection is empty" } }
+ infix fun <T> Collection<T>?.exists(e: T) {
+ assertTrue(this.orEmpty().isNotEmpty(), "Collection cannot be null or empty")
+ assertTrue(this!!.any{it == e}, "Collection doesn't contain $e")
+ }
+
+ infix fun <T> Collection<T>?.counts(n: Int) = this.orEmpty().assertCount(n)
+
+ infix fun <T> T?.notNull(name: String): T = this.assertNotNull(name)
+
+ fun <T> Collection<T>.assertCount(n: Int, prefix: String = "") =
+ assert(count() == n) { "${prefix}Expected $n, got ${count()}" }
+
+ fun <T> T?.assertEqual(expected: T, prefix: String = "") = assert(this == expected) {
+ "${prefix}Expected $expected, got $this"
+ }
+}
+
+inline fun <reified T : Any> Any?.assertIsInstance(name: String): T =
+ this.let { it as? T } ?: throw AssertionError("$name should not be null")
+
+fun TagWrapper.text(): String = when (val t = this) {
+ is NamedTagWrapper -> "${t.name}: [${t.root.text()}]"
+ else -> t.root.text()
+}
+
+fun DocTag.text(): String = when (val t = this) {
+ is Text -> t.body
+ is Code -> t.children.joinToString("\n") { it.text() }
+ is P -> t.children.joinToString(separator = "\n") { it.text() }
+ else -> t.toString()
+}
+
+fun <T : Documentable> T?.comments(): String = docs().map { it.text() }
+ .joinToString(separator = "\n") { it }
+
+fun <T> T?.assertNotNull(name: String = ""): T = this ?: throw AssertionError("$name should not be null")
+
+fun <T : Documentable> T?.docs() = this?.documentation.orEmpty().values.flatMap { it.children }
+
+val DClass.supers
+ get() = supertypes.flatMap { it.component2() }
+
+val Bound.name: String?
+ get() = when (this) {
+ is Nullable -> inner.name
+ is OtherParameter -> name
+ is PrimitiveJavaType -> name
+ is TypeConstructor -> dri.classNames
+ is JavaObject -> "Object"
+ is Void -> "void"
+ is Dynamic -> "dynamic"
+ is UnresolvedBound -> "<ERROR CLASS>"
+ } \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/utils/contentUtils.kt b/plugins/base/src/test/kotlin/utils/contentUtils.kt
new file mode 100644
index 00000000..7fcd8e89
--- /dev/null
+++ b/plugins/base/src/test/kotlin/utils/contentUtils.kt
@@ -0,0 +1,243 @@
+package utils
+
+import matchers.content.*
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.pages.ContentGroup
+import kotlin.text.Typography.nbsp
+
+//TODO: Try to unify those functions after update to 1.4
+fun ContentMatcherBuilder<*>.functionSignature(
+ annotations: Map<String, Set<String>>,
+ visibility: String,
+ modifier: String,
+ keywords: Set<String>,
+ name: String,
+ returnType: String? = null,
+ vararg params: Pair<String, ParamAttributes>
+) =
+ platformHinted {
+ bareSignature(annotations, visibility, modifier, keywords, name, returnType, *params)
+ }
+
+fun ContentMatcherBuilder<*>.bareSignature(
+ annotations: Map<String, Set<String>>,
+ visibility: String,
+ modifier: String,
+ keywords: Set<String>,
+ name: String,
+ returnType: String? = null,
+ vararg params: Pair<String, ParamAttributes>
+) = group {
+ annotations.entries.forEach {
+ group {
+ unwrapAnnotation(it)
+ }
+ }
+ +("$visibility $modifier ${keywords.joinToString("") { "$it " }} fun")
+ link { +name }
+ +"("
+ params.forEachIndexed { id, (n, t) ->
+
+ t.annotations.forEach {
+ unwrapAnnotation(it)
+ }
+ t.keywords.forEach {
+ +it
+ }
+
+ +"$n:"
+ group { link { +(t.type) } }
+ if (id != params.lastIndex)
+ +", "
+ }
+ +")"
+ if (returnType != null) {
+ +(": ")
+ group {
+ link {
+ +(returnType)
+ }
+ }
+ }
+}
+
+fun ContentMatcherBuilder<*>.functionSignatureWithReceiver(
+ annotations: Map<String, Set<String>>,
+ visibility: String?,
+ modifier: String?,
+ keywords: Set<String>,
+ receiver: String,
+ name: String,
+ returnType: String? = null,
+ vararg params: Pair<String, ParamAttributes>
+) =
+ platformHinted {
+ bareSignatureWithReceiver(annotations, visibility, modifier, keywords, receiver, name, returnType, *params)
+ }
+
+fun ContentMatcherBuilder<*>.bareSignatureWithReceiver(
+ annotations: Map<String, Set<String>>,
+ visibility: String?,
+ modifier: String?,
+ keywords: Set<String>,
+ receiver: String,
+ name: String,
+ returnType: String? = null,
+ vararg params: Pair<String, ParamAttributes>
+) = group { // TODO: remove it when double wrapping for signatures will be resolved
+ annotations.entries.forEach {
+ group {
+ unwrapAnnotation(it)
+ }
+ }
+ +("$visibility $modifier ${keywords.joinToString("") { "$it " }} fun")
+ group {
+ link { +receiver }
+ }
+ +"."
+ link { +name }
+ +"("
+ params.forEachIndexed { id, (n, t) ->
+
+ t.annotations.forEach {
+ unwrapAnnotation(it)
+ }
+ t.keywords.forEach {
+ +it
+ }
+
+ +"$n:"
+ group { link { +(t.type) } }
+ if (id != params.lastIndex)
+ +", "
+ }
+ +")"
+ if (returnType != null) {
+ +(": ")
+ group {
+ link {
+ +(returnType)
+ }
+ }
+ }
+}
+
+fun ContentMatcherBuilder<*>.propertySignature(
+ annotations: Map<String, Set<String>>,
+ visibility: String,
+ modifier: String,
+ keywords: Set<String>,
+ preposition: String,
+ name: String,
+ type: String? = null
+) {
+ group {
+ header { +"Package test" }
+ skipAllNotMatching()
+ }
+ group {
+ group {
+ skipAllNotMatching()
+ header { +"Properties" }
+ table {
+ group {
+ link { +name }
+ platformHinted {
+ group {
+ annotations.entries.forEach {
+ group {
+ unwrapAnnotation(it)
+ }
+ }
+ +("$visibility $modifier ${keywords.joinToString("") { "$it " }} $preposition")
+ link { +name }
+ if (type != null) {
+ +(": ")
+ group {
+ link {
+ +(type)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+fun ContentMatcherBuilder<*>.typealiasSignature(name: String, expressionTarget: String) {
+ group {
+ header { +"Package test" }
+ skipAllNotMatching()
+ }
+ group {
+ group {
+ skipAllNotMatching()
+ header { +"Types" }
+ table {
+ group {
+ link { +name }
+ divergentGroup {
+ divergentInstance {
+ group {
+ group {
+ group {
+ group {
+ +"typealias "
+ group {
+ link { +name }
+ skipAllNotMatching()
+ }
+ +" = "
+ group {
+ link { +expressionTarget }
+ }
+ }
+ }
+ }
+ }
+ }
+ skipAllNotMatching()
+ }
+ }
+ skipAllNotMatching()
+ }
+ skipAllNotMatching()
+ }
+ }
+}
+
+fun ContentMatcherBuilder<*>.pWrapped(text: String) =
+ group {// TODO: remove it when double wrapping for descriptions will be resolved
+ group { +text }
+ }
+
+fun ContentMatcherBuilder<*>.unnamedTag(tag: String, content: ContentMatcherBuilder<ContentGroup>.() -> Unit) =
+ group {
+ header(4) { +tag }
+ group { content() }
+ }
+
+fun ContentMatcherBuilder<*>.unwrapAnnotation(elem: Map.Entry<String, Set<String>>) {
+ group {
+ +"@"
+ link { +elem.key }
+ +"("
+ elem.value.forEach {
+ group {
+ +("$it = ")
+ skipAllNotMatching()
+ }
+ }
+ +")"
+ }
+}
+
+data class ParamAttributes(
+ val annotations: Map<String, Set<String>>,
+ val keywords: Set<String>,
+ val type: String
+)
diff --git a/plugins/base/src/test/resources/linkable/includes/include1.md b/plugins/base/src/test/resources/linkable/includes/include1.md
new file mode 100644
index 00000000..03d9037d
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/includes/include1.md
@@ -0,0 +1,7 @@
+# Module example
+
+This is JVM documentation for module example
+
+# Package example
+
+This is JVM documentation for package example \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/includes/include2.md b/plugins/base/src/test/resources/linkable/includes/include2.md
new file mode 100644
index 00000000..1574003d
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/includes/include2.md
@@ -0,0 +1,7 @@
+# Module example
+
+This is JS documentation for module example
+
+# Package greeteer
+
+This is JS documentation for package greeteer \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt b/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt
new file mode 100644
index 00000000..b61ce704
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt
@@ -0,0 +1,9 @@
+package p2
+
+class JsClass {
+
+ /**
+ * @sample samples.SamplesJs.exampleUsage
+ */
+ fun printWithExclamation(msg: String) = println(msg + "!")
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt b/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt
new file mode 100644
index 00000000..55be0ad8
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt
@@ -0,0 +1,10 @@
+package samples
+
+import p2.JsClass
+
+class SamplesJs {
+
+ fun exampleUsage() {
+ JsClass().printWithExclamation("Hi, Js")
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt b/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt
new file mode 100644
index 00000000..960184e6
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt
@@ -0,0 +1,9 @@
+package p2
+
+class JvmClass {
+
+ /**
+ * @sample samples.SamplesJvm.exampleUsage
+ */
+ fun printWithExclamation(msg: String) = println(msg + "!")
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt b/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt
new file mode 100644
index 00000000..69418fa9
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt
@@ -0,0 +1,10 @@
+package samples
+
+import p2.JvmClass
+
+class SamplesJvm {
+
+ fun exampleUsage() {
+ JvmClass().printWithExclamation("Hi, Jvm")
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt b/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt
new file mode 100644
index 00000000..00dd009b
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt
@@ -0,0 +1,3 @@
+package p1
+
+class JsClass \ No newline at end of file
diff --git a/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt b/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt
new file mode 100644
index 00000000..2113c589
--- /dev/null
+++ b/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt
@@ -0,0 +1,3 @@
+package p1
+
+class JvmClass \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt
new file mode 100644
index 00000000..4753cb32
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt
@@ -0,0 +1,15 @@
+package example
+
+/**
+ * Documentation for expected class Clock
+ * in common module
+ */
+expect open class Clock() {
+ fun getTime(): String
+ /**
+ * Time in minis
+ */
+ fun getTimesInMillis(): String
+ fun getYear(): String
+}
+
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt
new file mode 100644
index 00000000..c879dee7
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt
@@ -0,0 +1,24 @@
+package example
+
+class House(val street: String, val number: Int) {
+
+ /**
+ * The owner of the house
+ */
+ var owner: String = ""
+
+ /**
+ * The owner of the house
+ */
+ val differentOwner: String = ""
+
+ fun addFloor() {}
+
+ class Basement {
+ val pickles : List<Any> = mutableListOf()
+ }
+
+ companion object {
+ val DEFAULT = House("",0)
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt
new file mode 100644
index 00000000..51b8fdc6
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt
@@ -0,0 +1,28 @@
+package example
+
+import greeteer.Greeter
+import kotlin.js.Date
+
+/**
+ * Documentation for actual class Clock in JS
+ */
+actual open class Clock {
+ actual fun getTime() = Date.now().toString()
+ fun onlyJsFunction(): Int = 42
+
+ /**
+ * JS implementation of getTimeInMillis
+ */
+ actual fun getTimesInMillis(): String = Date.now().toString()
+
+ /**
+ * JS custom kdoc
+ */
+ actual fun getYear(): String {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+}
+
+fun main() {
+ Greeter().greet().also { println(it) }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt
new file mode 100644
index 00000000..8a52e2f3
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt
@@ -0,0 +1,10 @@
+package greeteer
+
+import example.Clock
+
+class Greeter {
+ /**
+ * Some docs for the [greet] function
+ */
+ fun greet() = Clock().let{ "Hello there! THe time is ${it.getTime()}" }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt
new file mode 100644
index 00000000..fec06207
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt
@@ -0,0 +1,41 @@
+package example
+
+import greeteer.Greeter
+
+/**
+ * Documentation for actual class Clock in JVM
+ */
+actual open class Clock {
+ actual fun getTime(): String = System.currentTimeMillis().toString()
+ actual fun getTimesInMillis(): String = System.currentTimeMillis().toString()
+
+ /**
+ * Documentation for onlyJVMFunction on...
+ * wait for it...
+ * ...JVM!
+ */
+ fun onlyJVMFunction(): Double = 2.5
+ /**
+ * Custom equals function
+ */
+ override fun equals(other: Any?): Boolean {
+ return super.equals(other)
+ }
+
+ open fun getDayOfTheWeek(): String {
+ TODO("not implemented")
+ }
+
+ /**
+ * JVM custom kdoc
+ */
+ actual fun getYear(): String {
+ TODO("not implemented")
+ }
+}
+
+fun clockList() = listOf(Clock())
+
+fun main() {
+ Greeter().greet().also { println(it) }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt
new file mode 100644
index 00000000..136ae5c8
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt
@@ -0,0 +1,15 @@
+package example
+
+/**
+ * frgergergrthe
+ * */
+enum class ClockDays {
+ /**
+ * dfsdfsdfds
+ * */
+ FIRST,
+ SECOND, // test2
+ THIRD, // test3
+ FOURTH, // test4
+ FIFTH // test5
+} \ No newline at end of file
diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt
new file mode 100644
index 00000000..40813b50
--- /dev/null
+++ b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt
@@ -0,0 +1,32 @@
+package example
+
+import greeteer.Greeter
+
+class ParticularClock(private val clockDay: ClockDays) : Clock() {
+
+ /**
+ * Rings bell [times]
+ */
+ fun ringBell(times: Int) {}
+
+ /**
+ * Uses provider [greeter]
+ */
+ fun useGreeter(greeter: Greeter) {
+
+ }
+
+ /**
+ * Day of the week
+ */
+ override fun getDayOfTheWeek() = clockDay.name
+}
+
+/**
+ * A sample extension function
+ * When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are $$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
+ * @usesMathJax
+ */
+fun Clock.extensionFun() {
+
+} \ No newline at end of file
diff --git a/plugins/base/test-utils/build.gradle.kts b/plugins/base/test-utils/build.gradle.kts
new file mode 100644
index 00000000..4c39ed60
--- /dev/null
+++ b/plugins/base/test-utils/build.gradle.kts
@@ -0,0 +1,4 @@
+dependencies {
+ compileOnly(project(":plugins:base"))
+ implementation(project(":testApi"))
+} \ No newline at end of file
diff --git a/plugins/base/test-utils/src/main/kotlin/renderers/RenderingOnlyTestBase.kt b/plugins/base/test-utils/src/main/kotlin/renderers/RenderingOnlyTestBase.kt
new file mode 100644
index 00000000..e5ff8fa8
--- /dev/null
+++ b/plugins/base/test-utils/src/main/kotlin/renderers/RenderingOnlyTestBase.kt
@@ -0,0 +1,8 @@
+package renderers
+
+import org.jetbrains.dokka.testApi.context.MockContext
+
+abstract class RenderingOnlyTestBase<T> {
+ abstract val context: MockContext
+ abstract val renderedContent: T
+}
diff --git a/plugins/base/test-utils/src/main/kotlin/renderers/TestPage.kt b/plugins/base/test-utils/src/main/kotlin/renderers/TestPage.kt
new file mode 100644
index 00000000..0dae8ce6
--- /dev/null
+++ b/plugins/base/test-utils/src/main/kotlin/renderers/TestPage.kt
@@ -0,0 +1,52 @@
+package renderers
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.Documentable
+import org.jetbrains.dokka.model.doc.DocTag
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.utilities.DokkaConsoleLogger
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+
+class TestPage(callback: PageContentBuilder.DocumentableContentBuilder.() -> Unit) : RootPageNode(), ContentPage {
+ override val dri: Set<DRI> = setOf(DRI.topLevel)
+ override val documentable: Documentable? = null
+ override val embeddedResources: List<String> = emptyList()
+ override val name: String
+ get() = "testPage"
+ override val children: List<PageNode>
+ get() = emptyList()
+
+ override val content: ContentNode = PageContentBuilder(
+ EmptyCommentConverter,
+ KotlinSignatureProvider(EmptyCommentConverter, DokkaConsoleLogger),
+ DokkaConsoleLogger
+ ).contentFor(
+ DRI.topLevel,
+ emptySet(),
+ block = callback
+ )
+
+ override fun modified(
+ name: String,
+ content: ContentNode,
+ dri: Set<DRI>,
+ embeddedResources: List<String>,
+ children: List<PageNode>
+ ) = this
+
+ override fun modified(name: String, children: List<PageNode>) = this
+}
+
+internal object EmptyCommentConverter : CommentsToContentConverter {
+ override fun buildContent(
+ docTag: DocTag,
+ dci: DCI,
+ sourceSets: Set<DokkaConfiguration.DokkaSourceSet>,
+ styles: Set<Style>,
+ extras: PropertyContainer<ContentNode>
+ ): List<ContentNode> = emptyList()
+} \ No newline at end of file
diff --git a/plugins/base/test-utils/src/main/kotlin/renderers/defaultSourceSet.kt b/plugins/base/test-utils/src/main/kotlin/renderers/defaultSourceSet.kt
new file mode 100644
index 00000000..7358d2c2
--- /dev/null
+++ b/plugins/base/test-utils/src/main/kotlin/renderers/defaultSourceSet.kt
@@ -0,0 +1,31 @@
+package renderers
+
+import org.jetbrains.dokka.DokkaSourceSetID
+import org.jetbrains.dokka.DokkaSourceSetImpl
+import org.jetbrains.dokka.Platform
+
+val defaultSourceSet = DokkaSourceSetImpl(
+ moduleDisplayName = "DEFAULT",
+ displayName = "DEFAULT",
+ sourceSetID = DokkaSourceSetID("DEFAULT", "DEFAULT"),
+ classpath = emptyList(),
+ sourceRoots = emptyList(),
+ dependentSourceSets = emptySet(),
+ samples = emptyList(),
+ includes = emptyList(),
+ includeNonPublic = false,
+ includeRootPackage = false,
+ reportUndocumented = false,
+ skipEmptyPackages = true,
+ skipDeprecated = false,
+ jdkVersion = 8,
+ sourceLinks = emptyList(),
+ perPackageOptions = emptyList(),
+ externalDocumentationLinks = emptyList(),
+ languageVersion = null,
+ apiVersion = null,
+ noStdlibLink = false,
+ noJdkLink = false,
+ suppressedFiles = emptyList(),
+ analysisPlatform = Platform.DEFAULT
+)
diff --git a/plugins/base/test-utils/src/main/kotlin/utils/TestOutputWriter.kt b/plugins/base/test-utils/src/main/kotlin/utils/TestOutputWriter.kt
new file mode 100644
index 00000000..00b865b4
--- /dev/null
+++ b/plugins/base/test-utils/src/main/kotlin/utils/TestOutputWriter.kt
@@ -0,0 +1,32 @@
+package utils
+
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.renderers.OutputWriter
+import org.jetbrains.dokka.plugability.DokkaPlugin
+
+class TestOutputWriterPlugin(failOnOverwrite: Boolean = true) : DokkaPlugin() {
+ val writer = TestOutputWriter(failOnOverwrite)
+
+ private val dokkaBase by lazy { plugin<DokkaBase>() }
+
+ val testWriter by extending {
+ (dokkaBase.outputWriter
+ with writer
+ override dokkaBase.fileWriter)
+ }
+}
+
+class TestOutputWriter(private val failOnOverwrite: Boolean = true) : OutputWriter {
+ val contents: Map<String, String> get() = _contents
+
+ private val _contents = mutableMapOf<String, String>()
+ override suspend fun write(path: String, text: String, ext: String) {
+ val fullPath = "$path$ext"
+ _contents.putIfAbsent(fullPath, text)?.also {
+ if (failOnOverwrite) throw AssertionError("File $fullPath is being overwritten.")
+ }
+ }
+
+ override suspend fun writeResources(pathFrom: String, pathTo: String) =
+ write(pathTo, "*** content of $pathFrom ***", "")
+}