IJPL-228243 drop web view for PluginGraphWriter's output

GitOrigin-RevId: ed538b731feb81ea1462fd543599eedfabe6f60a
This commit is contained in:
Vadim Salavatov
2026-01-12 15:49:34 +00:00
committed by intellij-monorepo-bot
parent 26e6ef64b9
commit cc770964bb
12 changed files with 0 additions and 9921 deletions
-26
View File
@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Plugin Graph</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
</head>
<body>
<!--suppress HtmlFormInputWithoutLabel -->
<input id="searchField"
type="search"
style="position: fixed; left: 50%; transform: translate(-50%, 0); z-index: 100;"
placeholder="filter"
spellcheck="false"
autofocus/>
<input id="fileInput"
type="file"
style="position: fixed; right: 0; z-index: 100;"
accept="application/json"/>
<div id="tooltip"></div>
<div id="cy" style="width: 100vw; height: 100vh;"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
-25
View File
@@ -1,25 +0,0 @@
{
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build --emptyOutDir",
"deploy": "pnpm run build && space hosting publish --public ij plugingraph ./dist",
"serve": "vite preview"
},
"dependencies": {
"@fontsource/jetbrains-mono": "^4.5.0",
"comlink": "^4.3.1",
"cytoscape": "^3.19.1",
"cytoscape-cola": "^2.5.0",
"cytoscape-expand-collapse": "^4.1.0",
"cytoscape-popper": "^2.0.0",
"flexsearch": "^0.7.21",
"p-debounce": "^4.0.0",
"tippy.js": "^6.3.1"
},
"devDependencies": {
"sass": "^1.38.0",
"vite": "^2.5.0"
}
}
File diff suppressed because it is too large Load Diff
-329
View File
@@ -1,329 +0,0 @@
lockfileVersion: 5.3
specifiers:
'@fontsource/jetbrains-mono': ^4.5.0
comlink: ^4.3.1
cytoscape: ^3.19.1
cytoscape-cola: ^2.5.0
cytoscape-expand-collapse: ^4.1.0
cytoscape-popper: ^2.0.0
flexsearch: ^0.7.21
p-debounce: ^4.0.0
sass: ^1.38.0
tippy.js: ^6.3.1
vite: ^2.5.0
dependencies:
'@fontsource/jetbrains-mono': 4.5.0
comlink: 4.3.1
cytoscape: 3.19.1
cytoscape-cola: 2.5.0_cytoscape@3.19.1
cytoscape-expand-collapse: 4.1.0_cytoscape@3.19.1
cytoscape-popper: 2.0.0_cytoscape@3.19.1
flexsearch: 0.7.21
p-debounce: 4.0.0
tippy.js: 6.3.1
devDependencies:
sass: 1.38.0
vite: 2.5.0
packages:
/@fontsource/jetbrains-mono/4.5.0:
resolution: {integrity: sha512-gxUlpdCLoIrEQ6+1hkPbFHuQz8E5bPZ/iERU+13zEKb8rD/h21v3uHuAT7dTD+Co9nbSlgk6fyVkFwF5edUMog==}
dev: false
/@popperjs/core/2.9.2:
resolution: {integrity: sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==}
dev: false
/anymatch/3.1.2:
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
engines: {node: '>= 8'}
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.0
dev: true
/binary-extensions/2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'}
dev: true
/braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
dependencies:
fill-range: 7.0.1
dev: true
/chokidar/3.5.2:
resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==}
engines: {node: '>= 8.10.0'}
dependencies:
anymatch: 3.1.2
braces: 3.0.2
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.1
normalize-path: 3.0.0
readdirp: 3.6.0
optionalDependencies:
fsevents: 2.3.2
dev: true
/colorette/1.3.0:
resolution: {integrity: sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==}
dev: true
/comlink/4.3.1:
resolution: {integrity: sha512-+YbhUdNrpBZggBAHWcgQMLPLH1KDF3wJpeqrCKieWQ8RL7atmgsgTQko1XEBK6PsecfopWNntopJ+ByYG1lRaA==}
dev: false
/cytoscape-cola/2.5.0_cytoscape@3.19.1:
resolution: {integrity: sha512-TCpzO+e7H7Bhi2uiAi2Nq7gFwcSGkffe1J6uQ7Dsx6SLN9OhIzrQkBkV6m8kHzar+flVbP76RwxAa2y97jdphA==}
peerDependencies:
cytoscape: ^3.2.0
dependencies:
cytoscape: 3.19.1
webcola: 3.4.0
dev: false
/cytoscape-expand-collapse/4.1.0_cytoscape@3.19.1:
resolution: {integrity: sha512-RJsoSDAC0ui6U6CeM7z2tiFzsk4Z2aPG8PgNIwKeFVykFmMr5S+5aT1YceQZ5XnwGFGH0uteZ96XyAfUAVb/fw==}
peerDependencies:
cytoscape: ^3.3.0
dependencies:
cytoscape: 3.19.1
dev: false
/cytoscape-popper/2.0.0_cytoscape@3.19.1:
resolution: {integrity: sha512-b7WSOn8qXHWtdIXFNmrgc8qkaOs16tMY0EwtRXlxzvn8X+al6TAFrUwZoYATkYSlotfd/36ZMoeKMEoUck6feA==}
peerDependencies:
cytoscape: ^3.2.0
dependencies:
'@popperjs/core': 2.9.2
cytoscape: 3.19.1
dev: false
/cytoscape/3.19.1:
resolution: {integrity: sha512-fQSymoCzmDF5dejZqv94WXQUnI3cVZfaHWFQR+Q9RhJ6LzEs7dtkwgFYaoklsbXcrXz0uCGx4i3vQ0FiuOUu9Q==}
engines: {node: '>=0.10'}
dependencies:
heap: 0.2.6
lodash.debounce: 4.0.8
dev: false
/d3-dispatch/1.0.6:
resolution: {integrity: sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==}
dev: false
/d3-drag/1.2.5:
resolution: {integrity: sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==}
dependencies:
d3-dispatch: 1.0.6
d3-selection: 1.4.2
dev: false
/d3-path/1.0.9:
resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
dev: false
/d3-selection/1.4.2:
resolution: {integrity: sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==}
dev: false
/d3-shape/1.3.7:
resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
dependencies:
d3-path: 1.0.9
dev: false
/d3-timer/1.0.10:
resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==}
dev: false
/esbuild/0.12.20:
resolution: {integrity: sha512-u7+0qTo9Z64MD9PhooEngCmzyEYJ6ovFhPp8PLNh3UasR5Ihjv6HWVXqm8uHmasdQlpsAf0IsY4U0YVUfCpt4Q==}
hasBin: true
requiresBuild: true
dev: true
/fill-range/7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
dependencies:
to-regex-range: 5.0.1
dev: true
/flexsearch/0.7.21:
resolution: {integrity: sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg==}
dev: false
/fsevents/2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
dev: true
optional: true
/function-bind/1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.1
dev: true
/has/1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/heap/0.2.6:
resolution: {integrity: sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=}
dev: false
/is-binary-path/2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
dependencies:
binary-extensions: 2.2.0
dev: true
/is-core-module/2.6.0:
resolution: {integrity: sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==}
dependencies:
has: 1.0.3
dev: true
/is-extglob/2.1.1:
resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
engines: {node: '>=0.10.0'}
dev: true
/is-glob/4.0.1:
resolution: {integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==}
engines: {node: '>=0.10.0'}
dependencies:
is-extglob: 2.1.1
dev: true
/is-number/7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
dev: true
/lodash.debounce/4.0.8:
resolution: {integrity: sha1-gteb/zCmfEAF/9XiUVMArZyk168=}
dev: false
/nanoid/3.1.25:
resolution: {integrity: sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
/normalize-path/3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
dev: true
/p-debounce/4.0.0:
resolution: {integrity: sha512-4Ispi9I9qYGO4lueiLDhe4q4iK5ERK8reLsuzH6BPaXn53EGaua8H66PXIFGrW897hwjXp+pVLrm/DLxN0RF0A==}
engines: {node: '>=12'}
dev: false
/path-parse/1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/picomatch/2.3.0:
resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==}
engines: {node: '>=8.6'}
dev: true
/postcss/8.3.6:
resolution: {integrity: sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
colorette: 1.3.0
nanoid: 3.1.25
source-map-js: 0.6.2
dev: true
/readdirp/3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
dependencies:
picomatch: 2.3.0
dev: true
/resolve/1.20.0:
resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==}
dependencies:
is-core-module: 2.6.0
path-parse: 1.0.7
dev: true
/rollup/2.56.2:
resolution: {integrity: sha512-s8H00ZsRi29M2/lGdm1u8DJpJ9ML8SUOpVVBd33XNeEeL3NVaTiUcSBHzBdF3eAyR0l7VSpsuoVUGrRHq7aPwQ==}
engines: {node: '>=10.0.0'}
hasBin: true
optionalDependencies:
fsevents: 2.3.2
dev: true
/sass/1.38.0:
resolution: {integrity: sha512-WBccZeMigAGKoI+NgD7Adh0ab1HUq+6BmyBUEaGxtErbUtWUevEbdgo5EZiJQofLUGcKtlNaO2IdN73AHEua5g==}
engines: {node: '>=8.9.0'}
hasBin: true
dependencies:
chokidar: 3.5.2
dev: true
/source-map-js/0.6.2:
resolution: {integrity: sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==}
engines: {node: '>=0.10.0'}
dev: true
/tippy.js/6.3.1:
resolution: {integrity: sha512-JnFncCq+rF1dTURupoJ4yPie5Cof978inW6/4S6kmWV7LL9YOSEVMifED3KdrVPEG+Z/TFH2CDNJcQEfaeuQww==}
dependencies:
'@popperjs/core': 2.9.2
dev: false
/to-regex-range/5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
dependencies:
is-number: 7.0.0
dev: true
/vite/2.5.0:
resolution: {integrity: sha512-Dn4B+g54PJsMG5WCc4QeFy1ygMXRdTtFrUPegqfk4+vzVQcbF/DqqmI/1bxezArzbujBJg/67QeT5wz8edfJVQ==}
engines: {node: '>=12.2.0'}
hasBin: true
dependencies:
esbuild: 0.12.20
postcss: 8.3.6
resolve: 1.20.0
rollup: 2.56.2
optionalDependencies:
fsevents: 2.3.2
dev: true
/webcola/3.4.0:
resolution: {integrity: sha512-4BiLXjXw3SJHo3Xd+rF+7fyClT6n7I+AR6TkBqyQ4kTsePSAMDLRCXY1f3B/kXJeP9tYn4G1TblxTO+jAt0gaw==}
dependencies:
d3-dispatch: 1.0.6
d3-drag: 1.2.5
d3-shape: 1.3.7
d3-timer: 1.0.10
dev: false
-66
View File
@@ -1,66 +0,0 @@
// 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.
export class GraphHighlighter {
constructor(cy, graphTextSearch) {
this.cy = cy
this.graphTextSearch = graphTextSearch
let timeout = null
cy.on("mouseover", "node", e => {
const target = e.target
timeout = setTimeout(() => {
timeout = null
this.selectNode(target)
}, 100)
})
cy.on("mouseout", "node", e => {
if (timeout === null) {
this.deselectNode(e.target)
}
else {
clearTimeout(timeout)
timeout = null
}
})
}
selectNode(selection) {
const cy = this.cy
if (!this.graphTextSearch.totalUnion.empty()) {
cy.elements().difference(this.graphTextSearch.totalUnion).removeClass("semiTransparent")
}
const toHighlight = GraphHighlighter.computeToHighlight(selection)
cy.elements().difference(toHighlight).difference(this.graphTextSearch.totalUnion).addClass("semiTransparent")
toHighlight.difference(this.graphTextSearch.totalUnion).addClass("highlight")
}
static computeToHighlight(selection) {
let result = null
if (selection.isParent()) {
for (const child of selection.children()) {
const partialResult = child.outgoers().union(child.incomers())
result = result === null ? partialResult : result.union(partialResult)
}
}
else {
result = selection.outgoers().union(selection.incomers())
const parent = selection.parent()
if (parent != null) {
result = result.union(parent)
}
}
return result.union(selection)
}
deselectNode(selection) {
const cy = this.cy
cy.elements().removeClass("semiTransparent")
if (!this.graphTextSearch.totalUnion.empty()) {
cy.elements().difference(this.graphTextSearch.totalUnion).addClass("semiTransparent")
}
GraphHighlighter.computeToHighlight(selection).difference(this.graphTextSearch.totalUnion).removeClass("highlight")
}
}
-78
View File
@@ -1,78 +0,0 @@
// 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.
import {GraphHighlighter} from "./GraphHighlighter"
import {wrap} from "comlink"
// https://bugs.webkit.org/show_bug.cgi?id=164860 - inline worker as workaround for Safari (module web worker is not supported)
// noinspection ES6CheckImport
import SearchWorker from "./SearchWorker?worker&inline"
export class GraphTextSearch {
constructor(graph, cy) {
this.cy = cy
this.selectedNodes = new Set()
this.totalUnion = cy.collection()
this.index = wrap(new SearchWorker())
this.index.add(graph
.filter(it => it.group === "nodes" && "type" in it.data /* not a compound node */)
.map(it => it.data))
}
async searchNodes(text) {
const {selectedNodes, cy, index} = this
const newNodes = []
if (text.length !== 0) {
const originalText = text
const extraPrefix = "com.intellij."
// if (text.startsWith(extraPrefix) && text.length !== extraPrefix.length) {
// // remove useless prefix to avoid a lot of results
// text = text.substring(extraPrefix.length)
// }
const result = await index.search(text)
console.log(`Search result for "${text}`, result)
for (const id of result) {
const node = cy.getElementById(id)
if (node == null) {
console.error(`Cannot find node by id ${id}`)
}
selectedNodes.delete(node)
newNodes.push(node)
}
}
cy.elements().removeClass("semiTransparent")
for (const prevNode of selectedNodes) {
prevNode.removeClass(["highlight", "found"])
prevNode.outgoers().union(prevNode.incomers()).removeClass("highlight")
}
selectedNodes.clear()
if (newNodes.length === 0) {
this.totalUnion = cy.collection()
return
}
let totalUnion = null
for (const newNode of newNodes) {
selectedNodes.add(newNode)
const union = GraphHighlighter.computeToHighlight(newNode)
totalUnion = totalUnion == null ? union : totalUnion.union(union)
newNode.addClass("found")
}
cy.elements().difference(totalUnion).addClass("semiTransparent")
totalUnion.addClass("highlight")
this.totalUnion = totalUnion
cy.animate({
// pan: totalUnion.boundingBox(),
// center: {eles: totalUnion},
fit: {eles: totalUnion},
})
}
}
@@ -1,119 +0,0 @@
// 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.
import Tippy from "tippy.js"
import "tippy.js/animations/scale.css"
import cytoscape from "cytoscape"
import popper from "cytoscape-popper"
export class GraphTooltipManager {
constructor(cy) {
cytoscape.use(popper)
this.tippy = null
this.lastNode = null
cy.on("tap", "node", function (event) {
const node = event.target
if (this.lastNode === node) {
this.lastNode = null
if (this.tippy != null) {
this.tippy.hide()
}
return
}
let data = node.data()
if (node.isParent()) {
data = node.children("[pluginId]").first().data()
}
this.lastNode = node
const ref = node.popperRef()
if (this.tippy == null) {
const host = document.getElementById("tooltip")
this.tippy = new Tippy(host, {
getReferenceClientRect: ref.getBoundingClientRect,
trigger: "manual",
appendTo: host,
animation: "scale",
interactive: true,
allowHTML: true,
content: buildTooltipContent(data),
onHidden: instance => {
if (instance === this.tippy) {
this.lastNode = null
}
},
})
}
else {
this.tippy.hide()
this.tippy.setProps({
getReferenceClientRect: ref.getBoundingClientRect,
content: buildTooltipContent(data),
})
}
this.tippy.show()
})
}
}
function buildTooltipContent(item) {
const isPackageSet = item.package != null && item.package.length !== 0
// for us is very important to understand dependencies between source modules, that's why on grap source module name is used
// for plugins as node name
const lines = [
{name: item.name, value: null, main: true},
{name: "package", value: isPackageSet ? item.package : "not set", extraStyle: isPackageSet ? null : "color: orange"},
]
if (item.pluginId !== undefined) {
lines.push({name: "pluginId", value: item.pluginId})
}
lines.push(
{name: "sourceModule", value: item.sourceModule},
{name: "descriptor", value: shortenPath(item.descriptor), hint: item.descriptor},
)
return buildTooltip(lines)
}
function buildTooltip(lines) {
let result = ""
for (const line of lines) {
if (line.main) {
result += `<span class="tooltipMainName">${line.name}</span>`
}
else {
result += `<br/><span style="user-select: none">${line.name}</span>`
}
const valueStyleClass = "tooltipValue"
if (line.value != null) {
result += `<span class="${valueStyleClass}"`
if (line.extraStyle != null && line.extraStyle.length > 0) {
result += ` style="${line.extraStyle}"`
}
if (line.hint != null && line.hint.length !== 0) {
result += ` title="${line.hint}"`
}
result += `>${line.value}</span>`
}
}
return result
}
function shortenPath(p) {
const prefix = "plugins/"
if (p.startsWith(prefix)) {
p = p.substring(prefix.length)
}
return p
.replace("/resources/META-INF/", " ")
.replace("/src/main/resources/", " ")
.replace("/META-INF/", " ")
.replace("/resources/", " ")
.replace("/src/main/java", " ")
.replace("/src/main/", " ")
.replace("/src/", " ")
}
-31
View File
@@ -1,31 +0,0 @@
// 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.
import {expose} from "comlink"
import Document from "flexsearch/src/document"
import {is_string} from "flexsearch/src/common"
// flexsearch is the only lib that able to handle search queries like ruby (prefix search)
// or com.intellij.microservices.config (a lot of not related results due to common prefix com.intellij or common word config)
const index = new Document({
document: {
id: "id",
index: ["name", "pluginId", "sourceModule", "package"],
},
})
expose({
add(data) {
for (const document of data) {
index.add(document.id, document)
}
},
search(query) {
const result = index.search(query)
const ids = new Set()
for (const resultPerField of result) {
for (const id of resultPerField.result) {
ids.add(id)
}
}
return ids
}
})
-17
View File
@@ -1,17 +0,0 @@
// 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.
import pDebounce from "p-debounce"
import { GraphTextSearch} from "./GraphTextSearch"
import { GraphTooltipManager} from "./GraphTooltipManager"
import { GraphHighlighter} from "./GraphHighlighter"
export function init(graph, cy) {
const search = new GraphTextSearch(graph, cy)
// noinspection JSCheckFunctionSignatures
document.getElementById("searchField").addEventListener("input", pDebounce(function (event) {
return search.searchNodes(event.target.value.trim())
}, 300))
new GraphHighlighter(cy, search)
new GraphTooltipManager(cy)
}
-184
View File
@@ -1,184 +0,0 @@
// 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.
import "@fontsource/jetbrains-mono/400.css"
import "@fontsource/jetbrains-mono/600.css"
import "../style.css"
import graphData from "../plugin-graph.json"
import cytoscape from "cytoscape"
import cola from "cytoscape-cola"
cytoscape.use(cola)
let cy = null
async function init() {
await Promise.all([
document.fonts.load("11px 'JetBrains Mono'"),
document.fonts.load("13px 'JetBrains Mono'"),
])
const fileInput = document.getElementById("fileInput")
fileInput.addEventListener("change", event => {
handleFile(event.target.files[0])
})
// https://stackoverflow.com/a/31205873
document.fonts.load("bold 13px 'JetBrains Mono'")
const dropbox = document.body
dropbox.addEventListener("dragenter", preventDefault)
dropbox.addEventListener("dragover", preventDefault)
dropbox.addEventListener("drop", event => {
event.stopPropagation()
event.preventDefault()
const file = event.dataTransfer.files[0]
// noinspection JSCheckFunctionSignatures
const timeFormat = new Intl.DateTimeFormat("default", {
timeStyle: "medium",
})
document.title = `${file.name} (${timeFormat.format(new Date())})`
handleFile(file)
})
initGraph(graphData)
// dynamic import - load after graph showing
const interactionModule = await import("./interaction")
interactionModule.init(graphData, cy)
}
function preventDefault(e) {
e.stopPropagation();
e.preventDefault();
}
function handleFile(selectedFile) {
selectedFile.text().then(it => {
if (cy != null) {
// noinspection JSCheckFunctionSignatures
cy.json(JSON.parse(it))
}
})
}
function getItemSizeStyle(factor) {
const baseNodeDiameter = 10
const size = `${Math.ceil(baseNodeDiameter * factor)}px`
return {
"width": size,
"height": size,
}
}
function initGraph(graph) {
const layoutOptions = {
name: "cola",
fit: true,
nodeDimensionsIncludeLabels: true,
flow: {axis: "y"},
}
// noinspection SpellCheckingInspection
cy = cytoscape({
container: document.getElementById("cy"),
elements: graph,
layout: layoutOptions,
minZoom: 0.2,
maxZoom: 3,
autoungrabify: true,
style: [
{
selector: "node",
style: {
"label": "data(n)",
"font-family": "JetBrains Mono",
"font-size": 13,
"color": "#515151",
},
},
// compound node - smaller label font size
{
selector: "node[^sourceModule]",
style: {
"font-size": 11,
"color": "#515151",
},
},
{
selector: ":parent",
style: {
"shape" : "roundrectangle",
}
},
{
selector: "node[type=0]",
style: getItemSizeStyle(1),
},
{
selector: "node[type=1]",
style: getItemSizeStyle(1.2),
},
{
selector: "node[type=2]",
style: getItemSizeStyle(1.4),
},
{
selector: "edge",
style: {
"curve-style": "straight",
"width": 1,
}
},
{
selector: "edge[type=0]",
style: {
"target-arrow-shape": "triangle-backcurve",
},
},
{
selector: "edge[type=1]",
style: {
"target-arrow-shape": "square",
// square is too big
"arrow-scale": 0.7,
},
},
// highlighting (https://stackoverflow.com/a/38468892)
{
selector: "node.semiTransparent",
style: {"opacity": "0.5"}
},
{
selector: "edge.highlight",
style: {"mid-target-arrow-color": "#FFF"}
},
{
selector: "edge.semiTransparent",
style: {"opacity": "0.2"}
},
{
selector: "node.found",
style: {
"font-weight": "600",
"background-color": "#FFFF00",
"text-background-color": "#FFFF00",
"text-background-opacity": 1,
"text-background-shape": "round-rectangle",
},
},
]
})
// ensure that dragging of element causes panning and not selecting
// https://github.com/cytoscape/cytoscape.js/issues/1905
cy.elements().panify()
}
init().catch(e => {
console.error(e)
})
-32
View File
@@ -1,32 +0,0 @@
/* 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. */
html, body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #515151;
}
.tooltipMainName {
font-family: 'JetBrains Mono', monospace;
font-size: 13px;
user-select: text;
}
.tooltipValue {
float: right;
margin-left: 10px;
user-select: text;
font-family: 'JetBrains Mono', monospace;
font-size: 13px;
}
.tippy-box {
line-height: 1.2;
background: rgba(255, 255, 255, 0.9);
font-size: 14px;
padding: 10px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
text-align: justify;
border: 1px solid #ebeef5;
width: fit-content;
max-width: 1000px !important;
}
-39
View File
@@ -1,39 +0,0 @@
// 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.
export default {
plugins: [
{
name: "vite-plugin-fontsource",
apply: "build",
transformIndexHtml(html, context) {
const tags = []
for (const item of Object.values(context.bundle)) {
if (item.type !== "asset" || !item.fileName.endsWith(".woff2")) {
continue
}
tags.push({
tag: "link",
attrs: {
rel: "preload",
href: `/${item.fileName}`,
as: "font",
type: "font/woff2",
crossorigin: true,
},
injectTo: "head",
})
}
return tags
},
}
],
build: {
rollupOptions: {
output: {
manualChunks: {
cytoscape: ["cytoscape", "cytoscape-cola"],
},
},
}
}
}