DS-1170: Jupyter in community.

Extract jupyter language to ``intellij.jupyter.core``.
It now has ``jupyter-core.xml`` with language only and ``jupyter-core-view-only.xml`` to be included in community versions.
It also provides framework to show jupyter using web applications

GitOrigin-RevId: fa80df820adab872768dc28ce567c7a86a2b552d
This commit is contained in:
Ilya.Kazakevich
2021-10-20 18:01:10 +00:00
committed by intellij-monorepo-bot
parent 7eec197140
commit 2d4b57a8bf
48 changed files with 73601 additions and 2 deletions
+2
View File
@@ -637,6 +637,8 @@
<module fileurl="file://$PROJECT_DIR$/plugins/junit_rt/intellij.junit.rt.iml" filepath="$PROJECT_DIR$/plugins/junit_rt/intellij.junit.rt.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/junit5_rt/intellij.junit.v5.rt.iml" filepath="$PROJECT_DIR$/plugins/junit5_rt/intellij.junit.v5.rt.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml" filepath="$PROJECT_DIR$/plugins/junit5_rt_tests/intellij.junit.v5.rt.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/jupyter/intellij.jupyter.core.iml" filepath="$PROJECT_DIR$/jupyter/intellij.jupyter.core.iml" />
<module fileurl="file://$PROJECT_DIR$/jupyter/viewOnly/intellij.jupyter.viewOnly.iml" filepath="$PROJECT_DIR$/jupyter/viewOnly/intellij.jupyter.viewOnly.iml" />
<module fileurl="file://$PROJECT_DIR$/jvm/jvm-analysis-api/intellij.jvm.analysis.iml" filepath="$PROJECT_DIR$/jvm/jvm-analysis-api/intellij.jvm.analysis.iml" />
<module fileurl="file://$PROJECT_DIR$/jvm/jvm-analysis-impl/intellij.jvm.analysis.impl.iml" filepath="$PROJECT_DIR$/jvm/jvm-analysis-impl/intellij.jvm.analysis.impl.iml" />
<module fileurl="file://$PROJECT_DIR$/jvm/jvm-analysis-java-tests/intellij.jvm.analysis.java.tests.iml" filepath="$PROJECT_DIR$/jvm/jvm-analysis-java-tests/intellij.jvm.analysis.java.tests.iml" />
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.platform.lang" />
<orderEntry type="module" module-name="intellij.python.psi" />
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
<orderEntry type="library" name="netty-codec-http" level="project" />
<orderEntry type="library" name="http-client" level="project" />
<orderEntry type="module" module-name="intellij.platform.ide.util.netty" />
<orderEntry type="library" name="netty-buffer" level="project" />
<orderEntry type="module" module-name="intellij.platform.builtInServer" />
</component>
</module>
@@ -0,0 +1,10 @@
<!-- Jupyter language -->
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<fileType name="Jupyter"
language="Jupyter"
extensions="ipynb"
implementationClass="org.jetbrains.plugins.notebooks.jupyter.JupyterFileType"
fieldName="INSTANCE"/>
</extensions>
</idea-plugin>
@@ -0,0 +1 @@
filetype.jupyter.description=Jupyter Notebook
@@ -0,0 +1,9 @@
package org.jetbrains.plugins.notebooks.core.api.lang
import com.intellij.lang.Language
/**
* General language for notebooks.
* To share some of the common features for the notebooks, their language should use [NotebookLanguage] as base one.
*/
object NotebookLanguage: Language("Notebook")
@@ -0,0 +1,18 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter
import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.openapi.vfs.VirtualFile
import icons.PythonPsiApiIcons
import org.jetbrains.annotations.NonNls
import javax.swing.Icon
object JupyterFileType : LanguageFileType(JupyterLanguage) {
@NonNls
override fun getName() = "Jupyter"
override fun getDescription() = JupyterPsiBundle.message("filetype.jupyter.description")
override fun getDefaultExtension() = "ipynb"
override fun getIcon(): Icon = PythonPsiApiIcons.IPythonNotebook
override fun getCharset(file: VirtualFile, content: ByteArray): String = CharsetToolkit.UTF8
}
@@ -0,0 +1,7 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter
import com.intellij.lang.Language
import org.jetbrains.plugins.notebooks.core.api.lang.NotebookLanguage
object JupyterLanguage : Language(NotebookLanguage, "Jupyter")
@@ -0,0 +1,16 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter
import com.intellij.DynamicBundle
import org.jetbrains.annotations.Nls
import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.PropertyKey
@NonNls
private const val BUNDLE = "messages.JupyterPsiBundle"
object JupyterPsiBundle : DynamicBundle(BUNDLE) {
@JvmStatic
@Nls
fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
}
@@ -0,0 +1,105 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter.preview
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.util.PathUtil
import io.netty.channel.Channel
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.http.EmptyHttpHeaders
import io.netty.handler.codec.http.FullHttpRequest
import io.netty.handler.codec.http.QueryStringDecoder
import org.apache.http.client.utils.URIBuilder
import org.jetbrains.ide.HttpRequestHandler
import java.io.File
import java.net.URI
import java.net.URL
/**
* "Web server" to serve Jupyter HTML
*/
abstract class JupyterCefHttpHandlerBase(private val absolutePathFiles: Collection<String> = emptyList()) : HttpRequestHandler() {
companion object {
private val allowedTypes = setOf("css", "js", "html", "svg", "woff2", "ttf")
private const val JUPYTER_HTTP_URI = "jupyter"
private const val prefix = "/$JUPYTER_HTTP_URI"
/**
* Jupyter HTTP files can be accessed with this url
*/
fun getJupyterHttpUrl(): URIBuilder = getJupyterBaseUrl("http").addPathSegment(JUPYTER_HTTP_URI)
/**
* Root of the web app
*/
fun getIndexUrl(): URIBuilder = getJupyterHttpUrl().addPathSegment("index.html")
/**
* Resources are in different folders when launched locally versus installation.
* This method handles this difference. See .groovy build scripts
*/
private fun getResource(path: String): URL {
val javaClass = Companion::class.java
val url = javaClass.classLoader.getResource(path)
if (url != null) {
return url
}
val myPath = PathUtil.getJarPathForClass(javaClass)
// static/css/.. <--our resource
// lib/python.jar <--getJarPathForClass
val result = File(File(myPath).parentFile.parentFile, path)
assert(result.exists()) { "Can't find $result" }
return result.toURI().toURL()
}
}
override fun isSupported(request: FullHttpRequest): Boolean =
super.isSupported(request) && request.uri().let { it.startsWith(prefix) || it in absolutePathFiles }
override fun process(urlDecoder: QueryStringDecoder,
request: FullHttpRequest,
context: ChannelHandlerContext): Boolean {
val str = request.uri()
val fullUri = URI(str).path
val uri = getFileFromUrl(fullUri) ?: return false
val extension = FileUtilRt.getExtension(uri)
if (extension in allowedTypes) {
return readFile(request, context.channel(), uri)
}
else {
Logger.getInstance(JupyterCefHttpHandlerBase::class.java).warn("Extension not allowed: $extension")
}
return false
}
private fun getFileFromUrl(fullUri: String): String? {
if (fullUri in absolutePathFiles) {
return fullUri
}
if (!fullUri.startsWith(prefix)) {
return null
}
val uri = fullUri.replace("//", "/").substring(prefix.length).trimStart('/')
if (uri.isEmpty()) {
return null
}
if (".." in uri) {
return null
}
return uri
}
abstract val appName: String
private fun readFile(request: FullHttpRequest, channel: Channel, file: String): Boolean {
val appName = appName
val resource = getResource("$appName/$file")
val bytes = resource.readBytes()
return sendData(bytes, "$appName/$file", request, channel, EmptyHttpHeaders.INSTANCE)
}
}
@@ -0,0 +1,14 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter.preview
import org.apache.http.client.utils.URIBuilder
import org.jetbrains.ide.BuiltInServerManager
/**
* Url for HTTP and WS Jupyter services
*/
fun getJupyterBaseUrl(scheme: String): URIBuilder =
URIBuilder().setScheme(scheme).setHost("127.0.0.1").setPort(BuiltInServerManager.getInstance().port)
fun URIBuilder.addPathSegment(string: String): URIBuilder = setPath((path ?: "") + "/$string")
fun URIBuilder.addParameter(name: String, value: Boolean): URIBuilder = addParameter(name, value.toString())
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.jupyter.core" />
<orderEntry type="module" module-name="intellij.platform.editor" />
<orderEntry type="module" module-name="intellij.platform.core" />
<orderEntry type="library" name="jcef" level="project" />
<orderEntry type="library" name="kotlinx-coroutines-jdk8" level="project" />
<orderEntry type="module" module-name="intellij.platform.ide" />
<orderEntry type="module" module-name="intellij.platform.util.ui" />
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
<orderEntry type="module" module-name="intellij.platform.ide.util.netty" />
<orderEntry type="library" name="http-client" level="project" />
</component>
</module>
@@ -0,0 +1,9 @@
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="/META-INF/jupyter-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
<extensions defaultExtensionNs="com.intellij">
<httpRequestHandler implementation="org.jetbrains.plugins.notebooks.jupyter.preview.viewOnly.JupyterViewOnlyHandler"/>
<fileEditorProvider implementation="org.jetbrains.plugins.notebooks.jupyter.preview.viewOnly.JupyterViewOnlyProvider"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,32 @@
<svg width="65" height="66" viewBox="0 0 65 66" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M60.4 8.53336C59.6666 8.13336 58.6666 7.80003 57.8666 7.6667C57.3333 7.6667 23.2666 1.13336 21.4666 1.00003C20.6 0.933364 19.6666 1.00003 18.8 1.13336C2.99997 3.4667 -1.00003 22.7334 12.0666 30.8C15.1333 32.6667 18.8 33.3334 22.3333 32.5334C28.5333 31.2 56.4 24.3334 58.2 23.9334C65.9333 22.2667 67.6 12.3334 60.4 8.53336Z" fill="url(#paint0_linear)"/>
<path d="M60.7333 38.2C59.4 36.6667 35.2667 9.26666 30.1333 4.79999C29.1333 3.93333 27.9333 3.13333 26.6 2.39999C24.2 1.13333 21.4667 0.66666 18.8 1.06666C4.53334 3.26666 -0.13333 19.2 8.73334 28.2C9.66667 29.2 36.2 58.6667 36.4667 59C37.6667 60.4667 39.1333 61.8667 41 63C44.0667 64.9333 47.8 65.5333 51.4 64.7333C64.4667 61.8 68.6667 47.0667 60.7333 38.2Z" fill="url(#paint1_linear)"/>
<path d="M55.6666 34.3334C55.1333 34.0667 54.6 33.8 54 33.6C53.5333 33.4667 17.6666 22.1333 16.8666 21.9333C15.5333 21.6 14.1333 21.5333 12.8 21.7333C-2.28292e-05 23.6 -3.26669 39.2667 7.33331 45.8667C9.79998 47.4 42.5333 63.8 43.4 64.1333C45.9333 65.0667 48.6666 65.2667 51.3333 64.6667C66.6666 61.3333 69.8 41.7334 55.6666 34.3334Z" fill="url(#paint2_linear)"/>
<path d="M60.4 8.53338C59.2 7.86671 57.8 7.66671 56.4 7.86671C55.6667 8.00005 55 8.13338 54.3333 8.40005C51.2 9.66671 10.1333 22.2667 8.99999 22.8C-0.533341 26.9334 -2.06667 40.0001 7.33333 45.8667C9.79999 47.4001 12.8 47.9334 15.7333 47.2667C16.8667 47.0001 18 46.6667 18.9333 46.2001C24 43.8001 60.0667 23.4 60.8 23C66.2 19.8667 66.6667 11.8667 60.4 8.53338Z" fill="url(#paint3_linear)"/>
<path d="M52 14H14V52H52V14Z" fill="url(#paint4_linear)"/>
<path d="M33.1444 45H19V47.3222H33.1444V45Z" fill="white"/>
<path d="M34 18.64H37.1283V30.1522H43.3224V32.78H34V18.64Z" fill="white"/>
<path d="M19 18.64H24.5058C28.9481 18.64 32.0138 21.7058 32.0138 25.6474V25.71C32.0138 29.7143 28.9481 32.78 24.5058 32.78H19V18.64ZM22.1283 21.4555V29.9645H24.5058C27.0711 29.9645 28.7604 28.2752 28.7604 25.7726V25.71C28.7604 23.2074 27.0711 21.4555 24.5058 21.4555H22.1283V21.4555Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear" x1="20.566" y1="16.8362" x2="59.4061" y2="24.5771" gradientUnits="userSpaceOnUse">
<stop offset="0.2421" stop-color="#3BEA62"/>
<stop offset="0.8566" stop-color="#FCF84A"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="16.407" y1="5.42879" x2="53.6996" y2="62.1501" gradientUnits="userSpaceOnUse">
<stop offset="0.0175975" stop-color="#3BEA62"/>
<stop offset="0.786" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="15.8887" y1="36.9893" x2="63.1221" y2="54.0488" gradientUnits="userSpaceOnUse">
<stop offset="0.1209" stop-color="#1FAEB5"/>
<stop offset="0.9746" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="2.30139" y1="39.6482" x2="63.3111" y2="12.6083" gradientUnits="userSpaceOnUse">
<stop offset="0.1209" stop-color="#1FAEB5"/>
<stop offset="0.8556" stop-color="#FCF84A"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="32.9493" y1="4.7641" x2="32.9493" y2="38.8425" gradientUnits="userSpaceOnUse">
<stop offset="0.0842986" stop-color="#878585"/>
<stop offset="0.5377"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,208 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M41.2 0L44.4 40.4L16.5 55.4L0 13L41.2 0Z" fill="url(#paint0_linear)"/>
<path d="M23.7 36.8L16.5 55.4L0 13L23.7 36.8Z" fill="url(#paint1_linear)"/>
<path d="M41.1999 0L42.3999 22.3H24.0999L15.8999 7.9L41.1999 0Z" fill="url(#paint2_linear)"/>
<path d="M34.3 21.2002L64 15.2002V43.3002L43.6 50.9002L35.2001 43.4002L34.3 21.2002Z" fill="url(#paint3_linear)"/>
<path d="M64 15.2L36.5 44.9L41.2 0L64 15.2Z" fill="#21D789"/>
<path d="M64 15.2001L48.8 11.6001L43.3 51.3001L64 43.3001V15.2001Z" fill="url(#paint4_linear)"/>
<path d="M21.8999 12.8999L42.3999 16.0999L63.9999 43.2999L43.2999 51.2999L35.1999 43.3999L21.8999 12.8999Z" fill="url(#paint5_linear)"/>
<path d="M13.2001 0L42.4001 16.1L32.3001 64H15.3001L0.600098 48.8L13.2001 0Z" fill="url(#paint6_linear)"/>
<path d="M23.2999 5.6001L10.6999 9.6001L5.8999 28.2001L16.4999 55.4001L36.8999 42.4001L42.3999 16.4001L42.2999 16.1001L23.2999 5.6001Z" fill="url(#paint7_linear)"/>
<path d="M38.1001 16.6001L42.4001 16.1001L38.1001 16.6001Z" fill="url(#paint8_linear)"/>
<path d="M20.1001 40.3L28.0001 17.6L13.2001 0L0.600098 48.8L20.1001 40.3Z" fill="url(#paint9_linear)"/>
<path d="M15.3002 64.0001L5.7002 54.1001L15.3002 64.0001H32.3002H15.3002Z" fill="url(#paint10_linear)"/>
<path d="M5.8999 28.1998L12.8999 46.1998L16.4999 55.3998L23.6999 36.7998L7.7999 20.7998L5.8999 28.1998Z" fill="url(#paint11_linear)"/>
<path d="M20.1001 40.2998L32.3001 63.9998H15.3001L0.600098 48.7998L20.1001 40.2998Z" fill="url(#paint12_linear)"/>
<path d="M20.1001 40.3001L32.3001 64.0001L42.4001 16.1001L28.0001 17.6001L20.1001 40.3001Z" fill="url(#paint13_linear)"/>
<path d="M36.2001 44.7998L32.3 63.9998H15.3L16.5 55.3998L36.2001 44.7998Z" fill="url(#paint14_linear)"/>
<path d="M16.5 55.3998L25.4 50.5998L20.1 40.2998L12 43.8998L16.5 55.3998Z" fill="url(#paint15_linear)"/>
<path d="M25.3999 50.5998L32.2999 63.9998L36.1999 44.7998L25.3999 50.5998Z" fill="url(#paint16_linear)"/>
<path d="M13.2 0L42.4 16.1L35.5 16.9L28 17.6L13.2 0Z" fill="url(#paint17_linear)"/>
<path d="M42 15.9001L23.3 5.6001L19 7.0001L28 17.6001L35.5 16.9001L42.1 16.2001L42 15.9001Z" fill="url(#paint18_linear)"/>
<path d="M39.5 16.4001L42.4 16.1001L39.7 14.6001L39.5 16.4001Z" fill="url(#paint19_linear)"/>
<path d="M64 43.3001L42.4 16.1001L35.5 16.9001L28 17.6001L64 43.3001Z" fill="url(#paint20_linear)"/>
<path d="M38.6001 25.2001L48.3001 32.1001L52.0001 28.2001L42.4001 16.1001L39.5001 16.4001L38.6001 25.2001Z" fill="url(#paint21_linear)"/>
<path d="M46.2 30.5998L64 43.2998L47.2999 22.2998L46.2 30.5998Z" fill="url(#paint22_linear)"/>
<path d="M64 43.3001L43.3 51.3001L36.5 44.9001L28 17.6001L64 43.3001Z" fill="url(#paint23_linear)"/>
<path d="M38.6 25.2002L36.5 44.9002L48.3 32.1002L38.6 25.2002Z" fill="url(#paint24_linear)"/>
<path d="M43.3 51.3001L64 43.3001L46.2001 30.6001L43.3 51.3001Z" fill="url(#paint25_linear)"/>
<path d="M36.6001 44.7001L36.7001 44.8001L45.5001 35.2001L46.2001 30.6001L37.8001 32.5001L36.6001 44.7001Z" fill="url(#paint26_linear)"/>
<path d="M43.3 51.3001L36.5 44.9001L28 17.6001L43.3 51.3001Z" fill="url(#paint27_linear)"/>
<path d="M36.5 44.9L43.3 51.3L37.2 38L36.5 44.9Z" fill="url(#paint28_linear)"/>
<path d="M41.2 0L36.5 44.9L45.5 35.2L48.8 11.6L41.2 0Z" fill="url(#paint29_linear)"/>
<path d="M64 15.2L48.7999 11.6L41.2 0L64 15.2Z" fill="url(#paint30_linear)"/>
<path d="M52 12H12V52H52V12Z" fill="url(#paint31_linear)"/>
<g opacity="0.3">
<path opacity="0.3" d="M12 44.2L15.05 52H21.85L44.15 39.95L41.9 12H12V44.2Z" fill="url(#paint32_linear)"/>
<path opacity="0.3" d="M39.6 12L36.25 44.5L45.25 34.8L48.4 12H39.6Z" fill="url(#paint33_linear)"/>
<path opacity="0.3" d="M52 12.05L51.7 12H48.4L43 50.95L52 47.45V12.05Z" fill="url(#paint34_linear)"/>
<path opacity="0.3" d="M52 34.55L27.7 17.25L36.25 44.5L43 50.95L52 47.45V34.55Z" fill="url(#paint35_linear)"/>
<path opacity="0.3" d="M12 52H34.5L42.15 15.75L35.35 12H12V52Z" fill="url(#paint36_linear)"/>
<path opacity="0.3" d="M12 43.35L19.8 39.95L27.7 17.25L23.3 12H12V43.35Z" fill="url(#paint37_linear)"/>
<path opacity="0.3" d="M27.7 17.25L35.25 16.45L42.15 15.75L41.75 15.55L36.35 12.55L35.35 12H23.3L27.7 17.25Z" fill="url(#paint38_linear)"/>
</g>
<path d="M32 44.4502H17V46.9502H32V44.4502Z" fill="white"/>
<path d="M17 17.001H22.8345C27.5625 17.001 30.8821 20.22 30.8821 24.445C30.8821 28.67 27.5625 31.9896 22.8345 31.9896H17V17.001ZM20.3196 20.0188V29.0724H22.8345C25.5506 29.0724 27.3613 27.2616 27.3613 24.5456C27.3613 21.8295 25.5506 20.0188 22.8345 20.0188H20.3196Z" fill="white"/>
<path d="M32.0891 29.9777L34.101 27.5634C35.5093 28.67 36.9177 29.3742 38.6278 29.3742C40.0361 29.3742 40.8409 28.8712 40.8409 27.9658C40.8409 27.1611 40.3379 26.6581 37.823 26.0545C34.8052 25.2498 32.7933 24.445 32.7933 21.4272C32.7933 18.7111 35.0064 16.7998 38.1248 16.7998C40.3379 16.7998 42.2492 17.504 43.7581 18.7111L42.048 21.226C40.7403 20.3206 39.3319 19.7171 38.1248 19.7171C36.8171 19.7171 36.2135 20.3206 36.2135 21.0248C36.2135 22.0307 36.8171 22.3325 39.5331 23.0367C42.6516 23.8414 44.3617 24.948 44.3617 27.5634C44.3617 30.5813 42.048 32.2914 38.829 32.2914C36.2135 32.392 33.8998 31.5872 32.0891 29.9777Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear" x1="49.727" y1="27.7225" x2="5.2827" y2="27.7225" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789"/>
<stop offset="0.8726" stop-color="#FCF84A"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="16.2104" y1="28.1752" x2="9.8675" y2="32.9751" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="white"/>
<stop offset="0.8726" stop-color="#FCF84A"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="33.1877" y1="9.2209" x2="39.6242" y2="-0.152201" gradientUnits="userSpaceOnUse">
<stop offset="0.095296" stop-color="#BBF8AF" stop-opacity="0"/>
<stop offset="1" stop-color="#21FF79"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="49.1567" y1="18.4761" x2="49.1567" y2="71.421" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#21D789"/>
<stop offset="1" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="69.468" y1="39.9763" x2="31.5395" y2="23.9049" gradientUnits="userSpaceOnUse">
<stop offset="0.0202374" stop-color="#21D789" stop-opacity="0"/>
<stop offset="1" stop-color="#00FF6A"/>
</linearGradient>
<linearGradient id="paint5_linear" x1="84.2411" y1="67.2158" x2="21.0946" y2="16.131" gradientUnits="userSpaceOnUse">
<stop offset="0.1049" stop-color="#21D789"/>
<stop offset="0.9668" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint6_linear" x1="55.3331" y1="-4.9262" x2="11.2222" y2="45.0665" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#21D789"/>
<stop offset="0.7396" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint7_linear" x1="-0.461798" y1="13.2262" x2="24.6524" y2="32.169" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789"/>
<stop offset="0.8283" stop-color="#087CFA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint8_linear" x1="40.1517" y1="16.5244" x2="41.0705" y2="15.3683" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789" stop-opacity="0"/>
<stop offset="0.8726" stop-color="#01D0FF"/>
</linearGradient>
<linearGradient id="paint9_linear" x1="8.7498" y1="30.0909" x2="25.4611" y2="9.0614" gradientUnits="userSpaceOnUse">
<stop offset="0.3826" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="1" stop-color="#01EFDB"/>
</linearGradient>
<linearGradient id="paint10_linear" x1="18.0063" y1="60.3357" x2="21.2341" y2="56.2737" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789" stop-opacity="0"/>
<stop offset="0.8726" stop-color="#01D0FF"/>
</linearGradient>
<linearGradient id="paint11_linear" x1="15.1782" y1="19.4402" x2="14.8354" y2="31.5259" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789"/>
<stop offset="0.8283" stop-color="#087CFA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint12_linear" x1="38.5193" y1="28.1168" x2="9.71929" y2="65.0596" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#083FFA"/>
<stop offset="0.7396" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint13_linear" x1="16.8468" y1="3.5218" x2="44.8753" y2="53.4074" gradientUnits="userSpaceOnUse">
<stop offset="0.2458" stop-color="#083FFA"/>
<stop offset="0.9131" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint14_linear" x1="16.931" y1="45.5604" x2="31.3218" y2="59.9512" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#089FFF"/>
<stop offset="0.7396" stop-color="#087CFA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint15_linear" x1="26.2115" y1="56.5247" x2="16.7044" y2="46.1611" gradientUnits="userSpaceOnUse">
<stop offset="0.1526" stop-color="#0832FF"/>
<stop offset="0.9138" stop-color="#087CFA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint16_linear" x1="39.7671" y1="60.9074" x2="28.1979" y2="47.2154" gradientUnits="userSpaceOnUse">
<stop offset="0.1526" stop-color="#0832FF"/>
<stop offset="0.9138" stop-color="#087CFA" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint17_linear" x1="27.528" y1="-14.3507" x2="27.9338" y2="19.7329" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#21D789"/>
<stop offset="0.8246" stop-color="#087CFA"/>
</linearGradient>
<linearGradient id="paint18_linear" x1="30.3738" y1="10.0041" x2="29.4971" y2="1.8946" gradientUnits="userSpaceOnUse">
<stop offset="0.095296" stop-color="#BBF8AF" stop-opacity="0"/>
<stop offset="1" stop-color="#21FF79"/>
</linearGradient>
<linearGradient id="paint19_linear" x1="41.8314" y1="17.3166" x2="39.0305" y2="14.0639" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#21D789" stop-opacity="0"/>
<stop offset="0.9185" stop-color="#21D789"/>
</linearGradient>
<linearGradient id="paint20_linear" x1="57.1468" y1="47.1884" x2="35.715" y2="15.0407" gradientUnits="userSpaceOnUse">
<stop offset="0.027928" stop-color="#21D789"/>
<stop offset="0.9294" stop-color="#0860FA"/>
</linearGradient>
<linearGradient id="paint21_linear" x1="45.7531" y1="30.1517" x2="43.3103" y2="12.1518" gradientUnits="userSpaceOnUse">
<stop offset="0.0757413" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="1" stop-color="#21D789" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="paint22_linear" x1="52.0768" y1="32.7816" x2="40.2483" y2="16.453" gradientUnits="userSpaceOnUse">
<stop offset="0.0757413" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="1" stop-color="#4F46C6" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="paint23_linear" x1="53.8147" y1="49.4098" x2="32.3829" y2="17.2621" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#18AFAF"/>
<stop offset="0.6591" stop-color="#0860FA"/>
<stop offset="0.9983" stop-color="#084CFA"/>
</linearGradient>
<linearGradient id="paint24_linear" x1="43.6022" y1="40.3684" x2="35.1165" y2="26.8684" gradientUnits="userSpaceOnUse">
<stop offset="0.0757413" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="1" stop-color="#21D789" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="paint25_linear" x1="53.5041" y1="47.1806" x2="39.9607" y2="34.554" gradientUnits="userSpaceOnUse">
<stop offset="0.0757413" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="1" stop-color="#21D789" stop-opacity="0.6"/>
</linearGradient>
<linearGradient id="paint26_linear" x1="40.0169" y1="36.3714" x2="35.3348" y2="32.0063" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="0.8547" stop-color="#0841FA"/>
</linearGradient>
<linearGradient id="paint27_linear" x1="44.6324" y1="49.825" x2="25.6975" y2="21.4227" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#089CFA"/>
<stop offset="0.7396" stop-color="#083CFA"/>
</linearGradient>
<linearGradient id="paint28_linear" x1="43.2912" y1="51.072" x2="35.8184" y2="39.8627" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#087CFA" stop-opacity="0"/>
<stop offset="0.9787" stop-color="#0860FA"/>
</linearGradient>
<linearGradient id="paint29_linear" x1="42.7051" y1="20.5031" x2="45.7051" y2="6.7888" gradientUnits="userSpaceOnUse">
<stop offset="0.3551" stop-color="#BBF8AF" stop-opacity="0"/>
<stop offset="1" stop-color="#21FF79"/>
</linearGradient>
<linearGradient id="paint30_linear" x1="39.7653" y1="0.9064" x2="57.4224" y2="14.1921" gradientUnits="userSpaceOnUse">
<stop offset="0.0202374" stop-color="#BBF8AF" stop-opacity="0"/>
<stop offset="1" stop-color="#21FF79"/>
</linearGradient>
<linearGradient id="paint31_linear" x1="12.3364" y1="12.3364" x2="53.3664" y2="53.3664" gradientUnits="userSpaceOnUse">
<stop offset="0.0284813" stop-color="#002846"/>
<stop offset="0.1369" stop-color="#002038"/>
<stop offset="0.4947" stop-color="#000910"/>
<stop offset="0.6795"/>
</linearGradient>
<linearGradient id="paint32_linear" x1="8.1777" y1="32" x2="40.3334" y2="32" gradientUnits="userSpaceOnUse">
<stop offset="0.0782105" stop-color="#21D789"/>
<stop offset="0.8726" stop-color="#FCF84A"/>
</linearGradient>
<linearGradient id="paint33_linear" x1="42.8253" y1="41.9366" x2="41.6443" y2="9.17915" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#218640"/>
<stop offset="0.8027" stop-color="#B5FA59"/>
</linearGradient>
<linearGradient id="paint34_linear" x1="46.8017" y1="14.3477" x2="48.5637" y2="58.3978" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#21D789"/>
<stop offset="1" stop-color="#083450"/>
</linearGradient>
<linearGradient id="paint35_linear" x1="49.9087" y1="48.2098" x2="29.8872" y2="18.1775" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#021A43"/>
<stop offset="0.6591" stop-color="#0860FA"/>
</linearGradient>
<linearGradient id="paint36_linear" x1="24.7139" y1="-0.0475" x2="28.605" y2="56.043" gradientUnits="userSpaceOnUse">
<stop offset="0.2348" stop-color="#21D789"/>
<stop offset="0.7396" stop-color="#083450"/>
</linearGradient>
<linearGradient id="paint37_linear" x1="21.2457" y1="43.4041" x2="17.7951" y2="10.9538" gradientUnits="userSpaceOnUse">
<stop offset="0.2268" stop-color="#086C93"/>
<stop offset="0.8196" stop-color="#01EFDB"/>
</linearGradient>
<linearGradient id="paint38_linear" x1="24.7196" y1="12.5017" x2="44.427" y2="18.6603" gradientUnits="userSpaceOnUse">
<stop offset="0.2508" stop-color="#21D789"/>
<stop offset="0.8847" stop-color="#0C515A"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
<svg width="7" height="7" viewBox="0 0 7 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 0H2L3.8958 1.8958L0.75 5.0416L1.95208 6.24368L5.09788 3.09788L7 5V0Z" fill="#7F8B91" fill-opacity="0.9"/>
</svg>

After

Width:  |  Height:  |  Size: 257 B

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en" theme="light">
<head>
<meta charset="UTF-8">
<script defer type="text/javascript" src="notebookViewer.tvm.min.js"></script>
<script defer type="text/javascript" src="notebookViewer.deps.min.js"></script>
<script defer type="text/javascript" src="editor.min.js"></script>
<link rel="stylesheet" href="notebookViewer.css">
<script type="text/x-mathjax-config">
MathJax.Hub.Config({ skipStartupTypeset: true, messageStyle: "none", tex2jax: { inlineMath: [['$','$'], ['\\(','\\)']], processEscapes: true }, asciimath2jax: { delimiters: [['``','``']] }, CommonHTML: { linebreaks: { automatic: true, width: "container" } }, "HTML-CSS": { linebreaks: { automatic: true, width: "container" } }, SVG: { linebreaks: { automatic: true, width: "container" } }, showMathMenu: false });
</script>
<script type="application/javascript">
document.addEventListener('contextmenu', event => event.preventDefault());
function render(obj) {
try {
IPythonRenderer.render(JSON.stringify(obj));
}
catch (ex) {
console.log(ex);
document.getElementsByClassName('main')[0].innerText = 'Notebook isn\'t supported by PyCharm';
}
}
</script>
</head>
<body style="overflow: auto;">
<div class="adviser">
<p>PyCharm Community edition supports Jupyter notebooks in read-only mode, to get full support for local notebooks download and try <a
href="https://www.jetbrains.com/pycharm/download/">PyCharm Professional</a> now!</p>
<div class="products-container">
<div class="product">
<img src="./dataspell.svg" width="32" height="32"/>
<p>Try <a href="https://www.jetbrains.com/dataspell/">DataSpell</a> &#8212; a dedicated IDE for data science,<br/> with
full
support for local and remote notebooks</p>
</div>
<div class="product">
<img src="./datalore.svg" width="32" height="32"/>
<p>Try <a href="https://datalore.jetbrains.com/">Datalore</a> &#8212; an online environment <br/> for Jupyter notebooks in the browser</p>
</div>
</div>
<p>Also read more about JetBrains Data Solutions in <a href="#">our new blog post</a></p>
</div>
<div class="main"></div>
</body>
</html>
@@ -0,0 +1,19 @@
body,
html {
margin: 0;
padding: 0;
}
html {
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 12px;
}
.menu {
display: none;
}
.output_area .jupyter-widgets-disconnected::before {
display: none;
}
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>IpyWidgets</title>
<link rel="stylesheet" href="/ipywidgets.css">
</head>
<body>
<div class="menu">
<div>
<div id="help_menu"></div>
</div>
</div>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/1.33.1/plotly.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
<script defer src="/ipywidgets.js"></script>
</body>
</html>
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
function __appendSprite(sprite) {
let container = document.createElement("div");
container.style.width = 0;
container.style.height = 0;
container.style.position = "absolute";
container.style.overflow = "hidden";
container.innerHTML = sprite;
document.body.append(container);
};
__appendSprite('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>');
@@ -0,0 +1,96 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter.preview.viewOnly
import com.intellij.ide.ui.LafManagerListener
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorLocation
import com.intellij.openapi.fileEditor.FileEditorState
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.UserDataHolderBase
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.jcef.JBCefBrowser
import com.intellij.util.ui.UIUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import org.cef.browser.CefBrowser
import org.cef.browser.CefFrame
import org.cef.handler.CefLoadHandlerAdapter
import org.jetbrains.plugins.notebooks.jupyter.preview.JupyterCefHttpHandlerBase
import org.jetbrains.plugins.notebooks.jupyter.preview.addPathSegment
import java.beans.PropertyChangeListener
import java.nio.ByteBuffer
import javax.swing.JComponent
/**
* Show jupyter file as web page in viewOnly mode
*/
class JupyterViewOnlyFileEditor private constructor(val myFile: VirtualFile) : UserDataHolderBase(), FileEditor {
// OSR is slower but doesn't work on Linux when component detached from Swing (i.e. tab switched)
private val browser = JBCefBrowser.createBuilder().setOffScreenRendering(SystemInfo.isLinux).setUrl(
JupyterCefHttpHandlerBase.getJupyterHttpUrl().addPathSegment("index.html").toString()).createBrowser()
private val browserComponent: JComponent = browser.component
private val darcula: MutableStateFlow<Boolean> = MutableStateFlow(UIUtil.isUnderDarcula())
private val scope = CoroutineScope(Dispatchers.EDT)
companion object {
fun create(file: VirtualFile): JupyterViewOnlyFileEditor = JupyterViewOnlyFileEditor(file).apply {
Disposer.register(this, browser)
browser.jbCefClient.addLoadHandler(object : CefLoadHandlerAdapter() {
override fun onLoadEnd(browser: CefBrowser, frame: CefFrame, httpStatusCode: Int) {
val str = Charsets.UTF_8.decode(ByteBuffer.wrap(myFile.contentsToByteArray())).toString()
configureLaf()
frame.executeJavaScript("const data=$str;", browser.url, 0)
frame.executeJavaScript("render(data);", browser.url, 0)
}
}, browser.cefBrowser)
browser.setOpenLinksInExternalBrowser(true)
ApplicationManager.getApplication().messageBus.connect(this).subscribe(LafManagerListener.TOPIC, LafManagerListener {
// May be called several times, buffer merges calls
darcula.value = UIUtil.isUnderDarcula()
})
scope.launch {
darcula.collect {
configureLaf()
}
}
}
}
private fun configureLaf() {
val theme = if (darcula.value) "dark" else "idea"
browser.cefBrowser.executeJavaScript("IPythonRenderer.setTheme('$theme')", browser.cefBrowser.url, 0)
}
override fun getComponent(): JComponent = browserComponent
override fun getPreferredFocusedComponent(): JComponent = browserComponent
override fun getName(): String = myFile.name
override fun getFile(): VirtualFile = myFile
override fun setState(state: FileEditorState) = Unit
override fun isModified(): Boolean = false
override fun isValid(): Boolean = true
override fun addPropertyChangeListener(listener: PropertyChangeListener) = Unit
override fun removePropertyChangeListener(listener: PropertyChangeListener) = Unit
override fun getCurrentLocation(): FileEditorLocation? = null
override fun dispose() {
scope.cancel()
}
}
@@ -0,0 +1,11 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter.preview.viewOnly
import org.jetbrains.plugins.notebooks.jupyter.preview.JupyterCefHttpHandlerBase
class JupyterViewOnlyHandler : JupyterCefHttpHandlerBase(absolutePathFiles = listOf(
"/ipywidgets.html",
"/ipywidgets.css",
"/ipywidgets.js")) {
override val appName: String = "jupyter-view-only"
}
@@ -0,0 +1,21 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.notebooks.jupyter.preview.viewOnly
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorPolicy
import com.intellij.openapi.fileEditor.FileEditorProvider
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.plugins.notebooks.jupyter.JupyterFileType
class JupyterViewOnlyProvider : FileEditorProvider, DumbAware {
override fun accept(project: Project, file: VirtualFile): Boolean = file.fileType == JupyterFileType
override fun createEditor(project: Project, file: VirtualFile): FileEditor = JupyterViewOnlyFileEditor.create(file)
override fun getEditorTypeId(): String = "jupyter-view-only-provider"
override fun getPolicy(): FileEditorPolicy = FileEditorPolicy.HIDE_DEFAULT_EDITOR
}
@@ -22,6 +22,7 @@ class PythonCommunityPluginModules {
"intellij.python.reStructuredText",
"intellij.python.sdk",
"intellij.python.featuresTrainer",
"intellij.jupyter.core"
]
static String pythonCommunityName = "python-ce"
@@ -36,6 +36,8 @@ class PyCharmCommunityProperties extends PyCharmPropertiesBase {
directoryName = "pythonIDE"
mainJarName = "python-ide.jar"
withModule("intellij.pycharm.community.ide.impl", mainJarName)
withModule("intellij.jupyter.viewOnly")
withModule("intellij.jupyter.core")
}
]
productLayout.pluginModulesToPublish = ["intellij.python.community.plugin"]
+2 -1
View File
@@ -10,6 +10,7 @@
<xi:include href="/META-INF/pycharm-community-customization.xml"/>
<xi:include href="/META-INF/tips-pycharm-community.xml"/>
<xi:include href="/META-INF/jupyter-view-only.xml"/>
<extensions defaultExtensionNs="com.intellij">
<applicationInitializedListener implementation="com.jetbrains.python.PyCharmCorePluginConfigurator"/>
@@ -23,4 +24,4 @@
<annotator language="JSON" implementationClass="com.jetbrains.python.PyCharmProfessionalAdvertiser"/>
<projectService serviceImplementation="com.jetbrains.python.PyCharmProfessionalAdvertiserSettings"/>
</extensions>
</idea-plugin>
</idea-plugin>
@@ -9,5 +9,6 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.pycharm.community.ide.impl" />
<orderEntry type="library" name="tips-pycharm-community" level="project" />
<orderEntry type="module" module-name="intellij.jupyter.viewOnly" />
</component>
</module>
+1
View File
@@ -18,5 +18,6 @@
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.python.featuresTrainer" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.notebooks.visualization" />
<orderEntry type="module" module-name="intellij.jupyter.core" />
</component>
</module>
@@ -11,4 +11,4 @@
<orderEntry type="module" module-name="intellij.python.grazie" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.python.markdown" scope="RUNTIME" />
</component>
</module>
</module>