├── gradle.properties
├── .gitignore
├── img
└── image.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── src
├── jsMain
│ ├── resources
│ │ ├── favicon-32x32.png
│ │ ├── filetree
│ │ │ ├── icon.png
│ │ │ └── src.css
│ │ ├── binaries
│ │ │ └── gradle-wrapper
│ │ ├── ic_info.svg
│ │ ├── ic_fb.svg
│ │ ├── ic_jb_blog.svg
│ │ ├── ic_feed.svg
│ │ ├── ic_insta.svg
│ │ ├── ic_twitter.svg
│ │ ├── ic_linkedin.svg
│ │ ├── ic_youtube.svg
│ │ ├── index.html
│ │ ├── ic_lang.svg
│ │ ├── ic_kotlin_logo.svg
│ │ ├── hljs.css
│ │ ├── filetree.css
│ │ ├── i1.svg
│ │ └── logos.css
│ └── kotlin
│ │ └── org
│ │ └── jetbrains
│ │ └── webwiz
│ │ ├── FileSaverJs.kt
│ │ ├── HighlightJs.kt
│ │ ├── JSZip.kt
│ │ ├── style
│ │ ├── WtSection.kt
│ │ ├── WtContainer.kt
│ │ ├── WtRow.kt
│ │ ├── Stylesheet.kt
│ │ ├── WtCol.kt
│ │ ├── WtOffest.kt
│ │ └── WtText.kt
│ │ ├── content
│ │ ├── Header.kt
│ │ ├── IntroSection.kt
│ │ ├── CodeSamplesSwitcher.kt
│ │ ├── Footer.kt
│ │ ├── Chips.kt
│ │ └── WizardSection.kt
│ │ ├── components
│ │ └── Layout.kt
│ │ └── Main.kt
├── commonMain
│ └── kotlin
│ │ └── org
│ │ └── jetbrains
│ │ └── webwiz
│ │ ├── models
│ │ ├── KotlinVersions.kt
│ │ ├── SourceSetType.kt
│ │ ├── NativeTargetLibrary.kt
│ │ ├── GradlePlugins.kt
│ │ ├── Targets.kt
│ │ ├── SingleTargetLibrary.kt
│ │ ├── ProjectInfo.kt
│ │ └── KmpLibraries.kt
│ │ └── generator
│ │ ├── files
│ │ ├── Gitignore.kt
│ │ ├── AndroidManifestXml.kt
│ │ ├── SettingsGradle.kt
│ │ ├── ApplicationKt.kt
│ │ ├── GradleProperties.kt
│ │ ├── GradleWrapper.kt
│ │ ├── PlatformKt.kt
│ │ ├── RootBuildGradle.kt
│ │ ├── PlatformTestKt.kt
│ │ ├── GradleBat.kt
│ │ ├── Gradlew.kt
│ │ └── ModuleBuildGradle.kt
│ │ └── generator.kt
└── commonTest
│ └── kotlin
│ └── org
│ └── jetbrains
│ └── webwiz
│ └── generator
│ └── ProjectBuilderTest.kt
├── settings.gradle.kts
├── .github
└── workflows
│ └── publish.yaml
├── README.md
├── gradlew.bat
└── gradlew
/gradle.properties:
--------------------------------------------------------------------------------
1 | kotlin.code.style=official
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | local.properties
3 | .gradle
4 | .idea
--------------------------------------------------------------------------------
/img/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/kmp-web-wizard/master/img/image.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/kmp-web-wizard/master/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/jsMain/resources/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/kmp-web-wizard/master/src/jsMain/resources/favicon-32x32.png
--------------------------------------------------------------------------------
/src/jsMain/resources/filetree/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/kmp-web-wizard/master/src/jsMain/resources/filetree/icon.png
--------------------------------------------------------------------------------
/src/jsMain/resources/binaries/gradle-wrapper:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/kmp-web-wizard/master/src/jsMain/resources/binaries/gradle-wrapper
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | mavenCentral()
5 | }
6 | }
7 | rootProject.name = "kmp-web-wizard"
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/KotlinVersions.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | enum class KotlinVersion(val versionName: String) {
4 | Stable("1.6.0"),
5 | EAP("1.6.0"),
6 | Dev("1.6.20-dev-967")
7 | }
8 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_info.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/FileSaverJs.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz
2 |
3 | import org.w3c.files.Blob
4 |
5 | @JsModule("file-saver")
6 | @JsNonModule
7 | external class FileSaverJs {
8 | companion object {
9 | fun saveAs(blob: Blob, fileName: String)
10 | }
11 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_fb.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_jb_blog.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/SourceSetType.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | enum class SourceSetType(val sourceSetTypeName: String) {
4 | MAIN("Main"),
5 | TEST("Test")
6 | }
7 |
8 | enum class SourceSetDelegate(val delegate: String) {
9 | CREATING("creating"),
10 | GETTING("getting")
11 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_feed.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_insta.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/HighlightJs.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz
2 |
3 | import org.w3c.dom.HTMLElement
4 |
5 | @JsName("hljs")
6 | @JsModule("highlight.js")
7 | @JsNonModule
8 | external class HighlightJs {
9 | companion object {
10 | fun highlightElement(block: HTMLElement)
11 | }
12 | }
13 |
14 | fun HTMLElement.setHighlightedCode(code: String) {
15 | innerText = code
16 | HighlightJs.highlightElement(this)
17 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/JSZip.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz
2 |
3 | import org.khronos.webgl.ArrayBuffer
4 | import kotlin.js.Promise
5 |
6 | @JsModule("jszip")
7 | @JsNonModule
8 | external class JSZip {
9 | fun file(name: String, content: String): JSZip
10 | fun file(name: String, content: String, options: dynamic): JSZip
11 | fun file(name: String, content: ArrayBuffer): JSZip
12 | fun generateAsync(type: dynamic): Promise
13 | }
14 |
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_twitter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/Gitignore.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class Gitignore : ProjectFile {
6 | override val path = ".gitignore"
7 | override val content: String
8 | get() = """
9 | *.iml
10 | .gradle
11 | /local.properties
12 | .idea
13 | .DS_Store
14 | /build
15 | */build
16 | /captures
17 | .externalNativeBuild
18 | .cxx
19 | local.properties
20 | """.trimIndent()
21 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/NativeTargetLibrary.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | import org.jetbrains.webwiz.models.SourceSetType.MAIN
4 |
5 | // Dependencies in here will be available for all native targets
6 | enum class NativeTargetLibrary(
7 | val userName: String,
8 | val dep: String,
9 | val sourceSetType: SourceSetType
10 | ) {
11 | SQLDELIGHT_DRIVER_NATIVE(
12 | "SQDelight Native Driver",
13 | "com.squareup.sqldelight:native-driver:1.5.3",
14 | MAIN
15 | ),
16 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_linkedin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/AndroidManifestXml.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 | import org.jetbrains.webwiz.models.ProjectInfo
5 |
6 | class AndroidManifestXml(val projectInfo: ProjectInfo) : ProjectFile {
7 | override val path = "${projectInfo.moduleName}/src/androidMain/AndroidManifest.xml"
8 | override val content: String
9 | get() = """
10 |
11 |
12 | """.trimIndent()
13 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/SettingsGradle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class SettingsGradle(val projectName: String, val moduleName: String) : ProjectFile {
6 | override val path = "settings.gradle.kts"
7 | override val content: String
8 | get() = """
9 | pluginManagement {
10 | repositories {
11 | google()
12 | gradlePluginPortal()
13 | mavenCentral()
14 | }
15 | }
16 |
17 | rootProject.name = "${projectName.replace(' ', '_')}"
18 | include(":$moduleName")
19 | """.trimIndent()
20 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/ApplicationKt.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 | import org.jetbrains.webwiz.models.ProjectInfo
5 |
6 | class ApplicationKt(val projectInfo: ProjectInfo) : ProjectFile {
7 | override val path = "${projectInfo.moduleName}/src/jvmMain/kotlin" +
8 | "/${projectInfo.packageName.replace('.', '/')}" +
9 | "/Application.kt"
10 | override val content: String
11 | get() = """
12 | package ${projectInfo.packageName}
13 |
14 | fun main() {
15 | println("Hello world!")
16 | }
17 | """.trimIndent()
18 | }
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: Build and Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | build-and-deploy:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v2.3.1
17 |
18 | - name: Test
19 | run: |
20 | ./gradlew check
21 |
22 | - name: Build
23 | run: |
24 | ./gradlew jsBrowserProductionWebpack
25 |
26 | - name: Deploy
27 | uses: JamesIves/github-pages-deploy-action@4.1.5
28 | with:
29 | branch: gh-pages
30 | folder: build/distributions
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kotlin Multiplatform Wizard
2 |
3 | [](https://terrakok.github.io/kmp-web-wizard/)
4 |
5 | This is JB hackathon project.
6 | Try it out [here](https://terrakok.github.io/kmp-web-wizard/)
7 |
8 | It is a fun project with bleeding-edge technologies: Kotlin JS + Compose for Web.
9 |
10 | If you see some problems (especially with CSS 😅) or want to add some cool feature PR is welcome! :)
11 |
12 | Team:
13 | [@terrakok](https://github.com/terrakok)
14 | [@vkormushkin](https://github.com/vkormushkin)
15 | [@ALD110](https://github.com/ALD110)
16 | [@atyrin](https://github.com/atyrin)
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/GradleProperties.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class GradleProperties : ProjectFile {
6 | override val path = "gradle.properties"
7 | override val content: String
8 | get() = """
9 | #Gradle
10 | org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
11 |
12 | #Kotlin
13 | kotlin.code.style=official
14 |
15 | #Android
16 | android.useAndroidX=true
17 |
18 | #MPP
19 | kotlin.mpp.enableGranularSourceSetsMetadata=true
20 | kotlin.native.enableDependencyPropagation=false
21 | kotlin.mpp.enableCInteropCommonization=true
22 | """.trimIndent()
23 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/GradlePlugins.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | enum class GradlePlugin(
4 | val mandatory: Set,
5 | val forbidden: Set,
6 | val userName: String
7 | ) {
8 | PUBLISH(
9 | emptySet(),
10 | emptySet(),
11 | "Maven Publish"
12 | ),
13 | APPLICATION(
14 | setOf(Target.JVM),
15 | setOf(Target.ANDROID),
16 | "JVM Application"
17 | ),
18 | SQL_DELIGHT(
19 | emptySet(),
20 | setOf(Target.WASM),
21 | "SQLDelight"
22 | );
23 |
24 | fun canBeApplied(targets: Set): Boolean =
25 | targets.containsAll(mandatory) && !targets.any { it in forbidden }
26 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_youtube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kotlin MPP Web Wizard
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/GradleWrapper.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class GradleWrapperProperties(val gradleVersion: String) : ProjectFile {
6 | override val path = "gradle/wrapper/gradle-wrapper.properties"
7 | override val content: String
8 | get() = """
9 | distributionBase=GRADLE_USER_HOME
10 | distributionPath=wrapper/dists
11 | distributionUrl=https\://services.gradle.org/distributions/gradle-$gradleVersion-bin.zip
12 | zipStoreBase=GRADLE_USER_HOME
13 | zipStorePath=wrapper/dists
14 | """.trimIndent()
15 | }
16 |
17 | class GradleWrapperJar : ProjectFile {
18 | override val path = "gradle/wrapper/gradle-wrapper.jar"
19 | override val content = "/* binary file */"
20 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_lang.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtSection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.*
4 |
5 | object WtSections : StyleSheet(AppStylesheet) {
6 |
7 | val wtSection by style {
8 | boxSizing("border-box")
9 | paddingBottom(96.px)
10 | paddingTop(1.px)
11 | property(
12 | propertyName = "padding-bottom",
13 | value = "calc(4*${AppCSSVariables.wtOffsetTopUnit.value(24.px)})"
14 | )
15 | backgroundColor(Color("#fff"))
16 | }
17 |
18 | val wtSectionBgGrayLight by style {
19 | backgroundColor(Color("#f4f4f4"))
20 | backgroundColor(AppCSSVariables.wtColorGreyLight.value())
21 | }
22 |
23 | val wtSectionBgGrayDark by style {
24 | backgroundColor(Color("#323236"))
25 | backgroundColor(AppCSSVariables.wtColorGreyDark.value())
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/jsMain/resources/ic_kotlin_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/src/jsMain/resources/filetree/src.css:
--------------------------------------------------------------------------------
1 | /* glue: 0.11.1 hash: ff145c7220 */
2 | .sprite-src-folder-c,
3 | .sprite-src-folder-o {
4 | background-image: url('icon.png');
5 | background-repeat: no-repeat;
6 | }
7 |
8 | .sprite-src-folder-c {
9 | background-position: 0 0;
10 | width: 33px;
11 | height: 33px;
12 | }
13 |
14 | .sprite-src-folder-o {
15 | background-position: 0 -33px;
16 | width: 30px;
17 | height: 30px;
18 | }
19 |
20 | @media screen and (-webkit-min-device-pixel-ratio: 1.0), screen and (min--moz-device-pixel-ratio: 1.0), screen and (-o-min-device-pixel-ratio: 100/100), screen and (min-device-pixel-ratio: 1.0), screen and (min-resolution: 1.0dppx) {
21 | .sprite-src-folder-c,
22 | .sprite-src-folder-o {
23 | background-image: url('icon.png');
24 | -webkit-background-size: 33px 63px;
25 | -moz-background-size: 33px 63px;
26 | background-size: 33px 63px;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtContainer.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.*
4 |
5 | object WtContainer : StyleSheet(AppStylesheet) {
6 | val wtContainer by style {
7 | property("margin-left", "auto")
8 | property("margin-right", "auto")
9 | boxSizing("border-box")
10 | paddingLeft(22.px)
11 | paddingRight(22.px)
12 | maxWidth(1276.px)
13 |
14 | media(mediaMaxWidth(640.px)) {
15 | self style {
16 | maxWidth(100.percent)
17 | paddingLeft(6.px)
18 | paddingRight(16.px)
19 | }
20 | }
21 |
22 | media(mediaMaxWidth(1276.px)) {
23 | self style {
24 | maxWidth(996.px)
25 | paddingLeft(2.px)
26 | paddingRight(22.px)
27 | }
28 | }
29 |
30 | media(mediaMaxWidth(1000.px)) {
31 | self style {
32 | maxWidth(100.percent)
33 | paddingLeft(2.px)
34 | paddingRight(22.px)
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtRow.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.*
4 |
5 | object WtRows : StyleSheet(AppStylesheet) {
6 |
7 | val wtRow by style {
8 | AppCSSVariables.wtHorizontalLayoutGutter(0.px)
9 | display(DisplayStyle.Flex)
10 | flexWrap(FlexWrap.Wrap)
11 |
12 | property(
13 | "margin-right",
14 | "calc(-1*${AppCSSVariables.wtHorizontalLayoutGutter.value()})"
15 | )
16 | property(
17 | "margin-left",
18 | "calc(-1*${AppCSSVariables.wtHorizontalLayoutGutter.value()})"
19 | )
20 | boxSizing("border-box")
21 | }
22 |
23 | val wtRowSizeM by style {
24 | AppCSSVariables.wtHorizontalLayoutGutter(16.px)
25 |
26 | media(mediaMaxWidth(640.px)) {
27 | self style {
28 | AppCSSVariables.wtHorizontalLayoutGutter(8.px)
29 | }
30 | }
31 | }
32 |
33 | val wtRowSizeXs by style {
34 | AppCSSVariables.wtHorizontalLayoutGutter(6.px)
35 | }
36 |
37 | val wtRowSmAlignItemsCenter by style {
38 | self style {
39 | alignItems(AlignItems.Center)
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/Header.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.attributes.ATarget
5 | import org.jetbrains.compose.web.attributes.target
6 | import org.jetbrains.compose.web.dom.A
7 | import org.jetbrains.compose.web.dom.Div
8 | import org.jetbrains.compose.web.dom.Section
9 | import org.jetbrains.webwiz.style.WtCols
10 | import org.jetbrains.webwiz.style.WtContainer
11 | import org.jetbrains.webwiz.style.WtRows
12 | import org.jetbrains.webwiz.style.WtSections
13 |
14 | @Composable
15 | fun Header() {
16 | Section(attrs = {
17 | classes(WtSections.wtSectionBgGrayDark)
18 | }) {
19 | Div({ classes(WtContainer.wtContainer) }) {
20 | Div({
21 | classes(WtRows.wtRow, WtRows.wtRowSizeM)
22 | }) {
23 | Logo()
24 | }
25 | }
26 | }
27 | }
28 |
29 | @Composable
30 | private fun Logo() {
31 | Div(attrs = {
32 | classes(WtCols.wtColInline)
33 | }) {
34 | A(attrs = {
35 | target(ATarget.Blank)
36 | }, href = "https://www.jetbrains.com/") {
37 | Div(attrs = {
38 | classes("jetbrains-logo", "_logo-jetbrains-square", "_size-3")
39 | }) {}
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/hljs.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * StackOverflow.com light style
3 | *
4 | * @stackoverflow/stacks v0.56.0
5 | * https://github.com/StackExchange/Stacks
6 | */
7 | .hljs {
8 | display: block;
9 | overflow-x: auto;
10 | padding: .5em;
11 | color: #2f3337;
12 | background: #f6f6f6
13 | }
14 |
15 | .hljs-comment {
16 | color: #656e77
17 | }
18 |
19 | .hljs-attr, .hljs-doctag, .hljs-keyword, .hljs-meta, .hljs-meta-keyword, .hljs-section, .hljs-selector-class, .hljs-selector-pseudo, .hljs-selector-tag {
20 | color: #015692;
21 | font-weight: bold;
22 | }
23 |
24 | .hljs-attribute {
25 | color: #803378
26 | }
27 |
28 | .hljs-built_in, .hljs-literal, .hljs-name, .hljs-number, .hljs-quote, .hljs-selector-id, .hljs-template-tag, .hljs-title, .hljs-type {
29 | color: #b75501
30 | }
31 |
32 | .hljs-title {
33 | font-style: italic;
34 | }
35 |
36 | .hljs-link, .hljs-meta-string, .hljs-regexp, .hljs-selector-attr, .hljs-string, .hljs-symbol, .hljs-template-variable, .hljs-variable {
37 | color: #54790d
38 | }
39 |
40 | .hljs-bullet, .hljs-code {
41 | color: #535a60
42 | }
43 |
44 | .hljs-deletion {
45 | color: #c02d2e
46 | }
47 |
48 | .hljs-addition {
49 | color: #2f6f44
50 | }
51 |
52 | .hljs-emphasis {
53 | font-style: italic
54 | }
55 |
56 | .hljs-strong {
57 | font-weight: 700
58 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/Targets.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | enum class Target(val targetName: String, val userName: String) {
4 | JVM("jvm", "JVM"),
5 | ANDROID("android", "Android"),
6 | JS("js", "JS"),
7 | IOS("ios", "iOS"),
8 | TV_OS("tvos", "tvOS"),
9 | WATCH_OS("watchos", "watchOS"),
10 | LINUX("linux", "Linux"),
11 | MACOS("macos", "macOS"),
12 | WINDOWS("windows", "Windows"),
13 | WASM("wasm", "WASM"),
14 | ANDROID_NATIVE("androidNative", "Android Native")
15 | }
16 |
17 | private val NativeTargets = setOf(
18 | Target.WASM,
19 | Target.ANDROID_NATIVE,
20 | Target.LINUX,
21 | Target.MACOS,
22 | Target.IOS,
23 | Target.TV_OS,
24 | Target.WATCH_OS,
25 | Target.WINDOWS
26 | )
27 |
28 | private val CommonNativeTargets = setOf(
29 | Target.LINUX,
30 | Target.MACOS,
31 | Target.IOS,
32 | Target.TV_OS,
33 | Target.WATCH_OS,
34 | Target.WINDOWS
35 | )
36 |
37 | fun Target.isJvm() = this in setOf(Target.JVM, Target.ANDROID)
38 |
39 | fun Set.isNativeTargetPresent() = this.any { it in NativeTargets }
40 | fun Set.isCommonNativeTargetPresent() = this.any { it in CommonNativeTargets }
41 | fun Set.isAndroidTargetPresent() = this.any { it == Target.ANDROID }
42 | fun Set.isJvmTargetPresent() = this.any { it.isJvm() }
43 |
--------------------------------------------------------------------------------
/src/jsMain/resources/filetree.css:
--------------------------------------------------------------------------------
1 | /**
2 | * filetree.css
3 | * */
4 |
5 | .filetree input[type="checkbox"] {
6 | display: none;
7 | }
8 |
9 | .filetree ul {
10 | height: 0;
11 | overflow: hidden;
12 | }
13 |
14 | .filetree > li input:checked ~ ul {
15 | height: auto;
16 | }
17 |
18 | .filetree li {
19 | list-style: none;
20 | }
21 |
22 | .filetree label {
23 | padding-left: 33px;
24 | line-height: 33px;
25 | display: inline-block;
26 | }
27 |
28 | /**
29 | * Icon
30 | * */
31 | .filetree label {
32 | background-image: url('./filetree/icon.png');
33 | background-repeat: no-repeat;
34 | }
35 |
36 | .filetree input[type="checkbox"] + label {
37 | background-position: 0 0;
38 | width: 33px;
39 | height: 33px;
40 | }
41 |
42 | .filetree input[type="checkbox"]:checked + label {
43 | background-position: 0 -33px;
44 | width: 30px;
45 | height: 30px;
46 | }
47 |
48 | @media screen and (-webkit-min-device-pixel-ratio: 1.0), screen and (min--moz-device-pixel-ratio: 1.0), screen and (-o-min-device-pixel-ratio: 100/100), screen and (min-device-pixel-ratio: 1.0), screen and (min-resolution: 1.0dppx) {
49 | filetree label {
50 | background-image: url('./filetree/icon.png');
51 | -webkit-background-size: 33px 63px;
52 | -moz-background-size: 33px 63px;
53 | background-size: 33px 63px;
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/SingleTargetLibrary.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | import org.jetbrains.webwiz.models.SourceSetType.MAIN
4 |
5 | enum class SingleTargetLibrary(
6 | val target: Target,
7 | val userName: String,
8 | val dep: String,
9 | val sourceSetType: SourceSetType
10 | ) {
11 | KTOR_CLIENT_IOS(
12 | Target.IOS,
13 | "Ktor iOS Client",
14 | "io.ktor:ktor-client-ios:1.6.7",
15 | MAIN
16 | ),
17 | KTOR_CLIENT_OKHTTP(
18 | Target.ANDROID,
19 | "Ktor OkHttp Client",
20 | "io.ktor:ktor-client-okhttp:1.6.7",
21 | MAIN
22 | ),
23 | KTOR_CLIENT_JVM(
24 | Target.JVM,
25 | "Ktor JVM Client",
26 | "io.ktor:ktor-client-jvm:1.6.7",
27 | MAIN
28 | ),
29 | KTOR_CLIENT_JS(
30 | Target.JS,
31 | "Ktor JS Client",
32 | "io.ktor:ktor-client-js:1.6.7",
33 | MAIN
34 | ),
35 | SQLDELIGHT_DRIVER_ANDROID(
36 | Target.ANDROID,
37 | "SQLDelight Android Driver",
38 | "com.squareup.sqldelight:android-driver:1.5.3",
39 | MAIN
40 | ),
41 | SQLDELIGHT_DRIVER_JVM(
42 | Target.JVM,
43 | "SQLDelight JVM Driver",
44 | "com.squareup.sqldelight:sqlite-driver:1.5.3",
45 | MAIN
46 | ),
47 | SQLDELIGHT_DRIVER_JS(
48 | Target.JS,
49 | "SQDelight JS Driver",
50 | "com.squareup.sqldelight:sqljs-driver:1.5.3",
51 | MAIN
52 | ),
53 | }
54 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/components/Layout.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.components
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.css.*
5 | import org.jetbrains.compose.web.dom.Div
6 | import org.jetbrains.compose.web.dom.Main
7 | import org.jetbrains.compose.web.dom.Section
8 | import org.jetbrains.webwiz.style.WtContainer
9 | import org.jetbrains.webwiz.style.WtOffsets
10 | import org.jetbrains.webwiz.style.WtSections
11 |
12 | @Composable
13 | fun Layout(content: @Composable () -> Unit) {
14 | Div({
15 | style {
16 | display(DisplayStyle.Flex)
17 | flexDirection(FlexDirection.Column)
18 | height(100.percent)
19 | margin(0.px)
20 | boxSizing("border-box")
21 | }
22 | }) {
23 | content()
24 | }
25 | }
26 |
27 | @Composable
28 | fun MainContentLayout(content: @Composable () -> Unit) {
29 | Main({
30 | style {
31 | flex("1 0 auto")
32 | boxSizing("border-box")
33 | }
34 | }) {
35 | content()
36 | }
37 | }
38 |
39 | @Composable
40 | fun ContainerInSection(sectionThemeStyleClass: String? = null, content: @Composable () -> Unit) {
41 | Section({
42 | if (sectionThemeStyleClass != null) {
43 | classes(WtSections.wtSection, sectionThemeStyleClass)
44 | } else {
45 | classes(WtSections.wtSection)
46 | }
47 | }) {
48 | Div({
49 | classes(WtContainer.wtContainer, WtOffsets.wtTopOffset96)
50 | }) {
51 | content()
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/PlatformKt.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 | import org.jetbrains.webwiz.models.ProjectInfo
5 | import org.jetbrains.webwiz.models.Target
6 |
7 | class CommonPlatformKt(val projectInfo: ProjectInfo) : ProjectFile {
8 | override val path = "${projectInfo.moduleName}/src/commonMain/kotlin" +
9 | "/${projectInfo.packageName.replace('.', '/')}" +
10 | "/Platform.kt"
11 | override val content: String
12 | get() = """
13 | package ${projectInfo.packageName}
14 |
15 | expect val platform: String
16 |
17 | class Greeting {
18 | fun greeting() = "Hello, ${'$'}platform!"
19 | }
20 | """.trimIndent()
21 | }
22 |
23 | class TargetPlatformKt(val target: Target, val projectInfo: ProjectInfo) : ProjectFile {
24 | override val path = "${projectInfo.moduleName}/src/${target.targetName}Main/kotlin" +
25 | "/${projectInfo.packageName.replace('.', '/')}" +
26 | "/Platform.kt"
27 | override val content: String
28 | get() = """
29 | package ${projectInfo.packageName}
30 |
31 | actual val platform: String = "${target.targetName}"
32 | """.trimIndent()
33 | }
34 |
35 | class IntermediatePlatformKt(val intermediateName: String, val projectInfo: ProjectInfo) : ProjectFile {
36 | override val path = "${projectInfo.moduleName}/src/${intermediateName}Main/kotlin" +
37 | "/${projectInfo.packageName.replace('.', '/')}" +
38 | "/Platform.kt"
39 | override val content: String
40 | get() = """
41 | package ${projectInfo.packageName}
42 |
43 | """.trimIndent()
44 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/ProjectInfo.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | data class ProjectInfo(
4 | val projectName: String,
5 | val moduleName: String,
6 | val packageName: String,
7 | val kotlinVersion: KotlinVersion,
8 | val targets: Set,
9 | val dependencies: Set,
10 | val singleTargetDependencies: Set,
11 | val nativeTargetLibraries: Set,
12 | val gradlePlugins: Set,
13 | val enableTests: Boolean
14 | ) {
15 | fun validate() {
16 | require(!moduleName.contains(' ')) {
17 | "module name contains space character"
18 | }
19 | require(gradlePlugins.all { it.canBeApplied(targets) }) {
20 | "incorrect gradle plugin was used for current set of targets"
21 | }
22 | require(dependencies.all { dep -> dep.targets == null || targets.all { dep.targets.contains(it) } }) {
23 | "incorrect dependency was used for current set of targets"
24 | }
25 | require(singleTargetDependencies.all { dep -> dep.target in targets}) {
26 | "incorrect dependency was used for current set of targets"
27 | }
28 | }
29 |
30 | fun normalize() = copy(
31 | moduleName = moduleName.replace(' ', '_'),
32 | gradlePlugins = gradlePlugins.filter { it.canBeApplied(targets) }.toSet(),
33 | dependencies = dependencies
34 | .filter { dep -> dep.targets == null || targets.all { dep.targets.contains(it) } }.toSet(),
35 | singleTargetDependencies = singleTargetDependencies
36 | .filter { dep -> dep.target in targets }.toSet(),
37 | nativeTargetLibraries = if (this.targets.isNativeTargetPresent()) nativeTargetLibraries else emptySet()
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/RootBuildGradle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.NAN
4 | import org.jetbrains.webwiz.generator.ProjectFile
5 | import org.jetbrains.webwiz.generator.deleteNans
6 | import org.jetbrains.webwiz.models.GradlePlugin
7 | import org.jetbrains.webwiz.models.KmpLibrary
8 | import org.jetbrains.webwiz.models.KotlinVersion
9 | import org.jetbrains.webwiz.models.ProjectInfo
10 | import org.jetbrains.webwiz.models.Target
11 |
12 | class RootBuildGradle(val projectInfo: ProjectInfo) : ProjectFile {
13 | override val path = "build.gradle.kts"
14 | override val content: String
15 | get() =
16 | """
17 | buildscript {
18 | repositories {
19 | gradlePluginPortal()
20 | google()
21 | mavenCentral()
22 | ${if (projectInfo.kotlinVersion == KotlinVersion.Dev) "maven(\"https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/\")" else NAN}
23 | }
24 | dependencies {
25 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${projectInfo.kotlinVersion.versionName}")
26 | ${if (projectInfo.dependencies.contains(KmpLibrary.SERIALIZATION)) "classpath(\"org.jetbrains.kotlin:kotlin-serialization:${projectInfo.kotlinVersion.versionName}\")" else NAN}
27 | ${if (projectInfo.targets.contains(Target.ANDROID)) "classpath(\"com.android.tools.build:gradle:7.0.2\")" else NAN}
28 | ${if (GradlePlugin.SQL_DELIGHT in projectInfo.gradlePlugins) "classpath(\"com.squareup.sqldelight:gradle-plugin:1.5.3\")" else NAN}
29 | }
30 | }
31 |
32 | allprojects {
33 | repositories {
34 | google()
35 | mavenCentral()
36 | ${if (projectInfo.kotlinVersion == KotlinVersion.Dev) "maven(\"https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/\")" else NAN}
37 | }
38 | }
39 | """.trimIndent().deleteNans()
40 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/generator.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator
2 |
3 | import org.jetbrains.webwiz.generator.files.*
4 | import org.jetbrains.webwiz.models.GradlePlugin
5 | import org.jetbrains.webwiz.models.ProjectInfo
6 | import org.jetbrains.webwiz.models.Target.ANDROID
7 | import org.jetbrains.webwiz.models.isNativeTargetPresent
8 |
9 | interface ProjectFile {
10 | val path: String
11 | val content: String
12 | }
13 |
14 | fun ProjectInfo.generate(): List = mutableListOf().apply {
15 | val info = this@generate.normalize()
16 |
17 | add(Gitignore())
18 | add(Gradlew())
19 | add(GradleBat())
20 | add(GradleWrapperProperties("7.3"))
21 | add(GradleWrapperJar())
22 |
23 | add(RootBuildGradle(info))
24 | add(SettingsGradle(projectName, moduleName))
25 | add(GradleProperties())
26 |
27 | add(ModuleBuildGradle(info))
28 |
29 | add(CommonPlatformKt(info))
30 | info.targets.forEach { target ->
31 | add(TargetPlatformKt(target, info))
32 | }
33 | if (info.targets.isNativeTargetPresent()) {
34 | add(IntermediatePlatformKt("native", info))
35 | }
36 |
37 | if (info.gradlePlugins.contains(GradlePlugin.APPLICATION)) {
38 | add(ApplicationKt(info))
39 | }
40 |
41 | if (info.targets.contains(ANDROID)) {
42 | add(AndroidManifestXml(info))
43 | }
44 |
45 | if (info.enableTests) {
46 | add(CommonPlatformTestKt(info))
47 | info.targets.forEach { target ->
48 | add(TargetPlatformTestKt(target, info))
49 | }
50 | if (info.targets.isNativeTargetPresent()) {
51 | add(IntermediatePlatformTestKt("native", info))
52 | }
53 | }
54 | }
55 |
56 | internal const val NAN = "®®®"
57 | internal fun String.deleteNans(): String =
58 | lines().filter { !it.contains(NAN) }.joinToString("\n")
59 |
60 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/Main.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.browser.window
2 | import org.jetbrains.compose.common.foundation.layout.Box
3 | import org.jetbrains.compose.common.ui.ExperimentalComposeWebWidgetsApi
4 | import org.jetbrains.compose.web.css.Style
5 | import org.jetbrains.compose.web.renderComposable
6 | import org.jetbrains.webwiz.FileSaverJs
7 | import org.jetbrains.webwiz.JSZip
8 | import org.jetbrains.webwiz.components.Layout
9 | import org.jetbrains.webwiz.components.MainContentLayout
10 | import org.jetbrains.webwiz.content.Header
11 | import org.jetbrains.webwiz.content.Intro
12 | import org.jetbrains.webwiz.content.PageFooter
13 | import org.jetbrains.webwiz.content.WizardSection
14 | import org.jetbrains.webwiz.generator.files.GradleWrapperJar
15 | import org.jetbrains.webwiz.generator.files.Gradlew
16 | import org.jetbrains.webwiz.generator.generate
17 | import org.jetbrains.webwiz.models.ProjectInfo
18 | import org.jetbrains.webwiz.style.AppStylesheet
19 | import org.w3c.files.Blob
20 |
21 | @OptIn(ExperimentalComposeWebWidgetsApi::class)
22 | fun main() {
23 | renderComposable(rootElementId = "root") {
24 | Box {
25 | Style(AppStylesheet)
26 |
27 | Layout {
28 | Header()
29 | MainContentLayout {
30 | Intro()
31 | WizardSection { generateProject(it) }
32 | }
33 | PageFooter()
34 | }
35 | }
36 | }
37 | }
38 |
39 | private fun generateProject(project: ProjectInfo) {
40 | window.fetch("./binaries/gradle-wrapper")
41 | .then { response -> response.arrayBuffer() }
42 | .then { gradleWrapperBlob ->
43 | val zip = JSZip()
44 | project.generate().forEach { file ->
45 | when (file) {
46 | is GradleWrapperJar -> zip.file(
47 | file.path,
48 | gradleWrapperBlob
49 | )
50 | is Gradlew -> zip.file(
51 | file.path,
52 | file.content,
53 | js("""{unixPermissions:"774"}""") //execution rights
54 | )
55 | else -> zip.file(
56 | file.path,
57 | file.content
58 | )
59 | }
60 | }
61 | //execution rights require UNIX mode
62 | zip.generateAsync(js("""{type:"blob",platform:"UNIX"}""")).then { blob ->
63 | FileSaverJs.saveAs(blob, "${project.projectName}.zip")
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/IntroSection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.attributes.ATarget
5 | import org.jetbrains.compose.web.attributes.target
6 | import org.jetbrains.compose.web.css.*
7 | import org.jetbrains.compose.web.dom.A
8 | import org.jetbrains.compose.web.dom.Div
9 | import org.jetbrains.compose.web.dom.H1
10 | import org.jetbrains.compose.web.dom.Img
11 | import org.jetbrains.compose.web.dom.P
12 | import org.jetbrains.compose.web.dom.Text
13 | import org.jetbrains.webwiz.components.ContainerInSection
14 | import org.jetbrains.webwiz.style.AppStylesheet
15 | import org.jetbrains.webwiz.style.WtCols
16 | import org.jetbrains.webwiz.style.WtOffsets
17 | import org.jetbrains.webwiz.style.WtRows
18 | import org.jetbrains.webwiz.style.WtTexts
19 |
20 | @Composable
21 | fun Intro() {
22 | ContainerInSection {
23 | Div({
24 | classes(WtRows.wtRow, WtRows.wtRowSizeM, WtRows.wtRowSmAlignItemsCenter)
25 | }) {
26 |
27 | Div({
28 | classes(WtCols.wtCol2, WtCols.wtColMd3)
29 | style {
30 | alignSelf(AlignSelf.Start)
31 | }
32 | }) {
33 | Img(src = "ic_kotlin_logo.svg", attrs = { classes(AppStylesheet.composeLogo) })
34 | }
35 |
36 | Div({
37 | classes(
38 | WtCols.wtCol10,
39 | WtCols.wtColMd8,
40 | WtCols.wtColSm12,
41 | WtOffsets.wtTopOffsetSm12
42 | )
43 | }) {
44 | H1(attrs = { classes(WtTexts.wtHero) }) {
45 | Text("Kotlin Multiplatform Wizard")
46 | }
47 | Div {
48 | IntroAboutKMP()
49 | }
50 | }
51 | }
52 |
53 | }
54 | }
55 |
56 | @Composable
57 | private fun IntroAboutKMP() {
58 | Div({
59 | classes(WtRows.wtRow, WtRows.wtRowSizeM)
60 | }) {
61 | Div({
62 | classes(WtCols.wtCol9, WtCols.wtColMd9, WtCols.wtColSm12)
63 | }) {
64 | P({ classes(WtTexts.wtSubtitle2, WtOffsets.wtTopOffset24) }) {
65 | Text("Support for multiplatform programming is one of Kotlin’s key benefits. ")
66 |
67 | Text("Learn more about ")
68 |
69 | A(href = "https://kotlinlang.org/docs/multiplatform.html", attrs = {
70 | classes(WtTexts.wtLink)
71 | target(ATarget.Blank)
72 | }) {
73 | Text("Kotlin Multiplatform benefits")
74 | }
75 | }
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/Stylesheet.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.*
4 | import org.jetbrains.compose.web.css.selectors.CSSSelector
5 |
6 | object AppCSSVariables {
7 | val wtColorGreyLight by variable()
8 | val wtColorGreyDark by variable()
9 |
10 | val wtOffsetTopUnit by variable()
11 | val wtHorizontalLayoutGutter by variable()
12 | val wtFlowUnit by variable()
13 |
14 | val wtHeroFontSize by variable()
15 | val wtHeroLineHeight by variable()
16 | val wtSubtitle2FontSize by variable()
17 | val wtSubtitle2LineHeight by variable()
18 | val wtH2FontSize by variable()
19 | val wtH2LineHeight by variable()
20 | val wtH3FontSize by variable()
21 | val wtH3LineHeight by variable()
22 |
23 | val wtColCount by variable()
24 | }
25 |
26 |
27 | object AppStylesheet : StyleSheet() {
28 | val composeLogo by style {
29 | maxWidth(100.percent)
30 | }
31 |
32 | init {
33 | "label, a, button" style {
34 | property(
35 | "font-family",
36 | "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
37 | )
38 | }
39 |
40 | CSSSelector.Universal style {
41 | AppCSSVariables.wtColorGreyLight(Color("#f4f4f4"))
42 | AppCSSVariables.wtColorGreyDark(Color("#323236"))
43 | AppCSSVariables.wtOffsetTopUnit(24.px)
44 |
45 | margin(0.px)
46 | }
47 |
48 | media(mediaMaxWidth(640.px)) {
49 | CSSSelector.Universal style {
50 | AppCSSVariables.wtOffsetTopUnit(16.px)
51 | AppCSSVariables.wtFlowUnit(16.px)
52 | }
53 | }
54 |
55 | CSSSelector.Attribute(
56 | name = "class",
57 | value = "wtCol",
58 | operator = CSSSelector.Attribute.Operator.Contains
59 | ) style {
60 | marginRight(AppCSSVariables.wtHorizontalLayoutGutter.value())
61 | marginLeft(AppCSSVariables.wtHorizontalLayoutGutter.value())
62 |
63 | property(
64 | "flex-basis",
65 | "calc(8.33333%*${AppCSSVariables.wtColCount.value()} - ${AppCSSVariables.wtHorizontalLayoutGutter.value()}*2)"
66 | )
67 | property(
68 | "max-width",
69 | "calc(8.33333%*${AppCSSVariables.wtColCount.value()} - ${AppCSSVariables.wtHorizontalLayoutGutter.value()}*2)"
70 | )
71 | boxSizing("border-box")
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/PlatformTestKt.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 | import org.jetbrains.webwiz.models.ProjectInfo
5 | import org.jetbrains.webwiz.models.Target
6 | import org.jetbrains.webwiz.models.isJvm
7 |
8 | class CommonPlatformTestKt(val projectInfo: ProjectInfo) : ProjectFile {
9 | override val path = "${projectInfo.moduleName}/src/commonTest/kotlin" +
10 | "/${projectInfo.packageName.replace('.', '/')}" +
11 | "/CommonTest.kt"
12 | override val content: String
13 | get() = """
14 | package ${projectInfo.packageName}
15 |
16 | import kotlin.test.Test
17 | import kotlin.test.assertTrue
18 |
19 | class CommonTest {
20 |
21 | @Test
22 | fun testExample() {
23 | assertTrue(Greeting().greeting().contains("Hello"), "Check 'Hello' is mentioned")
24 | }
25 | }
26 | """.trimIndent()
27 | }
28 |
29 | class TargetPlatformTestKt(val target: Target, val projectInfo: ProjectInfo) :
30 | ProjectFile {
31 | override val path = "${projectInfo.moduleName}/src/${target.targetName}Test/kotlin" +
32 | "/${projectInfo.packageName.replace('.', '/')}" +
33 | "/PlatformTest.kt"
34 | override val content: String = if (target.isJvm()) {
35 | """
36 | package ${projectInfo.packageName}
37 |
38 | import org.junit.Assert.assertTrue
39 | import org.junit.Test
40 |
41 | class PlatformTest {
42 |
43 | @Test
44 | fun testExample() {
45 | assertTrue("Check ${target.targetName} is mentioned", Greeting().greeting().contains("${target.targetName}"))
46 | }
47 | }
48 | """.trimIndent()
49 | } else {
50 | """
51 | package ${projectInfo.packageName}
52 |
53 | import kotlin.test.Test
54 | import kotlin.test.assertTrue
55 |
56 | class PlatformTest {
57 |
58 | @Test
59 | fun testExample() {
60 | assertTrue(Greeting().greeting().contains("${target.targetName}"), "Check ${target.targetName} is mentioned")
61 | }
62 | }
63 | """.trimIndent()
64 | }
65 | }
66 |
67 | class IntermediatePlatformTestKt(
68 | val intermediateName: String,
69 | val projectInfo: ProjectInfo
70 | ) : ProjectFile {
71 | private val interName = intermediateName.lowercase().replaceFirstChar { it.uppercaseChar() }
72 |
73 | override val path = "${projectInfo.moduleName}/src/${intermediateName.lowercase()}Test/kotlin" +
74 | "/${projectInfo.packageName.replace('.', '/')}" +
75 | "/${interName}Test.kt"
76 | override val content: String
77 | get() = """
78 | package ${projectInfo.packageName}
79 |
80 | import kotlin.test.Test
81 | import kotlin.test.assertTrue
82 |
83 | class ${interName}Test {
84 |
85 | @Test
86 | fun testExample() {
87 | assertTrue(Greeting().greeting().contains("Hello"), "Check 'Hello' is mentioned")
88 | }
89 | }
90 | """.trimIndent()
91 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/CodeSamplesSwitcher.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.attributes.InputType
5 | import org.jetbrains.compose.web.attributes.name
6 | import org.jetbrains.compose.web.css.*
7 | import org.jetbrains.compose.web.css.selectors.CSSSelector
8 | import org.jetbrains.compose.web.css.selectors.descendant
9 | import org.jetbrains.compose.web.css.selectors.selector
10 | import org.jetbrains.compose.web.dom.Form
11 | import org.jetbrains.compose.web.dom.Input
12 | import org.jetbrains.compose.web.dom.Label
13 | import org.jetbrains.compose.web.dom.Text
14 | import org.jetbrains.webwiz.models.KotlinVersion
15 | import org.jetbrains.webwiz.style.AppStylesheet
16 |
17 | private object SwitcherVariables {
18 | val labelWidth by variable()
19 | val labelPadding by variable()
20 | }
21 |
22 | @Composable
23 | fun KotlinVersionSwitcher(state: KotlinVersion, onSelect: (KotlinVersion) -> Unit) {
24 | Form(attrs = {
25 | classes(KotlinSwitcherStylesheet.boxed)
26 | }) {
27 | KotlinVersion.values().filter { it != KotlinVersion.Dev }.forEach { version ->
28 | Input(type = InputType.Radio, attrs = {
29 | name("code-snippet")
30 | value("snippet$version")
31 | id("snippet$version")
32 | checked(version == state)
33 | onClick { onSelect(version) }
34 | })
35 | Label(forId = "snippet$version") { Text("${version.name}") }
36 | }
37 | }
38 | }
39 |
40 |
41 | object KotlinSwitcherStylesheet : StyleSheet(AppStylesheet) {
42 | val boxed by style {
43 |
44 | backgroundColor(Color("rgb(244,244,244)"))
45 |
46 | descendant(self, CSSSelector.Type("label")) style {
47 | display(DisplayStyle.InlineBlock)
48 | width(SwitcherVariables.labelWidth.value(100.px))
49 | padding(SwitcherVariables.labelPadding.value(5.px))
50 | property("transition", "all 0.3s")
51 | textAlign("center")
52 | boxSizing("border-box")
53 |
54 | border {
55 | style(LineStyle.Solid)
56 | width(3.px)
57 | color(Color("transparent"))
58 | borderRadius(20.px, 20.px, 20.px)
59 | }
60 |
61 | }
62 |
63 | border {
64 | style(LineStyle.Solid)
65 | width(0.px)
66 | color(Color("#aaa"))
67 | padding(0.px)
68 | borderRadius(22.px, 22.px, 22.px)
69 | }
70 |
71 | descendant(self, selector("input[type=\"radio\"]")) style {
72 | display(DisplayStyle.None)
73 |
74 | }
75 |
76 | descendant(self, selector("input[type=\"radio\"]:checked + label")) style {
77 | border {
78 | style(LineStyle.Solid)
79 | width(3.px)
80 | color(Color("#167dff"))
81 | property("background-color", "#167dff")
82 | borderRadius(20.px, 20.px, 20.px)
83 | }
84 | color(Color("white"))
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/i1.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/GradleBat.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class GradleBat : ProjectFile {
6 | override val path = "gradle.bat"
7 | override val content: String
8 | get() = """
9 | @rem
10 | @rem Copyright 2015 the original author or authors.
11 | @rem
12 | @rem Licensed under the Apache License, Version 2.0 (the "License");
13 | @rem you may not use this file except in compliance with the License.
14 | @rem You may obtain a copy of the License at
15 | @rem
16 | @rem https://www.apache.org/licenses/LICENSE-2.0
17 | @rem
18 | @rem Unless required by applicable law or agreed to in writing, software
19 | @rem distributed under the License is distributed on an "AS IS" BASIS,
20 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | @rem See the License for the specific language governing permissions and
22 | @rem limitations under the License.
23 | @rem
24 |
25 | @if "%DEBUG%" == "" @echo off
26 | @rem ##########################################################################
27 | @rem
28 | @rem Gradle startup script for Windows
29 | @rem
30 | @rem ##########################################################################
31 |
32 | @rem Set local scope for the variables with windows NT shell
33 | if "%OS%"=="Windows_NT" setlocal
34 |
35 | set DIRNAME=%~dp0
36 | if "%DIRNAME%" == "" set DIRNAME=.
37 | set APP_BASE_NAME=%~n0
38 | set APP_HOME=%DIRNAME%
39 |
40 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
41 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
42 |
43 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
44 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
45 |
46 | @rem Find java.exe
47 | if defined JAVA_HOME goto findJavaFromJavaHome
48 |
49 | set JAVA_EXE=java.exe
50 | %JAVA_EXE% -version >NUL 2>&1
51 | if "%ERRORLEVEL%" == "0" goto execute
52 |
53 | echo.
54 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
55 | echo.
56 | echo Please set the JAVA_HOME variable in your environment to match the
57 | echo location of your Java installation.
58 |
59 | goto fail
60 |
61 | :findJavaFromJavaHome
62 | set JAVA_HOME=%JAVA_HOME:"=%
63 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
64 |
65 | if exist "%JAVA_EXE%" goto execute
66 |
67 | echo.
68 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
69 | echo.
70 | echo Please set the JAVA_HOME variable in your environment to match the
71 | echo location of your Java installation.
72 |
73 | goto fail
74 |
75 | :execute
76 | @rem Setup the command line
77 |
78 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
79 |
80 |
81 | @rem Execute Gradle
82 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
83 |
84 | :end
85 | @rem End local scope for the variables with windows NT shell
86 | if "%ERRORLEVEL%"=="0" goto mainEnd
87 |
88 | :fail
89 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
90 | rem the _cmd.exe /c_ return code!
91 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
92 | exit /b 1
93 |
94 | :mainEnd
95 | if "%OS%"=="Windows_NT" endlocal
96 |
97 | :omega
98 | """.trimIndent()
99 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/models/KmpLibraries.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.models
2 |
3 | import org.jetbrains.webwiz.models.SourceSetType.MAIN
4 |
5 | enum class KmpLibrary(
6 | val targets: Set?, //null means any target
7 | val userName: String,
8 | val dep: String,
9 | val sourceSetType: SourceSetType
10 | ) {
11 | COROUTINES(
12 | setOf(
13 | Target.ANDROID,
14 | Target.JVM,
15 | Target.JS,
16 | Target.MACOS,
17 | Target.IOS,
18 | Target.TV_OS,
19 | Target.WATCH_OS,
20 | Target.LINUX,
21 | Target.WINDOWS
22 | ),
23 | "KotlinX Coroutines",
24 | "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2",
25 | MAIN
26 | ),
27 | SERIALIZATION(
28 | setOf(
29 | Target.ANDROID,
30 | Target.JVM,
31 | Target.JS,
32 | Target.MACOS,
33 | Target.IOS,
34 | Target.TV_OS,
35 | Target.WATCH_OS,
36 | Target.LINUX,
37 | Target.WINDOWS
38 | ),
39 | "KotlinX Serialization",
40 | "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1",
41 | MAIN
42 | ),
43 | DATE_TIME(
44 | setOf(
45 | Target.ANDROID,
46 | Target.JVM,
47 | Target.JS,
48 | Target.MACOS,
49 | Target.IOS,
50 | Target.TV_OS,
51 | Target.WATCH_OS,
52 | Target.LINUX,
53 | Target.WINDOWS
54 | ),
55 | "KotlinX DateTime",
56 | "org.jetbrains.kotlinx:kotlinx-datetime:0.3.1",
57 | MAIN
58 | ),
59 | KERMIT_LOGGER(
60 | setOf(
61 | Target.ANDROID,
62 | Target.JVM,
63 | Target.JS,
64 | Target.MACOS,
65 | Target.IOS,
66 | Target.TV_OS,
67 | Target.WATCH_OS,
68 | Target.LINUX,
69 | Target.WINDOWS
70 | ),
71 | "Kermit Logger",
72 | "co.touchlab:kermit:1.0.0",
73 | MAIN
74 | ),
75 | NAPIER_LOGGER(
76 | setOf(
77 | Target.ANDROID,
78 | Target.JVM,
79 | Target.JS,
80 | Target.MACOS,
81 | Target.IOS,
82 | Target.TV_OS,
83 | Target.WATCH_OS
84 | ),
85 | "Napier logger",
86 | "io.github.aakira:napier:2.1.0",
87 | MAIN
88 | ),
89 | SQLDELIGHT_COROUTINES(
90 | setOf(
91 | Target.ANDROID,
92 | Target.JVM,
93 | Target.JS,
94 | Target.IOS,
95 | Target.LINUX,
96 | Target.MACOS,
97 | Target.WINDOWS,
98 | Target.TV_OS,
99 | Target.WATCH_OS
100 | ),
101 | "SQLDelight Coroutines",
102 | "com.squareup.sqldelight:coroutines-extensions:1.5.3",
103 | MAIN
104 | ),
105 | KTOR_CORE(
106 | setOf(
107 | Target.JVM,
108 | Target.ANDROID,
109 | Target.JS,
110 | Target.IOS,
111 | Target.LINUX,
112 | Target.MACOS,
113 | Target.WINDOWS
114 | ),
115 | "Ktor Core",
116 | "io.ktor:ktor-client-core:1.6.7",
117 | MAIN
118 | ),
119 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtCol.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.CSSBuilder
4 | import org.jetbrains.compose.web.css.CSSUnitValue
5 | import org.jetbrains.compose.web.css.GenericStyleSheetBuilder
6 | import org.jetbrains.compose.web.css.StyleSheet
7 | import org.jetbrains.compose.web.css.flexGrow
8 | import org.jetbrains.compose.web.css.maxWidth
9 | import org.jetbrains.compose.web.css.media
10 | import org.jetbrains.compose.web.css.percent
11 | import org.jetbrains.compose.web.css.px
12 | import org.jetbrains.compose.web.css.mediaMaxWidth
13 | import org.jetbrains.compose.web.css.selectors.CSSSelector
14 |
15 | fun GenericStyleSheetBuilder.mediaMaxWidth(
16 | value: CSSUnitValue,
17 | cssSelector: CSSSelector,
18 | rulesBuild: TBuilder.() -> Unit
19 | ) {
20 | media(mediaMaxWidth(value)) {
21 | cssSelector style rulesBuild
22 | }
23 | }
24 |
25 | fun CSSBuilder.forMaxWidth(value: CSSUnitValue, builder: CSSBuilder.() -> Unit) {
26 | mediaMaxWidth(value, self, builder)
27 | }
28 |
29 | object WtCols : StyleSheet(AppStylesheet) {
30 | val wtCol2 by style {
31 | AppCSSVariables.wtColCount(2)
32 | }
33 |
34 | val wtCol3 by style {
35 | AppCSSVariables.wtColCount(3)
36 | }
37 |
38 | val wtCol4 by style {
39 | AppCSSVariables.wtColCount(4)
40 | }
41 |
42 | val wtCol5 by style {
43 | AppCSSVariables.wtColCount(5)
44 | }
45 |
46 | val wtCol6 by style {
47 | AppCSSVariables.wtColCount(6)
48 | }
49 |
50 | val wtCol9 by style {
51 | AppCSSVariables.wtColCount(9)
52 | }
53 |
54 | val wtCol10 by style {
55 | AppCSSVariables.wtColCount(10)
56 | }
57 |
58 | val wtColMd3 by style {
59 | forMaxWidth(1000.px) {
60 | AppCSSVariables.wtColCount(3)
61 | }
62 | }
63 |
64 | val wtColMd4 by style {
65 | forMaxWidth(1000.px) {
66 | AppCSSVariables.wtColCount(4)
67 | }
68 | }
69 |
70 | val wtColMd8 by style {
71 | forMaxWidth(1000.px) {
72 | AppCSSVariables.wtColCount(8)
73 | }
74 | }
75 |
76 | val wtColMd9 by style {
77 | forMaxWidth(1000.px) {
78 | AppCSSVariables.wtColCount(9)
79 | }
80 | }
81 |
82 | val wtColMd10 by style {
83 | forMaxWidth(1000.px) {
84 | AppCSSVariables.wtColCount(10)
85 | }
86 | }
87 |
88 | val wtColMd11 by style {
89 | forMaxWidth(1000.px) {
90 | AppCSSVariables.wtColCount(11)
91 | }
92 | }
93 |
94 | val wtColMd6 by style {
95 | forMaxWidth(1000.px) {
96 | AppCSSVariables.wtColCount(6)
97 | }
98 | }
99 |
100 | val wtColMd12 by style {
101 | forMaxWidth(1000.px) {
102 | AppCSSVariables.wtColCount(12)
103 | }
104 | }
105 |
106 | val wtColSm12 by style {
107 | forMaxWidth(640.px) {
108 | AppCSSVariables.wtColCount(12)
109 | }
110 | }
111 |
112 | val wtColLg6 by style {
113 | forMaxWidth(1276.px) {
114 | AppCSSVariables.wtColCount(6)
115 | }
116 | }
117 |
118 | val wtColSmAutoFill by style {
119 | forMaxWidth(640.px) {
120 | AppCSSVariables.wtColCount(0)
121 | flexGrow(1)
122 | maxWidth(100.percent)
123 | }
124 | }
125 |
126 | val wtColAutoFill by style {
127 | AppCSSVariables.wtColCount(0)
128 | flexGrow(1)
129 | maxWidth(100.percent)
130 | }
131 |
132 | val wtColInline by style {
133 | AppCSSVariables.wtColCount(0)
134 | maxWidth(100.percent)
135 | property("flex-basis", "auto")
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/Footer.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.attributes.ATarget
5 | import org.jetbrains.compose.web.attributes.target
6 | import org.jetbrains.compose.web.css.*
7 | import org.jetbrains.compose.web.dom.*
8 | import org.jetbrains.webwiz.style.*
9 |
10 |
11 | @Composable
12 | fun PageFooter() {
13 | Footer({
14 | style {
15 | flexShrink(0)
16 | boxSizing("border-box")
17 | }
18 | }) {
19 | Section({
20 | classes(WtSections.wtSectionBgGrayDark)
21 | style {
22 | padding(24.px, 0.px)
23 | }
24 | }) {
25 | Div({ classes(WtContainer.wtContainer) }) {
26 | Div({
27 | classes(WtRows.wtRow, WtRows.wtRowSizeM, WtRows.wtRowSmAlignItemsCenter)
28 | style {
29 | justifyContent(JustifyContent.Center)
30 | flexWrap(FlexWrap.Wrap)
31 | }
32 | }) {
33 |
34 | Div({
35 | classes(WtCols.wtColInline)
36 | }) {
37 | P({
38 | classes(WtTexts.wtText1, WtTexts.wtText1ThemeDark)
39 | }) {
40 | Text("Follow us")
41 | }
42 | }
43 |
44 | Div({
45 | classes(WtCols.wtColInline)
46 | }) {
47 | getSocialLinks().forEach { SocialIconLink(it) }
48 | }
49 | }
50 |
51 | CopyrightInFooter()
52 | }
53 | }
54 | }
55 | }
56 |
57 | @Composable
58 | private fun CopyrightInFooter() {
59 | Div({
60 | classes(WtRows.wtRow, WtRows.wtRowSizeM, WtRows.wtRowSmAlignItemsCenter, WtOffsets.wtTopOffset48)
61 | style {
62 | justifyContent(JustifyContent.SpaceEvenly)
63 | flexWrap(FlexWrap.Wrap)
64 | padding(0.px, 12.px)
65 | }
66 | }) {
67 | Span({
68 | classes(WtTexts.wtText3, WtTexts.wtTextPale)
69 | }) {
70 | Text("Copyright © 2000-2021 JetBrains s.r.o.")
71 | }
72 |
73 | Span({
74 | classes(WtTexts.wtText3, WtTexts.wtTextPale)
75 | }) {
76 | Text("Developed with drive and IntelliJ IDEA")
77 | }
78 | }
79 | }
80 |
81 | @Composable
82 | private fun SocialIconLink(link: SocialLink) {
83 | A(attrs = {
84 | classes(WtTexts.wtSocialButtonItem)
85 | target(ATarget.Blank)
86 | }, href = link.url) {
87 | Img(src = link.iconSvg) {}
88 | }
89 | }
90 |
91 | private data class SocialLink(
92 | val id: String,
93 | val url: String,
94 | val title: String,
95 | val iconSvg: String
96 | )
97 |
98 | private fun getSocialLinks(): List {
99 | return listOf(
100 | SocialLink("facebook", "https://www.facebook.com/JetBrains", "JetBrains on Facebook", "ic_fb.svg"),
101 | SocialLink("twitter", "https://twitter.com/jetbrains", "JetBrains on Twitter", "ic_twitter.svg"),
102 | SocialLink(
103 | "linkedin",
104 | "https://www.linkedin.com/company/jetbrains",
105 | "JetBrains on Linkedin",
106 | "ic_linkedin.svg"
107 | ),
108 | SocialLink("youtube", "https://www.youtube.com/user/JetBrainsTV", "JetBrains on YouTube", "ic_youtube.svg"),
109 | SocialLink("instagram", "https://www.instagram.com/jetbrains/", "JetBrains on Instagram", "ic_insta.svg"),
110 | SocialLink("blog", "https://blog.jetbrains.com/", "JetBrains blog", "ic_jb_blog.svg"),
111 | SocialLink("rss", "https://blog.jetbrains.com/feed/", "JetBrains RSS Feed", "ic_feed.svg"),
112 | )
113 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtOffest.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.ExperimentalComposeWebApi
4 | import org.jetbrains.compose.web.css.*
5 | import org.jetbrains.compose.web.css.selectors.descendant
6 | import org.jetbrains.compose.web.css.selectors.selector
7 |
8 | object WtOffsets : StyleSheet(AppStylesheet) {
9 | val wtTopOffset96 by style {
10 | marginTop(96.px)
11 | property(
12 | "margin-top",
13 | "calc(4*${AppCSSVariables.wtOffsetTopUnit.value(24.px)})"
14 | )
15 | }
16 |
17 | val wtTopOffset24 by style {
18 | marginTop(24.px)
19 | property(
20 | "margin-top",
21 | "calc(1*${AppCSSVariables.wtOffsetTopUnit.value(24.px)})"
22 | )
23 | }
24 |
25 | val wtTopOffset48 by style {
26 | marginTop(48.px)
27 | }
28 |
29 | val wtTopOffsetSm12 by style {
30 | media(mediaMaxWidth(640.px)) {
31 | self style {
32 | marginTop(12.px)
33 | }
34 | }
35 | }
36 |
37 | val wtTopOffsetSm24 by style {
38 | media(mediaMaxWidth(640.px)) {
39 | self style {
40 | marginTop(24.px)
41 | }
42 | }
43 | }
44 |
45 | val textInputLabelsStyle by style {
46 | width(20.percent)
47 | display(DisplayStyle.InlineBlock)
48 | }
49 |
50 |
51 | val textInputStyle by style {
52 | property("border", "1px solid rgb(170, 170, 170, 42%)")
53 | property("color", "rgb(39 40 44 / 79%)")
54 | property("font-famyly", "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif")
55 | fontSize(15.px)
56 | width(70.percent)
57 | padding(10.px)
58 | }
59 |
60 |
61 | val rowItems by style {
62 | display(DisplayStyle.LegacyInlineFlex)
63 | alignItems(AlignItems.Center)
64 | marginBottom(16.px)
65 | width(100.percent)
66 | }
67 |
68 | val rowTargetsItems by style {
69 | display(DisplayStyle.LegacyInlineFlex)
70 | alignItems("top")
71 | marginBottom(16.px)
72 | width(100.percent)
73 | }
74 |
75 | val targetsCheckboxesListStyle by style {
76 | display(DisplayStyle.Flex)
77 | property("flex-wrap","wrap")
78 | width(77.percent)
79 | }
80 | val targetsCheckboxesStyle by style {
81 | marginBottom(10.px)
82 | marginRight(10.px)
83 |
84 | descendant(self, selector("input[type=\"checkbox\"]")) style {
85 | display(DisplayStyle.None)
86 | }
87 |
88 | descendant(self, selector("input[type=\"checkbox\"] + label")) style {
89 | property("-webkit-transition","all 500ms ease")
90 | property("transition","all 500ms ease")
91 | property("font-size","18px")
92 | property("background-color","rgb(244,244,244)")
93 | property("padding","0.5rem 2rem")
94 | property("-moz-user-select","-moz-none")
95 | property("-ms-user-select","none")
96 | property("-webkit-user-select","none")
97 | property("user-select","none")
98 | cursor("pointer")
99 | borderRadius(50.px)
100 | display(DisplayStyle.InlineBlock);
101 | }
102 |
103 | descendant(self, selector("input[type=\"checkbox\"]:checked + label")) style {
104 | property("-webkit-transition: all", "500ms ease")
105 | property("transition", "all 300ms ease")
106 | property("background-color", "#167dff")
107 | property("color", "white")
108 | property("border-color", "#167dff")
109 | }
110 |
111 | descendant(self, selector("input[type=\"checkbox\"]:disabled + label")) style {
112 | property("-webkit-transition: all", "500ms ease")
113 | property("transition", "all 300ms ease")
114 | property("background-color", "rgb(244,244,244)")
115 | property("color", "#bfbfbf")
116 | property("cursor", "not-allowed")
117 | }
118 | }
119 | @OptIn(ExperimentalComposeWebApi::class)
120 | val testsCheckboxStyle by style {
121 |
122 | descendant(self, selector("input[type=\"checkbox\"]")) style {
123 | property("box-sizing", "border-box")
124 | padding(0.px)
125 | transform{scale(1.5) }
126 | }
127 |
128 | descendant(self, selector("input[type=\"checkbox\"]:checked")) style {
129 | property("box-sizing", "border-box")
130 | padding(0.px)
131 | property("border-color","#aaa")
132 | property("background-color","#aaa")
133 | }
134 | }
135 |
136 | val generateButtonStyle by style {
137 | display(DisplayStyle.Flex)
138 | justifyContent(JustifyContent.Center)
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MSYS* | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/style/WtText.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.style
2 |
3 | import org.jetbrains.compose.web.css.*
4 | import org.jetbrains.compose.web.css.selectors.hover
5 |
6 | object WtTexts : StyleSheet(AppStylesheet) {
7 |
8 | val wtHero by style {
9 | color(Color("#27282c"))
10 | fontSize(60.px)
11 | fontSize(AppCSSVariables.wtHeroFontSize.value(60.px))
12 | letterSpacing((-1.5).px)
13 | fontWeight(900)
14 | lineHeight(64.px)
15 | lineHeight(AppCSSVariables.wtHeroLineHeight.value(64.px))
16 |
17 | media(mediaMaxWidth(640.px)) {
18 | self style {
19 | AppCSSVariables.wtHeroFontSize(42.px)
20 | AppCSSVariables.wtHeroLineHeight(48.px)
21 | }
22 | }
23 |
24 | property(
25 | "font-family",
26 | "Gotham SSm A,Gotham SSm B,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
27 | )
28 | }
29 |
30 | val wtSubtitle2 by style {
31 | color(Color("#27282c"))
32 | fontSize(28.px)
33 | fontSize(AppCSSVariables.wtSubtitle2FontSize.value(28.px))
34 | letterSpacing("normal")
35 | fontWeight(300)
36 | lineHeight(40.px)
37 | lineHeight(AppCSSVariables.wtSubtitle2LineHeight.value(40.px))
38 |
39 | media(mediaMaxWidth(640.px)) {
40 | self style {
41 | AppCSSVariables.wtSubtitle2FontSize(24.px)
42 | AppCSSVariables.wtSubtitle2LineHeight(32.px)
43 | }
44 | }
45 |
46 | property(
47 | "font-family",
48 | "Gotham SSm A,Gotham SSm B,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
49 | )
50 | }
51 |
52 | val wtText1 by style {
53 | color(rgba(39, 40, 44, .7))
54 | fontSize(18.px)
55 | letterSpacing("normal")
56 | fontWeight(400)
57 | lineHeight(28.px)
58 | property("width", "90%")
59 |
60 | property(
61 | "font-family",
62 | "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
63 | )
64 | }
65 |
66 | val wtText1ThemeDark by style {
67 | color(rgba(255, 255, 255, 0.6))
68 | minWidth(80.px)
69 | }
70 |
71 | val wtText2 by style {
72 | color(rgba(39, 40, 44, .7))
73 | fontSize(15.px)
74 | letterSpacing("normal")
75 | fontWeight(400)
76 | lineHeight(24.px)
77 |
78 | property(
79 | "font-family",
80 | "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
81 | )
82 | }
83 |
84 | val wtText3 by style {
85 | color(rgba(39, 40, 44, .7))
86 | fontSize(12.px)
87 | letterSpacing("normal")
88 | fontWeight(400)
89 | lineHeight(16.px)
90 |
91 | property(
92 | "font-family",
93 | "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
94 | )
95 | }
96 |
97 | val wtTextPale by style {
98 | color(rgba(255, 255, 255, 0.30))
99 | }
100 |
101 | val wtText2ThemeDark by style {
102 | color(rgba(255, 255, 255, 0.6))
103 | }
104 |
105 | val wtText3ThemeDark by style {
106 | color(rgba(255, 255, 255, 0.6))
107 | }
108 |
109 | val wtLink by style {
110 | property("border-bottom", "1px solid transparent")
111 | property("text-decoration", "none")
112 | color(Color("#167dff"))
113 |
114 | hover(self) style {
115 | property("border-bottom-color", "#167dff")
116 | }
117 | }
118 |
119 | val wtH2 by style {
120 | color(Color("#27282c"))
121 | fontSize(31.px)
122 | fontSize(AppCSSVariables.wtH2FontSize.value(31.px))
123 | letterSpacing((-.5).px)
124 | fontWeight(700)
125 | lineHeight(40.px)
126 | lineHeight(40.px)
127 |
128 | media(mediaMaxWidth(640.px)) {
129 | self style {
130 | AppCSSVariables.wtH2FontSize(24.px)
131 | AppCSSVariables.wtH2LineHeight(32.px)
132 | }
133 | }
134 |
135 | property(
136 | "font-family",
137 | "Gotham SSm A,Gotham SSm B,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
138 | )
139 | }
140 |
141 | val wtH2ThemeDark by style {
142 | color(Color("#fff"))
143 | }
144 |
145 | val wtH3 by style {
146 | color(Color("#27282c"))
147 | fontSize(21.px)
148 | fontSize(AppCSSVariables.wtH3FontSize.value(20.px))
149 | letterSpacing("normal")
150 | fontWeight(700)
151 | lineHeight(28.px)
152 | lineHeight(AppCSSVariables.wtH3LineHeight.value(28.px))
153 |
154 | property(
155 | "font-family",
156 | "system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Droid Sans,Helvetica Neue,Arial,sans-serif"
157 | )
158 | }
159 |
160 | val wtH3ThemeDark by style {
161 | color(Color("#fff"))
162 | }
163 |
164 | val wtButton by style {
165 | color(Color("white"))
166 | backgroundColor(Color("#167dff"))
167 | fontSize(15.px)
168 | display(DisplayStyle.InlineBlock)
169 | textDecoration("none")
170 | borderRadius(24.px)
171 | padding(12.px, 32.px)
172 | lineHeight(24.px)
173 | fontWeight(400)
174 | border(0.px)
175 | property("width", "fit-content")
176 |
177 | hover(self) style {
178 | backgroundColor(rgba(22, 125, 255, .8))
179 | }
180 | }
181 |
182 | val wtLangButton by style {
183 | display(DisplayStyle.LegacyInlineFlex)
184 | justifyContent(JustifyContent.Center)
185 | alignItems(AlignItems.Center)
186 | backgroundColor(Color("transparent"))
187 | border(0.px)
188 |
189 | outline("none")
190 |
191 | hover(self) style {
192 | backgroundColor(rgba(255, 255, 255, 0.1))
193 | }
194 | }
195 |
196 | val wtButtonContrast by style {
197 | color(Color("white"))
198 | backgroundColor(Color("#27282c"))
199 |
200 | hover(self) style {
201 | backgroundColor(rgba(39, 40, 44, .7))
202 | }
203 | }
204 |
205 | val wtSocialButtonItem by style {
206 | marginRight(16.px)
207 | marginLeft(16.px)
208 | padding(12.px)
209 | backgroundColor(Color("transparent"))
210 | display(DisplayStyle.LegacyInlineFlex)
211 |
212 | hover(self) style {
213 | backgroundColor(rgba(255, 255, 255, 0.1))
214 | borderRadius(24.px)
215 | }
216 |
217 | media(mediaMaxWidth(640.px)) {
218 | self style {
219 | marginRight(8.px)
220 | marginLeft(8.px)
221 | }
222 | }
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/Gradlew.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.ProjectFile
4 |
5 | class Gradlew : ProjectFile {
6 | override val path = "gradlew"
7 | override val content: String
8 | get() = """
9 | #!/usr/bin/env sh
10 |
11 | #
12 | # Copyright 2015 the original author or authors.
13 | #
14 | # Licensed under the Apache License, Version 2.0 (the "License");
15 | # you may not use this file except in compliance with the License.
16 | # You may obtain a copy of the License at
17 | #
18 | # https://www.apache.org/licenses/LICENSE-2.0
19 | #
20 | # Unless required by applicable law or agreed to in writing, software
21 | # distributed under the License is distributed on an "AS IS" BASIS,
22 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 | # See the License for the specific language governing permissions and
24 | # limitations under the License.
25 | #
26 |
27 | ##############################################################################
28 | ##
29 | ## Gradle start up script for UN*X
30 | ##
31 | ##############################################################################
32 |
33 | # Attempt to set APP_HOME
34 | # Resolve links: ${'$'}{'$'}0 may be a link
35 | PRG="${'$'}0"
36 | # Need this for relative symlinks.
37 | while [ -h "${'$'}PRG" ] ; do
38 | ls=`ls -ld "${'$'}PRG"`
39 | link=`expr "${'$'}ls" : '.*-> \(.*\)${'$'}{'$'}'`
40 | if expr "${'$'}link" : '/.*' > /dev/null; then
41 | PRG="${'$'}link"
42 | else
43 | PRG=`dirname "${'$'}PRG"`"/${'$'}link"
44 | fi
45 | done
46 | SAVED="`pwd`"
47 | cd "`dirname \"${'$'}PRG\"`/" >/dev/null
48 | APP_HOME="`pwd -P`"
49 | cd "${'$'}SAVED" >/dev/null
50 |
51 | APP_NAME="Gradle"
52 | APP_BASE_NAME=`basename "${'$'}0"`
53 |
54 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
55 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
56 |
57 | # Use the maximum available, or set MAX_FD != -1 to use that value.
58 | MAX_FD="maximum"
59 |
60 | warn () {
61 | echo "${'$'}{'$'}*"
62 | }
63 |
64 | die () {
65 | echo
66 | echo "${'$'}{'$'}*"
67 | echo
68 | exit 1
69 | }
70 |
71 | # OS specific support (must be 'true' or 'false').
72 | cygwin=false
73 | msys=false
74 | darwin=false
75 | nonstop=false
76 | case "`uname`" in
77 | CYGWIN* )
78 | cygwin=true
79 | ;;
80 | Darwin* )
81 | darwin=true
82 | ;;
83 | MSYS* | MINGW* )
84 | msys=true
85 | ;;
86 | NONSTOP* )
87 | nonstop=true
88 | ;;
89 | esac
90 |
91 | CLASSPATH=${'$'}APP_HOME/gradle/wrapper/gradle-wrapper.jar
92 |
93 |
94 | # Determine the Java command to use to start the JVM.
95 | if [ -n "${'$'}JAVA_HOME" ] ; then
96 | if [ -x "${'$'}JAVA_HOME/jre/sh/java" ] ; then
97 | # IBM's JDK on AIX uses strange locations for the executables
98 | JAVACMD="${'$'}JAVA_HOME/jre/sh/java"
99 | else
100 | JAVACMD="${'$'}JAVA_HOME/bin/java"
101 | fi
102 | if [ ! -x "${'$'}JAVACMD" ] ; then
103 | die "ERROR: JAVA_HOME is set to an invalid directory: ${'$'}JAVA_HOME
104 |
105 | Please set the JAVA_HOME variable in your environment to match the
106 | location of your Java installation."
107 | fi
108 | else
109 | JAVACMD="java"
110 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
111 |
112 | Please set the JAVA_HOME variable in your environment to match the
113 | location of your Java installation."
114 | fi
115 |
116 | # Increase the maximum file descriptors if we can.
117 | if [ "${'$'}cygwin" = "false" -a "${'$'}darwin" = "false" -a "${'$'}nonstop" = "false" ] ; then
118 | MAX_FD_LIMIT=`ulimit -H -n`
119 | if [ ${'$'}? -eq 0 ] ; then
120 | if [ "${'$'}MAX_FD" = "maximum" -o "${'$'}MAX_FD" = "max" ] ; then
121 | MAX_FD="${'$'}MAX_FD_LIMIT"
122 | fi
123 | ulimit -n ${'$'}MAX_FD
124 | if [ ${'$'}? -ne 0 ] ; then
125 | warn "Could not set maximum file descriptor limit: ${'$'}MAX_FD"
126 | fi
127 | else
128 | warn "Could not query maximum file descriptor limit: ${'$'}MAX_FD_LIMIT"
129 | fi
130 | fi
131 |
132 | # For Darwin, add options to specify how the application appears in the dock
133 | if ${'$'}darwin; then
134 | GRADLE_OPTS="${'$'}GRADLE_OPTS \"-Xdock:name=${'$'}APP_NAME\" \"-Xdock:icon=${'$'}APP_HOME/media/gradle.icns\""
135 | fi
136 |
137 | # For Cygwin or MSYS, switch paths to Windows format before running java
138 | if [ "${'$'}cygwin" = "true" -o "${'$'}msys" = "true" ] ; then
139 | APP_HOME=`cygpath --path --mixed "${'$'}APP_HOME"`
140 | CLASSPATH=`cygpath --path --mixed "${'$'}CLASSPATH"`
141 |
142 | JAVACMD=`cygpath --unix "${'$'}JAVACMD"`
143 |
144 | # We build the pattern for arguments to be converted via cygpath
145 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
146 | SEP=""
147 | for dir in ${'$'}ROOTDIRSRAW ; do
148 | ROOTDIRS="${'$'}ROOTDIRS${'$'}SEP${'$'}dir"
149 | SEP="|"
150 | done
151 | OURCYGPATTERN="(^(${'$'}ROOTDIRS))"
152 | # Add a user-defined pattern to the cygpath arguments
153 | if [ "${'$'}GRADLE_CYGPATTERN" != "" ] ; then
154 | OURCYGPATTERN="${'$'}OURCYGPATTERN|(${'$'}GRADLE_CYGPATTERN)"
155 | fi
156 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
157 | i=0
158 | for arg in "${'$'}@" ; do
159 | CHECK=`echo "${'$'}arg"|egrep -c "${'$'}OURCYGPATTERN" -`
160 | CHECK2=`echo "${'$'}arg"|egrep -c "^-"` ### Determine if an option
161 |
162 | if [ ${'$'}CHECK -ne 0 ] && [ ${'$'}CHECK2 -eq 0 ] ; then ### Added a condition
163 | eval `echo args${'$'}i`=`cygpath --path --ignore --mixed "${'$'}arg"`
164 | else
165 | eval `echo args${'$'}i`="\"${'$'}arg\""
166 | fi
167 | i=`expr ${'$'}i + 1`
168 | done
169 | case ${'$'}i in
170 | 0) set -- ;;
171 | 1) set -- "${'$'}args0" ;;
172 | 2) set -- "${'$'}args0" "${'$'}args1" ;;
173 | 3) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" ;;
174 | 4) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" ;;
175 | 5) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" "${'$'}args4" ;;
176 | 6) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" "${'$'}args4" "${'$'}args5" ;;
177 | 7) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" "${'$'}args4" "${'$'}args5" "${'$'}args6" ;;
178 | 8) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" "${'$'}args4" "${'$'}args5" "${'$'}args6" "${'$'}args7" ;;
179 | 9) set -- "${'$'}args0" "${'$'}args1" "${'$'}args2" "${'$'}args3" "${'$'}args4" "${'$'}args5" "${'$'}args6" "${'$'}args7" "${'$'}args8" ;;
180 | esac
181 | fi
182 |
183 | # Escape application args
184 | save () {
185 | for i do printf %s\\n "${'$'}i" | sed "s/'/'\\\\''/g;1s/^/'/;\${'$'}s/\${'$'}/' \\\\/" ; done
186 | echo " "
187 | }
188 | APP_ARGS=`save "${'$'}@"`
189 |
190 | # Collect all arguments for the java command, following the shell quoting and substitution rules
191 | eval set -- ${'$'}DEFAULT_JVM_OPTS ${'$'}JAVA_OPTS ${'$'}GRADLE_OPTS "\"-Dorg.gradle.appname=${'$'}APP_BASE_NAME\"" -classpath "\"${'$'}CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "${'$'}APP_ARGS"
192 |
193 | exec "${'$'}JAVACMD" "${'$'}@"
194 | """.trimIndent()
195 | }
--------------------------------------------------------------------------------
/src/commonTest/kotlin/org/jetbrains/webwiz/generator/ProjectBuilderTest.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator
2 |
3 | import org.jetbrains.webwiz.generator.files.ModuleBuildGradle
4 | import org.jetbrains.webwiz.generator.files.SettingsGradle
5 | import org.jetbrains.webwiz.models.GradlePlugin
6 | import org.jetbrains.webwiz.models.KmpLibrary
7 | import org.jetbrains.webwiz.models.KotlinVersion
8 | import org.jetbrains.webwiz.models.ProjectInfo
9 | import org.jetbrains.webwiz.models.Target.*
10 | import kotlin.test.Test
11 | import kotlin.test.assertEquals
12 |
13 |
14 | internal class ProjectBuilderTest {
15 |
16 | @Test
17 | fun testGeneratedStructure() {
18 | val projectInfo = ProjectInfo(
19 | "wizard-sample",
20 | "library",
21 | "my.test.package",
22 | KotlinVersion.Stable,
23 | setOf(JVM, JS, IOS, ANDROID),
24 | emptySet(),
25 | emptySet(),
26 | emptySet(),
27 | setOf(GradlePlugin.PUBLISH),
28 | true
29 | )
30 | val actual = projectInfo.generate().joinToString("\n") { it.path }
31 | val expect = """
32 | .gitignore
33 | gradlew
34 | gradle.bat
35 | gradle/wrapper/gradle-wrapper.properties
36 | gradle/wrapper/gradle-wrapper.jar
37 | build.gradle.kts
38 | settings.gradle.kts
39 | gradle.properties
40 | library/build.gradle.kts
41 | library/src/commonMain/kotlin/my/test/package/Platform.kt
42 | library/src/jvmMain/kotlin/my/test/package/Platform.kt
43 | library/src/jsMain/kotlin/my/test/package/Platform.kt
44 | library/src/iosMain/kotlin/my/test/package/Platform.kt
45 | library/src/androidMain/kotlin/my/test/package/Platform.kt
46 | library/src/nativeMain/kotlin/my/test/package/Platform.kt
47 | library/src/androidMain/AndroidManifest.xml
48 | library/src/commonTest/kotlin/my/test/package/CommonTest.kt
49 | library/src/jvmTest/kotlin/my/test/package/PlatformTest.kt
50 | library/src/jsTest/kotlin/my/test/package/PlatformTest.kt
51 | library/src/iosTest/kotlin/my/test/package/PlatformTest.kt
52 | library/src/androidTest/kotlin/my/test/package/PlatformTest.kt
53 | library/src/nativeTest/kotlin/my/test/package/NativeTest.kt
54 | """.trimIndent()
55 | assertEquals(expect, actual)
56 | }
57 |
58 | @Test
59 | fun testGeneratedBuildConfig() {
60 | val projectInfo = ProjectInfo(
61 | "wizard-sample",
62 | "lib",
63 | "my.test.package",
64 | KotlinVersion.EAP,
65 | setOf(JVM, JS, IOS, ANDROID),
66 | setOf(KmpLibrary.SERIALIZATION),
67 | emptySet(),
68 | emptySet(),
69 | setOf(GradlePlugin.PUBLISH),
70 | true
71 | )
72 | val actual = projectInfo.generate().first { it is ModuleBuildGradle }.content
73 | val expect = """
74 | plugins {
75 | kotlin("multiplatform")
76 | kotlin("plugin.serialization")
77 | id("com.android.library")
78 | `maven-publish`
79 | }
80 |
81 | /* required for maven publication */
82 | group = "my.test.package"
83 | version = "0.1"
84 |
85 | kotlin {
86 | jvm()
87 | js {
88 | browser()
89 | nodejs()
90 | }
91 | iosX64()
92 | iosArm64()
93 | /* iosSimulatorArm64() sure all ios dependencies support this target */
94 | android()
95 |
96 | sourceSets {
97 | /* Main source sets */
98 | val commonMain by getting {
99 | dependencies {
100 | implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
101 | }
102 | }
103 | val jvmMain by getting
104 | val jsMain by getting
105 | val iosX64Main by getting
106 | val iosArm64Main by getting
107 | /* val iosSimulatorArm64Main by getting */
108 | val androidMain by getting
109 | val iosMain by creating
110 | val nativeMain by creating
111 |
112 | /* Main hierarchy */
113 | jvmMain.dependsOn(commonMain)
114 | jsMain.dependsOn(commonMain)
115 | iosMain.dependsOn(nativeMain)
116 | iosX64Main.dependsOn(iosMain)
117 | iosArm64Main.dependsOn(iosMain)
118 | /* iosSimulatorArm64Main.dependsOn(iosMain) */
119 | androidMain.dependsOn(commonMain)
120 | nativeMain.dependsOn(commonMain)
121 |
122 | /* Test source sets */
123 | val commonTest by getting {
124 | dependencies {
125 | implementation(kotlin("test"))
126 | }
127 | }
128 | val jvmTest by getting
129 | val jsTest by getting
130 | val iosX64Test by getting
131 | val iosArm64Test by getting
132 | /* val iosSimulatorArm64Test by getting */
133 | val androidTest by getting
134 | val iosTest by creating
135 | val nativeTest by creating
136 |
137 | /* Test hierarchy */
138 | jvmTest.dependsOn(commonTest)
139 | jsTest.dependsOn(commonTest)
140 | iosTest.dependsOn(nativeTest)
141 | iosX64Test.dependsOn(iosTest)
142 | iosArm64Test.dependsOn(iosTest)
143 | /* iosSimulatorArm64Test.dependsOn(iosTest) */
144 | androidTest.dependsOn(commonTest)
145 | nativeTest.dependsOn(commonTest)
146 | }
147 | }
148 |
149 | android {
150 | compileSdk = 31
151 | sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
152 | defaultConfig {
153 | minSdk = 21
154 | targetSdk = 31
155 | }
156 | }
157 |
158 | """.trimIndent()
159 | assertEquals(expect, actual)
160 | }
161 |
162 | @Test
163 | fun testGeneratedSettingsGradle() {
164 | val projectInfo = ProjectInfo(
165 | "New Project",
166 | "module",
167 | "my.test.package",
168 | KotlinVersion.EAP,
169 | setOf(JVM, JS, IOS, ANDROID),
170 | setOf(KmpLibrary.SERIALIZATION),
171 | emptySet(),
172 | emptySet(),
173 | setOf(GradlePlugin.PUBLISH),
174 | true
175 | )
176 | val actual = projectInfo.generate().first { it is SettingsGradle }.content
177 | val expect = """
178 | pluginManagement {
179 | repositories {
180 | google()
181 | gradlePluginPortal()
182 | mavenCentral()
183 | }
184 | }
185 |
186 | rootProject.name = "New_Project"
187 | include(":module")
188 | """.trimIndent()
189 | assertEquals(expect, actual)
190 | }
191 |
192 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/Chips.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import org.jetbrains.compose.web.attributes.disabled
5 | import org.jetbrains.compose.web.dom.CheckboxInput
6 | import org.jetbrains.compose.web.dom.Div
7 | import org.jetbrains.compose.web.dom.Label
8 | import org.jetbrains.compose.web.dom.Span
9 | import org.jetbrains.compose.web.dom.Text
10 | import org.jetbrains.webwiz.models.GradlePlugin
11 | import org.jetbrains.webwiz.models.KmpLibrary
12 | import org.jetbrains.webwiz.models.NativeTargetLibrary
13 | import org.jetbrains.webwiz.models.SingleTargetLibrary
14 | import org.jetbrains.webwiz.models.Target
15 | import org.jetbrains.webwiz.models.isCommonNativeTargetPresent
16 | import org.jetbrains.webwiz.models.isNativeTargetPresent
17 | import org.jetbrains.webwiz.style.WtOffsets
18 |
19 | @Composable
20 | fun TargetChips() {
21 | Div({ classes(WtOffsets.targetsCheckboxesListStyle) }) {
22 | Target.values().forEach { t ->
23 | Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
24 | CheckboxInput(projectInfoState.value.targets.contains(t)) {
25 | onChange { event ->
26 | val current = projectInfoState.value.targets.toMutableSet()
27 | val new: Set = when {
28 | event.value -> current.plus(t)
29 | current.size > 1 -> current.minus(t)
30 | else -> current
31 | }
32 | applyTargetsUpdate(targets = new)
33 | }
34 | id("checkbox_${t.name}")
35 | }
36 | Label(forId = "checkbox_${t.name}") {
37 | Text(t.userName)
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
44 |
45 | @Composable
46 | fun LibrariesChips() {
47 | Div({ classes(WtOffsets.targetsCheckboxesListStyle) }) {
48 | KmpLibrary.values().forEach { t ->
49 |
50 | if (t.targets != null && projectInfoState.value.targets.any { it !in t.targets }) {
51 | return@forEach DisabledChip(t.userName)
52 | }
53 |
54 | return@forEach Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
55 | CheckboxInput(projectInfoState.value.dependencies.contains(t)) {
56 | onChange { event ->
57 | val current = projectInfoState.value.dependencies.toMutableSet()
58 | val new: Set = when {
59 | event.value -> current.plus(t)
60 | else -> current.minus(t)
61 | }
62 | projectInfoState.value = projectInfoState.value.copy(dependencies = new)
63 | }
64 | id("checkbox_${t.name}")
65 | }
66 | Label(forId = "checkbox_${t.name}") {
67 | Text(t.userName)
68 | }
69 | }
70 | }
71 | }
72 | }
73 |
74 | @Composable
75 | fun SingleTargetLibraryChips() {
76 | Div({ classes(WtOffsets.targetsCheckboxesListStyle) }) {
77 | SingleTargetLibrary.values().forEach { t ->
78 |
79 | if (t.target !in projectInfoState.value.targets ) {
80 | return@forEach DisabledChip(t.userName)
81 | }
82 |
83 | return@forEach Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
84 | CheckboxInput(projectInfoState.value.singleTargetDependencies.contains(t)) {
85 | onChange { event ->
86 | val current = projectInfoState.value.singleTargetDependencies.toMutableSet()
87 | val new: Set = when {
88 | event.value -> current.plus(t)
89 | else -> current.minus(t)
90 | }
91 | projectInfoState.value = projectInfoState.value.copy(singleTargetDependencies = new)
92 | }
93 | id("checkbox_${t.name}")
94 | }
95 | Label(forId = "checkbox_${t.name}") {
96 | Text(t.userName)
97 | }
98 | }
99 | }
100 | }
101 | }
102 |
103 | @Composable
104 | fun NativeTargetLibraryChips() {
105 | Div({ classes(WtOffsets.targetsCheckboxesListStyle) }) {
106 | NativeTargetLibrary.values().forEach { t ->
107 |
108 | if (!projectInfoState.value.targets.isCommonNativeTargetPresent() ) {
109 | return@forEach DisabledChip(t.userName)
110 | }
111 |
112 | return@forEach Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
113 | CheckboxInput(projectInfoState.value.nativeTargetLibraries.contains(t)) {
114 | onChange { event ->
115 | val current = projectInfoState.value.nativeTargetLibraries.toMutableSet()
116 | val new: Set = when {
117 | event.value -> current.plus(t)
118 | else -> current.minus(t)
119 | }
120 | projectInfoState.value = projectInfoState.value.copy(nativeTargetLibraries = new)
121 | }
122 | id("checkbox_${t.name}")
123 | }
124 | Label(forId = "checkbox_${t.name}") {
125 | Text(t.userName)
126 | }
127 | }
128 | }
129 | }
130 | }
131 |
132 | @Composable
133 | fun PluginsChips() {
134 | Div({ classes(WtOffsets.targetsCheckboxesListStyle) }) {
135 | GradlePlugin.values().forEach { t ->
136 | val targets = projectInfoState.value.targets
137 |
138 | if (t.mandatory.any { !targets.contains(it) } || t.forbidden.any { targets.contains(it) }) {
139 | return@forEach DisabledChip(t.userName)
140 | }
141 |
142 | return@forEach Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
143 | CheckboxInput(projectInfoState.value.gradlePlugins.contains(t)) {
144 | onChange { event ->
145 | val current = projectInfoState.value.gradlePlugins.toMutableSet()
146 | val new: Set = when {
147 | event.value -> current.plus(t)
148 | else -> current.minus(t)
149 | }
150 | projectInfoState.value = projectInfoState.value.copy(gradlePlugins = new)
151 | }
152 | id("checkbox_gradle_plugin_${t.name}")
153 | }
154 | Label(forId = "checkbox_gradle_plugin_${t.name}") {
155 | Text(t.userName)
156 | }
157 | }
158 | }
159 | }
160 | }
161 |
162 | @Composable
163 | fun DisabledChip(label: String) {
164 | Span({ classes(WtOffsets.targetsCheckboxesStyle) }) {
165 | CheckboxInput() {
166 | id("checkbox_disabled_$label")
167 | disabled()
168 | }
169 |
170 | Label(forId = "checkbox_disabled_$label") {
171 | Text(label)
172 | }
173 | }
174 | }
175 |
176 | private fun applyTargetsUpdate(targets: Set) {
177 | val currentLibraries = projectInfoState.value.dependencies.toMutableSet()
178 | val currentPlugins = projectInfoState.value.gradlePlugins.toMutableSet()
179 |
180 | for (library in KmpLibrary.values()) {
181 | if (library.targets != null && targets.any { it !in library.targets }) {
182 | currentLibraries.remove(library)
183 | }
184 | }
185 |
186 | for (plugin in GradlePlugin.values()) {
187 | if (targets.containsAll(plugin.mandatory) && !targets.any { it in plugin.forbidden })
188 | continue
189 | if (plugin.mandatory.isNotEmpty() && targets.any { !plugin.mandatory.contains(it) }) {
190 | currentPlugins.remove(plugin)
191 | }
192 | }
193 |
194 | projectInfoState.value = projectInfoState.value.copy(
195 | targets = targets,
196 | dependencies = currentLibraries,
197 | gradlePlugins = currentPlugins
198 | )
199 | }
--------------------------------------------------------------------------------
/src/commonMain/kotlin/org/jetbrains/webwiz/generator/files/ModuleBuildGradle.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.generator.files
2 |
3 | import org.jetbrains.webwiz.generator.NAN
4 | import org.jetbrains.webwiz.generator.ProjectFile
5 | import org.jetbrains.webwiz.generator.deleteNans
6 | import org.jetbrains.webwiz.models.GradlePlugin
7 | import org.jetbrains.webwiz.models.KmpLibrary
8 | import org.jetbrains.webwiz.models.ProjectInfo
9 | import org.jetbrains.webwiz.models.SourceSetDelegate
10 | import org.jetbrains.webwiz.models.SourceSetDelegate.CREATING
11 | import org.jetbrains.webwiz.models.SourceSetDelegate.GETTING
12 | import org.jetbrains.webwiz.models.SourceSetType.MAIN
13 | import org.jetbrains.webwiz.models.Target
14 | import org.jetbrains.webwiz.models.isNativeTargetPresent
15 |
16 | class ModuleBuildGradle(val projectInfo: ProjectInfo) : ProjectFile {
17 | override val path = "${projectInfo.moduleName}/build.gradle.kts"
18 | override val content: String
19 | get() = """
20 | ${generatePluginsBlock()}
21 |
22 | ${if (GradlePlugin.PUBLISH in projectInfo.gradlePlugins) generatePublishPluginConfig("0.1") else NAN}
23 | ${generateKotlinBlock()}
24 |
25 | ${if (Target.ANDROID in projectInfo.targets) generateAndroidPluginConfig("21", "31") else NAN}
26 | ${if (GradlePlugin.APPLICATION in projectInfo.gradlePlugins) generateApplicationPluginConfig() else NAN}
27 | """.trimIndent().deleteNans()
28 |
29 | private fun generatePluginsBlock(): String = """
30 | plugins {
31 | kotlin("multiplatform")
32 | ${if (KmpLibrary.SERIALIZATION in projectInfo.dependencies) "kotlin(\"plugin.serialization\")" else NAN}
33 | ${if (Target.ANDROID in projectInfo.targets) "id(\"com.android.library\")" else NAN}
34 | ${if (GradlePlugin.APPLICATION in projectInfo.gradlePlugins) "application" else NAN}
35 | ${if (GradlePlugin.PUBLISH in projectInfo.gradlePlugins) "`maven-publish`" else NAN}
36 | ${if (GradlePlugin.SQL_DELIGHT in projectInfo.gradlePlugins) "id(\"com.squareup.sqldelight\")" else NAN}
37 | }
38 | """.trimIndent().deleteNans()
39 |
40 | private fun generateKotlinBlock() = """
41 | kotlin {
42 | ${registerTargets(projectInfo.targets)}
43 |
44 | ${setupSourceSets()}
45 | }
46 | """.trimIndent()
47 |
48 | private fun registerTargets(
49 | targets: Set
50 | ) = targets.joinToString("\n ") {
51 | when (it) {
52 | Target.ANDROID -> "android()"
53 | Target.JVM -> if (projectInfo.gradlePlugins.contains(GradlePlugin.APPLICATION)) "jvm {\n withJava()\n }" else "jvm()"
54 | Target.JS -> "js {\n browser()\n nodejs()\n }"
55 | Target.WASM -> "wasm32()"
56 | Target.ANDROID_NATIVE -> "androidNativeArm64()"
57 | Target.LINUX -> "linuxX64()"
58 | Target.MACOS -> "macosX64()\n /* macosArm64() sure all macos dependencies support this target */"
59 | Target.IOS -> "iosX64()\n iosArm64()\n /* iosSimulatorArm64() sure all ios dependencies support this target */"
60 | Target.TV_OS -> "tvosX64()\n tvosArm64()\n /* tvosSimulatorArm64() sure all tvos dependencies support this target */"
61 | Target.WATCH_OS -> "watchosX64()\n watchosArm64()\n /* watchosSimulatorArm64() sure all watchos dependencies support this target */"
62 | Target.WINDOWS -> "mingwX64()"
63 | }
64 | }
65 |
66 | private fun setupSourceSets() = """
67 | |sourceSets {
68 | | /* Main source sets */
69 | ${commonMainSourceSet()}
70 | | ${leafSourceSets("Main")}
71 | | ${sharedSourceSets("Main")}
72 | | ${if (projectInfo.targets.isNativeTargetPresent()) nativeSourceSets("Main") else NAN}
73 | |
74 | | /* Main hierarchy */
75 | | ${sourceSetsDependencies("Main")}
76 | | ${if (projectInfo.targets.isNativeTargetPresent()) nativeSourceSetsDependencies("Main") else NAN}
77 | |
78 | | /* Test source sets */
79 | ${commonTestSourceSet()}
80 | | ${leafSourceSets("Test")}
81 | | ${sharedSourceSets("Test")}
82 | | ${if (projectInfo.targets.isNativeTargetPresent()) nativeSourceSets("Test") else NAN}
83 | |
84 | | /* Test hierarchy */
85 | | ${sourceSetsDependencies("Test")}
86 | | ${if (projectInfo.targets.isNativeTargetPresent()) nativeSourceSetsDependencies("Test") else NAN}
87 | | }
88 | """.trimMargin().deleteNans()
89 |
90 | private fun commonMainSourceSet(): String {
91 | val deps = projectInfo.dependencies.filter {
92 | it.sourceSetType.sourceSetTypeName == MAIN.sourceSetTypeName
93 | }.map { "implementation(\"${it.dep}\")" }
94 | return if (deps.isEmpty()) {
95 | " | val commonMain by getting"
96 | } else {
97 | """| val commonMain by getting {
98 | | dependencies {
99 | | ${deps.joinToString("\n| ")}
100 | | }
101 | | }"""
102 | }
103 | }
104 |
105 | private fun singleSourceSet(
106 | target: Target,
107 | compilation: String,
108 | sourceSetDelegate: SourceSetDelegate
109 | ): String {
110 | val deps = projectInfo.singleTargetDependencies
111 | .filter { it.target == target && it.sourceSetType.sourceSetTypeName == compilation }
112 | .map { "implementation(\"${it.dep}\")" }
113 | return if (deps.isEmpty()) {
114 | "val ${target.targetName}$compilation by ${sourceSetDelegate.delegate}"
115 | } else {
116 | """val ${target.targetName}$compilation by ${sourceSetDelegate.delegate} {
117 | | dependencies {
118 | | ${deps.joinToString("\n| ")}
119 | | }
120 | | }"""
121 | }
122 | }
123 |
124 | private fun commonTestSourceSet() =
125 | """| val commonTest by getting {
126 | | dependencies {
127 | | implementation(kotlin("test"))
128 | | }
129 | | }"""
130 |
131 | private fun leafSourceSets(compilation: String): String {
132 | val intention = "\n| "
133 | return projectInfo.targets.joinToString(intention) {
134 | when (it) {
135 | Target.ANDROID -> singleSourceSet(Target.ANDROID, compilation, GETTING)
136 | Target.JVM -> singleSourceSet(Target.JVM, compilation, GETTING)
137 | Target.JS -> singleSourceSet(Target.JS, compilation, GETTING)
138 | Target.WASM -> "val wasm32$compilation by getting"
139 | Target.ANDROID_NATIVE -> "val androidNativeArm64$compilation by getting"
140 | Target.LINUX -> "val linuxX64$compilation by getting"
141 | Target.MACOS -> "val macosX64$compilation by getting ${intention}/* val macosArm64$compilation by getting */"
142 | Target.IOS -> "val iosX64$compilation by getting ${intention}val iosArm64$compilation by getting${intention}/* val iosSimulatorArm64$compilation by getting */"
143 | Target.TV_OS -> "val tvosX64$compilation by getting ${intention}val tvosArm64$compilation by getting ${intention}/* val tvosSimulatorArm64$compilation by getting */"
144 | Target.WATCH_OS -> "val watchosX64$compilation by getting ${intention}val watchosArm64$compilation by getting ${intention}/* val watchosSimulatorArm64$compilation by getting */"
145 | Target.WINDOWS -> "val mingwX64$compilation by getting"
146 | }
147 | }
148 | }
149 |
150 | private fun sharedSourceSets(compilation: String): String =
151 | projectInfo.targets.joinToString("\n| ") {
152 | when (it) {
153 | Target.ANDROID -> NAN
154 | Target.JVM -> NAN
155 | Target.JS -> NAN
156 | Target.WASM -> "val wasm$compilation by creating"
157 | Target.ANDROID_NATIVE -> "val androidNative$compilation by creating"
158 | Target.LINUX -> "val linux$compilation by creating"
159 | Target.MACOS -> "val macos$compilation by creating"
160 | Target.IOS -> singleSourceSet(Target.IOS, compilation, CREATING)
161 | Target.TV_OS -> "val tvos$compilation by creating"
162 | Target.WATCH_OS -> "val watchos$compilation by creating"
163 | Target.WINDOWS -> "val windows$compilation by creating"
164 | }
165 | }
166 |
167 | private fun sourceSetsDependencies(compilation: String): String {
168 | val intention = "\n| "
169 | return projectInfo.targets.joinToString(intention) {
170 | when (it) {
171 | Target.ANDROID -> "android$compilation.dependsOn(common$compilation)"
172 | Target.JVM -> "jvm$compilation.dependsOn(common$compilation)"
173 | Target.JS -> "js$compilation.dependsOn(common$compilation)"
174 | Target.WASM -> "wasm$compilation.dependsOn(native$compilation)${intention}wasm32$compilation.dependsOn(wasm$compilation)"
175 | Target.ANDROID_NATIVE -> "androidNative$compilation.dependsOn(native$compilation) ${intention}androidNativeArm64$compilation.dependsOn(androidNative$compilation)"
176 | Target.LINUX -> "linux$compilation.dependsOn(native$compilation)${intention}linuxX64$compilation.dependsOn(linux$compilation)"
177 | Target.MACOS -> "macos$compilation.dependsOn(native$compilation)${intention}macosX64$compilation.dependsOn(macos$compilation)${intention}/* macosArm64$compilation.dependsOn(macos$compilation) */"
178 | Target.IOS -> "ios$compilation.dependsOn(native$compilation)${intention}iosX64$compilation.dependsOn(ios$compilation)${intention}iosArm64$compilation.dependsOn(ios$compilation)${intention}/* iosSimulatorArm64$compilation.dependsOn(ios$compilation) */"
179 | Target.TV_OS -> "tvos$compilation.dependsOn(native$compilation)${intention}tvosX64$compilation.dependsOn(tvos$compilation)${intention}tvosArm64$compilation.dependsOn(tvos$compilation)${intention}/* tvosSimulatorArm64$compilation.dependsOn(tvos$compilation) */"
180 | Target.WATCH_OS -> "watchos$compilation.dependsOn(native$compilation)${intention}watchosX64$compilation.dependsOn(watchos$compilation)${intention}watchosArm64$compilation.dependsOn(watchos$compilation)${intention}/* watchosSimulatorArm64$compilation.dependsOn(watchos$compilation) */"
181 | Target.WINDOWS -> "windows$compilation.dependsOn(native$compilation)${intention}mingwX64$compilation.dependsOn(windows$compilation)"
182 | }
183 | }
184 | }
185 |
186 | private fun nativeUmbrellaSourceSet(
187 | compilation: String,
188 | sourceSetDelegate: SourceSetDelegate
189 | ): String {
190 | val deps = projectInfo.nativeTargetLibraries
191 | .filter { it.sourceSetType.sourceSetTypeName == compilation }
192 | .map { "implementation(\"${it.dep}\")" }
193 | return if (deps.isEmpty()) {
194 | "val native$compilation by ${sourceSetDelegate.delegate}"
195 | } else {
196 | """val native$compilation by ${sourceSetDelegate.delegate} {
197 | | dependencies {
198 | | ${deps.joinToString("\n| ")}
199 | | }
200 | | }"""
201 | }
202 | }
203 |
204 | private fun nativeSourceSets(compilation: String): String {
205 | return nativeUmbrellaSourceSet(compilation, CREATING)
206 | }
207 | private fun nativeSourceSetsDependencies(compilation: String) = "native$compilation.dependsOn(common$compilation)"
208 |
209 | private fun generateAndroidPluginConfig(minSdk: String, compileSdk: String) = """
210 | android {
211 | compileSdk = $compileSdk
212 | sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
213 | defaultConfig {
214 | minSdk = $minSdk
215 | targetSdk = $compileSdk
216 | }
217 | }
218 |
219 | """.trimIndent()
220 |
221 | private fun generateApplicationPluginConfig() = """
222 | application {
223 | mainClass.set("${projectInfo.packageName}.ApplicationKt")
224 | }
225 |
226 | """.trimIndent()
227 |
228 | private fun generatePublishPluginConfig(version: String) = """
229 | /* required for maven publication */
230 | group = "${projectInfo.packageName}"
231 | version = "$version"
232 |
233 | """.trimIndent()
234 |
235 | }
--------------------------------------------------------------------------------
/src/jsMain/kotlin/org/jetbrains/webwiz/content/WizardSection.kt:
--------------------------------------------------------------------------------
1 | package org.jetbrains.webwiz.content
2 |
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.runtime.MutableState
5 | import androidx.compose.runtime.mutableStateOf
6 | import androidx.compose.runtime.remember
7 | import org.jetbrains.compose.common.foundation.layout.Row
8 | import org.jetbrains.compose.common.ui.ExperimentalComposeWebWidgetsApi
9 | import org.jetbrains.compose.web.attributes.InputType
10 | import org.jetbrains.compose.web.css.*
11 | import org.jetbrains.compose.web.dom.*
12 | import org.jetbrains.webwiz.generator.ProjectFile
13 | import org.jetbrains.webwiz.generator.files.RootBuildGradle
14 | import org.jetbrains.webwiz.generator.generate
15 | import org.jetbrains.webwiz.models.KmpLibrary
16 | import org.jetbrains.webwiz.models.KotlinVersion
17 | import org.jetbrains.webwiz.models.ProjectInfo
18 | import org.jetbrains.webwiz.models.Target
19 | import org.jetbrains.webwiz.setHighlightedCode
20 | import org.jetbrains.webwiz.style.WtContainer
21 | import org.jetbrains.webwiz.style.WtOffsets
22 | import org.jetbrains.webwiz.style.WtSections
23 | import org.jetbrains.webwiz.style.WtTexts
24 | import kotlin.random.Random
25 |
26 | private val defaultProject = ProjectInfo(
27 | projectName = "KMP Project",
28 | moduleName = "shared",
29 | packageName = "org.sample.application",
30 | kotlinVersion = KotlinVersion.Stable,
31 | targets = setOf(Target.ANDROID, Target.IOS),
32 | enableTests = false,
33 | dependencies = setOf(KmpLibrary.SERIALIZATION),
34 | singleTargetDependencies = emptySet(),
35 | nativeTargetLibraries = emptySet(),
36 | gradlePlugins = emptySet()
37 | ).normalize()
38 |
39 | internal val projectInfoState = mutableStateOf(defaultProject)
40 |
41 | @Composable
42 | @OptIn(ExperimentalComposeWebWidgetsApi::class)
43 | fun WizardSection(callback: (projectInfo: ProjectInfo) -> Unit) = Section({
44 | classes(WtSections.wtSection)
45 | }) {
46 | Div({
47 | classes(WtContainer.wtContainer)
48 | }) {
49 | Div({
50 | classes(WtTexts.wtText1)
51 | }) {
52 | Row {
53 | Div({ classes(WtOffsets.rowItems) }) {
54 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
55 | Text("Project name")
56 | }
57 |
58 | TextInput(projectInfoState.value.projectName) {
59 |
60 | onInput { event ->
61 | projectInfoState.value = projectInfoState.value.copy(projectName = event.value)
62 | }
63 |
64 | classes(WtOffsets.textInputStyle)
65 | }
66 | }
67 | }
68 | Row {
69 | Div({ classes(WtOffsets.rowItems) }) {
70 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
71 | Text("Module name")
72 | }
73 |
74 | TextInput(projectInfoState.value.moduleName) {
75 |
76 | onInput { event ->
77 | projectInfoState.value = projectInfoState.value.copy(moduleName = event.value)
78 | }
79 |
80 | classes(WtOffsets.textInputStyle)
81 | }
82 | }
83 | }
84 | Row {
85 | Div({ classes(WtOffsets.rowItems) }) {
86 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
87 | Text("Package")
88 | }
89 | TextInput(projectInfoState.value.packageName) {
90 | onInput { event ->
91 | projectInfoState.value = projectInfoState.value.copy(packageName = event.value)
92 | }
93 | classes(WtOffsets.textInputStyle)
94 | }
95 | }
96 | }
97 | Row {
98 | Div({ classes(WtOffsets.rowItems) }) {
99 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
100 | Text("Kotlin version")
101 | }
102 |
103 | Div {
104 | KotlinVersionSwitcher(projectInfoState.value.kotlinVersion) {
105 | projectInfoState.value = projectInfoState.value.copy(kotlinVersion = it)
106 | }
107 | }
108 | }
109 | }
110 | Row {
111 | Div({ classes(WtOffsets.rowItems) }) {
112 | Div({ classes(WtOffsets.rowTargetsItems) }) {
113 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
114 | Text("Targets")
115 | }
116 | TargetChips()
117 | }
118 | }
119 | }
120 |
121 | Row {
122 | Div({ classes(WtOffsets.rowTargetsItems) }) {
123 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
124 | Text("Libraries")
125 | }
126 | LibrariesChips()
127 | }
128 | }
129 |
130 | Row {
131 | Div({ classes(WtOffsets.rowTargetsItems) }) {
132 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
133 | Text("Single Target Libraries")
134 | }
135 | SingleTargetLibraryChips()
136 | }
137 | }
138 |
139 | Row {
140 | Div({ classes(WtOffsets.rowTargetsItems) }) {
141 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
142 | Text("Native Target Libraries")
143 | }
144 | NativeTargetLibraryChips()
145 | }
146 | }
147 |
148 | Row {
149 | Div({ classes(WtOffsets.rowTargetsItems) }) {
150 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
151 | Text("Plugins")
152 | }
153 | PluginsChips()
154 | }
155 | }
156 |
157 | Row {
158 | Span({ classes(WtOffsets.textInputLabelsStyle) }) {
159 | Text("Include tests")
160 | }
161 | Span({ classes(WtOffsets.testsCheckboxStyle) }) {
162 | CheckboxInput(projectInfoState.value.enableTests) {
163 | onChange {
164 | projectInfoState.value =
165 | projectInfoState.value.copy(enableTests = !projectInfoState.value.enableTests)
166 | }
167 | }
168 | }
169 | }
170 |
171 | Div({ classes(WtOffsets.generateButtonStyle) }) {
172 | Button(attrs = {
173 | classes(WtTexts.wtButton, WtTexts.wtButtonContrast, WtOffsets.wtTopOffset24)
174 | onClick { callback(projectInfoState.value) }
175 | style {
176 | cursor("pointer")
177 | }
178 | }) {
179 | Text("Download new project")
180 | }
181 | }
182 |
183 | Div({
184 | classes(WtOffsets.wtTopOffset24)
185 | style {
186 | backgroundColor(rgba(39, 40, 44, 0.05))
187 | borderRadius(8.px, 8.px, 8.px)
188 | padding(12.px, 16.px)
189 | property("font-family", "'JetBrains Mono', monospace")
190 | fontSize(10.pt)
191 | display(DisplayStyle.Flex)
192 | flexDirection(FlexDirection.Row)
193 | minHeight(600.pt)
194 | }
195 | }) {
196 | val structure = projectInfoState.value.generate()
197 | val selectedFile = remember(projectInfoState.value) { mutableStateOf(structure.first { it is RootBuildGradle }) }
198 |
199 | filesStructure(structure, selectedFile)
200 | Span(attrs = {
201 | style {
202 | width(1.pt)
203 | backgroundColor(Color("gray"))
204 | marginLeft(5.px)
205 | marginRight(5.px)
206 | }
207 | })
208 | selectedFile.value.let { f ->
209 | val lang = when {
210 | f.path.endsWith(".kt") -> "kotlin"
211 | f.path.endsWith(".kts") -> "gradle"
212 | f.path.endsWith(".xml") -> "xml"
213 | else -> "text"
214 | }
215 | Pre(attrs = {
216 | style {
217 | overflow("auto")
218 | }
219 | }) {
220 | Code({
221 | classes("language-$lang", "hljs")
222 | style {
223 | property("tab-size", 4)
224 | backgroundColor(Color("transparent"))
225 | }
226 | }) {
227 | DomSideEffect(f.content) {
228 | it.setHighlightedCode(f.content)
229 | }
230 | }
231 | }
232 | }
233 | }
234 | }
235 | }
236 | }
237 |
238 | @Composable
239 | private fun filesStructure(list: List, selectedFile: MutableState) {
240 | fun putFileToDir(f: ProjectFile, path: List, dir: MutableMap): MutableMap {
241 | if (path.size == 1) {
242 | dir[path.first()] = f
243 | } else {
244 | val m = dir.getOrPut(path.first()) { mutableMapOf() } as MutableMap
245 | dir[path.first()] = putFileToDir(f, path.slice(1 until path.size), m)
246 | }
247 | return dir
248 | }
249 |
250 | val root = mutableMapOf()
251 | list.forEach { f -> putFileToDir(f, f.path.split('/'), root) }
252 | fileTree(0, root, selectedFile)
253 | }
254 |
255 | @Composable
256 | private fun fileTree(level: Int, map: Map, selectedFile: MutableState) {
257 | Ul(attrs = {
258 | if (level == 0) {
259 | classes("filetree")
260 | style {
261 | width(200.pt)
262 | paddingLeft(0.px)
263 | }
264 | } else {
265 | style {
266 | paddingLeft(10.px)
267 | }
268 | }
269 | }) {
270 | map.entries.sortedWith(FileEntryComparator).forEach { fileEntry ->
271 | val name = fileEntry.key
272 | val content = fileEntry.value as? Map
273 | if (content == null) {
274 | val f = fileEntry.value as ProjectFile
275 | Li(attrs = {
276 | onClick { selectedFile.value = f }
277 | style {
278 | cursor("pointer")
279 | }
280 | }) {
281 | if (selectedFile.value.path == f.path) B { Text(name) }
282 | else Text(name)
283 | }
284 | } else {
285 | Li {
286 | val id = "level-$level-$name-${Random.nextFloat()}"
287 | Input(InputType.Checkbox) { id(id) }
288 | Label(forId = id, attrs = {
289 | style {
290 | cursor("pointer")
291 | }
292 | }) { Text(name) }
293 | fileTree(level + 1, content, selectedFile)
294 | }
295 | }
296 | }
297 | }
298 | }
299 |
300 | private object FileEntryComparator : Comparator> {
301 | override fun compare(a: Map.Entry, b: Map.Entry): Int {
302 | val aIsDir = (a.value as? Map) != null
303 | val bIsDir = (b.value as? Map) != null
304 | return if (aIsDir == bIsDir) {
305 | a.key.compareTo(b.key)
306 | } else {
307 | if (aIsDir) -1 else 1
308 | }
309 | }
310 | }
--------------------------------------------------------------------------------
/src/jsMain/resources/logos.css:
--------------------------------------------------------------------------------
1 | .jetbrains-logo {
2 | display: inline-block;
3 | background-color: transparent;
4 | background-repeat: no-repeat;
5 | background-size: contain;
6 | vertical-align: top;
7 | text-indent: -9000px
8 | }
9 |
10 | .jetbrains-logo._logo-jetbrains {
11 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='120.1' height='130.2' viewBox='0 0 120.1 130.2' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='31.841' y1='120.558' x2='110.24' y2='73.24'%3E%3Cstop offset='0' stop-color='%23FCEE39'/%3E%3Cstop offset='1' stop-color='%23F37B3D'/%3E%3C/linearGradient%3E%3Cpath d='M118.6,71.8c0.9-0.8,1.4-1.9,1.5-3.2c0.1-2.6-1.8-4.7-4.4-4.9 c-1.2-0.1-2.4,0.4-3.3,1.1l0,0l-83.8,45.9c-1.9,0.8-3.6,2.2-4.7,4.1c-2.9,4.8-1.3,11,3.6,13.9c3.4,2,7.5,1.8,10.7-0.2l0,0l0,0 c0.2-0.2,0.5-0.3,0.7-0.5l78-54.8C117.3,72.9,118.4,72.1,118.6,71.8L118.6,71.8L118.6,71.8z' fill='url(%23a)'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='48.361' y1='6.908' x2='119.918' y2='69.555'%3E%3Cstop offset='0' stop-color='%23EF5A6B'/%3E%3Cstop offset='.57' stop-color='%23F26F4E'/%3E%3Cstop offset='1' stop-color='%23F37B3D'/%3E%3C/linearGradient%3E%3Cpath d='M118.8,65.1L118.8,65.1L55,2.5C53.6,1,51.6,0,49.3,0 c-4.3,0-7.7,3.5-7.7,7.7v0c0,2.1,0.8,3.9,2.1,5.3l0,0l0,0c0.4,0.4,0.8,0.7,1.2,1l67.4,57.7l0,0c0.8,0.7,1.8,1.2,3,1.3 c2.6,0.1,4.7-1.8,4.9-4.4C120.2,67.3,119.7,66,118.8,65.1z' fill='url(%23b)'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='52.947' y1='63.641' x2='10.538' y2='37.156'%3E%3Cstop offset='0' stop-color='%237C59A4'/%3E%3Cstop offset='.385' stop-color='%23AF4C92'/%3E%3Cstop offset='.765' stop-color='%23DC4183'/%3E%3Cstop offset='.957' stop-color='%23ED3D7D'/%3E%3C/linearGradient%3E%3Cpath d='M57.1,59.5C57,59.5,17.7,28.5,16.9,28l0,0l0,0c-0.6-0.3-1.2-0.6-1.8-0.9 c-5.8-2.2-12.2,0.8-14.4,6.6c-1.9,5.1,0.2,10.7,4.6,13.4l0,0l0,0C6,47.5,6.6,47.8,7.3,48c0.4,0.2,45.4,18.8,45.4,18.8l0,0 c1.8,0.8,3.9,0.3,5.1-1.2C59.3,63.7,59,61,57.1,59.5z' fill='url(%23c)'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='52.174' y1='3.702' x2='10.771' y2='37.897'%3E%3Cstop offset='0' stop-color='%23EF5A6B'/%3E%3Cstop offset='.364' stop-color='%23EE4E72'/%3E%3Cstop offset='1' stop-color='%23ED3D7D'/%3E%3C/linearGradient%3E%3Cpath d='M49.3,0c-1.7,0-3.3,0.6-4.6,1.5L4.9,28.3c-0.1,0.1-0.2,0.1-0.2,0.2l-0.1,0 l0,0c-1.7,1.2-3.1,3-3.9,5.1C-1.5,39.4,1.5,45.9,7.3,48c3.6,1.4,7.5,0.7,10.4-1.4l0,0l0,0c0.7-0.5,1.3-1,1.8-1.6l34.6-31.2l0,0 c1.8-1.4,3-3.6,3-6.1v0C57.1,3.5,53.6,0,49.3,0z' fill='url(%23d)'/%3E%3Cpath fill='%23000' d='M34.6 37.4H85.6V88.4H34.6z'/%3E%3Cpath fill='%23FFF' d='M39 78.8H58.1V82H39z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M38.8,50.8l1.5-1.4c0.4,0.5,0.8,0.8,1.3,0.8c0.6,0,0.9-0.4,0.9-1.2l0-5.3l2.3,0 l0,5.3c0,1-0.3,1.8-0.8,2.3c-0.5,0.5-1.3,0.8-2.3,0.8C40.2,52.2,39.4,51.6,38.8,50.8z'/%3E%3Cpath d='M45.3,43.8l6.7,0v1.9l-4.4,0V47l4,0l0,1.8l-4,0l0,1.3l4.5,0l0,2l-6.7,0 L45.3,43.8z'/%3E%3Cpath d='M55,45.8l-2.5,0l0-2l7.3,0l0,2l-2.5,0l0,6.3l-2.3,0L55,45.8z'/%3E%3Cpath d='M39,54l4.3,0c1,0,1.8,0.3,2.3,0.7c0.3,0.3,0.5,0.8,0.5,1.4v0 c0,1-0.5,1.5-1.3,1.9c1,0.3,1.6,0.9,1.6,2v0c0,1.4-1.2,2.3-3.1,2.3l-4.3,0L39,54z M43.8,56.6c0-0.5-0.4-0.7-1-0.7l-1.5,0l0,1.5 l1.4,0C43.4,57.3,43.8,57.1,43.8,56.6L43.8,56.6z M43,59l-1.8,0l0,1.5H43c0.7,0,1.1-0.3,1.1-0.8v0C44.1,59.2,43.7,59,43,59z'/%3E%3Cpath d='M46.8,54l3.9,0c1.3,0,2.1,0.3,2.7,0.9c0.5,0.5,0.7,1.1,0.7,1.9v0 c0,1.3-0.7,2.1-1.7,2.6l2,2.9l-2.6,0l-1.7-2.5h-1l0,2.5l-2.3,0L46.8,54z M50.6,58c0.8,0,1.2-0.4,1.2-1v0c0-0.7-0.5-1-1.2-1 l-1.5,0v2H50.6z'/%3E%3Cpath d='M56.8,54l2.2,0l3.5,8.4l-2.5,0l-0.6-1.5l-3.2,0l-0.6,1.5l-2.4,0L56.8,54z M58.8,59l-0.9-2.3L57,59L58.8,59z'/%3E%3Cpath d='M62.8,54l2.3,0l0,8.3l-2.3,0L62.8,54z'/%3E%3Cpath d='M65.7,54l2.1,0l3.4,4.4l0-4.4l2.3,0l0,8.3l-2,0L68,57.8l0,4.6l-2.3,0L65.7,54z'/%3E%3Cpath d='M73.7,61.1l1.3-1.5c0.8,0.7,1.7,1,2.7,1c0.6,0,1-0.2,1-0.6v0 c0-0.4-0.3-0.5-1.4-0.8c-1.8-0.4-3.1-0.9-3.1-2.6v0c0-1.5,1.2-2.7,3.2-2.7c1.4,0,2.5,0.4,3.4,1.1l-1.2,1.6 c-0.8-0.5-1.6-0.8-2.3-0.8c-0.6,0-0.8,0.2-0.8,0.5v0c0,0.4,0.3,0.5,1.4,0.8c1.9,0.4,3.1,1,3.1,2.6v0c0,1.7-1.3,2.7-3.4,2.7 C76.1,62.5,74.7,62,73.7,61.1z'/%3E%3C/g%3E%3C/svg%3E")
12 | }
13 |
14 | .jetbrains-logo._logo-jetbrains._size-1 {
15 | width: 40px;
16 | height: 40px
17 | }
18 |
19 | .jetbrains-logo._logo-jetbrains._size-2 {
20 | width: 60px;
21 | height: 60px
22 | }
23 |
24 | .jetbrains-logo._logo-jetbrains._size-3 {
25 | width: 75px;
26 | height: 75px
27 | }
28 |
29 | .jetbrains-logo._logo-jetbrains._size-4 {
30 | width: 100px;
31 | height: 100px
32 | }
33 |
34 | .jetbrains-logo._logo-jetbrains._size-5 {
35 | width: 150px;
36 | height: 150px
37 | }
38 |
39 | .jetbrains-logo._logo-jetbrains-square {
40 | background-image: url("data:image/svg+xml,%3Csvg data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 700 700'%3E%3Ctitle%3Ejetbrains-simple_2%3C/title%3E%3Cpath d='M0 0H700V700H0z'/%3E%3Cpath fill='%23fff' d='M60.379 568.75H322.879V612.5H60.379z'/%3E%3Cpath d='M57.428,184.315L77.8,165.083c5.542,6.682,10.758,10.594,17.929,10.594,7.823,0,12.877-5.378,12.877-15.972V87.5h31.457v72.367c0,14.343-3.586,24.448-11.246,32.109-7.5,7.5-18.254,11.572-31.294,11.572C77.638,203.548,65.577,195.236,57.428,184.315Z' fill='%23fff'/%3E%3Cpath fill='%23fff' d='M147.394 87.5L239.156 87.5 239.156 114.23 178.688 114.23 178.688 131.67 233.451 131.67 233.451 156.607 178.688 156.607 178.688 174.699 239.971 174.699 239.971 201.592 147.394 201.592 147.394 87.5z'/%3E%3Cpath fill='%23fff' d='M280.491 115.208L246.427 115.208 246.427 87.5 346.338 87.5 346.338 115.208 312.111 115.208 312.111 201.592 280.491 201.592 280.491 115.208z'/%3E%3Cpath d='M139.736,282.7c10.106-4.4,17.6-12.224,17.6-25.426v-0.326A25.675,25.675,0,0,0,150,238.364c-6.682-6.52-16.788-10.106-31.131-10.106H60.362V342.35H119.2c27.218,0,43.191-11.9,43.191-31.457v-0.326C162.392,295.083,153.591,287.26,139.736,282.7Zm-48.57-29.011h20.7c9.29,0,14.343,3.422,14.343,9.779v0.326c0,6.682-5.542,9.942-15.158,9.942H91.166V253.685Zm39.607,52.808c0,6.682-5.379,10.431-15.158,10.431H91.166V295.9h24.123c10.594,0,15.484,4.075,15.484,10.269v0.326Z' fill='%23fff'/%3E%3Cpath d='M335.8,227.444H305.325l-42.63,101.193-17.833-26.056c14.18-6.031,23.469-17.6,23.469-35.205V267.05c0-11.246-3.422-19.885-10.1-26.567-7.661-7.661-19.722-12.224-37.162-12.224H167.116V342.35h31.619V307.8h14.017l22.981,34.553H290l8.15-20.536h44.169l8.149,20.536h33.9Zm-99.093,42.05c0,8.312-6.357,13.529-16.951,13.529H198.736V255.477H219.6c10.432,0,17.114,4.564,17.114,13.692v0.325ZM307.444,297.2l12.877-32.271L333.033,297.2H307.444Z' fill='%23fff'/%3E%3Cpath fill='%23fff' d='M388.119 228.258H419.73800000000006V342.35H388.119z'/%3E%3Cpath fill='%23fff' d='M427.56 228.258L457.061 228.258 504.001 288.564 504.001 228.258 535.295 228.258 535.295 342.35 507.75 342.35 458.854 279.763 458.854 342.35 427.56 342.35 427.56 228.258z'/%3E%3Cpath d='M537.277,325.4l17.6-21.025c11.409,8.964,23.8,13.691,37,13.691,8.638,0,13.2-2.934,13.2-7.824v-0.325c0-4.89-3.749-7.335-19.4-11.084-24.286-5.541-43.03-12.387-43.03-35.694v-0.326c0-21.188,16.788-36.509,44.17-36.509,19.4,0,34.553,5.216,46.94,15.158L617.956,263.79c-10.431-7.5-21.84-11.246-31.946-11.246-7.66,0-11.409,3.1-11.409,7.334V260.2c0,5.216,3.912,7.5,19.885,11.083,26.078,5.7,42.377,14.18,42.377,35.531v0.326c0,23.307-18.418,37.161-46.126,37.161C570.526,344.306,551.457,337.95,537.277,325.4Z' fill='%23fff'/%3E%3C/svg%3E")
41 | }
42 |
43 | .jetbrains-logo._logo-jetbrains-square._size-1 {
44 | width: 40px;
45 | height: 40px
46 | }
47 |
48 | .jetbrains-logo._logo-jetbrains-square._size-2 {
49 | width: 60px;
50 | height: 60px
51 | }
52 |
53 | .jetbrains-logo._logo-jetbrains-square._size-3 {
54 | width: 75px;
55 | height: 75px
56 | }
57 |
58 | .jetbrains-logo._logo-jetbrains-square._size-4 {
59 | width: 100px;
60 | height: 100px
61 | }
62 |
63 | .jetbrains-logo._logo-jetbrains-square._size-5 {
64 | width: 150px;
65 | height: 150px
66 | }
67 |
68 | .jetbrains-logo._logo-appcode {
69 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3Cpath fill='%23247CE6' d='M59.2 55L70 26.3 37.3 19 33 31.2z'/%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='20.617' y1='57.755' x2='70' y2='57.755'%3E%3Cstop offset='.194' stop-color='%2300DAF0'/%3E%3Cstop offset='.903' stop-color='%23247CE6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M70 56.1L53.5 70 20.6 61.5 29.4 45.5z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='1.274' y1='17.415' x2='38.41' y2='17.415'%3E%3Cstop offset='.194' stop-color='%2300DAF0'/%3E%3Cstop offset='.903' stop-color='%23247CE6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M9.7 34.8L1.3 10.8 38.4 0 35.4 31z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='45.876' y1='72.222' x2='11.197' y2='23.824'%3E%3Cstop offset='.091' stop-color='%231DDF93'/%3E%3Cstop offset='.484' stop-color='%2300DAF0'/%3E%3Cstop offset='.903' stop-color='%23247CE6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M61.1 40.5L50.7 22.7 50.9 22.6 38.4 0 0 41.5 0 70 69.8 56.1z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cpath d='M24.5,19h3.6l7.6,17.9h-4.1l-1.6-4h-7.5l-1.6,4h-4L24.5,19z M28.6,29.4l-2.4-5.8l-2.4,5.8H28.6z' fill='%23FFF'/%3E%3Cpath d='M34.7,28.1L34.7,28.1c0-5.2,3.9-9.4,9.4-9.4c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2 c-3,0-5.2,2.5-5.2,5.6V28c0,3.1,2.1,5.7,5.2,5.7c2.1,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.9,2-3.9,3.2-7.4,3.2 C38.6,37.3,34.7,33.2,34.7,28.1' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
70 | }
71 |
72 | .jetbrains-logo._logo-appcode._size-1 {
73 | width: 40px;
74 | height: 40px
75 | }
76 |
77 | .jetbrains-logo._logo-appcode._size-2 {
78 | width: 60px;
79 | height: 60px
80 | }
81 |
82 | .jetbrains-logo._logo-appcode._size-3 {
83 | width: 75px;
84 | height: 75px
85 | }
86 |
87 | .jetbrains-logo._logo-appcode._size-4 {
88 | width: 100px;
89 | height: 100px
90 | }
91 |
92 | .jetbrains-logo._logo-appcode._size-5 {
93 | width: 150px;
94 | height: 150px
95 | }
96 |
97 | .jetbrains-logo._logo-clion {
98 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='22.254' y1='15.137' x2='45.654' y2='15.137'%3E%3Cstop offset='0' stop-color='%23ED358C'/%3E%3Cstop offset='.155' stop-color='%23E9388C'/%3E%3Cstop offset='.297' stop-color='%23DE418C'/%3E%3Cstop offset='.433' stop-color='%23CC508C'/%3E%3Cstop offset='.566' stop-color='%23B2658D'/%3E%3Cstop offset='.697' stop-color='%2390808D'/%3E%3Cstop offset='.826' stop-color='%2367A18E'/%3E%3Cstop offset='.951' stop-color='%2337C78F'/%3E%3Cstop offset='1' stop-color='%2322D88F'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M26.9 28.4L22.3 30.3 26.4 0 42.6 8.8z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='17.8' y1='8.982' x2='7.505' y2='78.065'%3E%3Cstop offset='.091' stop-color='%2322D88F'/%3E%3Cstop offset='.903' stop-color='%23029DE0'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M24.3 42L26.7 0 6.5 12.7 0 51.5z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='63.836' y1='6.492' x2='-6.583' y2='80.865'%3E%3Cstop offset='.091' stop-color='%2322D88F'/%3E%3Cstop offset='.903' stop-color='%23029DE0'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M68.6 21L59.6 2.7 42.6 8.8 30.1 22.7 0 51.5 22.7 68 51.2 42.3z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='40.114' y1='49.366' x2='66.875' y2='53.171'%3E%3Cstop offset='.091' stop-color='%2322D88F'/%3E%3Cstop offset='.903' stop-color='%23029DE0'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M29.4 29.9L25.5 53.9 41.5 66.2 59 70 70 45z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M17.2,28.1L17.2,28.1c0-5.1,3.8-9.3,9.3-9.3c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2 c-3,0-5.2,2.5-5.2,5.6V28c0,3.1,2.1,5.6,5.2,5.6c2,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.8,2-3.9,3.2-7.3,3.2 C21.1,37.3,17.2,33.2,17.2,28.1' fill='%23FFF'/%3E%3Cpath d='M36.4,19.1h3.9v14.6h7.8v3.3H36.4V19.1z' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
99 | }
100 |
101 | .jetbrains-logo._logo-clion._size-1 {
102 | width: 40px;
103 | height: 40px
104 | }
105 |
106 | .jetbrains-logo._logo-clion._size-2 {
107 | width: 60px;
108 | height: 60px
109 | }
110 |
111 | .jetbrains-logo._logo-clion._size-3 {
112 | width: 75px;
113 | height: 75px
114 | }
115 |
116 | .jetbrains-logo._logo-clion._size-4 {
117 | width: 100px;
118 | height: 100px
119 | }
120 |
121 | .jetbrains-logo._logo-clion._size-5 {
122 | width: 150px;
123 | height: 150px
124 | }
125 |
126 | .jetbrains-logo._logo-datagrip {
127 | background-image: url("data:image/svg+xml,%3Csvg version='1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3Cpath fill='%239775F8' d='M65.5 10.9L70 39.5 53 49.4 49.8 33.2z'/%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='41.069' y1='54.357' x2='46.521' y2='67.944' gradientTransform='matrix(1 0 0 -1 0 72)'%3E%3Cstop offset='0' stop-color='%239775F8'/%3E%3Cstop offset='.952' stop-color='%2322D88F'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M65.5 10.9L40.5 0 19.4 17.5 49.8 33.2z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='17.067' y1='35.739' x2='24.146' y2='4.895' gradientTransform='matrix(1 0 0 -1 0 72)'%3E%3Cstop offset='0' stop-color='%239775F8'/%3E%3Cstop offset='.214' stop-color='%23689CCE'/%3E%3Cstop offset='.423' stop-color='%2342BDAC'/%3E%3Cstop offset='.59' stop-color='%232BD197'/%3E%3Cstop offset='.694' stop-color='%2322D88F'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M47.3 70L18 30.6 9.3 36.4 0.6 62.5z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='4.9' y1='37.969' x2='66.239' y2='4.102' gradientTransform='matrix(1 0 0 -1 0 72)'%3E%3Cstop offset='.075' stop-color='%2322D88F'/%3E%3Cstop offset='.72' stop-color='%239775F8'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M52.8 50.1L32.3 36.6 0 32.3 47.3 70z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='0' y1='45.15' x2='61.646' y2='45.15' gradientTransform='matrix(1 0 0 -1 0 72)'%3E%3Cstop offset='.075' stop-color='%2322D88F'/%3E%3Cstop offset='.266' stop-color='%235AB0B4'/%3E%3Cstop offset='.565' stop-color='%23B86CF2'/%3E%3Cstop offset='1' stop-color='%23FF59E6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M0 0.5L0 32.3 60.8 53.2 65.5 10.9z'/%3E%3Cg%3E%3Cpath d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.8,19h7c5.6,0,9.5,3.9,9.5,8.9V28c0,5-3.9,8.9-9.5,8.9h-7V19z M21.7,22.6v10.8h3 c3.2,0,5.4-2.2,5.4-5.3V28c0-3.2-2.2-5.4-5.4-5.4H21.7z'/%3E%3Cpath d='M35,28L35,28c0-5.1,4-9.3,9.4-9.3c3.2,0,5.2,0.9,7,2.5l-2.5,3c-1.4-1.2-2.6-1.8-4.7-1.8 c-2.9,0-5.1,2.5-5.1,5.6V28c0,3.3,2.2,5.7,5.4,5.7c1.4,0,2.7-0.4,3.7-1.1V30h-4v-3.4H52v7.8c-1.8,1.6-4.4,2.8-7.6,2.8 C38.8,37.2,35,33.3,35,28z'/%3E%3C/g%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3C/g%3E%3C/svg%3E")
128 | }
129 |
130 | .jetbrains-logo._logo-datagrip._size-1 {
131 | width: 40px;
132 | height: 40px
133 | }
134 |
135 | .jetbrains-logo._logo-datagrip._size-2 {
136 | width: 60px;
137 | height: 60px
138 | }
139 |
140 | .jetbrains-logo._logo-datagrip._size-3 {
141 | width: 75px;
142 | height: 75px
143 | }
144 |
145 | .jetbrains-logo._logo-datagrip._size-4 {
146 | width: 100px;
147 | height: 100px
148 | }
149 |
150 | .jetbrains-logo._logo-datagrip._size-5 {
151 | width: 150px;
152 | height: 150px
153 | }
154 |
155 | .jetbrains-logo._logo-dotcover {
156 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='37.049' y1='55.637' x2='23.558' y2='5.422'%3E%3Cstop offset='.048' stop-color='%237866FF'/%3E%3Cstop offset='.135' stop-color='%238265FA'/%3E%3Cstop offset='.281' stop-color='%239C64EE'/%3E%3Cstop offset='.467' stop-color='%23C661D9'/%3E%3Cstop offset='.608' stop-color='%23EB5FC7'/%3E%3Cstop offset='.729' stop-color='%23FA6398'/%3E%3Cstop offset='.769' stop-color='%23FF6488'/%3E%3Cstop offset='.995' stop-color='%23FF7500'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M42.8 0L0 4.8 0 26.8 10.7 62.6 64.6 48.9z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='69.11' y1='50.451' x2='57.169' y2='46.132'%3E%3Cstop offset='.247' stop-color='%237866FF'/%3E%3Cstop offset='.346' stop-color='%238F5FFA'/%3E%3Cstop offset='.531' stop-color='%23B353F1'/%3E%3Cstop offset='.705' stop-color='%23CD4AEB'/%3E%3Cstop offset='.859' stop-color='%23DD45E7'/%3E%3Cstop offset='.979' stop-color='%23E343E6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M70 41.3L65.9 22.2 56.7 34.9 50.3 54.2 48.2 70 64 60z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='57.012' y1='46.84' x2='23.73' y2='32.867'%3E%3Cstop offset='.006' stop-color='%23E343E6'/%3E%3Cstop offset='.064' stop-color='%23E649CA'/%3E%3Cstop offset='.19' stop-color='%23EF5982'/%3E%3Cstop offset='.372' stop-color='%23FD7110'/%3E%3Cstop offset='.398' stop-color='%23FF7500'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M65.9 22.2L52.5 15.8 36.8 17.2 21.4 27.9 18.3 47.1 31.8 65.5 48.2 70z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.5,19.1h7c5.6,0,9.5,3.9,9.5,8.9v0.1c0,5-3.9,8.9-9.5,8.9h-7V19.1z M21.4,22.7v10.8h3 c3.2,0,5.4-2.2,5.4-5.3v-0.1c0-3.2-2.2-5.4-5.4-5.4H21.4z'/%3E%3Cpath d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M35.4,28.1L35.4,28.1c0-5.1,3.8-9.3,9.3-9.3c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2 c-3,0-5.2,2.5-5.2,5.6v0.1c0,3.1,2.1,5.6,5.2,5.6c2,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.8,2-3.9,3.2-7.3,3.2 C39.4,37.3,35.4,33.3,35.4,28.1'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
157 | }
158 |
159 | .jetbrains-logo._logo-dotcover._size-1 {
160 | width: 40px;
161 | height: 40px
162 | }
163 |
164 | .jetbrains-logo._logo-dotcover._size-2 {
165 | width: 60px;
166 | height: 60px
167 | }
168 |
169 | .jetbrains-logo._logo-dotcover._size-3 {
170 | width: 75px;
171 | height: 75px
172 | }
173 |
174 | .jetbrains-logo._logo-dotcover._size-4 {
175 | width: 100px;
176 | height: 100px
177 | }
178 |
179 | .jetbrains-logo._logo-dotcover._size-5 {
180 | width: 150px;
181 | height: 150px
182 | }
183 |
184 | .jetbrains-logo._logo-dotmemory {
185 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='20.477' y1='18.782' x2='32.464' y2='68.958'%3E%3Cstop offset='0' stop-color='%237866FF'/%3E%3Cstop offset='.023' stop-color='%237E64FE'/%3E%3Cstop offset='.195' stop-color='%23AA56F3'/%3E%3Cstop offset='.349' stop-color='%23C94CEC'/%3E%3Cstop offset='.48' stop-color='%23DC45E8'/%3E%3Cstop offset='.57' stop-color='%23E343E6'/%3E%3Cstop offset='.641' stop-color='%23E859BC'/%3E%3Cstop offset='.819' stop-color='%23F48F58'/%3E%3Cstop offset='.942' stop-color='%23FCB019'/%3E%3Cstop offset='1' stop-color='%23FFBD00'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M8 65.1L0.1 37.6 51.7 45.2 44.3 70z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='49.418' y1='41.451' x2='32.72' y2='7.516'%3E%3Cstop offset='0' stop-color='%237866FF'/%3E%3Cstop offset='.202' stop-color='%23965CF8'/%3E%3Cstop offset='.64' stop-color='%23E343E6'/%3E%3Cstop offset='.968' stop-color='%23FFBD00'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M23.5 0.1L42.1 5.4 63.2 0 70 46.3 13.4 37.6z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='26.353' y1='53.604' x2='36.21' y2='30.222'%3E%3Cstop offset='.118' stop-color='%23E343E6'/%3E%3Cstop offset='.211' stop-color='%23C84CEC'/%3E%3Cstop offset='.338' stop-color='%23AB55F3'/%3E%3Cstop offset='.472' stop-color='%23955DF8'/%3E%3Cstop offset='.618' stop-color='%238562FC'/%3E%3Cstop offset='.781' stop-color='%237B65FE'/%3E%3Cstop offset='1' stop-color='%237866FF'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M70 46.1L67.3 28.9 25.6 14.4 0.1 19.9 0 37.7 49.6 51.3z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cpath d='M17.4,19h6.9c5.6,0,9.5,3.9,9.5,8.9V28c0,5-3.9,9-9.5,9h-6.9V19z M21.3,22.6v10.8h2.9 c3.2,0,5.4-2.2,5.4-5.4V28c0-3.2-2.2-5.4-5.4-5.4H21.3z' fill='%23FFF'/%3E%3Cpath fill='%23FFF' d='M34.8 19.1L39.1 19.1 43.7 26.6 48.4 19.1 52.6 19.1 52.6 36.9 48.7 36.9 48.7 25.2 43.7 32.8 43.6 32.8 38.7 25.3 38.7 36.9 34.8 36.9z'/%3E%3C/g%3E%3C/svg%3E")
186 | }
187 |
188 | .jetbrains-logo._logo-dotmemory._size-1 {
189 | width: 40px;
190 | height: 40px
191 | }
192 |
193 | .jetbrains-logo._logo-dotmemory._size-2 {
194 | width: 60px;
195 | height: 60px
196 | }
197 |
198 | .jetbrains-logo._logo-dotmemory._size-3 {
199 | width: 75px;
200 | height: 75px
201 | }
202 |
203 | .jetbrains-logo._logo-dotmemory._size-4 {
204 | width: 100px;
205 | height: 100px
206 | }
207 |
208 | .jetbrains-logo._logo-dotmemory._size-5 {
209 | width: 150px;
210 | height: 150px
211 | }
212 |
213 | .jetbrains-logo._logo-dotpeek {
214 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='10.879' y1='26.793' x2='47.049' y2='63.717'%3E%3Cstop offset='.097' stop-color='%23E343E6'/%3E%3Cstop offset='.108' stop-color='%23D948E8'/%3E%3Cstop offset='.165' stop-color='%23AC5DEF'/%3E%3Cstop offset='.222' stop-color='%23876FF5'/%3E%3Cstop offset='.279' stop-color='%236B7DF9'/%3E%3Cstop offset='.336' stop-color='%235687FC'/%3E%3Cstop offset='.392' stop-color='%234A8DFE'/%3E%3Cstop offset='.446' stop-color='%23468FFF'/%3E%3Cstop offset='.935' stop-color='%2300CAFF'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M44.3 20.9L5.2 30.3 0 40.8 14.1 70 49.3 63.9z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='9.66' y1='55.746' x2='32.843' y2='36.427'%3E%3Cstop offset='.097' stop-color='%23E343E6'/%3E%3Cstop offset='.118' stop-color='%23DE45E7'/%3E%3Cstop offset='.289' stop-color='%23B951F0'/%3E%3Cstop offset='.462' stop-color='%239D5AF6'/%3E%3Cstop offset='.632' stop-color='%238861FB'/%3E%3Cstop offset='.802' stop-color='%237C65FE'/%3E%3Cstop offset='.968' stop-color='%237866FF'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M65.8 31.5L38.2 14 0 22.1 0 40.8 62.6 53.3z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='39.855' y1='16.927' x2='56.356' y2='50.653'%3E%3Cstop offset='.199' stop-color='%23E343E6'/%3E%3Cstop offset='.31' stop-color='%23DA46E8'/%3E%3Cstop offset='.491' stop-color='%23C24EEE'/%3E%3Cstop offset='.718' stop-color='%239A5BF7'/%3E%3Cstop offset='.887' stop-color='%237866FF'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M70 31.3L39.6 0 15.8 7.2 23.6 30.9 62.6 53.3z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='19.875' y1='18.305' x2='61.328' y2='8.256'%3E%3Cstop offset='.097' stop-color='%23E343E6'/%3E%3Cstop offset='.175' stop-color='%23DA48E7'/%3E%3Cstop offset='.302' stop-color='%23C157EA'/%3E%3Cstop offset='.464' stop-color='%23996FEE'/%3E%3Cstop offset='.653' stop-color='%236290F4'/%3E%3Cstop offset='.863' stop-color='%231CB9FC'/%3E%3Cstop offset='.941' stop-color='%2300CAFF'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M64.5 19.6L61.8 0 51.3 0 39.6 0 15.8 7.2 23.6 30.9z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.5,19.1h7c5.6,0,9.5,3.9,9.5,8.9v0.1c0,5-3.9,8.9-9.5,8.9h-7V19.1z M21.4,22.7v10.8h3 c3.2,0,5.4-2.2,5.4-5.3v-0.1c0-3.2-2.2-5.4-5.4-5.4H21.4z'/%3E%3Cpath d='M35.6,19.1h7.3c4.3,0,6.9,2.5,6.9,6.2v0.1c0,4.1-3.2,6.3-7.2,6.3h-3V37h-3.9V19.1z M42.6,28.1 c2,0,3.1-1.2,3.1-2.7v-0.1c0-1.8-1.2-2.7-3.2-2.7h-3v5.5H42.6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
215 | }
216 |
217 | .jetbrains-logo._logo-dotpeek._size-1 {
218 | width: 40px;
219 | height: 40px
220 | }
221 |
222 | .jetbrains-logo._logo-dotpeek._size-2 {
223 | width: 60px;
224 | height: 60px
225 | }
226 |
227 | .jetbrains-logo._logo-dotpeek._size-3 {
228 | width: 75px;
229 | height: 75px
230 | }
231 |
232 | .jetbrains-logo._logo-dotpeek._size-4 {
233 | width: 100px;
234 | height: 100px
235 | }
236 |
237 | .jetbrains-logo._logo-dotpeek._size-5 {
238 | width: 150px;
239 | height: 150px
240 | }
241 |
242 | .jetbrains-logo._logo-dottrace {
243 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='-1.332' y1='43.737' x2='67.042' y2='26.097'%3E%3Cstop offset='.124' stop-color='%237866FF'/%3E%3Cstop offset='.538' stop-color='%23FE2EB6'/%3E%3Cstop offset='.855' stop-color='%23FD0486'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M67.3 16L43.7 0 0 31.1 11.1 70 58.9 60.3z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='45.915' y1='38.91' x2='67.658' y2='9.099'%3E%3Cstop offset='.124' stop-color='%23FF0080'/%3E%3Cstop offset='.259' stop-color='%23FE0385'/%3E%3Cstop offset='.411' stop-color='%23FA0C92'/%3E%3Cstop offset='.571' stop-color='%23F41BA9'/%3E%3Cstop offset='.736' stop-color='%23EB2FC8'/%3E%3Cstop offset='.866' stop-color='%23E343E6'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M67.3 16L43.7 0 38 15.7 38 47.8 70 47.8z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.4,19.1h6.9c5.6,0,9.5,3.8,9.5,8.9V28c0,5-3.9,8.9-9.5,8.9h-6.9V19.1z M21.4,22.7v10.7h3 c3.2,0,5.4-2.2,5.4-5.3V28c0-3.2-2.2-5.4-5.4-5.4H21.4z'/%3E%3Cpath d='M40.3 22.7L34.9 22.7 34.9 19.1 49.6 19.1 49.6 22.7 44.2 22.7 44.2 37 40.3 37z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
244 | }
245 |
246 | .jetbrains-logo._logo-dottrace._size-1 {
247 | width: 40px;
248 | height: 40px
249 | }
250 |
251 | .jetbrains-logo._logo-dottrace._size-2 {
252 | width: 60px;
253 | height: 60px
254 | }
255 |
256 | .jetbrains-logo._logo-dottrace._size-3 {
257 | width: 75px;
258 | height: 75px
259 | }
260 |
261 | .jetbrains-logo._logo-dottrace._size-4 {
262 | width: 100px;
263 | height: 100px
264 | }
265 |
266 | .jetbrains-logo._logo-dottrace._size-5 {
267 | width: 150px;
268 | height: 150px
269 | }
270 |
271 | .jetbrains-logo._logo-gogland {
272 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='218.31' y1='276.731' x2='206.336' y2='294.988' gradientTransform='translate(-286.906 -405.031) scale(1.5625)'%3E%3Cstop offset='.174' stop-color='%23078EFC'/%3E%3Cstop offset='.204' stop-color='%23118AFC'/%3E%3Cstop offset='.435' stop-color='%235971FC'/%3E%3Cstop offset='.627' stop-color='%238E5EFC'/%3E%3Cstop offset='.77' stop-color='%23AF52FC'/%3E%3Cstop offset='.849' stop-color='%23BB4EFC'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M57.274,22.361l9.541,21.197l-13.49,23.045L20.922,40.202L37.493,24.23L57.274,22.361z'/%3E%3Cpath fill='%23BB4EFC' d='M43.499,42.747l9.826,23.857L23.39,56.314l-2.468-16.111L43.499,42.747z'/%3E%3Cpath fill='%23078EFC' d='M24.281,9.433l13.776,7.06l-12.398,37.54L0.69,53.773l5.364-11.895L0.69,26.677L24.281,9.433z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='188.25' y1='278.506' x2='212.533' y2='260.237' gradientTransform='translate(-286.906 -405.031) scale(1.5625)'%3E%3Cstop offset='.174' stop-color='%23078EFC'/%3E%3Cstop offset='.204' stop-color='%23118AFC'/%3E%3Cstop offset='.435' stop-color='%235971FC'/%3E%3Cstop offset='.627' stop-color='%238E5EFC'/%3E%3Cstop offset='.77' stop-color='%23AF52FC'/%3E%3Cstop offset='.849' stop-color='%23BB4EFC'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M41.563,0.479l6.515,22.17L0.69,26.677L15.761,0.479H41.563z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='189.941' y1='296.496' x2='220.469' y2='276.879' gradientTransform='translate(-286.906 -405.031) scale(1.5625)'%3E%3Cstop offset='0' stop-color='%23078EFC'/%3E%3Cstop offset='.106' stop-color='%2315A7D3'/%3E%3Cstop offset='.228' stop-color='%2323BFAA'/%3E%3Cstop offset='.348' stop-color='%232DD28B'/%3E%3Cstop offset='.463' stop-color='%2335DF74'/%3E%3Cstop offset='.573' stop-color='%2339E767'/%3E%3Cstop offset='.67' stop-color='%233BEA62'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M66.815 14.519L39.091 21.099 0.69 53.773 25.458 66.604 46.973 44.423z'/%3E%3Cg%3E%3Cpath d='M11.711 11.5H55.794V55.583H11.711z'/%3E%3Cpath fill='%23FFF' d='M16.119 48.309H32.65V50.954H16.119z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M14.607,25.88v-0.054c-0.18-5.295,3.967-9.734,9.262-9.913c0.09-0.003,0.179-0.005,0.269-0.005 c2.64-0.135,5.22,0.815,7.142,2.63l-2.52,3.206c-1.251-1.272-2.969-1.975-4.753-1.945c-3.083,0.226-5.41,2.889-5.22,5.974v0.054 c-0.258,3.091,2.039,5.805,5.13,6.063c0.125,0.01,0.251,0.017,0.377,0.019c1.347,0.04,2.67-0.365,3.765-1.151v-2.74h-4.025v-3.643 h7.895v8.328c-2.113,1.955-4.886,3.041-7.765,3.043c-5.162,0.123-9.446-3.963-9.569-9.125c0,0,0,0,0,0 C14.59,26.374,14.594,26.127,14.607,25.88z'/%3E%3Cpath d='M33.609,25.88v-0.054c-0.141-5.335,4.069-9.774,9.405-9.915s9.774,4.069,9.915,9.405 c0.004,0.152,0.004,0.305,0.001,0.457v0.054c0.141,5.335-4.069,9.774-9.405,9.915c-5.335,0.141-9.774-4.069-9.915-9.405l0,0 C33.606,26.185,33.606,26.033,33.609,25.88z M48.75,25.88v-0.054c0.186-3.14-2.209-5.835-5.349-6.021 c-0.053-0.003-0.105-0.005-0.158-0.007c-3.096,0.078-5.542,2.65-5.464,5.746c0,0,0,0,0,0c0.002,0.076,0.005,0.152,0.01,0.229 v0.054c-0.186,3.14,2.209,5.835,5.349,6.021c0.053,0.003,0.105,0.005,0.158,0.007c3.096-0.078,5.542-2.65,5.464-5.746c0,0,0,0,0,0 C48.758,26.033,48.755,25.956,48.75,25.88z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
273 | }
274 |
275 | .jetbrains-logo._logo-gogland._size-1 {
276 | width: 40px;
277 | height: 40px
278 | }
279 |
280 | .jetbrains-logo._logo-gogland._size-2 {
281 | width: 60px;
282 | height: 60px
283 | }
284 |
285 | .jetbrains-logo._logo-gogland._size-3 {
286 | width: 75px;
287 | height: 75px
288 | }
289 |
290 | .jetbrains-logo._logo-gogland._size-4 {
291 | width: 100px;
292 | height: 100px
293 | }
294 |
295 | .jetbrains-logo._logo-gogland._size-5 {
296 | width: 150px;
297 | height: 150px
298 | }
299 |
300 | .jetbrains-logo._logo-hub {
301 | background-image: url("data:image/svg+xml,%3Csvg version='1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' viewBox='0 0 70 70' width='70' height='70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='40.415' y1='69.001' x2='39.585' y2='30.566' gradientTransform='matrix(1 0 0 -1 0 69.89)'%3E%3Cstop offset='.328' stop-color='%2300B8F1'/%3E%3Cstop offset='.973' stop-color='%239758FB'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M61.3,0.9c-1.7-0.8-3.6-1-5.5-0.8c-0.3,0-45.3,3.8-45.3,3.8l31.8,37.5l5.8,0.3L66.3,22 C72.4,15.9,71.1,5,61.3,0.9z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='58.345' y1='64.017' x2='11.932' y2='13.636'%3E%3Cstop offset='0' stop-color='%23FFEE45'/%3E%3Cstop offset='1' stop-color='%239758FB'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M53.6,47.2l-1.3,2l-16-19.5L20.8,40.1L46.5,68c0.5,0.5,1.2,0.9,1.9,1.3c1.4,0.7,3,0.9,4.6,0.4 c1.5-0.4,2.6-1.2,3.5-2.1c0.1-0.1,10.8-10.7,10.8-10.7L53.6,47.2z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='31.025' y1='60.401' x2='21.392' y2='39.808' gradientTransform='matrix(1 0 0 -1 0 69.89)'%3E%3Cstop offset='.328' stop-color='%2300B8F1'/%3E%3Cstop offset='.79' stop-color='%239758FB'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M45.7,41.6L19.6,8.4l0,0c-1.1-1.6-2.8-2.9-5-3.8c-1.7-0.7-3.7-0.9-5.5-0.5 C-0.5,6.2-2.7,16.7,3.5,22.3l18.1,18.6L45.7,41.6z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='-3.259' y1='17.766' x2='68.816' y2='17.766' gradientTransform='matrix(1 0 0 -1 0 69.89)'%3E%3Cstop offset='0' stop-color='%2300B8F1'/%3E%3Cstop offset='.306' stop-color='%239758FB'/%3E%3Cstop offset='.989' stop-color='%23FFEE45'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M63.2,40.5c-3.4-1-5.3-0.7-9.8-0.8l-38-5.4L4.5,44.7c-6.9,6.8-5.8,18.7,4.4,23.8 c2.6,1.3,5.5,1.7,8.2,1.3l0,0c19.3-3.6,43.5-9.4,43.7-9.4c0.4-0.1,0.9-0.2,1.3-0.3c6.3-1.9,8.9-7.8,7.4-12.8 C68.7,44.5,66.5,41.5,63.2,40.5z'/%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.4,19.1h4v7.2h7.4v-7.2h4v18.1h-4v-7.3h-7.4v7.3h-4V19.1z'/%3E%3Cpath d='M35.7,19.1h8.4c2.1,0,3.7,0.6,4.7,1.6c0.8,0.8,1.2,1.8,1.2,3.1v0.1c0,2-1.1,3.2-2.4,3.9 c2.1,0.8,3.4,2,3.4,4.5v0.1c0,3.3-2.7,5-6.8,5h-8.6V19.1H35.7z M46.2,24.4c0-1.2-0.9-1.9-2.6-1.9h-3.9v3.8h3.7 C45.1,26.4,46.2,25.8,46.2,24.4L46.2,24.4z M44.2,29.7h-4.6v4h4.7c1.8,0,2.8-0.6,2.8-2v-0.1C47.2,30.5,46.3,29.7,44.2,29.7z'/%3E%3C/g%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3C/svg%3E")
302 | }
303 |
304 | .jetbrains-logo._logo-hub._size-1 {
305 | width: 40px;
306 | height: 40px
307 | }
308 |
309 | .jetbrains-logo._logo-hub._size-2 {
310 | width: 60px;
311 | height: 60px
312 | }
313 |
314 | .jetbrains-logo._logo-hub._size-3 {
315 | width: 75px;
316 | height: 75px
317 | }
318 |
319 | .jetbrains-logo._logo-hub._size-4 {
320 | width: 100px;
321 | height: 100px
322 | }
323 |
324 | .jetbrains-logo._logo-hub._size-5 {
325 | width: 150px;
326 | height: 150px
327 | }
328 |
329 | .jetbrains-logo._logo-intellij-idea {
330 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='.79' y1='40.089' x2='33.317' y2='40.089'%3E%3Cstop offset='.258' stop-color='%23F97A12'/%3E%3Cstop offset='.459' stop-color='%23B07B58'/%3E%3Cstop offset='.724' stop-color='%23577BAE'/%3E%3Cstop offset='.91' stop-color='%231E7CE5'/%3E%3Cstop offset='1' stop-color='%23087CFA'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M17.7 54.6L0.8 41.2 9.2 25.6 33.3 35z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='25.767' y1='24.88' x2='79.424' y2='54.57'%3E%3Cstop offset='0' stop-color='%23F97A12'/%3E%3Cstop offset='.072' stop-color='%23CB7A3E'/%3E%3Cstop offset='.154' stop-color='%239E7B6A'/%3E%3Cstop offset='.242' stop-color='%23757B91'/%3E%3Cstop offset='.334' stop-color='%23537BB1'/%3E%3Cstop offset='.432' stop-color='%23387CCC'/%3E%3Cstop offset='.538' stop-color='%23237CE0'/%3E%3Cstop offset='.655' stop-color='%23147CEF'/%3E%3Cstop offset='.792' stop-color='%230B7CF7'/%3E%3Cstop offset='1' stop-color='%23087CFA'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M70 18.7L68.7 59.2 41.8 70 25.6 59.6 49.3 35 38.9 12.3 48.2 1.1z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='63.228' y1='42.915' x2='48.29' y2='-1.719'%3E%3Cstop offset='0' stop-color='%23FE315D'/%3E%3Cstop offset='.078' stop-color='%23CB417E'/%3E%3Cstop offset='.16' stop-color='%239E4E9B'/%3E%3Cstop offset='.247' stop-color='%23755BB4'/%3E%3Cstop offset='.339' stop-color='%235365CA'/%3E%3Cstop offset='.436' stop-color='%23386DDB'/%3E%3Cstop offset='.541' stop-color='%232374E9'/%3E%3Cstop offset='.658' stop-color='%231478F3'/%3E%3Cstop offset='.794' stop-color='%230B7BF8'/%3E%3Cstop offset='1' stop-color='%23087CFA'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M70 18.7L48.7 43.9 38.9 12.3 48.2 1.1z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='10.72' y1='16.473' x2='55.524' y2='90.58'%3E%3Cstop offset='0' stop-color='%23FE315D'/%3E%3Cstop offset='.04' stop-color='%23F63462'/%3E%3Cstop offset='.104' stop-color='%23DF3A71'/%3E%3Cstop offset='.167' stop-color='%23C24383'/%3E%3Cstop offset='.291' stop-color='%23AD4A91'/%3E%3Cstop offset='.55' stop-color='%23755BB4'/%3E%3Cstop offset='.917' stop-color='%231D76ED'/%3E%3Cstop offset='1' stop-color='%23087CFA'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M33.7 58.1L5.6 68.3 10.1 52.5 16 33.1 0 27.7 10.1 0 32.1 2.7 53.7 27.4z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.7 13.5H56.900000000000006V56.7H13.7z'/%3E%3Cpath fill='%23FFF' d='M17.7 48.6H33.9V51.300000000000004H17.7z'/%3E%3Cpath fill='%23FFF' d='M29.4 22.4L29.4 19.1 20.4 19.1 20.4 22.4 23 22.4 23 33.7 20.4 33.7 20.4 37 29.4 37 29.4 33.7 26.9 33.7 26.9 22.4z'/%3E%3Cpath d='M38,37.3c-1.4,0-2.6-0.3-3.5-0.8c-0.9-0.5-1.7-1.2-2.3-1.9l2.5-2.8c0.5,0.6,1,1,1.5,1.3 c0.5,0.3,1.1,0.5,1.7,0.5c0.7,0,1.3-0.2,1.8-0.7c0.4-0.5,0.6-1.2,0.6-2.3V19.1h4v11.7c0,1.1-0.1,2-0.4,2.8c-0.3,0.8-0.7,1.4-1.3,2 c-0.5,0.5-1.2,1-2,1.2C39.8,37.1,39,37.3,38,37.3' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
331 | }
332 |
333 | .jetbrains-logo._logo-intellij-idea._size-1 {
334 | width: 40px;
335 | height: 40px
336 | }
337 |
338 | .jetbrains-logo._logo-intellij-idea._size-2 {
339 | width: 60px;
340 | height: 60px
341 | }
342 |
343 | .jetbrains-logo._logo-intellij-idea._size-3 {
344 | width: 75px;
345 | height: 75px
346 | }
347 |
348 | .jetbrains-logo._logo-intellij-idea._size-4 {
349 | width: 100px;
350 | height: 100px
351 | }
352 |
353 | .jetbrains-logo._logo-intellij-idea._size-5 {
354 | width: 150px;
355 | height: 150px
356 | }
357 |
358 | .jetbrains-logo._logo-kotlin {
359 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' viewBox='0 0 60 60' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='15.959' y1='-13.014' x2='44.307' y2='15.333' gradientTransform='matrix(1 0 0 -1 0 61)'%3E%3Cstop offset='.097' stop-color='%230095D5'/%3E%3Cstop offset='.301' stop-color='%23238AD9'/%3E%3Cstop offset='.621' stop-color='%23557BDE'/%3E%3Cstop offset='.864' stop-color='%237472E2'/%3E%3Cstop offset='1' stop-color='%23806EE3'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M0 60L30.1 29.9 60 60z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='4.209' y1='48.941' x2='20.673' y2='65.405' gradientTransform='matrix(1 0 0 -1 0 61)'%3E%3Cstop offset='.118' stop-color='%230095D5'/%3E%3Cstop offset='.418' stop-color='%233C83DC'/%3E%3Cstop offset='.696' stop-color='%236D74E1'/%3E%3Cstop offset='.833' stop-color='%23806EE3'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M0 0L30.1 0 0 32.5z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='-10.102' y1='5.836' x2='45.731' y2='61.669' gradientTransform='matrix(1 0 0 -1 0 61)'%3E%3Cstop offset='.107' stop-color='%23C757BC'/%3E%3Cstop offset='.214' stop-color='%23D0609A'/%3E%3Cstop offset='.425' stop-color='%23E1725C'/%3E%3Cstop offset='.605' stop-color='%23EE7E2F'/%3E%3Cstop offset='.743' stop-color='%23F58613'/%3E%3Cstop offset='.823' stop-color='%23F88909'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M30.1 0L0 31.7 0 60 30.1 29.9 60 0z'/%3E%3C/svg%3E")
360 | }
361 |
362 | .jetbrains-logo._logo-kotlin._size-1 {
363 | width: 40px;
364 | height: 40px
365 | }
366 |
367 | .jetbrains-logo._logo-kotlin._size-2 {
368 | width: 60px;
369 | height: 60px
370 | }
371 |
372 | .jetbrains-logo._logo-kotlin._size-3 {
373 | width: 75px;
374 | height: 75px
375 | }
376 |
377 | .jetbrains-logo._logo-kotlin._size-4 {
378 | width: 100px;
379 | height: 100px
380 | }
381 |
382 | .jetbrains-logo._logo-kotlin._size-5 {
383 | width: 150px;
384 | height: 150px
385 | }
386 |
387 | .jetbrains-logo._logo-mps {
388 | background-image: url("data:image/svg+xml,%3Csvg data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 140 140'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='105.979' y1='186.085' x2='-27.244' y2='15.44' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.091' stop-color='%230b8fff'/%3E%3Cstop offset='.208' stop-color='%230d94f6'/%3E%3Cstop offset='.396' stop-color='%2311a3de'/%3E%3Cstop offset='.633' stop-color='%2318bbb7'/%3E%3Cstop offset='.871' stop-color='%2321d789'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='178.605' y1='129.386' x2='45.382' y2='-41.259' xlink:href='%23a'/%3E%3ClinearGradient id='c' x1='78.586' y1='105.516' x2='126.297' y2='-22.788' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.123' stop-color='%2321d789'/%3E%3Cstop offset='.132' stop-color='%2327d788'/%3E%3Cstop offset='.216' stop-color='%2359d87b'/%3E%3Cstop offset='.303' stop-color='%2385d970'/%3E%3Cstop offset='.394' stop-color='%23abda67'/%3E%3Cstop offset='.487' stop-color='%23cadb5f'/%3E%3Cstop offset='.585' stop-color='%23e1db59'/%3E%3Cstop offset='.688' stop-color='%23f2dc55'/%3E%3Cstop offset='.802' stop-color='%23fcdc53'/%3E%3Cstop offset='.946' stop-color='%23ffdc52'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ctitle%3Emps_logo%3C/title%3E%3Cpath fill='url(%23a)' d='M0 140L140 140 70 70 0 0 0 140z'/%3E%3Cpath data-name='<Path>' fill='url(%23b)' d='M140 140L70 70 140 0 140 140z'/%3E%3Cpath data-name='<Path>' fill='url(%23c)' d='M102 102L70 70 140 0 102 102z'/%3E%3C/svg%3E")
389 | }
390 |
391 | .jetbrains-logo._logo-mps._size-1 {
392 | width: 40px;
393 | height: 40px
394 | }
395 |
396 | .jetbrains-logo._logo-mps._size-2 {
397 | width: 60px;
398 | height: 60px
399 | }
400 |
401 | .jetbrains-logo._logo-mps._size-3 {
402 | width: 75px;
403 | height: 75px
404 | }
405 |
406 | .jetbrains-logo._logo-mps._size-4 {
407 | width: 100px;
408 | height: 100px
409 | }
410 |
411 | .jetbrains-logo._logo-mps._size-5 {
412 | width: 150px;
413 | height: 150px
414 | }
415 |
416 | .jetbrains-logo._logo-phpstorm {
417 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='.558' y1='46.846' x2='29.947' y2='8.026'%3E%3Cstop offset='.016' stop-color='%23765AF8'/%3E%3Cstop offset='.382' stop-color='%23B345F1'/%3E%3Cstop offset='.758' stop-color='%23FA3293'/%3E%3Cstop offset='.941' stop-color='%23FF318C'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M39.6 15.2L36.3 5.2 11.9 0 0 13.5 37.2 32.5z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='2.73' y1='48.379' x2='32.072' y2='9.621'%3E%3Cstop offset='.016' stop-color='%23765AF8'/%3E%3Cstop offset='.382' stop-color='%23B345F1'/%3E%3Cstop offset='.758' stop-color='%23FA3293'/%3E%3Cstop offset='.941' stop-color='%23FF318C'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M28 41.4L27.3 20.6 0 13.5 6.7 53.6 28 53.4z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='50.857' y1='46.405' x2='34.274' y2='7.048'%3E%3Cstop offset='.183' stop-color='%23765AF8'/%3E%3Cstop offset='.238' stop-color='%238655F6'/%3E%3Cstop offset='.345' stop-color='%239F4CF3'/%3E%3Cstop offset='.443' stop-color='%23AE47F2'/%3E%3Cstop offset='.522' stop-color='%23B345F1'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M22.1 41L23.4 24.5 43.2 4.2 60.9 7.4 70 30.1 60.5 39.5 45 37 35.4 47.1z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='63.266' y1='57.339' x2='24.698' y2='27.516'%3E%3Cstop offset='.016' stop-color='%23765AF8'/%3E%3Cstop offset='.382' stop-color='%23B345F1'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M43.2 4.2L14.8 29.4 20.3 61.8 43.9 70 70 54.4z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M17.3,19h7.3c4.3,0,6.9,2.5,6.9,6.2v0.1c0,4.2-3.2,6.3-7.3,6.3h-3l0,5.4h-3.9L17.3,19z M24.4,28 c2,0,3.1-1.2,3.1-2.7v-0.1c0-1.8-1.2-2.7-3.2-2.7h-3V28H24.4z' fill='%23FFF'/%3E%3Cpath d='M32.5,34.4l2.3-2.8c1.6,1.3,3.3,2.2,5.4,2.2c1.6,0,2.6-0.6,2.6-1.7V32c0-1-0.6-1.5-3.6-2.3 c-3.6-0.9-6-1.9-6-5.5v-0.1c0-3.3,2.6-5.4,6.3-5.4c2.6,0,4.9,0.8,6.7,2.3l-2.1,3c-1.6-1.1-3.2-1.8-4.7-1.8c-1.5,0-2.3,0.7-2.3,1.6 v0.1c0,1.2,0.8,1.6,3.9,2.4c3.6,1,5.7,2.3,5.7,5.4v0.1c0,3.6-2.7,5.6-6.6,5.6C37.4,37.3,34.7,36.3,32.5,34.4' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
418 | }
419 |
420 | .jetbrains-logo._logo-phpstorm._size-1 {
421 | width: 40px;
422 | height: 40px
423 | }
424 |
425 | .jetbrains-logo._logo-phpstorm._size-2 {
426 | width: 60px;
427 | height: 60px
428 | }
429 |
430 | .jetbrains-logo._logo-phpstorm._size-3 {
431 | width: 75px;
432 | height: 75px
433 | }
434 |
435 | .jetbrains-logo._logo-phpstorm._size-4 {
436 | width: 100px;
437 | height: 100px
438 | }
439 |
440 | .jetbrains-logo._logo-phpstorm._size-5 {
441 | width: 150px;
442 | height: 150px
443 | }
444 |
445 | .jetbrains-logo._logo-pycharm {
446 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='24.998' y1='27.046' x2='66.656' y2='27.046'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='1' stop-color='%2307C3F2'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M49.1 11L69.5 28.1 62.2 43 49.8 39.6 39.2 39.6z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='-24.559' y1='59.081' x2='61.22' y2='-4.241'%3E%3Cstop offset='.011' stop-color='%23FCF84A'/%3E%3Cstop offset='.112' stop-color='%23A7EB62'/%3E%3Cstop offset='.206' stop-color='%235FE077'/%3E%3Cstop offset='.273' stop-color='%2332DA84'/%3E%3Cstop offset='.306' stop-color='%2321D789'/%3E%3Cstop offset='.577' stop-color='%2321D789'/%3E%3Cstop offset='.597' stop-color='%2321D789'/%3E%3Cstop offset='.686' stop-color='%2320D68C'/%3E%3Cstop offset='.763' stop-color='%231ED497'/%3E%3Cstop offset='.835' stop-color='%2319D1A9'/%3E%3Cstop offset='.904' stop-color='%2313CCC2'/%3E%3Cstop offset='.971' stop-color='%230BC6E1'/%3E%3Cstop offset='1' stop-color='%2307C3F2'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M28.5 22.1L24.5 43 24.1 50.2 14.2 54.5 0 56 4.3 10.7 29.9 0 45.7 10.4z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='9.33' y1='77.654' x2='23.637' y2='32.76'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='.164' stop-color='%2324D788'/%3E%3Cstop offset='.305' stop-color='%232FD886'/%3E%3Cstop offset='.437' stop-color='%2341DA82'/%3E%3Cstop offset='.564' stop-color='%235ADC7D'/%3E%3Cstop offset='.688' stop-color='%237AE077'/%3E%3Cstop offset='.809' stop-color='%23A1E36E'/%3E%3Cstop offset='.925' stop-color='%23CFE865'/%3E%3Cstop offset='1' stop-color='%23F1EB5E'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M28.5 22.1L30.4 62.5 24 70 0 56 19.7 26.6z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='28.275' y1='38.623' x2='59.409' y2='-3.236'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='.061' stop-color='%2324D788'/%3E%3Cstop offset='.113' stop-color='%232FD886'/%3E%3Cstop offset='.162' stop-color='%2341DA82'/%3E%3Cstop offset='.209' stop-color='%235ADD7D'/%3E%3Cstop offset='.255' stop-color='%2379E077'/%3E%3Cstop offset='.258' stop-color='%237CE076'/%3E%3Cstop offset='.499' stop-color='%238CE173'/%3E%3Cstop offset='.925' stop-color='%23B2E56B'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M54.9 19.1L30.6 19.1 52.1 0z'/%3E%3ClinearGradient id='e' gradientUnits='userSpaceOnUse' x1='75.889' y1='43.95' x2='13.158' y2='43.369'%3E%3Cstop offset='.387' stop-color='%23FCF84A'/%3E%3Cstop offset='.536' stop-color='%23ECF451'/%3E%3Cstop offset='.826' stop-color='%23C2E964'/%3E%3Cstop offset='.925' stop-color='%23B2E56B'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23e)' d='M70 62.6L48.6 69.9 20.2 61.9 28.5 22.1 31.8 19.1 49.1 17.5 47.5 34.9 61.3 29.6z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M17.3,19.1h7.3c4.3,0,6.9,2.5,6.9,6.2v0.1c0,4.1-3.2,6.3-7.2,6.3h-3V37h-3.9V19.1z M24.4,28.1 c2,0,3.1-1.2,3.1-2.7v-0.1c0-1.8-1.2-2.7-3.2-2.7h-3v5.5H24.4z' fill='%23FFF'/%3E%3Cpath d='M33.1,28.1L33.1,28.1c0-5.1,3.8-9.3,9.3-9.3c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2 c-3,0-5.2,2.5-5.2,5.6V28c0,3.1,2.1,5.6,5.2,5.6c2,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.8,2-3.9,3.2-7.3,3.2C37,37.3,33.1,33.2,33.1,28.1' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
447 | }
448 |
449 | .jetbrains-logo._logo-pycharm._size-1 {
450 | width: 40px;
451 | height: 40px
452 | }
453 |
454 | .jetbrains-logo._logo-pycharm._size-2 {
455 | width: 60px;
456 | height: 60px
457 | }
458 |
459 | .jetbrains-logo._logo-pycharm._size-3 {
460 | width: 75px;
461 | height: 75px
462 | }
463 |
464 | .jetbrains-logo._logo-pycharm._size-4 {
465 | width: 100px;
466 | height: 100px
467 | }
468 |
469 | .jetbrains-logo._logo-pycharm._size-5 {
470 | width: 150px;
471 | height: 150px
472 | }
473 |
474 | .jetbrains-logo._logo-pycharm-edu {
475 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='24.998' y1='27.046' x2='66.656' y2='27.046'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='1' stop-color='%2307C3F2'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M49.1 11L69.5 28.1 62.2 43 49.8 39.6 39.2 39.6z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='-24.559' y1='59.081' x2='61.22' y2='-4.241'%3E%3Cstop offset='.011' stop-color='%23FCF84A'/%3E%3Cstop offset='.112' stop-color='%23A7EB62'/%3E%3Cstop offset='.206' stop-color='%235FE077'/%3E%3Cstop offset='.273' stop-color='%2332DA84'/%3E%3Cstop offset='.306' stop-color='%2321D789'/%3E%3Cstop offset='.577' stop-color='%2321D789'/%3E%3Cstop offset='.597' stop-color='%2321D789'/%3E%3Cstop offset='.686' stop-color='%2320D68C'/%3E%3Cstop offset='.763' stop-color='%231ED497'/%3E%3Cstop offset='.835' stop-color='%2319D1A9'/%3E%3Cstop offset='.904' stop-color='%2313CCC2'/%3E%3Cstop offset='.971' stop-color='%230BC6E1'/%3E%3Cstop offset='1' stop-color='%2307C3F2'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M28.5 22.1L24.5 43 24.1 50.2 14.2 54.5 0 56 4.3 10.7 29.9 0 45.7 10.4z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='9.33' y1='77.654' x2='23.637' y2='32.76'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='.164' stop-color='%2324D788'/%3E%3Cstop offset='.305' stop-color='%232FD886'/%3E%3Cstop offset='.437' stop-color='%2341DA82'/%3E%3Cstop offset='.564' stop-color='%235ADC7D'/%3E%3Cstop offset='.688' stop-color='%237AE077'/%3E%3Cstop offset='.809' stop-color='%23A1E36E'/%3E%3Cstop offset='.925' stop-color='%23CFE865'/%3E%3Cstop offset='1' stop-color='%23F1EB5E'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M28.5 22.1L30.4 62.5 24 70 0 56 19.7 26.6z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='28.275' y1='38.623' x2='59.409' y2='-3.236'%3E%3Cstop offset='0' stop-color='%2321D789'/%3E%3Cstop offset='.061' stop-color='%2324D788'/%3E%3Cstop offset='.113' stop-color='%232FD886'/%3E%3Cstop offset='.162' stop-color='%2341DA82'/%3E%3Cstop offset='.209' stop-color='%235ADD7D'/%3E%3Cstop offset='.255' stop-color='%2379E077'/%3E%3Cstop offset='.258' stop-color='%237CE076'/%3E%3Cstop offset='.499' stop-color='%238CE173'/%3E%3Cstop offset='.925' stop-color='%23B2E56B'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M54.9 19.1L30.6 19.1 52.1 0z'/%3E%3ClinearGradient id='e' gradientUnits='userSpaceOnUse' x1='75.889' y1='43.95' x2='13.158' y2='43.369'%3E%3Cstop offset='.387' stop-color='%23FCF84A'/%3E%3Cstop offset='.536' stop-color='%23ECF451'/%3E%3Cstop offset='.826' stop-color='%23C2E964'/%3E%3Cstop offset='.925' stop-color='%23B2E56B'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23e)' d='M70 62.6L48.6 69.9 20.2 61.9 28.5 22.1 31.8 19.1 49.1 17.5 47.5 34.9 61.3 29.6z'/%3E%3Cg%3E%3Cpath d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M17.3,19.1h7.3c4.3,0,6.9,2.5,6.9,6.2v0.1c0,4.1-3.2,6.3-7.2,6.3h-3V37h-3.9V19.1z M24.4,28.1 c2,0,3.1-1.2,3.1-2.7v-0.1c0-1.8-1.2-2.7-3.2-2.7h-3v5.5H24.4z' fill='%23FFF'/%3E%3Cpath d='M33.6,19.1h13.5v3.5h-9.6v3.6H46v3.5h-8.4v3.8h9.7V37H33.6V19.1z' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
476 | }
477 |
478 | .jetbrains-logo._logo-pycharm-edu._size-1 {
479 | width: 40px;
480 | height: 40px
481 | }
482 |
483 | .jetbrains-logo._logo-pycharm-edu._size-2 {
484 | width: 60px;
485 | height: 60px
486 | }
487 |
488 | .jetbrains-logo._logo-pycharm-edu._size-3 {
489 | width: 75px;
490 | height: 75px
491 | }
492 |
493 | .jetbrains-logo._logo-pycharm-edu._size-4 {
494 | width: 100px;
495 | height: 100px
496 | }
497 |
498 | .jetbrains-logo._logo-pycharm-edu._size-5 {
499 | width: 150px;
500 | height: 150px
501 | }
502 |
503 | .jetbrains-logo._logo-rider {
504 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='70.226' y1='27.799' x2='-5.13' y2='63.122' gradientTransform='matrix(1 0 0 -1 0 71.28)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23c90f5e'/%3E%3Cstop offset='.221' stop-color='%23c90f5e'/%3E%3Cstop offset='.236' stop-color='%23c90f5e'/%3E%3Cstop offset='.356' stop-color='%23ca135c'/%3E%3Cstop offset='.466' stop-color='%23ce1e57'/%3E%3Cstop offset='.574' stop-color='%23d4314e'/%3E%3Cstop offset='.678' stop-color='%23dc4b41'/%3E%3Cstop offset='.782' stop-color='%23e66d31'/%3E%3Cstop offset='.883' stop-color='%23f3961d'/%3E%3Cstop offset='.942' stop-color='%23fcb20f'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='24.659' y1='61.996' x2='46.048' y2='2.934' gradientTransform='matrix(1 0 0 -1 0 71.28)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.042' stop-color='%23077cfb'/%3E%3Cstop offset='.445' stop-color='%23c90f5e'/%3E%3Cstop offset='.958' stop-color='%23077cfb'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='17.396' y1='63.346' x2='33.194' y2='7.201' gradientTransform='matrix(1 0 0 -1 0 71.28)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.277' stop-color='%23c90f5e'/%3E%3Cstop offset='.974' stop-color='%23fcb20f'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ctitle%3Erider%3C/title%3E%3Cpath fill='url(%23a)' d='M70 27.237L63.391 23.75 20.926 0 3.827 17.921 21.619 41.068 60.537 44.397 70 27.237z'/%3E%3Cpath fill='url(%23b)' d='M50.423 16.132L44.271 1.107 27.643 17.471 11.768 50.194 49.411 70 70 57.98 50.423 16.132z'/%3E%3Cpath fill='url(%23c)' d='M20.926 0L0 14.095 7.779 62.172 27.848 69.889 53.78 48.823 20.926 0z'/%3E%3Cg%3E%3Cpath d='M13.302 13.193H56.916V56.806999999999995H13.302z'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M17.22741,18.86293h8.39564a7.38416,7.38416,0,0,1,5.34268,1.85358,5.86989,5.86989,0,0,1,1.52648,4.1433h0A5.74339,5.74339,0,0,1,28.567,30.5296l4.47041,6.54206H28.34891L24.42368,31.1838h-3.162v5.88785H17.22741V18.86293h0ZM25.296,27.69471c1.96262,0,3.053-1.09034,3.053-2.61682h0c0-1.74455-1.19938-2.61682-3.162-2.61682H21.15265v5.23365H25.296Z'/%3E%3Cpath d='M36.09034,18.86293H43.2866c5.77882,0,9.70405,3.92523,9.70405,9.15888h0c0,5.12461-3.92523,9.15888-9.70405,9.15888H36.09034V18.86293Zm4.03427,3.59813V33.47352h3.162a5.23727,5.23727,0,0,0,5.56075-5.45171h0a5.26493,5.26493,0,0,0-5.56075-5.56075h-3.162Z'/%3E%3C/g%3E%3Cpath fill='%23fff' d='M17.227 48.629H33.582V51.355H17.227z'/%3E%3C/g%3E%3C/svg%3E")
505 | }
506 |
507 | .jetbrains-logo._logo-rider._size-1 {
508 | width: 40px;
509 | height: 40px
510 | }
511 |
512 | .jetbrains-logo._logo-rider._size-2 {
513 | width: 60px;
514 | height: 60px
515 | }
516 |
517 | .jetbrains-logo._logo-rider._size-3 {
518 | width: 75px;
519 | height: 75px
520 | }
521 |
522 | .jetbrains-logo._logo-rider._size-4 {
523 | width: 100px;
524 | height: 100px
525 | }
526 |
527 | .jetbrains-logo._logo-rider._size-5 {
528 | width: 150px;
529 | height: 150px
530 | }
531 |
532 | .jetbrains-logo._logo-resharper {
533 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='22.945' y1='75.787' x2='74.787' y2='20.642'%3E%3Cstop offset='.016' stop-color='%23B35BA3'/%3E%3Cstop offset='.404' stop-color='%23C41E57'/%3E%3Cstop offset='.468' stop-color='%23C41E57'/%3E%3Cstop offset='.65' stop-color='%23EB8523'/%3E%3Cstop offset='.952' stop-color='%23FEBD11'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M49.8 15.2L36 36.7 58.4 70 70 23.1z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='17.719' y1='73.292' x2='69.556' y2='18.152'%3E%3Cstop offset='.016' stop-color='%23B35BA3'/%3E%3Cstop offset='.404' stop-color='%23C41E57'/%3E%3Cstop offset='.468' stop-color='%23C41E57'/%3E%3Cstop offset='.704' stop-color='%23EB8523'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M51.1 15.7L49 0 18.8 33.6 27.6 42.3 20.8 70 58.4 70z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='1.828' y1='53.428' x2='48.825' y2='9.226'%3E%3Cstop offset='.016' stop-color='%23B35BA3'/%3E%3Cstop offset='.661' stop-color='%23C41E57'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M49 0L11.6 0 0 47.1 55.6 47.1z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='49.894' y1='-11.557' x2='48.859' y2='24.035'%3E%3Cstop offset='.5' stop-color='%23C41E57'/%3E%3Cstop offset='.667' stop-color='%23D13F48'/%3E%3Cstop offset='.795' stop-color='%23D94F39'/%3E%3Cstop offset='.866' stop-color='%23DD5433'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23d)' d='M55.3 47.1L51.1 15.7 49 0 41.7 23z'/%3E%3Cg%3E%3Cpath transform='matrix(-1 .00258 -.00258 -1 70.029 70.081)' fill='%23000' d='M13.4 13.5H56.6V56.7H13.4z'/%3E%3Cpath transform='rotate(-.148 25.676 49.97)' fill='%23FFF' d='M17.6 48.6H33.8V51.300000000000004H17.6z'/%3E%3Cpath d='M17.4,19.1l8.2,0c2.3,0,4,0.6,5.2,1.8c1,1,1.5,2.4,1.5,4.1l0,0.1c0,1.5-0.3,2.6-1.1,3.5 c-0.7,0.9-1.6,1.6-2.8,2l4.4,6.4l-4.6,0l-3.7-5.5l-3.3,0l0,5.5l-3.9,0L17.4,19.1z M25.3,27.8c1,0,1.7-0.2,2.2-0.7 c0.5-0.5,0.8-1.1,0.8-1.8l0-0.1c0-0.9-0.3-1.5-0.8-1.9c-0.5-0.4-1.3-0.6-2.3-0.6l-3.9,0l0,5.1L25.3,27.8z' fill='%23FFF'/%3E%3Cpath d='M36,33.2l-1.9,0l0-3.3l2.5,0l0.6-3.8l-2.3,0l0-3.3l2.8,0l0.6-3.7l3.4,0l-0.6,3.7l3.7,0l0.6-3.7 l3.4,0l-0.6,3.7l1.9,0l0,3.3l-2.5,0L47,29.9l2.3,0l0,3.3l-2.8,0L45.8,37l-3.4,0l0.7-3.8l-3.7,0L38.7,37l-3.4,0L36,33.2z M43.7,29.9l0.6-3.8l-3.7,0L40,29.9L43.7,29.9z' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
534 | }
535 |
536 | .jetbrains-logo._logo-resharper._size-1 {
537 | width: 40px;
538 | height: 40px
539 | }
540 |
541 | .jetbrains-logo._logo-resharper._size-2 {
542 | width: 60px;
543 | height: 60px
544 | }
545 |
546 | .jetbrains-logo._logo-resharper._size-3 {
547 | width: 75px;
548 | height: 75px
549 | }
550 |
551 | .jetbrains-logo._logo-resharper._size-4 {
552 | width: 100px;
553 | height: 100px
554 | }
555 |
556 | .jetbrains-logo._logo-resharper._size-5 {
557 | width: 150px;
558 | height: 150px
559 | }
560 |
561 | .jetbrains-logo._logo-resharper-cpp {
562 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='8.063' y1='16.141' x2='29.26' y2='69.757'%3E%3Cstop offset='.22' stop-color='%23C40B55'/%3E%3Cstop offset='.683' stop-color='%23E343E6'/%3E%3Cstop offset='.925' stop-color='%23F59252'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M20.2 15.2L34 36.7 11.6 70 0 23.1z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='875.719' y1='73.292' x2='927.556' y2='18.152' gradientTransform='matrix(-1 0 0 1 928 0)'%3E%3Cstop offset='.113' stop-color='%23FFBD00'/%3E%3Cstop offset='.586' stop-color='%23E343E6'/%3E%3Cstop offset='.817' stop-color='%23EC841B'/%3E%3Cstop offset='.935' stop-color='%23FFBD00'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M18.9 15.7L21 0 51.2 33.6 42.4 42.3 49.2 70 11.6 70z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='25.5' y1='-1.93' x2='69.96' y2='51.168'%3E%3Cstop offset='.129' stop-color='%23FFBD00'/%3E%3Cstop offset='.64' stop-color='%23E343E6'/%3E%3Cstop offset='.909' stop-color='%23C40B55'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M35.3 47.1L70 47.1 58.4 0 21 0z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath d='M17.4,19h8.2c2.3,0,4,0.6,5.2,1.8c1,1,1.5,2.4,1.5,4.1V25c0,1.5-0.4,2.6-1.1,3.5 c-0.7,0.9-1.6,1.6-2.8,2l4.4,6.4h-4.6l-3.7-5.5h-3.3l0,5.5h-3.9V19z M25.4,27.7c1,0,1.7-0.2,2.2-0.7c0.5-0.5,0.8-1.1,0.8-1.8 v-0.1c0-0.9-0.3-1.5-0.8-1.9c-0.5-0.4-1.3-0.6-2.3-0.6h-3.9v5.1H25.4z' fill='%23FFF'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cg%3E%3Cpath d='M43.7,24.4h-4v-3.6h4v-4h3.7v4h4v3.6h-4v4h-3.7V24.4z' fill='%23FFF'/%3E%3C/g%3E%3Cg%3E%3Cpath d='M37.1,34.6h-4V31h4v-4h3.7v4h4v3.6h-4v4h-3.7V34.6z' fill='%23FFF'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
563 | }
564 |
565 | .jetbrains-logo._logo-resharper-cpp._size-1 {
566 | width: 40px;
567 | height: 40px
568 | }
569 |
570 | .jetbrains-logo._logo-resharper-cpp._size-2 {
571 | width: 60px;
572 | height: 60px
573 | }
574 |
575 | .jetbrains-logo._logo-resharper-cpp._size-3 {
576 | width: 75px;
577 | height: 75px
578 | }
579 |
580 | .jetbrains-logo._logo-resharper-cpp._size-4 {
581 | width: 100px;
582 | height: 100px
583 | }
584 |
585 | .jetbrains-logo._logo-resharper-cpp._size-5 {
586 | width: 150px;
587 | height: 150px
588 | }
589 |
590 | .jetbrains-logo._logo-rubymine {
591 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='49.609' y1='52.554' x2='30.346' y2='7.163'%3E%3Cstop offset='.172' stop-color='%23FF1F51'/%3E%3Cstop offset='.28' stop-color='%23FF3648'/%3E%3Cstop offset='.468' stop-color='%23FF593B'/%3E%3Cstop offset='.646' stop-color='%23FF7231'/%3E%3Cstop offset='.809' stop-color='%23FF812B'/%3E%3Cstop offset='.941' stop-color='%23FF8629'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M58.2 0L38.2 7.2 22.4 0 6.9 38.9 24.7 31.8 24.4 51.5 62.5 52.2 70 13.7z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='33.259' y1='12.887' x2='25.105' y2='33.436'%3E%3Cstop offset='.022' stop-color='%239039D0'/%3E%3Cstop offset='.629' stop-color='%23FF1F51'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M50.8 22.7L25.6 6.2 5.3 18.7 49.8 35.9z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='.29' y1='11.224' x2='45.284' y2='68.42'%3E%3Cstop offset='.107' stop-color='%239039D0'/%3E%3Cstop offset='.387' stop-color='%23FF1F51'/%3E%3Cstop offset='.629' stop-color='%23FF1F51'/%3E%3Cstop offset='.66' stop-color='%23FF3648'/%3E%3Cstop offset='.714' stop-color='%23FF593B'/%3E%3Cstop offset='.765' stop-color='%23FF7231'/%3E%3Cstop offset='.812' stop-color='%23FF812B'/%3E%3Cstop offset='.85' stop-color='%23FF8629'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M29.1 68.2L55.3 64.7 47 48.7 52.5 42 53.1 37.9 25.6 6.1 0 12.4 0 49.1 14.8 70 29.1 68.2 29.1 68.2 29.1 68.2 29.1 68.2z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath fill='%23FFF' d='M34.6 19L38.9 19 43.6 26.6 48.3 19 52.6 19 52.6 36.9 48.6 36.9 48.6 25.2 43.6 32.9 43.5 32.9 38.5 25.3 38.5 36.9 34.6 36.9z'/%3E%3Cpath d='M17.4,19h8.2c2.3,0,4,0.6,5.2,1.8c1,1,1.5,2.4,1.5,4.1v0.1c0,1.5-0.4,2.6-1.1,3.5 c-0.7,0.9-1.6,1.6-2.8,2l4.4,6.4h-4.6l-3.7-5.5h-3.3l0,5.5h-3.9V19z M25.4,27.7c1,0,1.7-0.2,2.2-0.7c0.5-0.5,0.8-1.1,0.8-1.8v-0.1 c0-0.9-0.3-1.5-0.8-1.9c-0.5-0.4-1.3-0.6-2.3-0.6h-3.9v5.1H25.4z' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
592 | }
593 |
594 | .jetbrains-logo._logo-rubymine._size-1 {
595 | width: 40px;
596 | height: 40px
597 | }
598 |
599 | .jetbrains-logo._logo-rubymine._size-2 {
600 | width: 60px;
601 | height: 60px
602 | }
603 |
604 | .jetbrains-logo._logo-rubymine._size-3 {
605 | width: 75px;
606 | height: 75px
607 | }
608 |
609 | .jetbrains-logo._logo-rubymine._size-4 {
610 | width: 100px;
611 | height: 100px
612 | }
613 |
614 | .jetbrains-logo._logo-rubymine._size-5 {
615 | width: 150px;
616 | height: 150px
617 | }
618 |
619 | .jetbrains-logo._logo-teamcity {
620 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='1.774' y1='31.273' x2='40.166' y2='31.273'%3E%3Cstop offset='0' stop-color='%23905CFB'/%3E%3Cstop offset='.068' stop-color='%23776CF9'/%3E%3Cstop offset='.173' stop-color='%235681F7'/%3E%3Cstop offset='.286' stop-color='%233B92F5'/%3E%3Cstop offset='.41' stop-color='%23269FF4'/%3E%3Cstop offset='.547' stop-color='%2317A9F3'/%3E%3Cstop offset='.711' stop-color='%230FAEF2'/%3E%3Cstop offset='.968' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M39.7,47.9l-6.1-34c-0.4-2.4-1.2-4.8-2.7-7.1c-2-3.2-5.2-5.4-8.8-6.3 C7.9-2.9-2.6,11.3,3.6,23.9c0,0,0,0,0,0l14.8,31.7c0.4,1,1,2,1.7,2.9c1.2,1.6,2.8,2.8,4.7,3.4C34.4,64.9,42.1,56.4,39.7,47.9z' fill='url(%23a)'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='5.311' y1='9.669' x2='69.228' y2='43.866'%3E%3Cstop offset='0' stop-color='%23905CFB'/%3E%3Cstop offset='.068' stop-color='%23776CF9'/%3E%3Cstop offset='.173' stop-color='%235681F7'/%3E%3Cstop offset='.286' stop-color='%233B92F5'/%3E%3Cstop offset='.41' stop-color='%23269FF4'/%3E%3Cstop offset='.547' stop-color='%2317A9F3'/%3E%3Cstop offset='.711' stop-color='%230FAEF2'/%3E%3Cstop offset='.968' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M67.4,26.5c-1.4-2.2-3.4-3.9-5.7-4.9L25.5,1.7l0,0c-1-0.5-2.1-1-3.3-1.3 C6.7-3.2-4.4,13.8,5.5,27c1.5,2,3.6,3.6,6,4.5L48,47.9c0.8,0.5,1.6,0.8,2.5,1.1C64.5,53.4,75.1,38.6,67.4,26.5z' fill='url(%23b)'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='-19.284' y1='70.82' x2='55.983' y2='33.186'%3E%3Cstop offset='0' stop-color='%233BEA62'/%3E%3Cstop offset='.117' stop-color='%2331DE80'/%3E%3Cstop offset='.302' stop-color='%2324CEA8'/%3E%3Cstop offset='.484' stop-color='%231AC1C9'/%3E%3Cstop offset='.659' stop-color='%2312B7DF'/%3E%3Cstop offset='.824' stop-color='%230EB2ED'/%3E%3Cstop offset='.968' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M67.4,26.5c-1.8-2.8-4.6-4.8-7.9-5.6c-3.5-0.8-6.8-0.5-9.6,0.7L11.4,36.1 c0,0-0.2,0.1-0.6,0.4C0.9,40.4-4,53.3,4,64c1.8,2.4,4.3,4.2,7.1,5c5.3,1.6,10.1,1,14-1.1c0,0,0.1,0,0.1,0l37.6-20.1 c0,0,0,0,0.1-0.1C69.5,43.9,72.6,34.6,67.4,26.5z' fill='url(%23c)'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='38.944' y1='5.85' x2='5.423' y2='77.509'%3E%3Cstop offset='0' stop-color='%233BEA62'/%3E%3Cstop offset='.094' stop-color='%232FDB87'/%3E%3Cstop offset='.196' stop-color='%2324CEA8'/%3E%3Cstop offset='.306' stop-color='%231BC3C3'/%3E%3Cstop offset='.426' stop-color='%2314BAD8'/%3E%3Cstop offset='.56' stop-color='%2310B5E7'/%3E%3Cstop offset='.719' stop-color='%230DB1EF'/%3E%3Cstop offset='.968' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M50.3,12.8c1.2-2.7,1.1-6-0.9-9c-1.1-1.8-2.9-3-4.9-3.5c-4.5-1.1-8.3,1-10.1,4.2L3.5,42 c0,0,0,0,0,0.1C-0.9,47.9-1.6,56.5,4,64c1.8,2.4,4.3,4.2,7.1,5c10.5,3.3,19.3-2.5,22.1-10.8L50.3,12.8z' fill='url(%23d)'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath fill='%23FFF' d='M22.9 22.7L17.5 22.7 17.5 19.1 32.3 19.1 32.3 22.7 26.8 22.7 26.8 37 22.9 37z'/%3E%3Cpath d='M32.5,28.1L32.5,28.1c0-5.1,3.8-9.3,9.3-9.3c3.4,0,5.4,1.1,7.1,2.8l-2.5,2.9c-1.4-1.3-2.8-2-4.6-2 c-3,0-5.2,2.5-5.2,5.6V28c0,3.1,2.1,5.6,5.2,5.6c2,0,3.3-0.8,4.7-2.1l2.5,2.5c-1.8,2-3.9,3.2-7.3,3.2 C36.4,37.3,32.5,33.2,32.5,28.1' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E")
621 | }
622 |
623 | .jetbrains-logo._logo-teamcity._size-1 {
624 | width: 40px;
625 | height: 40px
626 | }
627 |
628 | .jetbrains-logo._logo-teamcity._size-2 {
629 | width: 60px;
630 | height: 60px
631 | }
632 |
633 | .jetbrains-logo._logo-teamcity._size-3 {
634 | width: 75px;
635 | height: 75px
636 | }
637 |
638 | .jetbrains-logo._logo-teamcity._size-4 {
639 | width: 100px;
640 | height: 100px
641 | }
642 |
643 | .jetbrains-logo._logo-teamcity._size-5 {
644 | width: 150px;
645 | height: 150px
646 | }
647 |
648 | .jetbrains-logo._logo-toolbox {
649 | background-image: url("data:image/svg+xml,%3Csvg data-name='Layer 1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='2.18' y1='23.255' x2='30.041' y2='8.782' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.043' stop-color='%23ff8618'/%3E%3Cstop offset='.382' stop-color='%23ff246e'/%3E%3Cstop offset='.989' stop-color='%23af1df5'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ctitle%3EToolBox_trayIcon_colour_32-01%3C/title%3E%3Cpath d='M26,22.4713l-6.83,3.8311V23.2578L26,19.4268v3.0445Z' fill='%23fff'/%3E%3Cpath fill='%23000001' d='M16 32.076L30 24.065 30 8.057 16 16.067 16 32.076z'/%3E%3Cpath fill='%23fff' d='M18.925 24.641L18.925 27.041 25.026 23.55 25.026 21.15 18.925 24.641z'/%3E%3Cpath fill='url(%23a)' d='M16 0.076L2 8.057 2 8.057 2 8.057 2 24.065 16 32.076 16 16.067 30 8.057 16 0.076z'/%3E%3C/svg%3E")
650 | }
651 |
652 | .jetbrains-logo._logo-toolbox._size-1 {
653 | width: 40px;
654 | height: 40px
655 | }
656 |
657 | .jetbrains-logo._logo-toolbox._size-2 {
658 | width: 60px;
659 | height: 60px
660 | }
661 |
662 | .jetbrains-logo._logo-toolbox._size-3 {
663 | width: 75px;
664 | height: 75px
665 | }
666 |
667 | .jetbrains-logo._logo-toolbox._size-4 {
668 | width: 100px;
669 | height: 100px
670 | }
671 |
672 | .jetbrains-logo._logo-toolbox._size-5 {
673 | width: 150px;
674 | height: 150px
675 | }
676 |
677 | .jetbrains-logo._logo-upsource {
678 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='64.913' y1='54.385' x2='17.513' y2='47.275' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%23FF8200'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M60.5 24L9.6 26.9 9.3 7.4 55.2 0.2z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='15.675' y1='30.593' x2='20.093' y2='55.275' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%230CB0F2'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath d='M20.3,43.2l16.4-20.8L18.9,10.2l0,0c-3.1-2.8-7.8-4-12.6-2c-2.4,1-4.3,2.9-5.3,5.3 c-2.1,5-0.8,9.9,2.4,12.9l0,0L20.3,43.2z' fill='url(%23b)'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='58.335' y1='11.729' x2='26.978' y2='27.043' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%230CB0F2'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M20.3 43.2L45.5 68.1 61.2 38.8 36.7 22.4z'/%3E%3ClinearGradient id='d' gradientUnits='userSpaceOnUse' x1='60.678' y1='9.337' x2='7.352' y2='28.508' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%230CB0F2'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath d='M53.9,36.6L53.9,36.6l-41.9-2l0,0c-1.6-0.3-3.4-0.2-5.3,0.6c-1.8,0.8-3.2,2.1-3.9,3.9 c-2.1,4.9,0.4,9.6,4.5,11.2l0,0L44.8,68c0.5,0.3,3,1,3,1c2,0.6,4.2,0.9,6.2,0.9c2.5,0,5.3-0.7,8.1-2.1c2.6-1.3,4.2-3.4,5.6-6 c1.7-3,2.2-5.8,2.2-8.6C69.8,44.5,62.6,37.2,53.9,36.6z' fill='url(%23d)'/%3E%3ClinearGradient id='e' gradientUnits='userSpaceOnUse' x1='64.194' y1='59.46' x2='18.524' y2='22.651' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%23FF8200'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath d='M52.1,1.1c-0.7,0.3-1.4,0.7-2,1.1l0,0L26.9,19.7l11.5,16.8l25.2-14.1 c1.9-0.9,3.4-2.5,4.3-4.3C73.5,7.3,63.1-3.5,52.1,1.1z' fill='url(%23e)'/%3E%3Cpath fill='%23905CFB' d='M14.5 49.8L38.4 36.5 26.9 19.7 4.9 36.2z'/%3E%3ClinearGradient id='f' gradientUnits='userSpaceOnUse' x1='30.448' y1='16.152' x2='2.265' y2='26.168' gradientTransform='matrix(1 0 0 -1 0 65.395)'%3E%3Cstop offset='0' stop-color='%230CB0F2'/%3E%3Cstop offset='.973' stop-color='%23905CFB'/%3E%3C/linearGradient%3E%3Cpath d='M20.4,56.4V35L12,34.6H12c-1.6-0.3-3.4-0.2-5.3,0.6c-1.8,0.8-3.2,2.1-3.9,3.9 c-2.1,4.9,0.4,9.6,4.5,11.2h0.1L20.4,56.4z' fill='url(%23f)'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M17.5,29.4V19h4v10.3c0,3,1.5,4.5,3.9,4.5s3.9-1.5,3.9-4.4V19h4v10.2c0,5.5-3.1,8.2-8,8.2 C20.5,37.5,17.5,34.7,17.5,29.4z'/%3E%3Cpath d='M35.4,19h7.4c4.3,0,6.9,2.6,6.9,6.3v0.1c0,4.2-3.3,6.4-7.3,6.4h-3v5.4h-4V19z M42.6,28.2 c2,0,3.2-1.2,3.2-2.7v-0.1c0-1.8-1.2-2.7-3.2-2.7h-3.1v5.5H42.6z'/%3E%3C/g%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3C/g%3E%3C/svg%3E")
679 | }
680 |
681 | .jetbrains-logo._logo-upsource._size-1 {
682 | width: 40px;
683 | height: 40px
684 | }
685 |
686 | .jetbrains-logo._logo-upsource._size-2 {
687 | width: 60px;
688 | height: 60px
689 | }
690 |
691 | .jetbrains-logo._logo-upsource._size-3 {
692 | width: 75px;
693 | height: 75px
694 | }
695 |
696 | .jetbrains-logo._logo-upsource._size-4 {
697 | width: 100px;
698 | height: 100px
699 | }
700 |
701 | .jetbrains-logo._logo-upsource._size-5 {
702 | width: 150px;
703 | height: 150px
704 | }
705 |
706 | .jetbrains-logo._logo-webstorm {
707 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='25.068' y1='1.46' x2='43.183' y2='66.675'%3E%3Cstop offset='.285' stop-color='%2300CDD7'/%3E%3Cstop offset='.941' stop-color='%232086D7'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M9.4 63.3L0 7.3 17.5 0.1 28.6 6.7 38.8 1.2 60.1 9.4 48.1 70z'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='30.72' y1='9.734' x2='61.365' y2='54.671'%3E%3Cstop offset='.14' stop-color='%23FFF045'/%3E%3Cstop offset='.366' stop-color='%2300CDD7'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23b)' d='M70 23.7L61 1.4 44.6 0 19.3 24.3 26.1 55.6 38.8 64.6 70 46 62.3 31.7z'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='61.082' y1='15.29' x2='65.106' y2='29.544'%3E%3Cstop offset='.285' stop-color='%2300CDD7'/%3E%3Cstop offset='.941' stop-color='%232086D7'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23c)' d='M56 20.4L62.3 31.7 70 23.7 64.4 9.8z'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.5 48.5H33.7V51.2H17.5z'/%3E%3Cpath d='M38.7,34.3l2.3-2.8c1.6,1.3,3.3,2.2,5.3,2.2c1.6,0,2.5-0.6,2.5-1.7v-0.1c0-1-0.6-1.5-3.6-2.3 c-3.6-0.9-5.8-1.9-5.8-5.5v-0.1c0-3.3,2.6-5.4,6.2-5.4c2.6,0,4.8,0.8,6.6,2.3l-2,3c-1.6-1.1-3.1-1.8-4.6-1.8 c-1.5,0-2.3,0.7-2.3,1.6v0.1c0,1.2,0.8,1.6,3.8,2.4c3.6,1,5.6,2.3,5.6,5.4v0.1c0,3.6-2.7,5.6-6.5,5.6 C43.5,37.2,40.8,36.2,38.7,34.3' fill='%23FFF'/%3E%3Cpath fill='%23FFF' d='M35.2 19L32.5 29.4 29.5 19 26.5 19 23.4 29.4 20.7 19 16.6 19 21.7 36.9 25 36.9 28 26.5 30.9 36.9 34.3 36.9 39.4 19z'/%3E%3C/g%3E%3C/svg%3E")
708 | }
709 |
710 | .jetbrains-logo._logo-webstorm._size-1 {
711 | width: 40px;
712 | height: 40px
713 | }
714 |
715 | .jetbrains-logo._logo-webstorm._size-2 {
716 | width: 60px;
717 | height: 60px
718 | }
719 |
720 | .jetbrains-logo._logo-webstorm._size-3 {
721 | width: 75px;
722 | height: 75px
723 | }
724 |
725 | .jetbrains-logo._logo-webstorm._size-4 {
726 | width: 100px;
727 | height: 100px
728 | }
729 |
730 | .jetbrains-logo._logo-webstorm._size-5 {
731 | width: 150px;
732 | height: 150px
733 | }
734 |
735 | .jetbrains-logo._logo-youtrack {
736 | background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' x='0' y='0' width='70' height='70' viewBox='0 0 70 70' xml:space='preserve'%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='7.083' y1='16.294' x2='64.106' y2='42.288' gradientTransform='matrix(1 0 0 -1 0 71.047)'%3E%3Cstop offset='0' stop-color='%23905CFB'/%3E%3Cstop offset='.165' stop-color='%236677F8'/%3E%3Cstop offset='.378' stop-color='%233596F5'/%3E%3Cstop offset='.54' stop-color='%2317A9F3'/%3E%3Cstop offset='.632' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M66.9,47.5c-0.2-0.2-13.1-12.6-13.1-12.6s9.8-10.4,12.4-13c0.8-0.8,1.5-1.6,2-2.6 c3.6-6.1,1.5-13.9-4.6-17.5c-4.5-2.6-10.1-2.2-14.1,0.8c-0.7,0.5-1.3,1-1.9,1.6C47.3,4.6,33.7,17,21.9,27.8l22.1,14L20.8,67.9 c-1.4,1-2.8,1.6-4.3,1.9c0.3,0,0.5,0,0.8-0.1c4.6-0.7,43.9-7.3,45.8-7.7c2.3-0.4,4.4-1.8,5.7-3.9C71,54.5,70,50,66.9,47.5z' fill='url(%23a)'/%3E%3ClinearGradient id='b' gradientUnits='userSpaceOnUse' x1='30.31' y1='42.916' x2='1.068' y2='68.744' gradientTransform='matrix(1 0 0 -1 0 71.047)'%3E%3Cstop offset='0' stop-color='%23905CFB'/%3E%3Cstop offset='.072' stop-color='%23A554E6'/%3E%3Cstop offset='.252' stop-color='%23D641B5'/%3E%3Cstop offset='.39' stop-color='%23F43597'/%3E%3Cstop offset='.468' stop-color='%23FF318C'/%3E%3C/linearGradient%3E%3Cpath d='M45.9,30.5c-0.4-2.7-1.8-4.9-3.8-6.5C40,22.4,23.8,5.6,22,3.7C19.2,1,15.2-0.5,11.1,0.2 C4.1,1.2-0.8,7.8,0.3,14.8c0.5,3.5,2.5,6.5,5.1,8.4c2.6,2,23,16,24.3,17c2.1,1.6,4.9,2.5,7.7,2C42.9,41.2,46.8,36,45.9,30.5z' fill='url(%23b)'/%3E%3ClinearGradient id='c' gradientUnits='userSpaceOnUse' x1='4.983' y1='12.362' x2='74.023' y2='55.864' gradientTransform='matrix(1 0 0 -1 0 71.047)'%3E%3Cstop offset='0' stop-color='%23905CFB'/%3E%3Cstop offset='.165' stop-color='%236677F8'/%3E%3Cstop offset='.378' stop-color='%233596F5'/%3E%3Cstop offset='.54' stop-color='%2317A9F3'/%3E%3Cstop offset='.632' stop-color='%230CB0F2'/%3E%3C/linearGradient%3E%3Cpath d='M23,67.8c0.1,0,23.3-26.1,23.3-26.1L22.9,26.9c-8.3,7.6-16,14.5-17.8,16.2 c-1.1,1-2.2,2.3-3,3.7c-4.3,7.4-1.8,16.8,5.6,21.1C10.7,69.6,17.5,71.7,23,67.8z' fill='url(%23c)'/%3E%3Cg%3E%3Cpath fill='%23000' d='M13.4 13.4H56.6V56.6H13.4z'/%3E%3Cpath fill='%23FFF' d='M17.4 48.5H33.599999999999994V51.2H17.4z'/%3E%3Cpath fill='%23FFF' d='M23.8 29.9L17 19.1 21.6 19.1 25.8 26.2 30.2 19.1 34.7 19.1 27.8 29.8 27.8 37 23.8 37z'/%3E%3Cpath fill='%23FFF' d='M41.6 22.7L36.1 22.7 36.1 19.1 51 19.1 51 22.7 45.5 22.7 45.5 37 41.6 37z'/%3E%3C/g%3E%3C/svg%3E")
737 | }
738 |
739 | .jetbrains-logo._logo-youtrack._size-1 {
740 | width: 40px;
741 | height: 40px
742 | }
743 |
744 | .jetbrains-logo._logo-youtrack._size-2 {
745 | width: 60px;
746 | height: 60px
747 | }
748 |
749 | .jetbrains-logo._logo-youtrack._size-3 {
750 | width: 75px;
751 | height: 75px
752 | }
753 |
754 | .jetbrains-logo._logo-youtrack._size-4 {
755 | width: 100px;
756 | height: 100px
757 | }
758 |
759 | .jetbrains-logo._logo-youtrack._size-5 {
760 | width: 150px;
761 | height: 150px
762 | }
--------------------------------------------------------------------------------