| author | |
| committer | |
| log | 166bce0389e2068ae48c5936692eb315b17a269d |
| tree | 70820d04717b06816403e37a0b7a159118f379df |
| parent | 1498335e398f2cd23b8fd1133ca3ba020d9b8905 |
| signature | Signed by PGP key B5690EEEBB952194 |
9 files changed, 977 insertions(+), 113 deletions(-)
apps/server/src/open.test.ts+227-1| ... | @@ -98,6 +98,105 @@ it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { | ... | @@ -98,6 +98,105 @@ it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { |
| 98 | command: "idea", | 98 | command: "idea", |
| 99 | args: ["/tmp/workspace"], | 99 | args: ["/tmp/workspace"], |
| 100 | }); | 100 | }); |
| 101 | |||
| 102 | const aquaLaunch = yield* resolveEditorLaunch( | ||
| 103 | { cwd: "/tmp/workspace", editor: "aqua" }, | ||
| 104 | "darwin", | ||
| 105 | ); | ||
| 106 | assert.deepEqual(aquaLaunch, { | ||
| 107 | command: "aqua", | ||
| 108 | args: ["/tmp/workspace"], | ||
| 109 | }); | ||
| 110 | |||
| 111 | const clionLaunch = yield* resolveEditorLaunch( | ||
| 112 | { cwd: "/tmp/workspace", editor: "clion" }, | ||
| 113 | "darwin", | ||
| 114 | ); | ||
| 115 | assert.deepEqual(clionLaunch, { | ||
| 116 | command: "clion", | ||
| 117 | args: ["/tmp/workspace"], | ||
| 118 | }); | ||
| 119 | |||
| 120 | const datagripLaunch = yield* resolveEditorLaunch( | ||
| 121 | { cwd: "/tmp/workspace", editor: "datagrip" }, | ||
| 122 | "darwin", | ||
| 123 | ); | ||
| 124 | assert.deepEqual(datagripLaunch, { | ||
| 125 | command: "datagrip", | ||
| 126 | args: ["/tmp/workspace"], | ||
| 127 | }); | ||
| 128 | |||
| 129 | const dataspellLaunch = yield* resolveEditorLaunch( | ||
| 130 | { cwd: "/tmp/workspace", editor: "dataspell" }, | ||
| 131 | "darwin", | ||
| 132 | ); | ||
| 133 | assert.deepEqual(dataspellLaunch, { | ||
| 134 | command: "dataspell", | ||
| 135 | args: ["/tmp/workspace"], | ||
| 136 | }); | ||
| 137 | |||
| 138 | const golandLaunch = yield* resolveEditorLaunch( | ||
| 139 | { cwd: "/tmp/workspace", editor: "goland" }, | ||
| 140 | "darwin", | ||
| 141 | ); | ||
| 142 | assert.deepEqual(golandLaunch, { | ||
| 143 | command: "goland", | ||
| 144 | args: ["/tmp/workspace"], | ||
| 145 | }); | ||
| 146 | |||
| 147 | const phpstormLaunch = yield* resolveEditorLaunch( | ||
| 148 | { cwd: "/tmp/workspace", editor: "phpstorm" }, | ||
| 149 | "darwin", | ||
| 150 | ); | ||
| 151 | assert.deepEqual(phpstormLaunch, { | ||
| 152 | command: "phpstorm", | ||
| 153 | args: ["/tmp/workspace"], | ||
| 154 | }); | ||
| 155 | |||
| 156 | const pycharmLaunch = yield* resolveEditorLaunch( | ||
| 157 | { cwd: "/tmp/workspace", editor: "pycharm" }, | ||
| 158 | "darwin", | ||
| 159 | ); | ||
| 160 | assert.deepEqual(pycharmLaunch, { | ||
| 161 | command: "pycharm", | ||
| 162 | args: ["/tmp/workspace"], | ||
| 163 | }); | ||
| 164 | |||
| 165 | const riderLaunch = yield* resolveEditorLaunch( | ||
| 166 | { cwd: "/tmp/workspace", editor: "rider" }, | ||
| 167 | "darwin", | ||
| 168 | ); | ||
| 169 | assert.deepEqual(riderLaunch, { | ||
| 170 | command: "rider", | ||
| 171 | args: ["/tmp/workspace"], | ||
| 172 | }); | ||
| 173 | |||
| 174 | const rubymineLaunch = yield* resolveEditorLaunch( | ||
| 175 | { cwd: "/tmp/workspace", editor: "rubymine" }, | ||
| 176 | "darwin", | ||
| 177 | ); | ||
| 178 | assert.deepEqual(rubymineLaunch, { | ||
| 179 | command: "rubymine", | ||
| 180 | args: ["/tmp/workspace"], | ||
| 181 | }); | ||
| 182 | |||
| 183 | const rustroverLaunch = yield* resolveEditorLaunch( | ||
| 184 | { cwd: "/tmp/workspace", editor: "rustrover" }, | ||
| 185 | "darwin", | ||
| 186 | ); | ||
| 187 | assert.deepEqual(rustroverLaunch, { | ||
| 188 | command: "rustrover", | ||
| 189 | args: ["/tmp/workspace"], | ||
| 190 | }); | ||
| 191 | |||
| 192 | const webstormLaunch = yield* resolveEditorLaunch( | ||
| 193 | { cwd: "/tmp/workspace", editor: "webstorm" }, | ||
| 194 | "darwin", | ||
| 195 | ); | ||
| 196 | assert.deepEqual(webstormLaunch, { | ||
| 197 | command: "webstorm", | ||
| 198 | args: ["/tmp/workspace"], | ||
| 199 | }); | ||
| 101 | }), | 200 | }), |
| 102 | ); | 201 | ); |
| 103 | 202 | ||
| ... | @@ -207,6 +306,105 @@ it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { | ... | @@ -207,6 +306,105 @@ it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { |
| 207 | command: "idea", | 306 | command: "idea", |
| 208 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | 307 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], |
| 209 | }); | 308 | }); |
| 309 | |||
| 310 | const aquaLineAndColumn = yield* resolveEditorLaunch( | ||
| 311 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "aqua" }, | ||
| 312 | "darwin", | ||
| 313 | ); | ||
| 314 | assert.deepEqual(aquaLineAndColumn, { | ||
| 315 | command: "aqua", | ||
| 316 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 317 | }); | ||
| 318 | |||
| 319 | const clionLineAndColumn = yield* resolveEditorLaunch( | ||
| 320 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "clion" }, | ||
| 321 | "darwin", | ||
| 322 | ); | ||
| 323 | assert.deepEqual(clionLineAndColumn, { | ||
| 324 | command: "clion", | ||
| 325 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 326 | }); | ||
| 327 | |||
| 328 | const datagripLineAndColumn = yield* resolveEditorLaunch( | ||
| 329 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "datagrip" }, | ||
| 330 | "darwin", | ||
| 331 | ); | ||
| 332 | assert.deepEqual(datagripLineAndColumn, { | ||
| 333 | command: "datagrip", | ||
| 334 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 335 | }); | ||
| 336 | |||
| 337 | const dataspellLineAndColumn = yield* resolveEditorLaunch( | ||
| 338 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "dataspell" }, | ||
| 339 | "darwin", | ||
| 340 | ); | ||
| 341 | assert.deepEqual(dataspellLineAndColumn, { | ||
| 342 | command: "dataspell", | ||
| 343 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 344 | }); | ||
| 345 | |||
| 346 | const golandLineAndColumn = yield* resolveEditorLaunch( | ||
| 347 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "goland" }, | ||
| 348 | "darwin", | ||
| 349 | ); | ||
| 350 | assert.deepEqual(golandLineAndColumn, { | ||
| 351 | command: "goland", | ||
| 352 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 353 | }); | ||
| 354 | |||
| 355 | const phpstormLineAndColumn = yield* resolveEditorLaunch( | ||
| 356 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "phpstorm" }, | ||
| 357 | "darwin", | ||
| 358 | ); | ||
| 359 | assert.deepEqual(phpstormLineAndColumn, { | ||
| 360 | command: "phpstorm", | ||
| 361 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 362 | }); | ||
| 363 | |||
| 364 | const pycharmLineAndColumn = yield* resolveEditorLaunch( | ||
| 365 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "pycharm" }, | ||
| 366 | "darwin", | ||
| 367 | ); | ||
| 368 | assert.deepEqual(pycharmLineAndColumn, { | ||
| 369 | command: "pycharm", | ||
| 370 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 371 | }); | ||
| 372 | |||
| 373 | const riderLineAndColumn = yield* resolveEditorLaunch( | ||
| 374 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rider" }, | ||
| 375 | "darwin", | ||
| 376 | ); | ||
| 377 | assert.deepEqual(riderLineAndColumn, { | ||
| 378 | command: "rider", | ||
| 379 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 380 | }); | ||
| 381 | |||
| 382 | const rubymineLineAndColumn = yield* resolveEditorLaunch( | ||
| 383 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rubymine" }, | ||
| 384 | "darwin", | ||
| 385 | ); | ||
| 386 | assert.deepEqual(rubymineLineAndColumn, { | ||
| 387 | command: "rubymine", | ||
| 388 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 389 | }); | ||
| 390 | |||
| 391 | const rustroverLineAndColumn = yield* resolveEditorLaunch( | ||
| 392 | { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rustrover" }, | ||
| 393 | "darwin", | ||
| 394 | ); | ||
| 395 | assert.deepEqual(rustroverLineAndColumn, { | ||
| 396 | command: "rustrover", | ||
| 397 | args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], | ||
| 398 | }); | ||
| 399 | |||
| 400 | const webstormLineOnly = yield* resolveEditorLaunch( | ||
| 401 | { cwd: "/tmp/workspace/AGENTS.md:48", editor: "webstorm" }, | ||
| 402 | "darwin", | ||
| 403 | ); | ||
| 404 | assert.deepEqual(webstormLineOnly, { | ||
| 405 | command: "webstorm", | ||
| 406 | args: ["--line", "48", "/tmp/workspace/AGENTS.md"], | ||
| 407 | }); | ||
| 210 | }), | 408 | }), |
| 211 | ); | 409 | ); |
| 212 | 410 | ||
| ... | @@ -377,12 +575,40 @@ it.layer(NodeServices.layer)("resolveAvailableEditors", (it) => { | ... | @@ -377,12 +575,40 @@ it.layer(NodeServices.layer)("resolveAvailableEditors", (it) => { |
| 377 | yield* fs.writeFileString(path.join(dir, "kiro.CMD"), "@echo off\r\n"); | 575 | yield* fs.writeFileString(path.join(dir, "kiro.CMD"), "@echo off\r\n"); |
| 378 | yield* fs.writeFileString(path.join(dir, "code-insiders.CMD"), "@echo off\r\n"); | 576 | yield* fs.writeFileString(path.join(dir, "code-insiders.CMD"), "@echo off\r\n"); |
| 379 | yield* fs.writeFileString(path.join(dir, "codium.CMD"), "@echo off\r\n"); | 577 | yield* fs.writeFileString(path.join(dir, "codium.CMD"), "@echo off\r\n"); |
| 578 | yield* fs.writeFileString(path.join(dir, "aqua.CMD"), "@echo off\r\n"); | ||
| 579 | yield* fs.writeFileString(path.join(dir, "clion.CMD"), "@echo off\r\n"); | ||
| 580 | yield* fs.writeFileString(path.join(dir, "datagrip.CMD"), "@echo off\r\n"); | ||
| 581 | yield* fs.writeFileString(path.join(dir, "dataspell.CMD"), "@echo off\r\n"); | ||
| 582 | yield* fs.writeFileString(path.join(dir, "goland.CMD"), "@echo off\r\n"); | ||
| 583 | yield* fs.writeFileString(path.join(dir, "phpstorm.CMD"), "@echo off\r\n"); | ||
| 584 | yield* fs.writeFileString(path.join(dir, "pycharm.CMD"), "@echo off\r\n"); | ||
| 585 | yield* fs.writeFileString(path.join(dir, "rider.CMD"), "@echo off\r\n"); | ||
| 586 | yield* fs.writeFileString(path.join(dir, "rubymine.CMD"), "@echo off\r\n"); | ||
| 587 | yield* fs.writeFileString(path.join(dir, "rustrover.CMD"), "@echo off\r\n"); | ||
| 588 | yield* fs.writeFileString(path.join(dir, "webstorm.CMD"), "@echo off\r\n"); | ||
| 380 | yield* fs.writeFileString(path.join(dir, "explorer.CMD"), "MZ"); | 589 | yield* fs.writeFileString(path.join(dir, "explorer.CMD"), "MZ"); |
| 381 | const editors = resolveAvailableEditors("win32", { | 590 | const editors = resolveAvailableEditors("win32", { |
| 382 | PATH: dir, | 591 | PATH: dir, |
| 383 | PATHEXT: ".COM;.EXE;.BAT;.CMD", | 592 | PATHEXT: ".COM;.EXE;.BAT;.CMD", |
| 384 | }); | 593 | }); |
| 385 | assert.deepEqual(editors, ["trae", "kiro", "vscode-insiders", "vscodium", "file-manager"]); | 594 | assert.deepEqual(editors, [ |
| 595 | "trae", | ||
| 596 | "kiro", | ||
| 597 | "vscode-insiders", | ||
| 598 | "vscodium", | ||
| 599 | "aqua", | ||
| 600 | "clion", | ||
| 601 | "datagrip", | ||
| 602 | "dataspell", | ||
| 603 | "goland", | ||
| 604 | "phpstorm", | ||
| 605 | "pycharm", | ||
| 606 | "rider", | ||
| 607 | "rubymine", | ||
| 608 | "rustrover", | ||
| 609 | "webstorm", | ||
| 610 | "file-manager", | ||
| 611 | ]); | ||
| 386 | }), | 612 | }), |
| 387 | ); | 613 | ); |
| 388 | 614 |
apps/web/src/components/ChatMarkdown.browser.tsx+2-2| ... | @@ -65,7 +65,7 @@ describe("ChatMarkdown", () => { | ... | @@ -65,7 +65,7 @@ describe("ChatMarkdown", () => { |
| 65 | try { | 65 | try { |
| 66 | const link = page.getByRole("link", { name: "PermissionRule.ts · L1" }); | 66 | const link = page.getByRole("link", { name: "PermissionRule.ts · L1" }); |
| 67 | await expect.element(link).toBeInTheDocument(); | 67 | await expect.element(link).toBeInTheDocument(); |
| 68 | await expect.element(link).toHaveAttribute("href", `${filePath}#L1`); | 68 | await expect.element(link).toHaveAttribute("href", `${filePath}:1`); |
| 69 | 69 | ||
| 70 | await link.click(); | 70 | await link.click(); |
| 71 | 71 | ||
| ... | @@ -87,7 +87,7 @@ describe("ChatMarkdown", () => { | ... | @@ -87,7 +87,7 @@ describe("ChatMarkdown", () => { |
| 87 | try { | 87 | try { |
| 88 | const link = page.getByRole("link", { name: "PermissionRule.ts · L1:C7" }); | 88 | const link = page.getByRole("link", { name: "PermissionRule.ts · L1:C7" }); |
| 89 | await expect.element(link).toBeInTheDocument(); | 89 | await expect.element(link).toBeInTheDocument(); |
| 90 | await expect.element(link).toHaveAttribute("href", `${filePath}#L1C7`); | 90 | await expect.element(link).toHaveAttribute("href", `${filePath}:1:7`); |
| 91 | 91 | ||
| 92 | await link.click(); | 92 | await link.click(); |
| 93 | 93 |
apps/web/src/components/ChatMarkdown.tsx+8-3| ... | @@ -26,7 +26,11 @@ import { resolveDiffThemeName, type DiffThemeName } from "../lib/diffRendering"; | ... | @@ -26,7 +26,11 @@ import { resolveDiffThemeName, type DiffThemeName } from "../lib/diffRendering"; |
| 26 | import { fnv1a32 } from "../lib/diffRendering"; | 26 | import { fnv1a32 } from "../lib/diffRendering"; |
| 27 | import { LRUCache } from "../lib/lruCache"; | 27 | import { LRUCache } from "../lib/lruCache"; |
| 28 | import { useTheme } from "../hooks/useTheme"; | 28 | import { useTheme } from "../hooks/useTheme"; |
| 29 | import { resolveMarkdownFileLinkMeta, rewriteMarkdownFileUriHref } from "../markdown-links"; | 29 | import { |
| 30 | normalizeMarkdownLinkDestination, | ||
| 31 | resolveMarkdownFileLinkMeta, | ||
| 32 | rewriteMarkdownFileUriHref, | ||
| 33 | } from "../markdown-links"; | ||
| 30 | import { readLocalApi } from "../localApi"; | 34 | import { readLocalApi } from "../localApi"; |
| 31 | import { cn } from "../lib/utils"; | 35 | import { cn } from "../lib/utils"; |
| 32 | 36 | ||
| ... | @@ -354,7 +358,8 @@ function extractMarkdownLinkHrefs(text: string): string[] { | ... | @@ -354,7 +358,8 @@ function extractMarkdownLinkHrefs(text: string): string[] { |
| 354 | } | 358 | } |
| 355 | 359 | ||
| 356 | function normalizeMarkdownLinkHrefKey(href: string): string { | 360 | function normalizeMarkdownLinkHrefKey(href: string): string { |
| 357 | return rewriteMarkdownFileUriHref(href.trim()) ?? href.trim(); | 361 | const normalizedHref = normalizeMarkdownLinkDestination(href); |
| 362 | return rewriteMarkdownFileUriHref(normalizedHref) ?? normalizedHref; | ||
| 358 | } | 363 | } |
| 359 | 364 | ||
| 360 | const MarkdownFileLink = memo(function MarkdownFileLink({ | 365 | const MarkdownFileLink = memo(function MarkdownFileLink({ |
| ... | @@ -549,7 +554,7 @@ function ChatMarkdown({ text, cwd, isStreaming = false }: ChatMarkdownProps) { | ... | @@ -549,7 +554,7 @@ function ChatMarkdown({ text, cwd, isStreaming = false }: ChatMarkdownProps) { |
| 549 | 554 | ||
| 550 | return ( | 555 | return ( |
| 551 | <MarkdownFileLink | 556 | <MarkdownFileLink |
| 552 | href={href ?? fileLinkMeta.targetPath} | 557 | href={fileLinkMeta.targetPath} |
| 553 | targetPath={fileLinkMeta.targetPath} | 558 | targetPath={fileLinkMeta.targetPath} |
| 554 | displayPath={fileLinkMeta.displayPath} | 559 | displayPath={fileLinkMeta.displayPath} |
| 555 | filePath={fileLinkMeta.filePath} | 560 | filePath={fileLinkMeta.filePath} |
apps/web/src/components/Icons.tsx+1-102| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { type SVGProps, useId } from "react"; | 1 | import React, { type SVGProps, useId } from "react"; |
| 2 | import { cn } from "~/lib/utils"; | 2 | import { cn } from "~/lib/utils"; |
| 3 | 3 | ||
| 4 | export type Icon = React.FC<SVGProps<SVGSVGElement>>; | 4 | export type Icon = React.FC<SVGProps<SVGSVGElement>>; |
| ... | @@ -635,107 +635,6 @@ export const AntigravityIcon: Icon = (props) => ( | ... | @@ -635,107 +635,6 @@ export const AntigravityIcon: Icon = (props) => ( |
| 635 | </svg> | 635 | </svg> |
| 636 | ); | 636 | ); |
| 637 | 637 | ||
| 638 | export const IntelliJIdeaIcon: Icon = (props) => { | ||
| 639 | const id = useId(); | ||
| 640 | const gradientAId = `${id}-idea-a`; | ||
| 641 | const gradientBId = `${id}-idea-b`; | ||
| 642 | const gradientCId = `${id}-idea-c`; | ||
| 643 | const gradientDId = `${id}-idea-d`; | ||
| 644 | |||
| 645 | return ( | ||
| 646 | <svg {...props} viewBox="0 0 70 70" fill="none"> | ||
| 647 | <defs> | ||
| 648 | <linearGradient | ||
| 649 | id={gradientAId} | ||
| 650 | x1="0.7898" | ||
| 651 | y1="40.0893" | ||
| 652 | x2="33.3172" | ||
| 653 | y2="40.0893" | ||
| 654 | gradientUnits="userSpaceOnUse" | ||
| 655 | > | ||
| 656 | <stop offset="0.2581" stopColor="#F97A12" /> | ||
| 657 | <stop offset="0.4591" stopColor="#B07B58" /> | ||
| 658 | <stop offset="0.7241" stopColor="#577BAE" /> | ||
| 659 | <stop offset="0.9105" stopColor="#1E7CE5" /> | ||
| 660 | <stop offset="1" stopColor="#087CFA" /> | ||
| 661 | </linearGradient> | ||
| 662 | <linearGradient | ||
| 663 | id={gradientBId} | ||
| 664 | x1="25.7674" | ||
| 665 | y1="24.88" | ||
| 666 | x2="79.424" | ||
| 667 | y2="54.57" | ||
| 668 | gradientUnits="userSpaceOnUse" | ||
| 669 | > | ||
| 670 | <stop stopColor="#F97A12" /> | ||
| 671 | <stop offset="0.07179946" stopColor="#CB7A3E" /> | ||
| 672 | <stop offset="0.1541" stopColor="#9E7B6A" /> | ||
| 673 | <stop offset="0.242" stopColor="#757B91" /> | ||
| 674 | <stop offset="0.3344" stopColor="#537BB1" /> | ||
| 675 | <stop offset="0.4324" stopColor="#387CCC" /> | ||
| 676 | <stop offset="0.5381" stopColor="#237CE0" /> | ||
| 677 | <stop offset="0.6552" stopColor="#147CEF" /> | ||
| 678 | <stop offset="0.7925" stopColor="#0B7CF7" /> | ||
| 679 | <stop offset="1" stopColor="#087CFA" /> | ||
| 680 | </linearGradient> | ||
| 681 | <linearGradient | ||
| 682 | id={gradientCId} | ||
| 683 | x1="63.2277" | ||
| 684 | y1="42.9153" | ||
| 685 | x2="48.2903" | ||
| 686 | y2="-1.7191" | ||
| 687 | gradientUnits="userSpaceOnUse" | ||
| 688 | > | ||
| 689 | <stop stopColor="#FE315D" /> | ||
| 690 | <stop offset="0.07840246" stopColor="#CB417E" /> | ||
| 691 | <stop offset="0.1601" stopColor="#9E4E9B" /> | ||
| 692 | <stop offset="0.2474" stopColor="#755BB4" /> | ||
| 693 | <stop offset="0.3392" stopColor="#5365CA" /> | ||
| 694 | <stop offset="0.4365" stopColor="#386DDB" /> | ||
| 695 | <stop offset="0.5414" stopColor="#2374E9" /> | ||
| 696 | <stop offset="0.6576" stopColor="#1478F3" /> | ||
| 697 | <stop offset="0.794" stopColor="#0B7BF8" /> | ||
| 698 | <stop offset="1" stopColor="#087CFA" /> | ||
| 699 | </linearGradient> | ||
| 700 | <linearGradient | ||
| 701 | id={gradientDId} | ||
| 702 | x1="10.7204" | ||
| 703 | y1="16.473" | ||
| 704 | x2="55.5237" | ||
| 705 | y2="90.58" | ||
| 706 | gradientUnits="userSpaceOnUse" | ||
| 707 | > | ||
| 708 | <stop stopColor="#FE315D" /> | ||
| 709 | <stop offset="0.04023279" stopColor="#F63462" /> | ||
| 710 | <stop offset="0.1037" stopColor="#DF3A71" /> | ||
| 711 | <stop offset="0.1667" stopColor="#C24383" /> | ||
| 712 | <stop offset="0.2912" stopColor="#AD4A91" /> | ||
| 713 | <stop offset="0.5498" stopColor="#755BB4" /> | ||
| 714 | <stop offset="0.9175" stopColor="#1D76ED" /> | ||
| 715 | <stop offset="1" stopColor="#087CFA" /> | ||
| 716 | </linearGradient> | ||
| 717 | </defs> | ||
| 718 | <polygon points="17.7,54.6 0.8,41.2 9.2,25.6 33.3,35" fill={`url(#${gradientAId})`} /> | ||
| 719 | <path | ||
| 720 | d="M70 18.7 68.7 59.2 41.8 70 25.6 59.6 49.3 35 38.9 12.3 48.2 1.1Z" | ||
| 721 | fill={`url(#${gradientBId})`} | ||
| 722 | /> | ||
| 723 | <polygon points="70,18.7 48.7,43.9 38.9,12.3 48.2,1.1" fill={`url(#${gradientCId})`} /> | ||
| 724 | <path | ||
| 725 | d="M33.7 58.1 5.6 68.3 10.1 52.5 16 33.1 0 27.7 10.1 0 32.1 2.7 53.7 27.4Z" | ||
| 726 | fill={`url(#${gradientDId})`} | ||
| 727 | /> | ||
| 728 | <rect x="13.7" y="13.5" width="43.2" height="43.2" fill="#000" /> | ||
| 729 | <rect x="17.7" y="48.6" width="16.2" height="2.7" fill="#fff" /> | ||
| 730 | <path d="M29.4 22.4v-3.3h-9v3.3h2.6v11.3h-2.6V37h9v-3.3h-2.5V22.4h2.5Z" fill="#fff" /> | ||
| 731 | <path | ||
| 732 | d="M38 37.3c-1.4 0-2.6-.3-3.5-.8-.9-.5-1.7-1.2-2.3-1.9l2.5-2.8c.5.6 1 1 1.5 1.3.5.3 1.1.5 1.7.5.7 0 1.3-.2 1.8-.7.4-.5.6-1.2.6-2.3V19.1h4v11.7c0 1.1-.1 2-.4 2.8-.3.8-.7 1.4-1.3 2-.5.5-1.2 1-2 1.2-.8.3-1.6.5-2.6.5Z" | ||
| 733 | fill="#fff" | ||
| 734 | /> | ||
| 735 | </svg> | ||
| 736 | ); | ||
| 737 | }; | ||
| 738 | |||
| 739 | export const OpenCodeIcon: Icon = (props) => ( | 638 | export const OpenCodeIcon: Icon = (props) => ( |
| 740 | <svg {...props} viewBox="0 0 32 40" fill="none" xmlns="http://www.w3.org/2000/svg"> | 639 | <svg {...props} viewBox="0 0 32 40" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| 741 | <g clipPath="url(#opencode__clip0_1311_94969)"> | 640 | <g clipPath="url(#opencode__clip0_1311_94969)"> |
apps/web/src/components/JetBrainsIcons.tsx created+610| ... | @@ -0,0 +1,610 @@ | ||
| 1 | import { useId } from "react"; | ||
| 2 | import type { Icon } from "./Icons"; | ||
| 3 | |||
| 4 | const useSvgGradientIds = (prefix: string, count: number) => { | ||
| 5 | const id = useId(); | ||
| 6 | return Array.from( | ||
| 7 | { length: count }, | ||
| 8 | (_, index) => `${id}-${prefix}-${String.fromCharCode(97 + index)}`, | ||
| 9 | ); | ||
| 10 | }; | ||
| 11 | |||
| 12 | export const AquaIcon: Icon = (props) => { | ||
| 13 | const [gradientAId, gradientBId] = useSvgGradientIds("aqua", 2); | ||
| 14 | |||
| 15 | return ( | ||
| 16 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 17 | <defs> | ||
| 18 | <linearGradient | ||
| 19 | id={gradientAId} | ||
| 20 | x1="59.932" | ||
| 21 | x2="1.336" | ||
| 22 | y1="59.676" | ||
| 23 | y2="1.079" | ||
| 24 | gradientUnits="userSpaceOnUse" | ||
| 25 | > | ||
| 26 | <stop offset=".25" stopColor="#7256FF" /> | ||
| 27 | <stop offset=".73" stopColor="#007DFE" /> | ||
| 28 | </linearGradient> | ||
| 29 | <linearGradient | ||
| 30 | id={gradientBId} | ||
| 31 | x1="7.671" | ||
| 32 | x2="61.125" | ||
| 33 | y1="64.392" | ||
| 34 | y2="39.609" | ||
| 35 | gradientUnits="userSpaceOnUse" | ||
| 36 | > | ||
| 37 | <stop offset=".3" stopColor="#00D886" /> | ||
| 38 | <stop offset=".54" stopColor="#7256FF" /> | ||
| 39 | </linearGradient> | ||
| 40 | </defs> | ||
| 41 | <path | ||
| 42 | fill={`url(#${gradientAId})`} | ||
| 43 | d="M0 4.125v34.128c0 1.658.993 3.154 2.52 3.8L39.943 57.85c.518.219 1.075.33 1.638.324l18.329-.15A4.125 4.125 0 0 0 64 53.9V36.234c0-.806-.236-1.593-.678-2.267L42.213 1.86A4.13 4.13 0 0 0 38.766 0H4.125A4.125 4.125 0 0 0 0 4.125" | ||
| 44 | /> | ||
| 45 | <path | ||
| 46 | fill={`url(#${gradientBId})`} | ||
| 47 | d="M6 49.015v10.862a4.125 4.125 0 0 0 4.125 4.125h12.566q.3 0 .598-.044l37.185-5.448A4.125 4.125 0 0 0 64 54.429V39.03a4.125 4.125 0 0 0-4.127-4.125l-18.504.005c-.426 0-.849.066-1.254.195L8.871 45.085A4.13 4.13 0 0 0 6 49.015z" | ||
| 48 | /> | ||
| 49 | <path | ||
| 50 | fill="#00D886" | ||
| 51 | d="M6 47.55v12.259a4.125 4.125 0 0 0 4.19 4.124L21 64c1.181-.019 2.531-.786 3.3-1.683l32.707-38.158c.64-.748.993-1.7.993-2.685V10.125A4.125 4.125 0 0 0 53.875 6H42.872c-1.19 0-2.321.514-3.105 1.409L7.021 44.834A4.12 4.12 0 0 0 6 47.55" | ||
| 52 | /> | ||
| 53 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 54 | <path | ||
| 55 | fill="#fff" | ||
| 56 | d="M33 44H17v3h16zM20.746 31.243a7.3 7.3 0 0 1-2.755-2.787q-1.002-1.774-1.003-3.961c0-2.187.334-2.778 1.003-3.96a7.3 7.3 0 0 1 2.755-2.787q1.752-1.013 3.917-1.014c1.443 0 2.739.338 3.907 1.013a7.3 7.3 0 0 1 2.75 2.787q.996 1.774.996 3.961c0 2.187-.332 2.778-.997 3.96a7.3 7.3 0 0 1-2.749 2.788q-1.752 1.013-3.907 1.013c-1.436 0-2.75-.338-3.917-1.013m6.308-2.23q1.06-.67 1.661-1.854.6-1.185.6-2.664t-.6-2.664a4.6 4.6 0 0 0-1.661-1.854q-1.061-.67-2.39-.67t-2.396.67a4.6 4.6 0 0 0-1.672 1.854q-.605 1.185-.605 2.664t.605 2.664 1.672 1.854q1.067.67 2.396.67 1.33 0 2.39-.67m-2.16 6.034a2.67 2.67 0 0 1-1.126-1.077q-.391-.696-.391-1.64l-.01-1.94h2.743v1.811q0 .332.129.573.128.242.37.365.24.123.574.123h1.833v2.165h-2.412q-.975 0-1.71-.38M38.233 16.992h3.173l5.563 15.006h-2.947l-1.212-3.483h-5.842l-1.136 3.483H32.82zm3.805 9.261-2.025-5.723-.225-.954-.215.954-1.908 5.723z" | ||
| 57 | /> | ||
| 58 | </svg> | ||
| 59 | ); | ||
| 60 | }; | ||
| 61 | |||
| 62 | export const CLionIcon: Icon = (props) => { | ||
| 63 | const [gradientAId, gradientBId] = useSvgGradientIds("clion", 2); | ||
| 64 | |||
| 65 | return ( | ||
| 66 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 67 | <defs> | ||
| 68 | <linearGradient | ||
| 69 | id={gradientAId} | ||
| 70 | x1="4.067" | ||
| 71 | x2="62.664" | ||
| 72 | y1="4.327" | ||
| 73 | y2="62.923" | ||
| 74 | gradientUnits="userSpaceOnUse" | ||
| 75 | > | ||
| 76 | <stop offset=".29" stopColor="#009AE5" /> | ||
| 77 | <stop offset=".7" stopColor="#00D980" /> | ||
| 78 | </linearGradient> | ||
| 79 | <linearGradient | ||
| 80 | id={gradientBId} | ||
| 81 | x1="56.329" | ||
| 82 | x2="2.874" | ||
| 83 | y1="-.391" | ||
| 84 | y2="24.393" | ||
| 85 | gradientUnits="userSpaceOnUse" | ||
| 86 | > | ||
| 87 | <stop offset=".3" stopColor="#FF2D90" /> | ||
| 88 | <stop offset=".54" stopColor="#009AE5" /> | ||
| 89 | </linearGradient> | ||
| 90 | </defs> | ||
| 91 | <path | ||
| 92 | fill={`url(#${gradientAId})`} | ||
| 93 | d="M64 59.878V25.75a4.13 4.13 0 0 0-2.52-3.8L24.057 6.153a4.1 4.1 0 0 0-1.638-.325l-18.329.15A4.124 4.124 0 0 0 0 10.103v17.665c0 .806.236 1.593.678 2.267l21.109 32.109a4.12 4.12 0 0 0 3.447 1.859h34.641A4.125 4.125 0 0 0 64 59.878" | ||
| 94 | /> | ||
| 95 | <path | ||
| 96 | fill={`url(#${gradientBId})`} | ||
| 97 | d="M58 14.988V4.125A4.125 4.125 0 0 0 53.875 0H41.309q-.3 0-.598.044L3.527 5.492A4.125 4.125 0 0 0 0 9.573v15.398a4.125 4.125 0 0 0 4.126 4.125l18.505-.005c.425 0 .848-.066 1.253-.195l31.246-9.98A4.13 4.13 0 0 0 58 14.988" | ||
| 98 | /> | ||
| 99 | <path | ||
| 100 | fill="#FF2D90" | ||
| 101 | d="M58 16.453V4.194A4.125 4.125 0 0 0 53.81.07L43.003.008c-1.18.019-2.535.781-3.304 1.678L6.993 39.844c-.64.748-.993 1.7-.993 2.684v11.35a4.125 4.125 0 0 0 4.125 4.125h11.003c1.19 0 2.321-.514 3.105-1.409L56.979 19.17A4.12 4.12 0 0 0 58 16.453" | ||
| 102 | /> | ||
| 103 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 104 | <path | ||
| 105 | fill="#fff" | ||
| 106 | d="M33 44H17v3h16zM20.747 31.243a7.3 7.3 0 0 1-2.744-2.787q-.997-1.774-.997-3.961c0-2.187.332-2.778.997-3.96a7.3 7.3 0 0 1 2.744-2.787q1.747-1.013 3.901-1.014 1.823 0 3.345.675a6.86 6.86 0 0 1 2.535 1.892 6.44 6.44 0 0 1 1.355 2.793h-3.065a4.05 4.05 0 0 0-.895-1.431 4 4 0 0 0-1.431-.95 4.9 4.9 0 0 0-1.822-.332q-1.33 0-2.402.665a4.6 4.6 0 0 0-1.677 1.827q-.606 1.164-.606 2.62 0 1.459.606 2.621a4.6 4.6 0 0 0 1.677 1.828q1.072.664 2.402.664a4.9 4.9 0 0 0 1.822-.332 4.02 4.02 0 0 0 2.326-2.38h3.065a6.44 6.44 0 0 1-1.355 2.792 6.86 6.86 0 0 1-2.535 1.892q-1.522.675-3.345.675-2.154 0-3.901-1.013zM37.33 16.992v12.37h7.117v2.636H34.414V16.992z" | ||
| 107 | /> | ||
| 108 | </svg> | ||
| 109 | ); | ||
| 110 | }; | ||
| 111 | |||
| 112 | export const DataGripIcon: Icon = (props) => { | ||
| 113 | const [gradientAId, gradientBId] = useSvgGradientIds("datagrip", 2); | ||
| 114 | |||
| 115 | return ( | ||
| 116 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 117 | <defs> | ||
| 118 | <linearGradient | ||
| 119 | id={gradientAId} | ||
| 120 | x1="59.676" | ||
| 121 | x2="1.08" | ||
| 122 | y1="4.067" | ||
| 123 | y2="62.663" | ||
| 124 | gradientUnits="userSpaceOnUse" | ||
| 125 | > | ||
| 126 | <stop offset=".28" stopColor="#7256FF" /> | ||
| 127 | <stop offset=".66" stopColor="#00D980" /> | ||
| 128 | </linearGradient> | ||
| 129 | <linearGradient | ||
| 130 | id={gradientBId} | ||
| 131 | x1="64.391" | ||
| 132 | x2="39.607" | ||
| 133 | y1="56.329" | ||
| 134 | y2="2.874" | ||
| 135 | gradientUnits="userSpaceOnUse" | ||
| 136 | > | ||
| 137 | <stop offset=".3" stopColor="#FF43F2" /> | ||
| 138 | <stop offset=".54" stopColor="#7256FF" /> | ||
| 139 | </linearGradient> | ||
| 140 | </defs> | ||
| 141 | <path | ||
| 142 | fill={`url(#${gradientAId})`} | ||
| 143 | d="M4.125 64h34.128a4.13 4.13 0 0 0 3.8-2.52L57.85 24.057c.219-.518.33-1.076.324-1.638l-.15-18.329A4.125 4.125 0 0 0 53.9 0H36.234c-.806 0-1.593.236-2.267.678L1.86 21.787A4.13 4.13 0 0 0 0 25.234v34.641A4.125 4.125 0 0 0 4.125 64" | ||
| 144 | /> | ||
| 145 | <path | ||
| 146 | fill={`url(#${gradientBId})`} | ||
| 147 | d="M49.013 58h10.862A4.125 4.125 0 0 0 64 53.875V41.309q0-.3-.044-.598L58.508 3.527A4.125 4.125 0 0 0 54.427 0H39.029a4.125 4.125 0 0 0-4.125 4.126l.005 18.505c0 .425.066.848.195 1.253l9.979 31.246a4.13 4.13 0 0 0 3.93 2.87" | ||
| 148 | /> | ||
| 149 | <path | ||
| 150 | fill="#FF43F2" | ||
| 151 | d="M47.55 58h12.259a4.125 4.125 0 0 0 4.124-4.19L64 43c-.018-1.181-.785-2.531-1.682-3.3L24.159 6.993A4.13 4.13 0 0 0 21.474 6H10.125A4.125 4.125 0 0 0 6 10.125v11.003c0 1.19.514 2.321 1.409 3.105l37.425 32.746A4.12 4.12 0 0 0 47.55 58" | ||
| 152 | /> | ||
| 153 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 154 | <path | ||
| 155 | fill="#fff" | ||
| 156 | d="M33 44H17v3h16zM17.012 16.992h5.713q2.133 0 3.821.965a6.9 6.9 0 0 1 2.642 2.674q.954 1.71.954 3.864t-.954 3.865a6.9 6.9 0 0 1-2.642 2.674q-1.688.964-3.821.964h-5.713zm8.028 11.876q1.008-.6 1.554-1.72.547-1.12.547-2.653 0-1.534-.547-2.653-.546-1.12-1.554-1.721-1.008-.6-2.348-.6h-2.755v9.947h2.755q1.34 0 2.348-.6M35.426 31.243a7.3 7.3 0 0 1-2.744-2.787q-.997-1.774-.997-3.961c0-2.187.333-2.778.997-3.96s1.58-2.112 2.744-2.787q1.747-1.013 3.902-1.014 1.746 0 3.221.622a6.9 6.9 0 0 1 2.487 1.747 6.36 6.36 0 0 1 1.42 2.594h-3.13a3.9 3.9 0 0 0-.927-1.228q-.585-.52-1.367-.803c-.782-.283-1.082-.284-1.683-.284q-1.329 0-2.401.664a4.6 4.6 0 0 0-1.678 1.828q-.605 1.163-.605 2.62c0 1.457.202 1.846.605 2.621a4.6 4.6 0 0 0 1.678 1.828q1.072.664 2.401.664 1.233 0 2.235-.461t1.592-1.276a3.3 3.3 0 0 0 .633-1.833l.01.31h-3.526v-2.304h6.356v1.18q0 1.982-.96 3.585a6.9 6.9 0 0 1-2.625 2.525q-1.668.921-3.736.921c-1.38 0-2.737-.337-3.902-1.013z" | ||
| 157 | /> | ||
| 158 | </svg> | ||
| 159 | ); | ||
| 160 | }; | ||
| 161 | |||
| 162 | export const DataSpellIcon: Icon = (props) => { | ||
| 163 | const [gradientAId, gradientBId] = useSvgGradientIds("dataspell", 2); | ||
| 164 | |||
| 165 | return ( | ||
| 166 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 167 | <defs> | ||
| 168 | <linearGradient | ||
| 169 | id={gradientAId} | ||
| 170 | x1="4.067" | ||
| 171 | x2="62.664" | ||
| 172 | y1="4.327" | ||
| 173 | y2="62.923" | ||
| 174 | gradientUnits="userSpaceOnUse" | ||
| 175 | > | ||
| 176 | <stop offset=".28" stopColor="#007DFE" /> | ||
| 177 | <stop offset=".73" stopColor="#00D980" /> | ||
| 178 | </linearGradient> | ||
| 179 | <linearGradient | ||
| 180 | id={gradientBId} | ||
| 181 | x1="56.329" | ||
| 182 | x2="2.875" | ||
| 183 | y1="-.391" | ||
| 184 | y2="24.392" | ||
| 185 | gradientUnits="userSpaceOnUse" | ||
| 186 | > | ||
| 187 | <stop offset=".32" stopColor="#F0EB18" /> | ||
| 188 | <stop offset=".55" stopColor="#007DFE" /> | ||
| 189 | </linearGradient> | ||
| 190 | </defs> | ||
| 191 | <path | ||
| 192 | fill={`url(#${gradientAId})`} | ||
| 193 | d="M64 59.878V25.75a4.13 4.13 0 0 0-2.52-3.8L24.057 6.153a4.1 4.1 0 0 0-1.638-.325l-18.329.15A4.124 4.124 0 0 0 0 10.103v17.665c0 .806.236 1.593.678 2.267l21.109 32.109a4.12 4.12 0 0 0 3.447 1.859h34.641A4.125 4.125 0 0 0 64 59.878" | ||
| 194 | /> | ||
| 195 | <path | ||
| 196 | fill={`url(#${gradientBId})`} | ||
| 197 | d="M58 14.988V4.125A4.125 4.125 0 0 0 53.875 0H41.309q-.3 0-.598.044L3.527 5.492A4.125 4.125 0 0 0 0 9.573v15.398a4.125 4.125 0 0 0 4.126 4.125l18.505-.005c.425 0 .848-.066 1.253-.195l31.246-9.98A4.13 4.13 0 0 0 58 14.988" | ||
| 198 | /> | ||
| 199 | <path | ||
| 200 | fill="#F0EB18" | ||
| 201 | d="M58 16.45V4.191A4.125 4.125 0 0 0 53.81.067L43 0c-1.181.019-2.531.786-3.3 1.683L6.993 39.84c-.64.748-.993 1.7-.993 2.685v11.349A4.125 4.125 0 0 0 10.125 58h11.003c1.19 0 2.321-.514 3.105-1.409l32.746-37.425A4.12 4.12 0 0 0 58 16.45" | ||
| 202 | /> | ||
| 203 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 204 | <path | ||
| 205 | fill="#fff" | ||
| 206 | d="M33 44H17v3h16zM17.012 16.992h5.713q2.133 0 3.821.965a6.9 6.9 0 0 1 2.642 2.674q.954 1.71.954 3.864t-.954 3.865a6.9 6.9 0 0 1-2.642 2.674q-1.688.964-3.821.964h-5.713zm8.028 11.876q1.008-.6 1.554-1.72.547-1.12.547-2.653 0-1.534-.547-2.653-.546-1.12-1.554-1.721-1.008-.6-2.348-.6h-2.755v9.947h2.755q1.34 0 2.348-.6M34.713 31.664q-1.26-.59-1.973-1.65t-.734-2.444h2.937q0 .654.343 1.147t.954.772q.61.278 1.404.278c.53 0 .952-.083 1.334-.251q.574-.252.89-.702t.316-1.029q0-.718-.434-1.19-.435-.471-1.195-.654l-2.648-.59q-1.071-.234-1.865-.809a4 4 0 0 1-1.232-1.42q-.44-.846-.44-1.908 0-1.286.665-2.31.664-1.023 1.854-1.597 1.19-.573 2.701-.573c1.511 0 1.933.186 2.733.558s1.424.888 1.871 1.549q.67.99.68 2.277h-2.926q0-.546-.289-.98c-.289-.435-.466-.515-.82-.676a2.9 2.9 0 0 0-1.217-.24q-.686 0-1.205.23a1.9 1.9 0 0 0-.81.643q-.29.412-.29.96 0 .621.403 1.028.402.407 1.098.579l2.552.557q1.103.226 1.967.852a4.45 4.45 0 0 1 1.345 1.544q.481.917.482 1.999 0 1.329-.702 2.385-.702 1.054-1.967 1.656-1.265.6-2.894.6t-2.889-.59" | ||
| 207 | /> | ||
| 208 | </svg> | ||
| 209 | ); | ||
| 210 | }; | ||
| 211 | |||
| 212 | export const GoLandIcon: Icon = (props) => { | ||
| 213 | const [gradientAId, gradientBId] = useSvgGradientIds("goland", 2); | ||
| 214 | |||
| 215 | return ( | ||
| 216 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 217 | <defs> | ||
| 218 | <linearGradient | ||
| 219 | id={gradientAId} | ||
| 220 | x1="64.391" | ||
| 221 | x2="39.607" | ||
| 222 | y1="56.329" | ||
| 223 | y2="2.874" | ||
| 224 | gradientUnits="userSpaceOnUse" | ||
| 225 | > | ||
| 226 | <stop offset=".24" stopColor="#00D886" /> | ||
| 227 | <stop offset=".51" stopColor="#007DFE" /> | ||
| 228 | </linearGradient> | ||
| 229 | <linearGradient | ||
| 230 | id={gradientBId} | ||
| 231 | x1="59.676" | ||
| 232 | x2="1.08" | ||
| 233 | y1="4.067" | ||
| 234 | y2="62.663" | ||
| 235 | gradientUnits="userSpaceOnUse" | ||
| 236 | > | ||
| 237 | <stop offset=".27" stopColor="#007DFE" /> | ||
| 238 | <stop offset=".7" stopColor="#D249FC" /> | ||
| 239 | </linearGradient> | ||
| 240 | </defs> | ||
| 241 | <path | ||
| 242 | fill="#00D886" | ||
| 243 | d="M47.55 58h12.259a4.125 4.125 0 0 0 4.124-4.19l-.176-11.044a4.13 4.13 0 0 0-1.44-3.066L24.159 6.993A4.13 4.13 0 0 0 21.474 6H10.125A4.125 4.125 0 0 0 6 10.125v11.003c0 1.19.514 2.321 1.409 3.105l37.425 32.746A4.12 4.12 0 0 0 47.55 58" | ||
| 244 | /> | ||
| 245 | <path | ||
| 246 | fill={`url(#${gradientAId})`} | ||
| 247 | d="M49.013 58h10.862A4.125 4.125 0 0 0 64 53.875V41.309q0-.3-.044-.598L58.508 3.527A4.124 4.124 0 0 0 54.427 0H39.029a4.125 4.125 0 0 0-4.125 4.126l.005 18.505c0 .425.066.848.195 1.253l9.979 31.246a4.13 4.13 0 0 0 3.93 2.87" | ||
| 248 | /> | ||
| 249 | <path | ||
| 250 | fill={`url(#${gradientBId})`} | ||
| 251 | d="M4.125 64h34.128a4.13 4.13 0 0 0 3.8-2.52L57.85 24.057c.219-.518.33-1.076.324-1.638l-.15-18.329A4.124 4.124 0 0 0 53.9 0H36.234c-.805 0-1.593.236-2.266.678L1.86 21.787A4.13 4.13 0 0 0 0 25.234v34.641A4.125 4.125 0 0 0 4.125 64" | ||
| 252 | /> | ||
| 253 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 254 | <path | ||
| 255 | fill="#fff" | ||
| 256 | d="M19.748 31.243a7.3 7.3 0 0 1-2.743-2.787q-.997-1.774-.997-3.961c0-2.187.332-2.778.997-3.96s1.58-2.112 2.743-2.787q1.747-1.013 3.902-1.014 1.747 0 3.222.622a6.9 6.9 0 0 1 2.486 1.747 6.4 6.4 0 0 1 1.42 2.594h-3.13a3.9 3.9 0 0 0-.926-1.228q-.584-.52-1.367-.803c-.783-.283-1.083-.284-1.683-.284q-1.33 0-2.402.664a4.6 4.6 0 0 0-1.677 1.828q-.606 1.163-.606 2.62c0 1.457.202 1.846.606 2.621a4.6 4.6 0 0 0 1.677 1.828q1.072.664 2.402.664 1.232 0 2.235-.461t1.591-1.276a3.3 3.3 0 0 0 .633-1.833l.01.31h-3.526v-2.304h6.357v1.18q0 1.982-.96 3.585a6.9 6.9 0 0 1-2.626 2.525q-1.666.921-3.736.921c-2.07 0-2.737-.337-3.902-1.013zM36.271 31.243a7.3 7.3 0 0 1-2.755-2.787q-1.002-1.774-1.002-3.961c0-2.187.333-2.778 1.002-3.96a7.3 7.3 0 0 1 2.755-2.787q1.752-1.013 3.918-1.014c1.443 0 2.738.338 3.907 1.013a7.3 7.3 0 0 1 2.749 2.787q.996 1.774.997 3.961c0 2.187-.333 2.778-.997 3.96s-1.581 2.113-2.75 2.788q-1.752 1.013-3.906 1.013c-1.437 0-2.75-.338-3.918-1.013m6.308-2.23q1.062-.67 1.662-1.854t.6-2.664-.6-2.664-1.662-1.854-2.39-.67-2.395.67a4.6 4.6 0 0 0-1.672 1.854q-.606 1.185-.606 2.664t.606 2.664 1.672 1.854 2.395.67q1.33 0 2.39-.67M33 44H17v3h16z" | ||
| 257 | /> | ||
| 258 | </svg> | ||
| 259 | ); | ||
| 260 | }; | ||
| 261 | |||
| 262 | export const IntelliJIdeaIcon: Icon = (props) => { | ||
| 263 | const [gradientAId, gradientBId] = useSvgGradientIds("intellij-idea", 2); | ||
| 264 | |||
| 265 | return ( | ||
| 266 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 267 | <defs> | ||
| 268 | <linearGradient | ||
| 269 | id={gradientAId} | ||
| 270 | x1="-.391" | ||
| 271 | x2="24.392" | ||
| 272 | y1="7.671" | ||
| 273 | y2="61.126" | ||
| 274 | gradientUnits="userSpaceOnUse" | ||
| 275 | > | ||
| 276 | <stop offset=".1" stopColor="#FC801D" /> | ||
| 277 | <stop offset=".59" stopColor="#FE2857" /> | ||
| 278 | </linearGradient> | ||
| 279 | <linearGradient | ||
| 280 | id={gradientBId} | ||
| 281 | x1="4.325" | ||
| 282 | x2="62.921" | ||
| 283 | y1="59.932" | ||
| 284 | y2="1.336" | ||
| 285 | gradientUnits="userSpaceOnUse" | ||
| 286 | > | ||
| 287 | <stop offset=".21" stopColor="#FE2857" /> | ||
| 288 | <stop offset=".7" stopColor="#007EFF" /> | ||
| 289 | </linearGradient> | ||
| 290 | </defs> | ||
| 291 | <path | ||
| 292 | fill="#FF8100" | ||
| 293 | d="M16.45 6H4.191a4.125 4.125 0 0 0-4.124 4.19l.176 11.044a4.13 4.13 0 0 0 1.44 3.066l38.159 32.707c.747.64 1.7.993 2.684.993h11.35A4.125 4.125 0 0 0 58 53.875V42.872c0-1.19-.514-2.321-1.41-3.105L19.167 7.021A4.12 4.12 0 0 0 16.45 6" | ||
| 294 | /> | ||
| 295 | <path | ||
| 296 | fill={`url(#${gradientAId})`} | ||
| 297 | d="M14.988 6H4.125A4.125 4.125 0 0 0 0 10.125v12.566q0 .3.044.598l5.448 37.185A4.125 4.125 0 0 0 9.573 64h15.398a4.125 4.125 0 0 0 4.125-4.127L29.09 41.37c0-.426-.066-.849-.195-1.254l-9.98-31.245A4.13 4.13 0 0 0 14.988 6z" | ||
| 298 | /> | ||
| 299 | <path | ||
| 300 | fill={`url(#${gradientBId})`} | ||
| 301 | d="M59.876 0H25.748a4.13 4.13 0 0 0-3.8 2.52L6.151 39.943a4.1 4.1 0 0 0-.325 1.638l.15 18.329A4.125 4.125 0 0 0 10.101 64h17.666c.806 0 1.593-.236 2.266-.678l32.11-21.109A4.12 4.12 0 0 0 64 38.766V4.125A4.125 4.125 0 0 0 59.876 0" | ||
| 302 | /> | ||
| 303 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 304 | <path | ||
| 305 | fill="#fff" | ||
| 306 | d="M33 44H17v3h16zM17 29.383h2.98v-9.775H17v-2.616h8.843v2.616h-2.98v9.775h2.98V32H17zM27.643 29.298h2.154a2.4 2.4 0 0 0 1.163-.279q.51-.279.788-.788.279-.51.279-1.163V16.992h2.926v10.28q0 1.35-.622 2.427a4.45 4.45 0 0 1-1.715 1.688q-1.092.612-2.454.611h-2.519z" | ||
| 307 | /> | ||
| 308 | </svg> | ||
| 309 | ); | ||
| 310 | }; | ||
| 311 | |||
| 312 | export const PhpStormIcon: Icon = (props) => { | ||
| 313 | const [gradientAId, gradientBId] = useSvgGradientIds("phpstorm", 2); | ||
| 314 | |||
| 315 | return ( | ||
| 316 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 317 | <defs> | ||
| 318 | <linearGradient | ||
| 319 | id={gradientAId} | ||
| 320 | x1="56.329" | ||
| 321 | x2="2.874" | ||
| 322 | y1="-.391" | ||
| 323 | y2="24.392" | ||
| 324 | gradientUnits="userSpaceOnUse" | ||
| 325 | > | ||
| 326 | <stop offset=".16" stopColor="#D249FC" /> | ||
| 327 | <stop offset=".55" stopColor="#FF2D90" /> | ||
| 328 | </linearGradient> | ||
| 329 | <linearGradient | ||
| 330 | id={gradientBId} | ||
| 331 | x1="4.067" | ||
| 332 | x2="62.664" | ||
| 333 | y1="4.326" | ||
| 334 | y2="62.923" | ||
| 335 | gradientUnits="userSpaceOnUse" | ||
| 336 | > | ||
| 337 | <stop offset=".3" stopColor="#FF2D90" /> | ||
| 338 | <stop offset=".7" stopColor="#7256FF" /> | ||
| 339 | </linearGradient> | ||
| 340 | </defs> | ||
| 341 | <path | ||
| 342 | fill="#D249FC" | ||
| 343 | d="M58 16.446V4.187A4.125 4.125 0 0 0 53.81.063L42.765.239A4.13 4.13 0 0 0 39.7 1.68L6.993 39.837c-.64.748-.993 1.7-.993 2.685v11.35a4.125 4.125 0 0 0 4.125 4.124h11.003c1.19 0 2.321-.514 3.105-1.409l32.746-37.425A4.12 4.12 0 0 0 58 16.446" | ||
| 344 | /> | ||
| 345 | <path | ||
| 346 | fill={`url(#${gradientAId})`} | ||
| 347 | d="M58 14.988V4.125A4.125 4.125 0 0 0 53.875 0H41.309q-.3 0-.598.044L3.527 5.492A4.125 4.125 0 0 0 0 9.573v15.398a4.125 4.125 0 0 0 4.126 4.125l18.505-.005c.425 0 .848-.066 1.253-.195l31.246-9.98A4.13 4.13 0 0 0 58 14.988" | ||
| 348 | /> | ||
| 349 | <path | ||
| 350 | fill={`url(#${gradientBId})`} | ||
| 351 | d="M64 59.878V25.75a4.13 4.13 0 0 0-2.52-3.8L24.057 6.153a4.1 4.1 0 0 0-1.638-.325l-18.329.15A4.124 4.124 0 0 0 0 10.103v17.665c0 .806.236 1.593.678 2.267l21.109 32.109a4.12 4.12 0 0 0 3.447 1.859h34.641A4.125 4.125 0 0 0 64 59.878" | ||
| 352 | /> | ||
| 353 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 354 | <path | ||
| 355 | fill="#fff" | ||
| 356 | d="M33 44H17v3h16zM16.993 16.992h6.442q1.586 0 2.78.579 1.196.579 1.845 1.63.648 1.05.648 2.432c0 .922-.22 1.759-.659 2.466q-.66 1.062-1.87 1.646-1.212.584-2.83.584h-3.43V32h-2.927zm7.54 6.63q.553-.273.852-.782.3-.51.3-1.195c0-.685-.1-.842-.3-1.174q-.3-.5-.852-.772-.552-.273-1.291-.273h-3.323v4.47h3.323q.74 0 1.291-.273M32.572 31.664q-1.26-.59-1.972-1.65t-.735-2.444h2.937q0 .654.343 1.147t.954.772q.611.278 1.404.278c.53 0 .952-.083 1.335-.251q.572-.252.89-.702c.317-.45.315-.643.315-1.029q0-.718-.434-1.19-.435-.471-1.195-.654l-2.647-.59q-1.073-.234-1.866-.809a4 4 0 0 1-1.232-1.42q-.44-.846-.44-1.908 0-1.286.665-2.31.665-1.023 1.854-1.597 1.19-.573 2.702-.573c1.512 0 1.933.186 2.733.558q1.2.558 1.87 1.549t.681 2.277h-2.926q0-.546-.29-.98a1.9 1.9 0 0 0-.82-.676 2.9 2.9 0 0 0-1.216-.24q-.687 0-1.206.23a1.9 1.9 0 0 0-.81.643q-.29.412-.289.96 0 .621.402 1.028t1.099.579l2.551.557q1.104.226 1.967.852a4.45 4.45 0 0 1 1.345 1.544q.482.917.482 1.999 0 1.329-.701 2.385-.703 1.054-1.967 1.656-1.264.6-2.895.6-1.63 0-2.888-.59" | ||
| 357 | /> | ||
| 358 | </svg> | ||
| 359 | ); | ||
| 360 | }; | ||
| 361 | |||
| 362 | export const PyCharmIcon: Icon = (props) => { | ||
| 363 | const [gradientAId, gradientBId] = useSvgGradientIds("pycharm", 2); | ||
| 364 | |||
| 365 | return ( | ||
| 366 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 367 | <defs> | ||
| 368 | <linearGradient | ||
| 369 | id={gradientAId} | ||
| 370 | x1="7.671" | ||
| 371 | x2="61.126" | ||
| 372 | y1="64.393" | ||
| 373 | y2="39.609" | ||
| 374 | gradientUnits="userSpaceOnUse" | ||
| 375 | > | ||
| 376 | <stop offset=".1" stopColor="#00D886" /> | ||
| 377 | <stop offset=".59" stopColor="#F0EB18" /> | ||
| 378 | </linearGradient> | ||
| 379 | <linearGradient | ||
| 380 | id={gradientBId} | ||
| 381 | x1="59.933" | ||
| 382 | x2="1.337" | ||
| 383 | y1="59.676" | ||
| 384 | y2="1.08" | ||
| 385 | gradientUnits="userSpaceOnUse" | ||
| 386 | > | ||
| 387 | <stop offset=".3" stopColor="#F0EB18" /> | ||
| 388 | <stop offset=".7" stopColor="#00C4F4" /> | ||
| 389 | </linearGradient> | ||
| 390 | </defs> | ||
| 391 | <path | ||
| 392 | fill="#00D886" | ||
| 393 | d="M6 47.55v12.259a4.125 4.125 0 0 0 4.19 4.124l11.044-.176a4.13 4.13 0 0 0 3.066-1.44l32.707-38.158c.64-.748.993-1.7.993-2.685V10.125A4.125 4.125 0 0 0 53.875 6H42.872c-1.19 0-2.321.514-3.105 1.409L7.021 44.834A4.12 4.12 0 0 0 6 47.55" | ||
| 394 | /> | ||
| 395 | <path | ||
| 396 | fill={`url(#${gradientAId})`} | ||
| 397 | d="M6 49.015v10.862a4.125 4.125 0 0 0 4.125 4.125h12.566q.3 0 .598-.044l37.185-5.448A4.125 4.125 0 0 0 64 54.429V39.03a4.125 4.125 0 0 0-4.127-4.125l-18.504.005c-.426 0-.849.066-1.254.195L8.871 45.085A4.13 4.13 0 0 0 6 49.015z" | ||
| 398 | /> | ||
| 399 | <path | ||
| 400 | fill={`url(#${gradientBId})`} | ||
| 401 | d="M0 4.125v34.128c0 1.658.993 3.154 2.52 3.8L39.943 57.85c.518.219 1.075.33 1.638.324l18.329-.15A4.125 4.125 0 0 0 64 53.9V36.234c0-.806-.236-1.593-.678-2.267L42.213 1.86A4.13 4.13 0 0 0 38.766 0H4.125A4.125 4.125 0 0 0 0 4.125" | ||
| 402 | /> | ||
| 403 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 404 | <path | ||
| 405 | fill="#fff" | ||
| 406 | d="M33 44H17v3h16zM16.993 16.992h6.442q1.586 0 2.78.579 1.196.579 1.845 1.63.648 1.05.648 2.432c0 .922-.22 1.759-.659 2.466q-.66 1.062-1.87 1.646-1.212.584-2.83.584h-3.43V32h-2.927zm7.54 6.63q.553-.273.852-.782.3-.51.3-1.195c0-.685-.1-.842-.3-1.174q-.3-.5-.852-.772-.552-.273-1.291-.273h-3.324v4.47h3.324q.74 0 1.291-.273M33.713 31.243a7.3 7.3 0 0 1-2.744-2.787q-.996-1.774-.996-3.961c0-2.187.332-2.778.996-3.96a7.3 7.3 0 0 1 2.744-2.787q1.748-1.013 3.902-1.014 1.823 0 3.344.675a6.86 6.86 0 0 1 2.535 1.892 6.44 6.44 0 0 1 1.356 2.793h-3.066a4.05 4.05 0 0 0-.895-1.431 4 4 0 0 0-1.43-.95 4.9 4.9 0 0 0-1.823-.332q-1.33 0-2.402.665a4.6 4.6 0 0 0-1.677 1.827q-.606 1.164-.606 2.62 0 1.459.606 2.621a4.6 4.6 0 0 0 1.677 1.828q1.072.664 2.402.664.986 0 1.822-.332a4.02 4.02 0 0 0 2.326-2.38h3.066a6.44 6.44 0 0 1-1.356 2.792 6.86 6.86 0 0 1-2.535 1.892q-1.522.675-3.344.675-2.154 0-3.902-1.013z" | ||
| 407 | /> | ||
| 408 | </svg> | ||
| 409 | ); | ||
| 410 | }; | ||
| 411 | |||
| 412 | export const RiderIcon: Icon = (props) => { | ||
| 413 | const [gradientAId, gradientBId] = useSvgGradientIds("rider", 2); | ||
| 414 | |||
| 415 | return ( | ||
| 416 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 417 | <defs> | ||
| 418 | <linearGradient | ||
| 419 | id={gradientAId} | ||
| 420 | x1="64.391" | ||
| 421 | x2="39.607" | ||
| 422 | y1="56.329" | ||
| 423 | y2="2.874" | ||
| 424 | gradientUnits="userSpaceOnUse" | ||
| 425 | > | ||
| 426 | <stop offset=".21" stopColor="#007DFE" /> | ||
| 427 | <stop offset=".55" stopColor="#FFB700" /> | ||
| 428 | </linearGradient> | ||
| 429 | <linearGradient | ||
| 430 | id={gradientBId} | ||
| 431 | x1="59.676" | ||
| 432 | x2="1.08" | ||
| 433 | y1="4.067" | ||
| 434 | y2="62.663" | ||
| 435 | gradientUnits="userSpaceOnUse" | ||
| 436 | > | ||
| 437 | <stop offset=".23" stopColor="#FFB700" /> | ||
| 438 | <stop offset=".73" stopColor="#FF0A67" /> | ||
| 439 | </linearGradient> | ||
| 440 | </defs> | ||
| 441 | <path | ||
| 442 | fill="#007DFE" | ||
| 443 | d="M47.55 58h12.258a4.125 4.125 0 0 0 4.124-4.19l-.176-11.044a4.12 4.12 0 0 0-1.44-3.066L24.158 6.993A4.13 4.13 0 0 0 21.474 6H10.125A4.125 4.125 0 0 0 6 10.125v11.003c0 1.19.514 2.321 1.409 3.105l37.425 32.746A4.12 4.12 0 0 0 47.55 58" | ||
| 444 | /> | ||
| 445 | <path | ||
| 446 | fill={`url(#${gradientAId})`} | ||
| 447 | d="M49.013 58h10.862A4.125 4.125 0 0 0 64 53.875V41.309q0-.3-.044-.598L58.508 3.527A4.125 4.125 0 0 0 54.427 0H39.029a4.125 4.125 0 0 0-4.125 4.126l.005 18.505c0 .425.066.848.195 1.253l9.979 31.246a4.13 4.13 0 0 0 3.93 2.87" | ||
| 448 | /> | ||
| 449 | <path | ||
| 450 | fill={`url(#${gradientBId})`} | ||
| 451 | d="M4.125 64h34.128a4.13 4.13 0 0 0 3.8-2.52L57.85 24.057c.219-.518.33-1.076.324-1.638l-.15-18.329A4.124 4.124 0 0 0 53.9 0H36.234c-.805 0-1.593.236-2.266.678L1.86 21.787A4.13 4.13 0 0 0 0 25.234v34.641A4.125 4.125 0 0 0 4.125 64" | ||
| 452 | /> | ||
| 453 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 454 | <path | ||
| 455 | fill="#fff" | ||
| 456 | d="M33 44H17v3h16zM16.992 16.992h6.442q1.576 0 2.776.579t1.85 1.63.648 2.432c0 .922-.22 1.75-.66 2.46q-.66 1.068-1.875 1.651-1.217.584-2.825.584h-3.43v5.67h-2.926zm7.54 6.63q.553-.274.853-.783.3-.51.3-1.184c0-.45-.1-.852-.3-1.185q-.3-.498-.852-.772-.552-.273-1.292-.273h-3.323v4.47h3.323q.74 0 1.292-.273m-2.63 1.763h3.194L29.03 32h-3.355zM31.613 16.992h5.713q2.133 0 3.822.965a6.9 6.9 0 0 1 2.641 2.674q.954 1.71.954 3.864t-.953 3.865a6.9 6.9 0 0 1-2.642 2.674q-1.688.964-3.822.964h-5.713zm8.028 11.876q1.008-.6 1.555-1.72t.547-2.653q0-1.534-.547-2.653-.547-1.12-1.555-1.721-1.008-.6-2.347-.6h-2.755v9.947h2.755q1.34 0 2.347-.6" | ||
| 457 | /> | ||
| 458 | </svg> | ||
| 459 | ); | ||
| 460 | }; | ||
| 461 | |||
| 462 | export const RubyMineIcon: Icon = (props) => { | ||
| 463 | const [gradientAId, gradientBId] = useSvgGradientIds("rubymine", 2); | ||
| 464 | |||
| 465 | return ( | ||
| 466 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 467 | <defs> | ||
| 468 | <linearGradient | ||
| 469 | id={gradientAId} | ||
| 470 | x1="4.325" | ||
| 471 | x2="62.921" | ||
| 472 | y1="59.932" | ||
| 473 | y2="1.337" | ||
| 474 | gradientUnits="userSpaceOnUse" | ||
| 475 | > | ||
| 476 | <stop offset=".29" stopColor="#FF2358" /> | ||
| 477 | <stop offset=".75" stopColor="#7256FF" /> | ||
| 478 | </linearGradient> | ||
| 479 | <linearGradient | ||
| 480 | id={gradientBId} | ||
| 481 | x1="-.391" | ||
| 482 | x2="24.393" | ||
| 483 | y1="7.671" | ||
| 484 | y2="61.125" | ||
| 485 | gradientUnits="userSpaceOnUse" | ||
| 486 | > | ||
| 487 | <stop offset=".29" stopColor="#FF8100" /> | ||
| 488 | <stop offset=".56" stopColor="#FF2358" /> | ||
| 489 | </linearGradient> | ||
| 490 | </defs> | ||
| 491 | <path | ||
| 492 | fill={`url(#${gradientAId})`} | ||
| 493 | d="M59.875 0H25.748a4.13 4.13 0 0 0-3.8 2.52L6.151 39.942a4.1 4.1 0 0 0-.325 1.639l.15 18.328A4.125 4.125 0 0 0 10.101 64h17.666c.805 0 1.593-.235 2.266-.678l32.109-21.108A4.12 4.12 0 0 0 64 38.766V4.125A4.125 4.125 0 0 0 59.875 0" | ||
| 494 | /> | ||
| 495 | <path | ||
| 496 | fill={`url(#${gradientBId})`} | ||
| 497 | d="M14.987 6H4.126A4.125 4.125 0 0 0 0 10.125v12.566q0 .3.044.598l5.448 37.184A4.125 4.125 0 0 0 9.572 64H24.97a4.125 4.125 0 0 0 4.125-4.126l-.004-18.504c0-.426-.067-.85-.196-1.254L18.917 8.87A4.13 4.13 0 0 0 14.987 6z" | ||
| 498 | /> | ||
| 499 | <path | ||
| 500 | fill="#FF8100" | ||
| 501 | d="M16.45 6H4.19a4.125 4.125 0 0 0-4.124 4.19L0 21c.019 1.181.786 2.531 1.683 3.3l38.158 32.706c.748.641 1.7.993 2.684.993h11.35A4.125 4.125 0 0 0 58 53.875V42.872c0-1.189-.514-2.32-1.41-3.104L19.167 7.021A4.12 4.12 0 0 0 16.45 6" | ||
| 502 | /> | ||
| 503 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 504 | <path | ||
| 505 | fill="#fff" | ||
| 506 | d="M33 44H17v3h16zM17.012 16.992h6.442q1.575 0 2.776.579t1.849 1.63.648 2.432c0 .922-.22 1.75-.66 2.46q-.658 1.068-1.875 1.651-1.216.584-2.824.584h-3.43v5.67h-2.926zm7.54 6.63q.552-.274.852-.783.3-.51.3-1.184c0-.45-.1-.852-.3-1.185q-.3-.498-.852-.772-.552-.273-1.292-.273h-3.323v4.47h3.323q.74 0 1.292-.273m-2.631 1.763h3.194L29.05 32h-3.355zM31.633 16.992h4.073l3.087 9.85.257 1.287.225-1.286 2.98-9.85h4.138v15.005h-2.894V21.29l.043-.782-3.494 11.49h-2.123l-3.451-11.415.043.707v10.708h-2.883V16.992z" | ||
| 507 | /> | ||
| 508 | </svg> | ||
| 509 | ); | ||
| 510 | }; | ||
| 511 | |||
| 512 | export const RustRoverIcon: Icon = (props) => { | ||
| 513 | const [gradientAId, gradientBId] = useSvgGradientIds("rustrover", 2); | ||
| 514 | |||
| 515 | return ( | ||
| 516 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 517 | <defs> | ||
| 518 | <linearGradient | ||
| 519 | id={gradientAId} | ||
| 520 | x1="7.671" | ||
| 521 | x2="61.125" | ||
| 522 | y1="64.393" | ||
| 523 | y2="39.609" | ||
| 524 | gradientUnits="userSpaceOnUse" | ||
| 525 | > | ||
| 526 | <stop offset=".08" stopColor="#00D886" /> | ||
| 527 | <stop offset=".46" stopColor="#FFAB00" /> | ||
| 528 | </linearGradient> | ||
| 529 | <linearGradient | ||
| 530 | id={gradientBId} | ||
| 531 | x1="59.932" | ||
| 532 | x2="1.336" | ||
| 533 | y1="59.676" | ||
| 534 | y2="1.08" | ||
| 535 | gradientUnits="userSpaceOnUse" | ||
| 536 | > | ||
| 537 | <stop offset=".19" stopColor="#FFAB00" /> | ||
| 538 | <stop offset=".83" stopColor="#FF004C" /> | ||
| 539 | </linearGradient> | ||
| 540 | </defs> | ||
| 541 | <path | ||
| 542 | fill="#00D886" | ||
| 543 | d="M6 47.55v12.258a4.125 4.125 0 0 0 4.19 4.124l11.044-.176a4.12 4.12 0 0 0 3.066-1.44l32.707-38.158c.64-.747.993-1.7.993-2.684V10.125A4.125 4.125 0 0 0 53.875 6H42.872c-1.19 0-2.321.514-3.105 1.409L7.021 44.833A4.12 4.12 0 0 0 6 47.55" | ||
| 544 | /> | ||
| 545 | <path | ||
| 546 | fill={`url(#${gradientAId})`} | ||
| 547 | d="M6 49.015v10.862a4.125 4.125 0 0 0 4.125 4.125h12.566q.3 0 .598-.044l37.185-5.448A4.125 4.125 0 0 0 64 54.429V39.03a4.125 4.125 0 0 0-4.127-4.125l-18.504.005c-.426 0-.849.066-1.254.195L8.871 45.085A4.13 4.13 0 0 0 6 49.015z" | ||
| 548 | /> | ||
| 549 | <path | ||
| 550 | fill={`url(#${gradientBId})`} | ||
| 551 | d="M0 4.125v34.128c0 1.658.993 3.154 2.52 3.8L39.943 57.85c.518.219 1.075.33 1.638.324l18.329-.15A4.125 4.125 0 0 0 64 53.9V36.234c0-.806-.236-1.593-.678-2.267L42.213 1.86A4.13 4.13 0 0 0 38.766 0H4.125A4.125 4.125 0 0 0 0 4.125" | ||
| 552 | /> | ||
| 553 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 554 | <path | ||
| 555 | fill="#fff" | ||
| 556 | d="M33 44H17v3h16zM16.992 16.992h6.442q1.576 0 2.776.579t1.85 1.63.648 2.432c0 .922-.22 1.75-.66 2.46q-.66 1.068-1.875 1.651-1.217.584-2.825.584h-3.43v5.67h-2.926zm7.54 6.63q.553-.274.853-.783.3-.51.3-1.184c0-.45-.1-.852-.3-1.185q-.3-.498-.852-.772-.552-.273-1.292-.273h-3.323v4.47h3.323q.74 0 1.292-.273m-2.63 1.763h3.194L29.03 32h-3.355zM31.613 16.992h6.442q1.575 0 2.776.579t1.85 1.63.648 2.432c0 .922-.22 1.75-.66 2.46q-.659 1.068-1.875 1.651-1.217.584-2.824.584h-3.43v5.67h-2.927zm7.54 6.63q.553-.274.853-.783.3-.51.3-1.184c0-.45-.1-.852-.3-1.185q-.3-.498-.852-.772-.552-.273-1.292-.273h-3.323v4.47h3.323q.74 0 1.292-.273m-2.63 1.763h3.194L43.651 32h-3.355z" | ||
| 557 | /> | ||
| 558 | </svg> | ||
| 559 | ); | ||
| 560 | }; | ||
| 561 | |||
| 562 | export const WebStormIcon: Icon = (props) => { | ||
| 563 | const [gradientAId, gradientBId] = useSvgGradientIds("webstorm", 2); | ||
| 564 | |||
| 565 | return ( | ||
| 566 | <svg {...props} viewBox="0 0 64 64" fill="none"> | ||
| 567 | <defs> | ||
| 568 | <linearGradient | ||
| 569 | id={gradientAId} | ||
| 570 | x1="7.671" | ||
| 571 | x2="61.126" | ||
| 572 | y1="64.392" | ||
| 573 | y2="39.609" | ||
| 574 | gradientUnits="userSpaceOnUse" | ||
| 575 | > | ||
| 576 | <stop offset=".22" stopColor="#F0EB18" /> | ||
| 577 | <stop offset=".59" stopColor="#00C4F4" /> | ||
| 578 | </linearGradient> | ||
| 579 | <linearGradient | ||
| 580 | id={gradientBId} | ||
| 581 | x1="59.932" | ||
| 582 | x2="1.337" | ||
| 583 | y1="59.676" | ||
| 584 | y2="1.079" | ||
| 585 | gradientUnits="userSpaceOnUse" | ||
| 586 | > | ||
| 587 | <stop offset=".19" stopColor="#00C4F4" /> | ||
| 588 | <stop offset=".83" stopColor="#007DFE" /> | ||
| 589 | </linearGradient> | ||
| 590 | </defs> | ||
| 591 | <path | ||
| 592 | fill="#F0EB18" | ||
| 593 | d="M6 47.55v12.258a4.125 4.125 0 0 0 4.19 4.124l11.044-.176a4.12 4.12 0 0 0 3.066-1.44l32.707-38.158c.64-.747.993-1.7.993-2.684V10.125A4.125 4.125 0 0 0 53.875 6H42.872c-1.19 0-2.321.514-3.105 1.409L7.021 44.833A4.12 4.12 0 0 0 6 47.55" | ||
| 594 | /> | ||
| 595 | <path | ||
| 596 | fill={`url(#${gradientAId})`} | ||
| 597 | d="M6 49.015v10.862a4.125 4.125 0 0 0 4.125 4.125h12.566q.3 0 .598-.044l37.185-5.448A4.125 4.125 0 0 0 64 54.429V39.03a4.125 4.125 0 0 0-4.127-4.125l-18.504.005c-.426 0-.849.066-1.254.195L8.871 45.085A4.13 4.13 0 0 0 6 49.015z" | ||
| 598 | /> | ||
| 599 | <path | ||
| 600 | fill={`url(#${gradientBId})`} | ||
| 601 | d="M0 4.125v34.128c0 1.658.993 3.154 2.52 3.8L39.943 57.85c.518.219 1.075.33 1.638.324l18.329-.15A4.125 4.125 0 0 0 64 53.9V36.234c0-.806-.236-1.593-.678-2.267L42.213 1.86A4.13 4.13 0 0 0 38.766 0H4.125A4.125 4.125 0 0 0 0 4.125" | ||
| 602 | /> | ||
| 603 | <path fill="#000" d="M52 12H12v40h40z" /> | ||
| 604 | <path | ||
| 605 | fill="#fff" | ||
| 606 | d="M33 44H17v3h16zM19.051 16.992l2.423 10.955 2.583-10.955h2.958l2.701 10.955 2.348-10.955h2.97l-3.645 15.006h-3.334l-2.53-10.9-2.561 10.9H19.64l-3.623-15.006zM38.662 31.664q-1.26-.59-1.972-1.65t-.735-2.444h2.937q0 .654.343 1.147t.954.772q.61.278 1.404.278c.53 0 .952-.083 1.335-.251q.573-.252.889-.702t.316-1.029q0-.718-.434-1.19-.435-.471-1.195-.654l-2.648-.59q-1.071-.234-1.865-.809a4 4 0 0 1-1.232-1.42q-.44-.846-.44-1.908 0-1.286.665-2.31.664-1.023 1.854-1.597 1.19-.573 2.701-.573c1.008 0 1.934.186 2.734.558q1.2.558 1.87 1.549t.68 2.277h-2.925q0-.546-.29-.98c-.29-.435-.466-.515-.82-.676a2.9 2.9 0 0 0-1.217-.24q-.686 0-1.205.23a1.9 1.9 0 0 0-.81.643q-.29.412-.289.96 0 .621.402 1.028t1.099.579l2.55.557q1.105.226 1.968.852a4.45 4.45 0 0 1 1.345 1.544 4.2 4.2 0 0 1 .482 1.999q0 1.329-.702 2.385-.702 1.054-1.966 1.656-1.266.6-2.894.6-1.63 0-2.889-.59" | ||
| 607 | /> | ||
| 608 | </svg> | ||
| 609 | ); | ||
| 610 | }; | ||
apps/web/src/components/chat/OpenInPicker.tsx+69-1| ... | @@ -12,12 +12,25 @@ import { | ... | @@ -12,12 +12,25 @@ import { |
| 12 | Icon, | 12 | Icon, |
| 13 | KiroIcon, | 13 | KiroIcon, |
| 14 | TraeIcon, | 14 | TraeIcon, |
| 15 | IntelliJIdeaIcon, | ||
| 16 | VisualStudioCode, | 15 | VisualStudioCode, |
| 17 | VisualStudioCodeInsiders, | 16 | VisualStudioCodeInsiders, |
| 18 | VSCodium, | 17 | VSCodium, |
| 19 | Zed, | 18 | Zed, |
| 20 | } from "../Icons"; | 19 | } from "../Icons"; |
| 20 | import { | ||
| 21 | AquaIcon, | ||
| 22 | CLionIcon, | ||
| 23 | DataGripIcon, | ||
| 24 | DataSpellIcon, | ||
| 25 | GoLandIcon, | ||
| 26 | IntelliJIdeaIcon, | ||
| 27 | PhpStormIcon, | ||
| 28 | PyCharmIcon, | ||
| 29 | RiderIcon, | ||
| 30 | RubyMineIcon, | ||
| 31 | RustRoverIcon, | ||
| 32 | WebStormIcon, | ||
| 33 | } from "../JetBrainsIcons"; | ||
| 21 | import { isMacPlatform, isWindowsPlatform } from "~/lib/utils"; | 34 | import { isMacPlatform, isWindowsPlatform } from "~/lib/utils"; |
| 22 | import { readLocalApi } from "~/localApi"; | 35 | import { readLocalApi } from "~/localApi"; |
| 23 | 36 | ||
| ... | @@ -68,6 +81,61 @@ const resolveOptions = (platform: string, availableEditors: ReadonlyArray<Editor | ... | @@ -68,6 +81,61 @@ const resolveOptions = (platform: string, availableEditors: ReadonlyArray<Editor |
| 68 | Icon: IntelliJIdeaIcon, | 81 | Icon: IntelliJIdeaIcon, |
| 69 | value: "idea", | 82 | value: "idea", |
| 70 | }, | 83 | }, |
| 84 | { | ||
| 85 | label: "Aqua", | ||
| 86 | Icon: AquaIcon, | ||
| 87 | value: "aqua", | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | label: "CLion", | ||
| 91 | Icon: CLionIcon, | ||
| 92 | value: "clion", | ||
| 93 | }, | ||
| 94 | { | ||
| 95 | label: "DataGrip", | ||
| 96 | Icon: DataGripIcon, | ||
| 97 | value: "datagrip", | ||
| 98 | }, | ||
| 99 | { | ||
| 100 | label: "DataSpell", | ||
| 101 | Icon: DataSpellIcon, | ||
| 102 | value: "dataspell", | ||
| 103 | }, | ||
| 104 | { | ||
| 105 | label: "GoLand", | ||
| 106 | Icon: GoLandIcon, | ||
| 107 | value: "goland", | ||
| 108 | }, | ||
| 109 | { | ||
| 110 | label: "PhpStorm", | ||
| 111 | Icon: PhpStormIcon, | ||
| 112 | value: "phpstorm", | ||
| 113 | }, | ||
| 114 | { | ||
| 115 | label: "PyCharm", | ||
| 116 | Icon: PyCharmIcon, | ||
| 117 | value: "pycharm", | ||
| 118 | }, | ||
| 119 | { | ||
| 120 | label: "Rider", | ||
| 121 | Icon: RiderIcon, | ||
| 122 | value: "rider", | ||
| 123 | }, | ||
| 124 | { | ||
| 125 | label: "RubyMine", | ||
| 126 | Icon: RubyMineIcon, | ||
| 127 | value: "rubymine", | ||
| 128 | }, | ||
| 129 | { | ||
| 130 | label: "RustRover", | ||
| 131 | Icon: RustRoverIcon, | ||
| 132 | value: "rustrover", | ||
| 133 | }, | ||
| 134 | { | ||
| 135 | label: "WebStorm", | ||
| 136 | Icon: WebStormIcon, | ||
| 137 | value: "webstorm", | ||
| 138 | }, | ||
| 71 | { | 139 | { |
| 72 | label: isMacPlatform(platform) | 140 | label: isMacPlatform(platform) |
| 73 | ? "Finder" | 141 | ? "Finder" |
apps/web/src/markdown-links.test.ts+30| ... | @@ -18,6 +18,20 @@ describe("rewriteMarkdownFileUriHref", () => { | ... | @@ -18,6 +18,20 @@ describe("rewriteMarkdownFileUriHref", () => { |
| 18 | "/Users/julius/project/file%2520name.md", | 18 | "/Users/julius/project/file%2520name.md", |
| 19 | ); | 19 | ); |
| 20 | }); | 20 | }); |
| 21 | |||
| 22 | it("normalizes file uri hrefs for windows drive paths", () => { | ||
| 23 | expect( | ||
| 24 | rewriteMarkdownFileUriHref( | ||
| 25 | "file:///D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69", | ||
| 26 | ), | ||
| 27 | ).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69"); | ||
| 28 | }); | ||
| 29 | |||
| 30 | it("unwraps angle-bracketed file uri hrefs", () => { | ||
| 31 | expect( | ||
| 32 | rewriteMarkdownFileUriHref(" <file:///D:/Programme/t3code/apps/web/src/markdown-links.ts> "), | ||
| 33 | ).toBe("D:/Programme/t3code/apps/web/src/markdown-links.ts"); | ||
| 34 | }); | ||
| 21 | }); | 35 | }); |
| 22 | 36 | ||
| 23 | describe("resolveMarkdownFileLinkTarget", () => { | 37 | describe("resolveMarkdownFileLinkTarget", () => { |
| ... | @@ -84,6 +98,22 @@ describe("resolveMarkdownFileLinkTarget", () => { | ... | @@ -84,6 +98,22 @@ describe("resolveMarkdownFileLinkTarget", () => { |
| 84 | }); | 98 | }); |
| 85 | }); | 99 | }); |
| 86 | 100 | ||
| 101 | it("normalizes slash-prefixed windows drive paths before resolving", () => { | ||
| 102 | expect( | ||
| 103 | resolveMarkdownFileLinkTarget( | ||
| 104 | "/D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69", | ||
| 105 | ), | ||
| 106 | ).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx:69"); | ||
| 107 | }); | ||
| 108 | |||
| 109 | it("resolves angle-bracketed windows drive paths", () => { | ||
| 110 | expect( | ||
| 111 | resolveMarkdownFileLinkTarget( | ||
| 112 | "</D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1>", | ||
| 113 | ), | ||
| 114 | ).toBe("D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1"); | ||
| 115 | }); | ||
| 116 | |||
| 87 | it("does not treat app routes as file links", () => { | 117 | it("does not treat app routes as file links", () => { |
| 88 | expect(resolveMarkdownFileLinkTarget("/chat/settings")).toBeNull(); | 118 | expect(resolveMarkdownFileLinkTarget("/chat/settings")).toBeNull(); |
| 89 | }); | 119 | }); |
apps/web/src/markdown-links.ts+19-4| ... | @@ -39,6 +39,14 @@ function safeDecode(value: string): string { | ... | @@ -39,6 +39,14 @@ function safeDecode(value: string): string { |
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | function unwrapMarkdownLinkDestination(value: string): string { | ||
| 43 | return value.startsWith("<") && value.endsWith(">") ? value.slice(1, -1) : value; | ||
| 44 | } | ||
| 45 | |||
| 46 | export function normalizeMarkdownLinkDestination(value: string): string { | ||
| 47 | return unwrapMarkdownLinkDestination(value.trim()); | ||
| 48 | } | ||
| 49 | |||
| 42 | function stripSearchAndHash(value: string): { path: string; hash: string } { | 50 | function stripSearchAndHash(value: string): { path: string; hash: string } { |
| 43 | const hashIndex = value.indexOf("#"); | 51 | const hashIndex = value.indexOf("#"); |
| 44 | const pathWithSearch = hashIndex >= 0 ? value.slice(0, hashIndex) : value; | 52 | const pathWithSearch = hashIndex >= 0 ? value.slice(0, hashIndex) : value; |
| ... | @@ -48,6 +56,10 @@ function stripSearchAndHash(value: string): { path: string; hash: string } { | ... | @@ -48,6 +56,10 @@ function stripSearchAndHash(value: string): { path: string; hash: string } { |
| 48 | return { path, hash: rawHash }; | 56 | return { path, hash: rawHash }; |
| 49 | } | 57 | } |
| 50 | 58 | ||
| 59 | function normalizeWindowsDrivePath(path: string): string { | ||
| 60 | return /^\/[A-Za-z]:[\\/]/.test(path) ? path.slice(1) : path; | ||
| 61 | } | ||
| 62 | |||
| 51 | function parseFileUrlHref( | 63 | function parseFileUrlHref( |
| 52 | href: string, | 64 | href: string, |
| 53 | options?: { readonly decodePath?: boolean }, | 65 | options?: { readonly decodePath?: boolean }, |
| ... | @@ -60,7 +72,7 @@ function parseFileUrlHref( | ... | @@ -60,7 +72,7 @@ function parseFileUrlHref( |
| 60 | if (rawPath.length === 0) return null; | 72 | if (rawPath.length === 0) return null; |
| 61 | 73 | ||
| 62 | // Browser URL parser encodes "C:/foo" as "/C:/foo" for file URLs. | 74 | // Browser URL parser encodes "C:/foo" as "/C:/foo" for file URLs. |
| 63 | const normalizedPath = /^\/[A-Za-z]:[\\/]/.test(rawPath) ? rawPath.slice(1) : rawPath; | 75 | const normalizedPath = normalizeWindowsDrivePath(rawPath); |
| 64 | 76 | ||
| 65 | return { | 77 | return { |
| 66 | path: options?.decodePath === false ? normalizedPath : safeDecode(normalizedPath), | 78 | path: options?.decodePath === false ? normalizedPath : safeDecode(normalizedPath), |
| ... | @@ -73,7 +85,8 @@ function parseFileUrlHref( | ... | @@ -73,7 +85,8 @@ function parseFileUrlHref( |
| 73 | 85 | ||
| 74 | export function rewriteMarkdownFileUriHref(href: string | undefined): string | null { | 86 | export function rewriteMarkdownFileUriHref(href: string | undefined): string | null { |
| 75 | if (!href) return null; | 87 | if (!href) return null; |
| 76 | const target = parseFileUrlHref(href.trim(), { decodePath: false }); | 88 | const normalizedHref = normalizeMarkdownLinkDestination(href); |
| 89 | const target = parseFileUrlHref(normalizedHref, { decodePath: false }); | ||
| 77 | if (!target) return null; | 90 | if (!target) return null; |
| 78 | return `${target.path}${target.hash}`; | 91 | return `${target.path}${target.hash}`; |
| 79 | } | 92 | } |
| ... | @@ -124,14 +137,16 @@ export function resolveMarkdownFileLinkTarget( | ... | @@ -124,14 +137,16 @@ export function resolveMarkdownFileLinkTarget( |
| 124 | cwd?: string, | 137 | cwd?: string, |
| 125 | ): string | null { | 138 | ): string | null { |
| 126 | if (!href) return null; | 139 | if (!href) return null; |
| 127 | const rawHref = href.trim(); | 140 | const rawHref = normalizeMarkdownLinkDestination(href); |
| 128 | if (rawHref.length === 0 || rawHref.startsWith("#")) return null; | 141 | if (rawHref.length === 0 || rawHref.startsWith("#")) return null; |
| 129 | 142 | ||
| 130 | const fileUrlTarget = rawHref.toLowerCase().startsWith("file:") | 143 | const fileUrlTarget = rawHref.toLowerCase().startsWith("file:") |
| 131 | ? parseFileUrlHref(rawHref) | 144 | ? parseFileUrlHref(rawHref) |
| 132 | : null; | 145 | : null; |
| 133 | const source = fileUrlTarget ?? stripSearchAndHash(rawHref); | 146 | const source = fileUrlTarget ?? stripSearchAndHash(rawHref); |
| 134 | const decodedPath = fileUrlTarget ? source.path.trim() : safeDecode(source.path.trim()); | 147 | const decodedPath = normalizeWindowsDrivePath( |
| 148 | fileUrlTarget ? source.path.trim() : safeDecode(source.path.trim()), | ||
| 149 | ); | ||
| 135 | const decodedHash = safeDecode(source.hash.trim()); | 150 | const decodedHash = safeDecode(source.hash.trim()); |
| 136 | 151 | ||
| 137 | if (decodedPath.length === 0) return null; | 152 | if (decodedPath.length === 0) return null; |
packages/contracts/src/editor.ts+11| ... | @@ -27,6 +27,17 @@ export const EDITORS = [ | ... | @@ -27,6 +27,17 @@ export const EDITORS = [ |
| 27 | { id: "zed", label: "Zed", commands: ["zed", "zeditor"], launchStyle: "direct-path" }, | 27 | { id: "zed", label: "Zed", commands: ["zed", "zeditor"], launchStyle: "direct-path" }, |
| 28 | { id: "antigravity", label: "Antigravity", commands: ["agy"], launchStyle: "goto" }, | 28 | { id: "antigravity", label: "Antigravity", commands: ["agy"], launchStyle: "goto" }, |
| 29 | { id: "idea", label: "IntelliJ IDEA", commands: ["idea"], launchStyle: "line-column" }, | 29 | { id: "idea", label: "IntelliJ IDEA", commands: ["idea"], launchStyle: "line-column" }, |
| 30 | { id: "aqua", label: "Aqua", commands: ["aqua"], launchStyle: "line-column" }, | ||
| 31 | { id: "clion", label: "CLion", commands: ["clion"], launchStyle: "line-column" }, | ||
| 32 | { id: "datagrip", label: "DataGrip", commands: ["datagrip"], launchStyle: "line-column" }, | ||
| 33 | { id: "dataspell", label: "DataSpell", commands: ["dataspell"], launchStyle: "line-column" }, | ||
| 34 | { id: "goland", label: "GoLand", commands: ["goland"], launchStyle: "line-column" }, | ||
| 35 | { id: "phpstorm", label: "PhpStorm", commands: ["phpstorm"], launchStyle: "line-column" }, | ||
| 36 | { id: "pycharm", label: "PyCharm", commands: ["pycharm"], launchStyle: "line-column" }, | ||
| 37 | { id: "rider", label: "Rider", commands: ["rider"], launchStyle: "line-column" }, | ||
| 38 | { id: "rubymine", label: "RubyMine", commands: ["rubymine"], launchStyle: "line-column" }, | ||
| 39 | { id: "rustrover", label: "RustRover", commands: ["rustrover"], launchStyle: "line-column" }, | ||
| 40 | { id: "webstorm", label: "WebStorm", commands: ["webstorm"], launchStyle: "line-column" }, | ||
| 30 | { id: "file-manager", label: "File Manager", commands: null, launchStyle: "direct-path" }, | 41 | { id: "file-manager", label: "File Manager", commands: null, launchStyle: "direct-path" }, |
| 31 | ] as const satisfies ReadonlyArray<EditorDefinition>; | 42 | ] as const satisfies ReadonlyArray<EditorDefinition>; |
| 32 | 43 |