From 7d9309d4c2b87e57b6158e9172ab3cc5562318eb Mon Sep 17 00:00:00 2001 From: Ankur Oberoi Date: Mon, 8 Dec 2025 10:12:52 -0500 Subject: [PATCH 01/11] npm install cleanup (#1988) * Resolve npm install warning for @types/diff deprecation > npm warn deprecated @types/diff@8.0.0: This is a stub types definition. diff provides its own type definitions, so you do not need this installed. Related: #1828 * Migrates away from unmaintained npm package fantasticon Replaces with @twbs/fantasticon fork, which is maintained. Tested by running `npm run compile-icons` (which is indirectly included in the `postinstall` script too), and then previewing the built font (assets/icons/icon-font.woff) on https://fontdrop.info. The 3 expected glyphs were present at the expected codepoints. This does NOT resolve the npm install warning I initially was pursuring. The transitive dep chain is deep, and @twbs/fantasticon still contains the deprecated version of @npmcli/move-file. > npm warn deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs --- package-lock.json | 1439 +++++++++----------------------------- package.json | 5 +- scripts/compile_icons.ts | 4 +- 3 files changed, 343 insertions(+), 1105 deletions(-) diff --git a/package-lock.json b/package-lock.json index d616cda65..cedb226c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,12 +21,12 @@ "devDependencies": { "@actions/core": "^1.11.1", "@trivago/prettier-plugin-sort-imports": "^6.0.0", + "@twbs/fantasticon": "^3.1.0", "@types/archiver": "^7.0.0", "@types/chai": "^4.3.19", "@types/chai-as-promised": "^7.1.8", "@types/chai-subset": "^1.3.6", "@types/decompress": "^4.2.7", - "@types/diff": "^8.0.0", "@types/lcov-parse": "^1.0.2", "@types/lodash.debounce": "^4.0.9", "@types/lodash.throttle": "^4.1.9", @@ -60,7 +60,6 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-mocha": "^10.5.0", - "fantasticon": "^1.2.3", "husky": "^9.1.7", "lint-staged": "^16.2.7", "lodash.debounce": "^4.0.8", @@ -2169,6 +2168,171 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@twbs/fantasticon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@twbs/fantasticon/-/fantasticon-3.1.0.tgz", + "integrity": "sha512-dqJvW4k9qXt7ktLoCFkAFLtIhV/r8Psj8jtmwh+emIoXYHL+9Y39m0rLMRRTkX2YPuwBL7Y2vX8DtNtsyoGZLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "case": "^1.6.3", + "commander": "^11.1.0", + "figures": "^3.2.0", + "glob": "^7.2.3", + "handlebars": "^4.7.8", + "picocolors": "^1.1.1", + "slugify": "^1.6.6", + "svg2ttf": "^6.0.3", + "svgicons2svgfont": "^12.0.0", + "ttf2eot": "^3.1.0", + "ttf2woff": "^3.0.0", + "ttf2woff2": "^5.0.0" + }, + "bin": { + "fantasticon": "bin/fantasticon" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@twbs/fantasticon/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@twbs/fantasticon/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/@twbs/fantasticon/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@twbs/fantasticon/node_modules/svgicons2svgfont": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-12.0.0.tgz", + "integrity": "sha512-fjyDkhiG0M1TPBtZzD12QV3yDcG2fUgiqHPOCYzf7hHE40Hl3GhnE6P1njsJCCByhwM7MiufyDW3L7IOR5dg9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^9.3.0", + "glob": "^8.0.3", + "sax": "^1.2.4", + "svg-pathdata": "^6.0.3" + }, + "bin": { + "svgicons2svgfont": "bin/svgicons2svgfont.js" + }, + "engines": { + "node": ">=16.15.0" + } + }, + "node_modules/@twbs/fantasticon/node_modules/svgicons2svgfont/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@twbs/fantasticon/node_modules/svgicons2svgfont/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@twbs/fantasticon/node_modules/svgicons2svgfont/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@twbs/fantasticon/node_modules/ttf2eot": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-3.1.0.tgz", + "integrity": "sha512-aHTbcYosNHVqb2Qtt9Xfta77ae/5y0VfdwNLUS6sGBeGr22cX2JDMo/i5h3uuOf+FAD3akYOr17+fYd5NK8aXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "ttf2eot": "ttf2eot.js" + } + }, + "node_modules/@twbs/fantasticon/node_modules/ttf2woff2": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-5.0.0.tgz", + "integrity": "sha512-FplhShJd3rT8JGa8N04YWQuP7xRvwr9AIq+9/z5O/5ubqNiCADshKl8v51zJDFkhDVcYpdUqUpm7T4M53Z2JoQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "bufferstreams": "^3.0.0", + "nan": "^2.14.2", + "node-gyp": "^9.0.0" + }, + "bin": { + "ttf2woff2": "bin/ttf2woff2.js" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/@types/archiver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-7.0.0.tgz", @@ -2236,16 +2400,6 @@ "@types/node": "*" } }, - "node_modules/@types/diff": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-8.0.0.tgz", - "integrity": "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==", - "deprecated": "This is a stub types definition. diff provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "diff": "*" - } - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -3914,17 +4068,6 @@ "node": ">=6" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -3937,16 +4080,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "node_modules/case": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", + "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" } }, "node_modules/chai": { @@ -4007,27 +4148,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", @@ -4131,23 +4251,6 @@ "node": ">=6" } }, - "node_modules/cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -4513,18 +4616,6 @@ "dev": true, "license": "ISC" }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4704,20 +4795,6 @@ "dev": true, "license": "MIT" }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -5140,17 +5217,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5322,62 +5388,6 @@ "node": ">= 0.4" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/esbuild": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", @@ -5585,22 +5595,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -5673,17 +5667,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -5723,74 +5706,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/fantasticon": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fantasticon/-/fantasticon-1.2.3.tgz", - "integrity": "sha512-VoPXI8+wbLq4qooK2LAFRcqKtOCR20+InF/Io/9I1kLp3IT+LwqJgeFijFvp9a3HRZptfCAxNvazoVHn4kihzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "change-case": "^4.1.2", - "cli-color": "^2.0.0", - "commander": "^7.2.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "slugify": "^1.6.0", - "svg2ttf": "^6.0.3", - "svgicons2svgfont": "^10.0.3", - "ttf2eot": "^2.0.0", - "ttf2woff": "^3.0.0", - "ttf2woff2": "^4.0.4" - }, - "bin": { - "fantasticon": "bin/fantasticon" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fantasticon/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/fantasticon/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5880,6 +5795,32 @@ "dev": true, "license": "MIT" }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6105,13 +6046,6 @@ "dev": true, "license": "ISC" }, - "node_modules/geometry-interfaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", - "integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA==", - "dev": true, - "license": "MIT" - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -6470,17 +6404,6 @@ "he": "bin/he" } }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/hosted-git-info": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", @@ -6831,13 +6754,6 @@ "node": ">=8" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -7473,16 +7389,6 @@ "get-func-name": "^2.0.1" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -7495,16 +7401,6 @@ "node": ">=10" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7664,29 +7560,9 @@ "node_modules/mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" }, "node_modules/meow": { "version": "14.0.0", @@ -8187,16 +8063,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "node_modules/neatequal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz", - "integrity": "sha512-sVt5awO4a4w24QmAthdrCPiVRW3naB8FGLdyadin01BH+6BzNPEBwGrpwCczQvPlULS6uXTItTe1PJ5P0kYm7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "varstream": "^0.3.2" - } - }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -8214,24 +8080,6 @@ "dev": true, "license": "MIT" }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, "node_modules/node-abi": { "version": "3.45.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", @@ -8696,17 +8544,6 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8796,28 +8633,6 @@ "parse5": "^6.0.1" } }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9628,18 +9443,6 @@ "node": ">=10" } }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -9879,17 +9682,6 @@ "npm": ">= 3.0.0" } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/socks": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", @@ -10255,75 +10047,6 @@ "node": ">=10.0.0" } }, - "node_modules/svgicons2svgfont": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-10.0.6.tgz", - "integrity": "sha512-fUgQEVg3XwTbOHvlXahHGqCet5Wvfo1bV4DCvbSRvjsOCPCRunYbG4dUJCPegps37BMph3eOrfoobhH5AWuC6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^7.2.0", - "geometry-interfaces": "^1.1.4", - "glob": "^7.1.6", - "neatequal": "^1.0.0", - "readable-stream": "^3.4.0", - "sax": "^1.2.4", - "svg-pathdata": "^6.0.0" - }, - "bin": { - "svgicons2svgfont": "bin/svgicons2svgfont.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/svgicons2svgfont/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/svgicons2svgfont/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/svgicons2svgfont/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/svgo": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", @@ -10712,20 +10435,6 @@ "dev": true, "license": "MIT" }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -11318,30 +11027,6 @@ "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/ttf2eot": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-2.0.0.tgz", - "integrity": "sha512-U56aG2Ylw7psLOmakjemAzmpqVgeadwENg9oaDjaZG5NYX4WB6+7h74bNPcc+0BXsoU5A/XWiHabDXyzFOmsxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.6", - "microbuffer": "^1.0.0" - }, - "bin": { - "ttf2eot": "ttf2eot.js" - } - }, - "node_modules/ttf2eot/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/ttf2woff": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-3.0.0.tgz", @@ -11356,26 +11041,6 @@ "ttf2woff": "ttf2woff.js" } }, - "node_modules/ttf2woff2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-4.0.5.tgz", - "integrity": "sha512-zpoU0NopfjoyVqkFeQ722SyKk/n607mm5OHxuDS/wCCSy82B8H3hHXrezftA2KMbKqfJIjie2lsJHdvPnBGbsw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "bindings": "^1.5.0", - "bufferstreams": "^3.0.0", - "nan": "^2.14.2", - "node-gyp": "^9.0.0" - }, - "bin": { - "ttf2woff2": "bin/ttf2woff2.js" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -11398,13 +11063,6 @@ "node": "*" } }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, - "license": "ISC" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -11587,26 +11245,6 @@ "node": ">= 10.0.0" } }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -11661,49 +11299,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/varstream": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz", - "integrity": "sha512-OpR3Usr9dGZZbDttlTxdviGdxiURI0prX68+DuaN/JfIDbK9ZOmREKM6PgmelsejMnhgjXmEEEgf+E4NbsSqMg==", - "dev": true, - "dependencies": { - "readable-stream": "^1.0.33" - }, - "bin": { - "json2varstream": "cli/json2varstream.js", - "varstream2json": "cli/varstream2json.js" - }, - "engines": { - "node": ">=0.10.*" - } - }, - "node_modules/varstream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/varstream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/varstream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true, - "license": "MIT" - }, "node_modules/version-range": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", @@ -13791,6 +13386,120 @@ } } }, + "@twbs/fantasticon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@twbs/fantasticon/-/fantasticon-3.1.0.tgz", + "integrity": "sha512-dqJvW4k9qXt7ktLoCFkAFLtIhV/r8Psj8jtmwh+emIoXYHL+9Y39m0rLMRRTkX2YPuwBL7Y2vX8DtNtsyoGZLg==", + "dev": true, + "requires": { + "case": "^1.6.3", + "commander": "^11.1.0", + "figures": "^3.2.0", + "glob": "^7.2.3", + "handlebars": "^4.7.8", + "picocolors": "^1.1.1", + "slugify": "^1.6.6", + "svg2ttf": "^6.0.3", + "svgicons2svgfont": "^12.0.0", + "ttf2eot": "^3.1.0", + "ttf2woff": "^3.0.0", + "ttf2woff2": "^5.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "svgicons2svgfont": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-12.0.0.tgz", + "integrity": "sha512-fjyDkhiG0M1TPBtZzD12QV3yDcG2fUgiqHPOCYzf7hHE40Hl3GhnE6P1njsJCCByhwM7MiufyDW3L7IOR5dg9w==", + "dev": true, + "requires": { + "commander": "^9.3.0", + "glob": "^8.0.3", + "sax": "^1.2.4", + "svg-pathdata": "^6.0.3" + }, + "dependencies": { + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "ttf2eot": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-3.1.0.tgz", + "integrity": "sha512-aHTbcYosNHVqb2Qtt9Xfta77ae/5y0VfdwNLUS6sGBeGr22cX2JDMo/i5h3uuOf+FAD3akYOr17+fYd5NK8aXw==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ttf2woff2": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-5.0.0.tgz", + "integrity": "sha512-FplhShJd3rT8JGa8N04YWQuP7xRvwr9AIq+9/z5O/5ubqNiCADshKl8v51zJDFkhDVcYpdUqUpm7T4M53Z2JoQ==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "bufferstreams": "^3.0.0", + "nan": "^2.14.2", + "node-gyp": "^9.0.0" + } + } + } + }, "@types/archiver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-7.0.0.tgz", @@ -13849,15 +13558,6 @@ "@types/node": "*" } }, - "@types/diff": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@types/diff/-/diff-8.0.0.tgz", - "integrity": "sha512-o7jqJM04gfaYrdCecCVMbZhNdG6T1MHg/oQoRFdERLV+4d+V7FijhiEAbFu0Usww84Yijk9yH58U4Jk4HbtzZw==", - "dev": true, - "requires": { - "diff": "*" - } - }, "@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -15073,33 +14773,18 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, + "case": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", + "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", + "dev": true + }, "chai": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", @@ -15140,26 +14825,6 @@ "supports-color": "^7.1.0" } }, - "change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", @@ -15237,19 +14902,6 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, - "cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - } - }, "cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -15501,17 +15153,6 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, - "constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -15640,16 +15281,6 @@ "integrity": "sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ==", "dev": true }, - "d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "requires": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - } - }, "debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -15950,16 +15581,6 @@ "domhandler": "^4.2.0" } }, - "dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -16091,51 +15712,6 @@ "hasown": "^2.0.2" } }, - "es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "requires": { - "d": "^1.0.2", - "ext": "^1.7.0" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "esbuild": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", @@ -16279,18 +15855,6 @@ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, - "esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - } - }, "espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -16338,16 +15902,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -16377,56 +15931,6 @@ "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "dev": true }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "requires": { - "type": "^2.7.2" - } - }, - "fantasticon": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fantasticon/-/fantasticon-1.2.3.tgz", - "integrity": "sha512-VoPXI8+wbLq4qooK2LAFRcqKtOCR20+InF/Io/9I1kLp3IT+LwqJgeFijFvp9a3HRZptfCAxNvazoVHn4kihzQ==", - "dev": true, - "requires": { - "change-case": "^4.1.2", - "cli-color": "^2.0.0", - "commander": "^7.2.0", - "glob": "^7.2.0", - "handlebars": "^4.7.7", - "slugify": "^1.6.0", - "svg2ttf": "^6.0.3", - "svgicons2svgfont": "^10.0.3", - "ttf2eot": "^2.0.0", - "ttf2woff": "^3.0.0", - "ttf2woff2": "^4.0.4" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -16501,6 +16005,23 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "dev": true }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -16670,12 +16191,6 @@ } } }, - "geometry-interfaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", - "integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA==", - "dev": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -16919,16 +16434,6 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "requires": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, "hosted-git-info": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", @@ -17160,12 +16665,6 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -17660,15 +17159,6 @@ "get-func-name": "^2.0.1" } }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -17678,15 +17168,6 @@ "yallist": "^4.0.0" } }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -17807,22 +17288,6 @@ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, - "memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "requires": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, "meow": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", @@ -18176,15 +17641,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "neatequal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz", - "integrity": "sha512-sVt5awO4a4w24QmAthdrCPiVRW3naB8FGLdyadin01BH+6BzNPEBwGrpwCczQvPlULS6uXTItTe1PJ5P0kYm7A==", - "dev": true, - "requires": { - "varstream": "^0.3.2" - } - }, "negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -18197,22 +17653,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, "node-abi": { "version": "3.45.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", @@ -18537,16 +17977,6 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -18622,26 +18052,6 @@ "parse5": "^6.0.1" } }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -19192,17 +18602,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==" }, - "sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, "serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -19355,16 +18754,6 @@ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true }, - "snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "socks": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", @@ -19639,54 +19028,6 @@ } } }, - "svgicons2svgfont": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-10.0.6.tgz", - "integrity": "sha512-fUgQEVg3XwTbOHvlXahHGqCet5Wvfo1bV4DCvbSRvjsOCPCRunYbG4dUJCPegps37BMph3eOrfoobhH5AWuC6A==", - "dev": true, - "requires": { - "commander": "^7.2.0", - "geometry-interfaces": "^1.1.4", - "glob": "^7.1.6", - "neatequal": "^1.0.0", - "readable-stream": "^3.4.0", - "sax": "^1.2.4", - "svg-pathdata": "^6.0.0" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "svgo": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", @@ -19970,16 +19311,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "requires": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - } - }, "tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -20284,27 +19615,6 @@ } } }, - "ttf2eot": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-2.0.0.tgz", - "integrity": "sha512-U56aG2Ylw7psLOmakjemAzmpqVgeadwENg9oaDjaZG5NYX4WB6+7h74bNPcc+0BXsoU5A/XWiHabDXyzFOmsxQ==", - "dev": true, - "requires": { - "argparse": "^1.0.6", - "microbuffer": "^1.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - } - } - }, "ttf2woff": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-3.0.0.tgz", @@ -20315,18 +19625,6 @@ "pako": "^1.0.0" } }, - "ttf2woff2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-4.0.5.tgz", - "integrity": "sha512-zpoU0NopfjoyVqkFeQ722SyKk/n607mm5OHxuDS/wCCSy82B8H3hHXrezftA2KMbKqfJIjie2lsJHdvPnBGbsw==", - "dev": true, - "requires": { - "bindings": "^1.5.0", - "bufferstreams": "^3.0.0", - "nan": "^2.14.2", - "node-gyp": "^9.0.0" - } - }, "tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -20343,12 +19641,6 @@ "safe-buffer": "^5.0.1" } }, - "type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -20477,24 +19769,6 @@ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true }, - "upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -20542,41 +19816,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "varstream": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz", - "integrity": "sha512-OpR3Usr9dGZZbDttlTxdviGdxiURI0prX68+DuaN/JfIDbK9ZOmREKM6PgmelsejMnhgjXmEEEgf+E4NbsSqMg==", - "dev": true, - "requires": { - "readable-stream": "^1.0.33" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - } - } - }, "version-range": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", diff --git a/package.json b/package.json index 82d46d843..bd05ebc80 100644 --- a/package.json +++ b/package.json @@ -2073,12 +2073,12 @@ "devDependencies": { "@actions/core": "^1.11.1", "@trivago/prettier-plugin-sort-imports": "^6.0.0", + "@twbs/fantasticon": "^3.1.0", "@types/archiver": "^7.0.0", "@types/chai": "^4.3.19", "@types/chai-as-promised": "^7.1.8", "@types/chai-subset": "^1.3.6", "@types/decompress": "^4.2.7", - "@types/diff": "^8.0.0", "@types/lcov-parse": "^1.0.2", "@types/lodash.debounce": "^4.0.9", "@types/lodash.throttle": "^4.1.9", @@ -2112,7 +2112,6 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-mocha": "^10.5.0", - "fantasticon": "^1.2.3", "husky": "^9.1.7", "lint-staged": "^16.2.7", "lodash.debounce": "^4.0.8", @@ -2129,11 +2128,11 @@ "sinon-chai": "^3.7.0", "source-map-support": "^0.5.21", "strip-ansi": "^6.0.1", - "vscode-tmgrammar-test": "^0.1.3", "svgo": "^4.0.0", "tsconfig-paths": "^4.2.0", "tsx": "^4.20.6", "typescript": "^5.9.3", + "vscode-tmgrammar-test": "^0.1.3", "winston": "^3.18.3", "winston-transport": "^4.9.0" }, diff --git a/scripts/compile_icons.ts b/scripts/compile_icons.ts index 22a153fb9..aee371900 100644 --- a/scripts/compile_icons.ts +++ b/scripts/compile_icons.ts @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// /* eslint-disable no-console */ -import { FontAssetType, generateFonts } from "fantasticon"; -import { CodepointsMap } from "fantasticon/lib/utils/codepoints"; +import { FontAssetType, generateFonts } from "@twbs/fantasticon"; +import { CodepointsMap } from "@twbs/fantasticon/lib/utils/codepoints"; import { mkdir, readFile, readdir, rm, writeFile } from "fs/promises"; import * as path from "path"; import * as svgo from "svgo"; From a59a38497a29115f2fc93a92bf0bea5070869bf4 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Mon, 8 Dec 2025 14:19:30 -0500 Subject: [PATCH 02/11] Add dynamic local schema detection for SourceKit-LSP (#1979) * Add dynamic local schema detection for SourceKit-LSP Implement support for using local schema files from the Swift toolchain when available, with automatic fallback to remote GitHub schemas for older toolchains. This enables the extension to use the accurate schema for the users toolchain, if its present, while maintaining backward compatibility with older toolchains. * Normalize paths in tests * Update CHANGELOG --- CHANGELOG.md | 4 + src/WorkspaceContext.ts | 5 + .../generateSourcekitConfiguration.ts | 32 ++- src/sourcekit-lsp/SourcekitSchemaRegistry.ts | 91 +++++++ .../generateSourcekitConfiguration.test.ts | 235 ++++++++++++++++++ 5 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 src/sourcekit-lsp/SourcekitSchemaRegistry.ts create mode 100644 test/unit-tests/commands/generateSourcekitConfiguration.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f352081f..7e6469434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## {{releaseVersion}} - {{releaseDate}} +### Added + +- When editing .sourcekit-lsp/config.json use the JSON schema from the toolchain ([#1979](https://github.com/swiftlang/vscode-swift/pull/1979)) + ### Fixed - Fix extension failing to activate when Swiftly was installed via Homebrew ([#1975](https://github.com/swiftlang/vscode-swift/pull/1975)) diff --git a/src/WorkspaceContext.ts b/src/WorkspaceContext.ts index 525a5c1dd..7feef65a6 100644 --- a/src/WorkspaceContext.ts +++ b/src/WorkspaceContext.ts @@ -28,6 +28,7 @@ import { CommentCompletionProviders } from "./editor/CommentCompletion"; import { SwiftLogger } from "./logging/SwiftLogger"; import { SwiftLoggerFactory } from "./logging/SwiftLoggerFactory"; import { LanguageClientToolchainCoordinator } from "./sourcekit-lsp/LanguageClientToolchainCoordinator"; +import { SourcekitSchemaRegistry } from "./sourcekit-lsp/SourcekitSchemaRegistry"; import { DocCDocumentationRequest, ReIndexProjectRequest } from "./sourcekit-lsp/extensions"; import { SwiftPluginTaskProvider } from "./tasks/SwiftPluginTaskProvider"; import { SwiftTaskProvider } from "./tasks/SwiftTaskProvider"; @@ -62,6 +63,7 @@ export class WorkspaceContext implements vscode.Disposable { public documentation: DocumentationManager; public testRunManager: TestRunManager; public projectPanel: ProjectPanelProvider; + private sourcekitSchemaRegistry: SourcekitSchemaRegistry; private lastFocusUri: vscode.Uri | undefined; private initialisationFinished = false; @@ -105,6 +107,7 @@ export class WorkspaceContext implements vscode.Disposable { this.currentDocument = null; this.commentCompletionProvider = new CommentCompletionProviders(); this.projectPanel = new ProjectPanelProvider(this); + this.sourcekitSchemaRegistry = new SourcekitSchemaRegistry(this); const onChangeConfig = vscode.workspace.onDidChangeConfiguration(async event => { // Clear build path cache when build-related configurations change @@ -229,6 +232,7 @@ export class WorkspaceContext implements vscode.Disposable { this.statusItem, this.buildStatus, this.projectPanel, + this.sourcekitSchemaRegistry.register(), ]; this.lastFocusUri = vscode.window.activeTextEditor?.document.uri; @@ -244,6 +248,7 @@ export class WorkspaceContext implements vscode.Disposable { } dispose() { + this.sourcekitSchemaRegistry.dispose(); this.folders.forEach(f => f.dispose()); this.folders.length = 0; this.subscriptions.forEach(item => item.dispose()); diff --git a/src/commands/generateSourcekitConfiguration.ts b/src/commands/generateSourcekitConfiguration.ts index 8ea269d29..1d38aae33 100644 --- a/src/commands/generateSourcekitConfiguration.ts +++ b/src/commands/generateSourcekitConfiguration.ts @@ -18,10 +18,11 @@ import { FolderContext } from "../FolderContext"; import { WorkspaceContext } from "../WorkspaceContext"; import configuration from "../configuration"; import { selectFolder } from "../ui/SelectFolderQuickPick"; +import { fileExists } from "../utilities/filesystem"; import restartLSPServer from "./restartLSPServer"; -export const sourcekitDotFolder: string = ".sourcekit-lsp"; -export const sourcekitConfigFileName: string = "config.json"; +const sourcekitDotFolder: string = ".sourcekit-lsp"; +const sourcekitConfigFileName: string = "config.json"; export async function generateSourcekitConfiguration(ctx: WorkspaceContext): Promise { if (ctx.folders.length === 0) { @@ -128,6 +129,13 @@ async function checkURLExists(url: string): Promise { } export async function determineSchemaURL(folderContext: FolderContext): Promise { + // Check if local schema exists first + if (await hasLocalSchema(folderContext)) { + const localPath = localSchemaPath(folderContext); + return vscode.Uri.file(localPath).toString(); + } + + // Fall back to remote URL for older toolchains const version = folderContext.toolchain.swiftVersion; const versionString = `${version.major}.${version.minor}`; let branch = @@ -138,6 +146,26 @@ export async function determineSchemaURL(folderContext: FolderContext): Promise< return schemaURL(branch); } +/** + * Returns the path to the local sourcekit-lsp schema file in the toolchain. + * This file only exists in newer toolchains (approximately Swift 6.3+). + */ +export function localSchemaPath(folderContext: FolderContext): string { + return join( + folderContext.toolchain.toolchainPath, + "share", + "sourcekit-lsp", + "config.schema.json" + ); +} + +/** + * Checks if the local schema file exists in the toolchain. + */ +export async function hasLocalSchema(folderContext: FolderContext): Promise { + return await fileExists(localSchemaPath(folderContext)); +} + async function getValidatedFolderContext( uri: vscode.Uri, workspaceContext: WorkspaceContext diff --git a/src/sourcekit-lsp/SourcekitSchemaRegistry.ts b/src/sourcekit-lsp/SourcekitSchemaRegistry.ts new file mode 100644 index 000000000..640617989 --- /dev/null +++ b/src/sourcekit-lsp/SourcekitSchemaRegistry.ts @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import * as vscode from "vscode"; + +import { FolderContext } from "../FolderContext"; +import { WorkspaceContext } from "../WorkspaceContext"; +import { + determineSchemaURL, + sourcekitConfigFilePath, +} from "../commands/generateSourcekitConfiguration"; + +/** + * Manages dynamic JSON schema associations for sourcekit-lsp config files. + * This allows VS Code to provide validation and IntelliSense using the + * appropriate schema (local or remote) based on the toolchain. + */ +export class SourcekitSchemaRegistry { + private disposables: vscode.Disposable[] = []; + + constructor(private workspaceContext: WorkspaceContext) {} + + /** + * Registers event handlers to dynamically configure JSON schemas + * for sourcekit-lsp config documents. + */ + register(): vscode.Disposable { + // Handle documents that are already open + vscode.workspace.textDocuments.forEach(doc => { + void this.configureSchemaForDocument(doc); + }); + + // Handle newly opened documents + const onDidOpenDisposable = vscode.workspace.onDidOpenTextDocument(doc => { + void this.configureSchemaForDocument(doc); + }); + + this.disposables.push(onDidOpenDisposable); + + return vscode.Disposable.from(...this.disposables); + } + + /** + * Configures the JSON schema for a document if it's a sourcekit-lsp config file. + */ + private async configureSchemaForDocument(document: vscode.TextDocument): Promise { + if (document.languageId !== "json") { + return; + } + + const folderContext = await this.getFolderContextForDocument(document); + if (!folderContext) { + return; + } + + const schemaUrl = await determineSchemaURL(folderContext); + + // Use VS Code's JSON language configuration API to associate the schema + await vscode.commands.executeCommand("json.setSchema", document.uri.toString(), schemaUrl); + } + + /** + * Gets the FolderContext for a document if it's a sourcekit-lsp config file. + */ + private async getFolderContextForDocument( + document: vscode.TextDocument + ): Promise { + for (const folderContext of this.workspaceContext.folders) { + const configPath = sourcekitConfigFilePath(folderContext); + if (document.uri.fsPath === configPath) { + return folderContext; + } + } + return null; + } + + dispose() { + this.disposables.forEach(d => d.dispose()); + this.disposables = []; + } +} diff --git a/test/unit-tests/commands/generateSourcekitConfiguration.test.ts b/test/unit-tests/commands/generateSourcekitConfiguration.test.ts new file mode 100644 index 000000000..e60ed775a --- /dev/null +++ b/test/unit-tests/commands/generateSourcekitConfiguration.test.ts @@ -0,0 +1,235 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import { expect } from "chai"; +import * as path from "path"; +import * as sinon from "sinon"; +import * as vscode from "vscode"; + +import { FolderContext } from "@src/FolderContext"; +import { + determineSchemaURL, + hasLocalSchema, + localSchemaPath, +} from "@src/commands/generateSourcekitConfiguration"; +import configuration from "@src/configuration"; +import { SwiftToolchain } from "@src/toolchain/toolchain"; +import * as filesystemModule from "@src/utilities/filesystem"; +import { Version } from "@src/utilities/version"; + +import { mockGlobalModule } from "../../MockUtils"; + +suite("generateSourcekitConfiguration - Schema Detection", () => { + let sandbox: sinon.SinonSandbox; + let mockFolderContext: FolderContext; + let fileExistsStub: sinon.SinonStub; + const mockedConfiguration = mockGlobalModule(configuration); + + function createMockFolderContext(toolchainPath: string, version: Version): FolderContext { + const mockToolchain = { + toolchainPath, + swiftVersion: version, + } as SwiftToolchain; + + return { + folder: vscode.Uri.file("/test/workspace"), + swiftVersion: version, + toolchain: mockToolchain, + name: "TestFolder", + } as FolderContext; + } + + setup(() => { + sandbox = sinon.createSandbox(); + fileExistsStub = sandbox.stub(filesystemModule, "fileExists"); + mockedConfiguration.lspConfigurationBranch = ""; + }); + + teardown(() => { + sandbox.restore(); + }); + + suite("localSchemaPath()", () => { + test("returns correct path for toolchain", () => { + mockFolderContext = createMockFolderContext("/path/to/toolchain", new Version(6, 3, 0)); + + const result = localSchemaPath(mockFolderContext); + + expect(result).to.equal( + path.normalize("/path/to/toolchain/share/sourcekit-lsp/config.schema.json") + ); + }); + + test("returns correct path for toolchain with trailing slash", () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain/"), + new Version(6, 3, 0) + ); + + const result = localSchemaPath(mockFolderContext); + + expect(result).to.equal( + path.normalize("/path/to/toolchain/share/sourcekit-lsp/config.schema.json") + ); + }); + + test("returns correct path for nested toolchain directory", () => { + mockFolderContext = createMockFolderContext( + path.normalize("/usr/local/swift-6.3.0"), + new Version(6, 3, 0) + ); + + const result = localSchemaPath(mockFolderContext); + + expect(result).to.equal( + path.normalize("/usr/local/swift-6.3.0/share/sourcekit-lsp/config.schema.json") + ); + }); + }); + + suite("hasLocalSchema()", () => { + test("returns true when schema file exists", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(6, 3, 0) + ); + fileExistsStub.resolves(true); + + const result = await hasLocalSchema(mockFolderContext); + + expect(result).to.be.true; + expect(fileExistsStub).to.have.been.calledWith( + path.normalize("/path/to/toolchain/share/sourcekit-lsp/config.schema.json") + ); + }); + + test("returns false when schema file doesn't exist", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(6, 1, 0) + ); + fileExistsStub.resolves(false); + + const result = await hasLocalSchema(mockFolderContext); + + expect(result).to.be.false; + }); + + test("returns false on filesystem errors", async () => { + mockFolderContext = createMockFolderContext("/path/to/toolchain", new Version(6, 3, 0)); + fileExistsStub.resolves(false); + + const result = await hasLocalSchema(mockFolderContext); + + expect(result).to.be.false; + }); + }); + + suite("determineSchemaURL()", () => { + test("returns file:// URL when local schema exists", async () => { + mockFolderContext = createMockFolderContext("/path/to/toolchain", new Version(6, 3, 0)); + fileExistsStub.resolves(true); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.match(/^file:\/\//); + expect(result).to.include("config.schema.json"); + expect(result).to.include("sourcekit-lsp"); + }); + + test("returns https:// URL when local schema doesn't exist", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(6, 1, 0) + ); + fileExistsStub.resolves(false); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.match(/^https:\/\//); + expect(result).to.include("githubusercontent.com"); + expect(result).to.include("sourcekit-lsp"); + }); + + test("local schema path includes share/sourcekit-lsp/config.schema.json", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/usr/local/swift-6.3"), + new Version(6, 3, 0) + ); + fileExistsStub.resolves(true); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.include("/usr/local/swift-6.3"); + expect(result).to.include("share/sourcekit-lsp/config.schema.json"); + }); + + test("remote URL uses correct branch for release version", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(6, 2, 0) + ); + fileExistsStub.resolves(false); + + const fetchStub = sandbox.stub(globalThis, "fetch"); + fetchStub.resolves({ + ok: true, + status: 200, + } as Response); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.include("release/6.2"); + }); + + test("remote URL uses main for dev version", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(6, 3, 0, true) + ); + fileExistsStub.resolves(false); + + const fetchStub = sandbox.stub(globalThis, "fetch"); + fetchStub.resolves({ + ok: true, + status: 200, + } as Response); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.include("main"); + }); + + test("falls back to main when branch doesn't exist", async () => { + mockFolderContext = createMockFolderContext( + path.normalize("/path/to/toolchain"), + new Version(5, 9, 0) + ); + fileExistsStub.resolves(false); + + const fetchStub = sandbox.stub(globalThis, "fetch"); + fetchStub.onFirstCall().resolves({ + ok: false, + status: 404, + } as Response); + fetchStub.onSecondCall().resolves({ + ok: true, + status: 200, + } as Response); + + const result = await determineSchemaURL(mockFolderContext); + + expect(result).to.include("main"); + }); + }); +}); From 8eefc3323f99377b1383e944b0b0e221f0a63d1b Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Mon, 8 Dec 2025 15:01:26 -0500 Subject: [PATCH 03/11] Re-enable Windows CI for Swift 6.2.1 (#1963) --- .github/workflows/nightly.yml | 2 -- .github/workflows/pull_request.yml | 2 +- .github/workflows/scripts/windows/setup.ps1 | 7 +------ test/integration-tests/debugger/lldb.test.ts | 11 ----------- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5636cb468..a434ef834 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -114,5 +114,3 @@ jobs: windows_pre_build_command: . .github\workflows\scripts\windows\setup.ps1 windows_build_command: Invoke-Program scripts\test_windows.ps1 enable_windows_docker: false - # TODO re-enable when 6.2.1 toolchain working - enable_windows_checks: false diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index dc40a62fc..00b679852 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -64,7 +64,7 @@ jobs: linux_pre_build_command: . .github/workflows/scripts/setup-linux.sh linux_build_command: ./scripts/test.sh # Windows - windows_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly\"},{\"swift_version\": \"6.2\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly\"}]' }}" + windows_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly\"}]' }}" windows_env_vars: | CI=1 FAST_TEST_RUN=${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '0' || '1'}} diff --git a/.github/workflows/scripts/windows/setup.ps1 b/.github/workflows/scripts/windows/setup.ps1 index 3404632ee..ec6ffe5a9 100644 --- a/.github/workflows/scripts/windows/setup.ps1 +++ b/.github/workflows/scripts/windows/setup.ps1 @@ -2,7 +2,7 @@ . .github\workflows\scripts\windows\install-nodejs.ps1 # Download the VSIX archived upstream -npm ci +npm ci --ignore-scripts $Process = Start-Process npx "tsx scripts/download_vsix.ts" -Wait -PassThru -NoNewWindow if ($Process.ExitCode -eq 0) { Write-Host 'SUCCESS' @@ -10,8 +10,3 @@ if ($Process.ExitCode -eq 0) { Write-Host ('FAILED ({0})' -f $Process.ExitCode) exit 1 } - -Get-Content $env:GITHUB_ENV | foreach { - $name, $value = $_.split('=') - Set-Content env:\$name $value -} diff --git a/test/integration-tests/debugger/lldb.test.ts b/test/integration-tests/debugger/lldb.test.ts index 7503333a3..bc993fb62 100644 --- a/test/integration-tests/debugger/lldb.test.ts +++ b/test/integration-tests/debugger/lldb.test.ts @@ -15,7 +15,6 @@ import { expect } from "chai"; import { WorkspaceContext } from "@src/WorkspaceContext"; import { getLLDBLibPath } from "@src/debugger/lldb"; -import { Version } from "@src/utilities/version"; import { activateExtensionForTest } from "../utilities/testutilities"; @@ -24,16 +23,6 @@ suite("lldb contract test suite", () => { activateExtensionForTest({ async setup(ctx) { - // This test is failing due to toolchain issues starting with Swift 6.2.1 - // Will re-enable once that is resolved. - // - // https://github.com/swiftlang/vscode-swift/issues/1947 - if ( - process.platform === "win32" && - ctx.globalToolchainSwiftVersion.isGreaterThanOrEqual(new Version(6, 2, 1)) - ) { - this.skip(); - } workspaceContext = ctx; }, requiresDebugger: true, From dff50962a986c60e5f038b4bd0cf65e00dc3b915 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Mon, 8 Dec 2025 15:37:01 -0500 Subject: [PATCH 04/11] bump changelog for 2.14.2 (#1991) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e6469434..bab867d4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ - When editing .sourcekit-lsp/config.json use the JSON schema from the toolchain ([#1979](https://github.com/swiftlang/vscode-swift/pull/1979)) +## 2.14.2 - 2025-12-07 + ### Fixed - Fix extension failing to activate when Swiftly was installed via Homebrew ([#1975](https://github.com/swiftlang/vscode-swift/pull/1975)) From 13802a4f11e029f466d1c58e0f2845a5173e75f8 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Tue, 9 Dec 2025 09:17:32 -0500 Subject: [PATCH 05/11] Use `vscode.Disposable.from` instead of `compositeDisposable` (#1980) Clean up the codebase so that it uses the built in `vscode.Disposable.from` to dispose multiple disposables at the same time. This replaces our own `compositeDisposable` method. Docs here: https://code.visualstudio.com/api/references/vscode-api#Disposable --- src/TestExplorer/TestExplorer.ts | 6 +++--- src/debugger/debugAdapterFactory.ts | 7 +------ src/debugger/logTracker.ts | 6 +----- src/utilities/utilities.ts | 13 ------------- 4 files changed, 5 insertions(+), 27 deletions(-) diff --git a/src/TestExplorer/TestExplorer.ts b/src/TestExplorer/TestExplorer.ts index 271a18005..94d70dff3 100644 --- a/src/TestExplorer/TestExplorer.ts +++ b/src/TestExplorer/TestExplorer.ts @@ -21,7 +21,7 @@ import { SwiftLogger } from "../logging/SwiftLogger"; import { buildOptions, getBuildAllTask } from "../tasks/SwiftTaskProvider"; import { TaskManager } from "../tasks/TaskManager"; import { SwiftExecOperation, TaskOperation } from "../tasks/TaskQueue"; -import { compositeDisposable, getErrorDescription } from "../utilities/utilities"; +import { getErrorDescription } from "../utilities/utilities"; import { Version } from "../utilities/version"; import { parseTestsFromDocumentSymbols } from "./DocumentSymbolTestDiscovery"; import { LSPTestDiscovery } from "./LSPTestDiscovery"; @@ -208,7 +208,7 @@ export class TestExplorer { } }); - return compositeDisposable(endProcessDisposable, didChangeSwiftFileDisposable); + return vscode.Disposable.from(endProcessDisposable, didChangeSwiftFileDisposable); } /** @@ -229,7 +229,7 @@ export class TestExplorer { break; } }); - return compositeDisposable(tokenSource, disposable); + return vscode.Disposable.from(tokenSource, disposable); } /** diff --git a/src/debugger/debugAdapterFactory.ts b/src/debugger/debugAdapterFactory.ts index eca0a3f83..b14182533 100644 --- a/src/debugger/debugAdapterFactory.ts +++ b/src/debugger/debugAdapterFactory.ts @@ -55,12 +55,7 @@ export function registerDebugger(workspaceContext: WorkspaceContext): vscode.Dis register(); } - return { - dispose: () => { - configurationEvent.dispose(); - subscriptions.map(sub => sub.dispose()); - }, - }; + return vscode.Disposable.from(configurationEvent, ...subscriptions); } /** diff --git a/src/debugger/logTracker.ts b/src/debugger/logTracker.ts index 5b34b9c27..18232b891 100644 --- a/src/debugger/logTracker.ts +++ b/src/debugger/logTracker.ts @@ -54,11 +54,7 @@ export function registerLoggingDebugAdapterTracker(): vscode.Disposable { ]; // Return a disposable that cleans everything up. - return { - dispose() { - subscriptions.forEach(sub => sub.dispose()); - }, - }; + return vscode.Disposable.from(...subscriptions); } /** diff --git a/src/utilities/utilities.ts b/src/utilities/utilities.ts index 44f6e7219..e8dadded2 100644 --- a/src/utilities/utilities.ts +++ b/src/utilities/utilities.ts @@ -457,16 +457,3 @@ export function destructuredPromise(): { return { promise: p, resolve: resolve!, reject: reject! }; } /* eslint-enable @typescript-eslint/no-explicit-any */ - -/** - * Creates a composite disposable from multiple disposables. - * @param disposables The disposables to include. - * @returns A composite disposable that disposes all included disposables. - */ -export function compositeDisposable(...disposables: vscode.Disposable[]): vscode.Disposable { - return { - dispose: () => { - disposables.forEach(d => d.dispose()); - }, - }; -} From 20eb6737bfa083a924762f8ea4eedcc6493a7b3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 09:47:05 -0500 Subject: [PATCH 06/11] Bump the all-dependencies group with 2 updates (#1990) Bumps the all-dependencies group with 2 updates: [prettier](https://github.com/prettier/prettier) and [tsx](https://github.com/privatenumber/tsx). Updates `prettier` from 3.6.2 to 3.7.3 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.6.2...3.7.3) Updates `tsx` from 4.20.6 to 4.21.0 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.20.6...v4.21.0) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.7.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all-dependencies - dependency-name: tsx dependency-version: 4.21.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 707 ++-------------------------------------------- package.json | 4 +- 2 files changed, 18 insertions(+), 693 deletions(-) diff --git a/package-lock.json b/package-lock.json index cedb226c6..9f0373ce1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "mocha": "^11.7.5", "mock-fs": "^5.5.0", "octokit": "^3.2.2", - "prettier": "^3.6.2", + "prettier": "^3.7.3", "replace-in-file": "^8.3.0", "semver": "^7.7.3", "simple-git": "^3.30.0", @@ -78,7 +78,7 @@ "strip-ansi": "^6.0.1", "svgo": "^4.0.0", "tsconfig-paths": "^4.2.0", - "tsx": "^4.20.6", + "tsx": "^4.21.0", "typescript": "^5.9.3", "vscode-tmgrammar-test": "^0.1.3", "winston": "^3.18.3", @@ -8854,9 +8854,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.3.tgz", + "integrity": "sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -10552,12 +10552,12 @@ "dev": true }, "node_modules/tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "dependencies": { - "esbuild": "~0.25.0", + "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -10570,463 +10570,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, "node_modules/ttf2woff": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-3.0.0.tgz", @@ -18198,9 +17741,9 @@ "dev": true }, "prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.3.tgz", + "integrity": "sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==", "dev": true }, "process": { @@ -19387,232 +18930,14 @@ "dev": true }, "tsx": { - "version": "4.20.6", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", - "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "requires": { - "esbuild": "~0.25.0", + "esbuild": "~0.27.0", "fsevents": "~2.3.3", "get-tsconfig": "^4.7.5" - }, - "dependencies": { - "@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "dev": true, - "optional": true - }, - "@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "dev": true, - "optional": true - }, - "@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "dev": true, - "optional": true - }, - "@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "dev": true, - "optional": true - }, - "@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "dev": true, - "optional": true - }, - "@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "dev": true, - "optional": true - }, - "@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "dev": true, - "optional": true - }, - "@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "dev": true, - "optional": true - }, - "@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "dev": true, - "optional": true - }, - "@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "dev": true, - "optional": true - }, - "@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "dev": true, - "optional": true - }, - "@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "dev": true, - "optional": true - }, - "@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "dev": true, - "optional": true - }, - "@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "dev": true, - "optional": true - }, - "@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "dev": true, - "optional": true - }, - "@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "dev": true, - "optional": true - }, - "esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "requires": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - } } }, "ttf2woff": { diff --git a/package.json b/package.json index bd05ebc80..e178a9e16 100644 --- a/package.json +++ b/package.json @@ -2120,7 +2120,7 @@ "mocha": "^11.7.5", "mock-fs": "^5.5.0", "octokit": "^3.2.2", - "prettier": "^3.6.2", + "prettier": "^3.7.3", "replace-in-file": "^8.3.0", "semver": "^7.7.3", "simple-git": "^3.30.0", @@ -2130,7 +2130,7 @@ "strip-ansi": "^6.0.1", "svgo": "^4.0.0", "tsconfig-paths": "^4.2.0", - "tsx": "^4.20.6", + "tsx": "^4.21.0", "typescript": "^5.9.3", "vscode-tmgrammar-test": "^0.1.3", "winston": "^3.18.3", From 1b136a0f7738e3324a8e797777657d5945bca55f Mon Sep 17 00:00:00 2001 From: award999 Date: Tue, 9 Dec 2025 09:51:34 -0500 Subject: [PATCH 07/11] Add Playgrounds to the project panel (#1967) * Add Playgrounds to the project panel - Support `workspace/playgrounds` request, persisting the playgrounds in memory and listening for new "swift.play" CodeLens to keep up to date - Display the list of playgrounds in the project panel - Clicking on playground in the project panel will open its location - Provide a play option Issue: #1782 * Better error handling and only fetch if workspace/playground is experimental capability * Context command to run playground * Add test * Fix failing unit test * Fix review comments --- package.json | 5 + src/FolderContext.ts | 49 +++++- src/WorkspaceContext.ts | 3 + src/commands.ts | 8 +- src/extension.ts | 2 + src/playgrounds/LSPPlaygroundsDiscovery.ts | 60 +++++++ src/playgrounds/PlaygroundProvider.ts | 153 ++++++++++++++++++ .../LanguageClientConfiguration.ts | 6 +- src/sourcekit-lsp/LanguageClientManager.ts | 24 ++- .../LanguageClientToolchainCoordinator.ts | 5 + .../extensions/WorkspacePlaygroundsRequest.ts | 57 +++++++ src/sourcekit-lsp/extensions/index.ts | 1 + src/ui/ProjectPanelProvider.ts | 117 +++++++++++++- .../commands/runPlayground.test.ts | 20 ++- .../LanguageClientManager.test.ts | 7 +- 15 files changed, 504 insertions(+), 13 deletions(-) create mode 100644 src/playgrounds/LSPPlaygroundsDiscovery.ts create mode 100644 src/playgrounds/PlaygroundProvider.ts create mode 100644 src/sourcekit-lsp/extensions/WorkspacePlaygroundsRequest.ts diff --git a/package.json b/package.json index e178a9e16..b125db4d2 100644 --- a/package.json +++ b/package.json @@ -1527,6 +1527,11 @@ "command": "swift.coverAllTests", "when": "view == projectPanel && viewItem == 'test_runnable'", "group": "inline@3" + }, + { + "command": "swift.play", + "when": "view == projectPanel && viewItem == 'playground'", + "group": "inline@1" } ] }, diff --git a/src/FolderContext.ts b/src/FolderContext.ts index 391ed4b10..27607a1bd 100644 --- a/src/FolderContext.ts +++ b/src/FolderContext.ts @@ -24,6 +24,7 @@ import { TestRunProxy } from "./TestExplorer/TestRunner"; import { FolderOperation, WorkspaceContext } from "./WorkspaceContext"; import configuration from "./configuration"; import { SwiftLogger } from "./logging/SwiftLogger"; +import { PlaygroundProvider } from "./playgrounds/PlaygroundProvider"; import { TaskQueue } from "./tasks/TaskQueue"; import { SwiftToolchain } from "./toolchain/toolchain"; import { showToolchainError } from "./ui/ToolchainSelection"; @@ -35,6 +36,7 @@ export class FolderContext implements vscode.Disposable { public taskQueue: TaskQueue; public testExplorer?: TestExplorer; public resolvedTestExplorer: Promise; + public playgroundProvider?: PlaygroundProvider; private testExplorerResolver?: (testExplorer: TestExplorer) => void; private packageWatcher: PackageWatcher; private testRunManager: TestRunManager; @@ -247,7 +249,7 @@ export class FolderContext implements vscode.Disposable { return this.testExplorer; } - /** Create Test explorer for this folder */ + /** Remove Test explorer from this folder */ removeTestExplorer() { this.testExplorer?.dispose(); this.testExplorer = undefined; @@ -260,11 +262,35 @@ export class FolderContext implements vscode.Disposable { } } - /** Return if package folder has a test explorer */ + /** Return `true` if package folder has a test explorer */ hasTestExplorer() { return this.testExplorer !== undefined; } + /** Create Playground provider for this folder */ + addPlaygroundProvider() { + if (!this.playgroundProvider) { + this.playgroundProvider = new PlaygroundProvider(this); + } + return this.playgroundProvider; + } + + /** Refresh the tests in the test explorer for this folder */ + async refreshPlaygroundProvider() { + await this.playgroundProvider?.fetch(); + } + + /** Remove playground provider from this folder */ + removePlaygroundProvider() { + this.playgroundProvider?.dispose(); + this.playgroundProvider = undefined; + } + + /** Return `true` if package folder has a playground provider */ + hasPlaygroundProvider() { + return this.playgroundProvider !== undefined; + } + static uriName(uri: vscode.Uri): string { return path.basename(uri.fsPath); } @@ -335,6 +361,25 @@ export class FolderContext implements vscode.Disposable { void this.testExplorer.getDocumentTests(this, uri, symbols); } } + + /** + * Called whenever we have new document CodeLens + */ + onDocumentCodeLens( + document: vscode.TextDocument, + codeLens: vscode.CodeLens[] | null | undefined + ) { + const uri = document?.uri; + if ( + this.playgroundProvider && + codeLens && + uri && + uri.scheme === "file" && + isPathInsidePath(uri.fsPath, this.folder.fsPath) + ) { + void this.playgroundProvider.onDocumentCodeLens(document, codeLens); + } + } } export interface EditedPackage { diff --git a/src/WorkspaceContext.ts b/src/WorkspaceContext.ts index 7feef65a6..c679b6c00 100644 --- a/src/WorkspaceContext.ts +++ b/src/WorkspaceContext.ts @@ -97,6 +97,9 @@ export class WorkspaceContext implements vscode.Disposable { onDocumentSymbols: (folder, document, symbols) => { folder.onDocumentSymbols(document, symbols); }, + onDocumentCodeLens: (folder, document, codelens) => { + folder.onDocumentCodeLens(document, codelens); + }, }); this.tasks = new TaskManager(this); this.diagnostics = new DiagnosticsManager(this); diff --git a/src/commands.ts b/src/commands.ts index 293f152a4..707aaa2b0 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -51,7 +51,7 @@ import { switchPlatform } from "./commands/switchPlatform"; import { extractTestItemsAndCount, runTestMultipleTimes } from "./commands/testMultipleTimes"; import { SwiftLogger } from "./logging/SwiftLogger"; import { SwiftToolchain } from "./toolchain/toolchain"; -import { PackageNode } from "./ui/ProjectPanelProvider"; +import { PackageNode, PlaygroundNode } from "./ui/ProjectPanelProvider"; import { showToolchainSelectionQuickPick } from "./ui/ToolchainSelection"; /** @@ -153,7 +153,11 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] { if (!folder || !target) { return false; } - return await runPlayground(folder, ctx.tasks, target); + return await runPlayground( + folder, + ctx.tasks, + PlaygroundNode.isPlaygroundNode(target) ? target.playground : target + ); }), vscode.commands.registerCommand(Commands.CLEAN_BUILD, async () => await cleanBuild(ctx)), vscode.commands.registerCommand( diff --git a/src/extension.ts b/src/extension.ts index cd2727ca4..ab9760e81 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -28,6 +28,7 @@ import { registerDebugger } from "./debugger/debugAdapterFactory"; import * as debug from "./debugger/launch"; import { SwiftLogger } from "./logging/SwiftLogger"; import { SwiftLoggerFactory } from "./logging/SwiftLoggerFactory"; +import { PlaygroundProvider } from "./playgrounds/PlaygroundProvider"; import { SwiftEnvironmentVariablesManager, SwiftTerminalProfileProvider } from "./terminal"; import { SelectedXcodeWatcher } from "./toolchain/SelectedXcodeWatcher"; import { checkForSwiftlyInstallation } from "./toolchain/swiftly"; @@ -159,6 +160,7 @@ export async function activate(context: vscode.ExtensionContext): Promise { // observer that will resolve package and build launch configurations context.subscriptions.push(workspaceContext.onDidChangeFolders(handleFolderEvent(logger))); context.subscriptions.push(TestExplorer.observeFolders(workspaceContext)); + context.subscriptions.push(PlaygroundProvider.observeFolders(workspaceContext)); context.subscriptions.push(registerSourceKitSchemaWatcher(workspaceContext)); const subscriptionsElapsed = Date.now() - subscriptionsStartTime; diff --git a/src/playgrounds/LSPPlaygroundsDiscovery.ts b/src/playgrounds/LSPPlaygroundsDiscovery.ts new file mode 100644 index 000000000..eb087f820 --- /dev/null +++ b/src/playgrounds/LSPPlaygroundsDiscovery.ts @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import { FolderContext } from "../FolderContext"; +import { checkExperimentalCapability } from "../sourcekit-lsp/LanguageClientManager"; +import { LanguageClientManager } from "../sourcekit-lsp/LanguageClientManager"; +import { Playground, WorkspacePlaygroundsRequest } from "../sourcekit-lsp/extensions"; +import { Version } from "../utilities/version"; + +export { Playground }; + +/** + * Uses document symbol request to keep a running copy of all the test methods + * in a file. When a file is saved it checks to see if any new methods have been + * added, or if any methods have been removed and edits the test items based on + * these results. + */ +export class LSPPlaygroundsDiscovery { + private languageClient: LanguageClientManager; + private toolchainVersion: Version; + + constructor(folderContext: FolderContext) { + this.languageClient = folderContext.languageClientManager; + this.toolchainVersion = folderContext.toolchain.swiftVersion; + } + + /** + * Return list of workspace playgrounds + */ + async getWorkspacePlaygrounds(): Promise { + return await this.languageClient.useLanguageClient(async (client, token) => { + // Only use the lsp for this request if it supports the + // workspace/playgrounds method. + if (checkExperimentalCapability(client, WorkspacePlaygroundsRequest.method, 1)) { + return await client.sendRequest(WorkspacePlaygroundsRequest.type, token); + } else { + throw new Error(`${WorkspacePlaygroundsRequest.method} requests not supported`); + } + }); + } + + async supportsPlaygrounds(): Promise { + if (this.toolchainVersion.isLessThan(new Version(6, 3, 0))) { + return false; + } + return await this.languageClient.useLanguageClient(async client => { + return checkExperimentalCapability(client, WorkspacePlaygroundsRequest.method, 1); + }); + } +} diff --git a/src/playgrounds/PlaygroundProvider.ts b/src/playgrounds/PlaygroundProvider.ts new file mode 100644 index 000000000..554f7cfaf --- /dev/null +++ b/src/playgrounds/PlaygroundProvider.ts @@ -0,0 +1,153 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +import * as vscode from "vscode"; + +import { FolderContext } from "../FolderContext"; +import { FolderOperation, WorkspaceContext } from "../WorkspaceContext"; +import { SwiftLogger } from "../logging/SwiftLogger"; +import { LSPPlaygroundsDiscovery, Playground } from "./LSPPlaygroundsDiscovery"; + +export { Playground }; + +export interface PlaygroundChangeEvent { + uri: string; + playgrounds: Playground[]; +} + +/** + * Uses document symbol request to keep a running copy of all the test methods + * in a file. When a file is saved it checks to see if any new methods have been + * added, or if any methods have been removed and edits the test items based on + * these results. + */ +export class PlaygroundProvider implements vscode.Disposable { + private hasFetched: boolean = false; + private fetchPromise: Promise | undefined; + private documentPlaygrounds: Map = new Map(); + private didChangePlaygroundsEmitter: vscode.EventEmitter = + new vscode.EventEmitter(); + + constructor(private folderContext: FolderContext) {} + + private get lspPlaygroundDiscovery(): LSPPlaygroundsDiscovery { + return new LSPPlaygroundsDiscovery(this.folderContext); + } + + private get logger(): SwiftLogger { + return this.folderContext.workspaceContext.logger; + } + + /** + * Create folder observer that creates a PlaygroundProvider when a folder is added and + * discovers available playgrounds when the folder is in focus + * @param workspaceContext Workspace context for extension + * @returns Observer disposable + */ + public static observeFolders(workspaceContext: WorkspaceContext): vscode.Disposable { + return workspaceContext.onDidChangeFolders(({ folder, operation }) => { + switch (operation) { + case FolderOperation.add: + case FolderOperation.packageUpdated: + if (folder) { + void this.setupPlaygroundProviderForFolder(folder); + } + break; + } + }); + } + + private static async setupPlaygroundProviderForFolder(folder: FolderContext) { + if (!folder.hasPlaygroundProvider()) { + folder.addPlaygroundProvider(); + } + await folder.refreshPlaygroundProvider(); + } + + /** + * Fetch the full list of playgrounds + */ + async getWorkspacePlaygrounds(): Promise { + if (this.fetchPromise) { + return await this.fetchPromise; + } else if (!this.hasFetched) { + await this.fetch(); + } + return Array.from(this.documentPlaygrounds.values()).flatMap(v => v); + } + + onDocumentCodeLens( + document: vscode.TextDocument, + codeLens: vscode.CodeLens[] | null | undefined + ) { + const playgrounds: Playground[] = ( + codeLens?.map(c => (c.command?.arguments ?? [])[0]) ?? [] + ) + .filter(p => !!p) + // Convert from LSP TextDocumentPlayground to Playground + .map(p => ({ + ...p, + range: undefined, + location: new vscode.Location(document.uri, p.range), + })); + const uri = document.uri.toString(); + if (playgrounds.length > 0) { + this.documentPlaygrounds.set(uri, playgrounds); + this.didChangePlaygroundsEmitter.fire({ uri, playgrounds }); + } else { + if (this.documentPlaygrounds.delete(uri)) { + this.didChangePlaygroundsEmitter.fire({ uri, playgrounds: [] }); + } + } + } + + onDidChangePlaygrounds: vscode.Event = + this.didChangePlaygroundsEmitter.event; + + async fetch() { + this.hasFetched = true; + if (this.fetchPromise) { + await this.fetchPromise; + return; + } + if (!(await this.lspPlaygroundDiscovery.supportsPlaygrounds())) { + this.logger.debug( + `Fetching playgrounds not supported by the language server`, + this.folderContext.name + ); + return; + } + this.fetchPromise = this.lspPlaygroundDiscovery.getWorkspacePlaygrounds(); + try { + const playgrounds = await this.fetchPromise; + this.documentPlaygrounds.clear(); + for (const playground of playgrounds) { + const uri = playground.location.uri; + this.documentPlaygrounds.set( + uri, + (this.documentPlaygrounds.get(uri) ?? []).concat(playground) + ); + } + } catch (error) { + this.logger.error( + `Failed to fetch workspace playgrounds: ${error}`, + this.folderContext.name + ); + } + this.fetchPromise = undefined; + } + + dispose() { + this.documentPlaygrounds.clear(); + } +} diff --git a/src/sourcekit-lsp/LanguageClientConfiguration.ts b/src/sourcekit-lsp/LanguageClientConfiguration.ts index fcc570140..8a08a9eff 100644 --- a/src/sourcekit-lsp/LanguageClientConfiguration.ts +++ b/src/sourcekit-lsp/LanguageClientConfiguration.ts @@ -215,7 +215,8 @@ export function lspClientOptions( documentSymbolWatcher?: ( document: vscode.TextDocument, symbols: vscode.DocumentSymbol[] - ) => void + ) => void, + documentCodeLensWatcher?: (document: vscode.TextDocument, codeLens: vscode.CodeLens[]) => void ): LanguageClientOptions { return { documentSelector: LanguagerClientDocumentSelectors.sourcekitLSPDocumentTypes(), @@ -247,6 +248,9 @@ export function lspClientOptions( }, provideCodeLenses: async (document, token, next) => { const result = await next(document, token); + if (documentCodeLensWatcher && result) { + documentCodeLensWatcher(document, result); + } return result?.map(codelens => { switch (codelens.command?.command) { case "swift.run": diff --git a/src/sourcekit-lsp/LanguageClientManager.ts b/src/sourcekit-lsp/LanguageClientManager.ts index 13ec7d139..8e7f22b21 100644 --- a/src/sourcekit-lsp/LanguageClientManager.ts +++ b/src/sourcekit-lsp/LanguageClientManager.ts @@ -43,15 +43,21 @@ import { activateGetReferenceDocument } from "./getReferenceDocument"; import { activateLegacyInlayHints } from "./inlayHints"; import { activatePeekDocuments } from "./peekDocuments"; +/** + * Options for the LanguageClientManager + */ interface LanguageClientManageOptions { - /** - * Options for the LanguageClientManager - */ onDocumentSymbols?: ( folder: FolderContext, document: vscode.TextDocument, symbols: vscode.DocumentSymbol[] | null | undefined ) => void; + + onDocumentCodeLens?: ( + folder: FolderContext, + document: vscode.TextDocument, + codeLens: vscode.CodeLens[] | null | undefined + ) => void; } /** @@ -472,6 +478,18 @@ export class LanguageClientManager implements vscode.Disposable { return; } this.options.onDocumentSymbols?.(documentFolderContext, document, symbols); + }, + (document, codeLens) => { + const documentFolderContext = [this.folderContext, ...this.addedFolders].find( + folderContext => document.uri.fsPath.startsWith(folderContext.folder.fsPath) + ); + if (!documentFolderContext) { + this.languageClientOutputChannel?.warn( + "Unable to find folder for document: " + document.uri.fsPath + ); + return; + } + this.options.onDocumentCodeLens?.(documentFolderContext, document, codeLens); } ); diff --git a/src/sourcekit-lsp/LanguageClientToolchainCoordinator.ts b/src/sourcekit-lsp/LanguageClientToolchainCoordinator.ts index 44800f876..a9d2fc458 100644 --- a/src/sourcekit-lsp/LanguageClientToolchainCoordinator.ts +++ b/src/sourcekit-lsp/LanguageClientToolchainCoordinator.ts @@ -39,6 +39,11 @@ export class LanguageClientToolchainCoordinator implements vscode.Disposable { document: vscode.TextDocument, symbols: vscode.DocumentSymbol[] | null | undefined ) => void; + onDocumentCodeLens?: ( + folder: FolderContext, + document: vscode.TextDocument, + symbols: vscode.CodeLens[] | null | undefined + ) => void; } = {}, languageClientFactory: LanguageClientFactory = new LanguageClientFactory() // used for testing only ) { diff --git a/src/sourcekit-lsp/extensions/WorkspacePlaygroundsRequest.ts b/src/sourcekit-lsp/extensions/WorkspacePlaygroundsRequest.ts new file mode 100644 index 000000000..e663e6fda --- /dev/null +++ b/src/sourcekit-lsp/extensions/WorkspacePlaygroundsRequest.ts @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// +// We use namespaces to store request information just like vscode-languageclient +/* eslint-disable @typescript-eslint/no-namespace */ +import { Location, MessageDirection, RequestType0 } from "vscode-languageclient"; + +/** Represents a single test returned from a {@link WorkspacePlaygroundsRequest}. */ +export interface Playground { + /** + * Unique identifier for the `Playground` with the format `/::[column]` where `target` + * corresponds to the Swift package's target where the playground is defined, `filename` is the basename of the file + * (not entire relative path), and `column` is optional only required if multiple playgrounds are defined on the same + * line. Client can run the playground by executing `swift play `. + * + * This property is always present whether the `Playground` has a `label` or not. + * + * Follows the format output by `swift play --list`. + */ + id: string; + + /** + * The label that can be used as a display name for the playground. This optional property is only available + * for named playgrounds. For example: `#Playground("hello") { print("Hello!) }` would have a `label` of `"hello"`. + */ + label?: string; + + /** + * The location of where the #Playground macro was used in the source code. + */ + location: Location; +} + +/** + * A request that returns symbols for all the playgrounds within the current workspace. + * + * ### LSP Extension + * + * This request is an extension to LSP supported by SourceKit-LSP. + * + * It requires the experimental client capability `"workspace/playgrounds"` to use. + */ +export namespace WorkspacePlaygroundsRequest { + export const method = "workspace/playgrounds" as const; + export const messageDirection: MessageDirection = MessageDirection.clientToServer; + export const type = new RequestType0(method); +} diff --git a/src/sourcekit-lsp/extensions/index.ts b/src/sourcekit-lsp/extensions/index.ts index 346eac36c..2db75614a 100644 --- a/src/sourcekit-lsp/extensions/index.ts +++ b/src/sourcekit-lsp/extensions/index.ts @@ -22,3 +22,4 @@ export * from "./PeekDocumentsRequest"; export * from "./ReIndexProjectRequest"; export * from "./SourceKitLogMessageNotification"; export * from "./SymbolInfoRequest"; +export * from "./WorkspacePlaygroundsRequest"; diff --git a/src/ui/ProjectPanelProvider.ts b/src/ui/ProjectPanelProvider.ts index a5399479f..61c643bd2 100644 --- a/src/ui/ProjectPanelProvider.ts +++ b/src/ui/ProjectPanelProvider.ts @@ -22,6 +22,7 @@ import { Dependency, ResolvedDependency, Target } from "../SwiftPackage"; import { WorkspaceContext } from "../WorkspaceContext"; import { FolderOperation } from "../WorkspaceContext"; import configuration from "../configuration"; +import { Playground } from "../playgrounds/PlaygroundProvider"; import { SwiftTask, TaskPlatformSpecificConfig } from "../tasks/SwiftTaskProvider"; import { getPlatformConfig, resolveTaskCwd } from "../utilities/tasks"; import { Version } from "../utilities/version"; @@ -399,6 +400,68 @@ class TargetNode { } } +export class PlaygroundNode { + constructor( + public playground: Playground, + private folder: FolderContext, + private activeTasks: Set + ) {} + + /** + * "instanceof" has a bad effect in our nightly tests when the VSIX + * bundled source is used. For example: + * + * ``` + * vscode.commands.registerCommand(Commands.PLAY, async (item, folder) => { + * if (item instanceof PlaygroundNode) { + * return await runPlayground(item.playground); + * } + * }), + * ``` + * + * So instead we'll check for this set boolean property. Even if the implementation of the + * {@link PlaygroundNode} class changes, this property should not need to change + */ + static isPlaygroundNode = (item: { __isPlaygroundNode?: boolean }) => + item.__isPlaygroundNode ?? false; + __isPlaygroundNode = true; + + get name(): string { + return this.playground.label ?? this.playground.id; + } + + toTreeItem(): vscode.TreeItem { + const name = this.name; + const item = new vscode.TreeItem(this.name, vscode.TreeItemCollapsibleState.None); + item.id = `${this.folder.name}:${this.playground.id}`; + item.iconPath = new vscode.ThemeIcon(this.icon()); + item.contextValue = "playground"; + item.accessibilityInformation = { label: name }; + item.tooltip = `${this.name} (${this.folder.name})`; + item.command = { + title: "Open Playground", + command: "vscode.openWith", + arguments: [ + vscode.Uri.parse(this.playground.location.uri), + "default", + { selection: this.playground.location.range }, + ], + }; + return item; + } + + private icon(): string { + if (this.activeTasks.has(this.name)) { + return LOADING_ICON; + } + return "symbol-numeric"; + } + + getChildren(): TreeNode[] { + return []; + } +} + class HeaderNode { constructor( private id: string, @@ -462,7 +525,14 @@ class ErrorNode { * * Can be either a {@link PackageNode}, {@link FileNode}, {@link TargetNode}, {@link TaskNode}, {@link ErrorNode} or {@link HeaderNode}. */ -export type TreeNode = PackageNode | FileNode | HeaderNode | TaskNode | TargetNode | ErrorNode; +export type TreeNode = + | PackageNode + | FileNode + | HeaderNode + | TaskNode + | TargetNode + | PlaygroundNode + | ErrorNode; /** * A {@link vscode.TreeDataProvider TreeDataProvider} for project dependencies, tasks and commands {@link vscode.TreeView TreeView}. @@ -477,6 +547,7 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { private lastComputedNodes: TreeNode[] = []; private buildPluginOutputWatcher?: vscode.FileSystemWatcher; private buildPluginFolderWatcher?: vscode.Disposable; + private playgroundWatcher?: vscode.Disposable; onDidChangeTreeData = this.didChangeTreeDataEmitter.event; @@ -491,6 +562,8 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { dispose() { this.workspaceObserver?.dispose(); + this.buildPluginFolderWatcher?.dispose(); + this.playgroundWatcher?.dispose(); this.disposables.forEach(d => d.dispose()); this.disposables.length = 0; } @@ -576,7 +649,7 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { if (!folder) { return; } - this.watchBuildPluginOutputs(folder); + this.observeFolder(folder); treeView.title = `Swift Project (${folder.name})`; this.workspaceContext.logger.info( `Project panel updating, focused folder ${folder.name}` @@ -611,7 +684,12 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { ); } - watchBuildPluginOutputs(folderContext: FolderContext) { + observeFolder(folderContext: FolderContext) { + this.watchBuildPluginOutputs(folderContext); + this.watchPlaygrounds(folderContext); + } + + private watchBuildPluginOutputs(folderContext: FolderContext) { if (this.buildPluginOutputWatcher) { this.buildPluginOutputWatcher.dispose(); } @@ -638,6 +716,19 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { ); } + private watchPlaygrounds(folderContext: FolderContext) { + if (this.playgroundWatcher) { + this.playgroundWatcher.dispose(); + } + + const playgroundProvider = folderContext.playgroundProvider; + if (playgroundProvider) { + this.playgroundWatcher = playgroundProvider.onDidChangePlaygrounds(() => + this.didChangeTreeDataEmitter.fire() + ); + } + } + getTreeItem(element: TreeNode): vscode.TreeItem { return element.toTreeItem(); } @@ -674,6 +765,7 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { const commands = await this.commands(); const targets = await this.targets(); const tasks = await this.tasks(folderContext); + const playgrounds = await this.playgrounds(); // TODO: Control ordering return [ @@ -711,6 +803,13 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { ), ] : []), + ...(playgrounds.length > 0 + ? [ + new HeaderNode("playgrounds", "Playgrounds", "symbol-numeric", () => + Promise.resolve(playgrounds) + ), + ] + : []), ]; } @@ -819,6 +918,18 @@ export class ProjectPanelProvider implements vscode.TreeDataProvider { .flatMap(target => new TargetNode(target, folderContext, this.activeTasks)) .sort((a, b) => a.name.localeCompare(b.name)); } + + private async playgrounds(): Promise { + const folderContext = this.workspaceContext.currentFolder; + if (!folderContext) { + return []; + } + const playgrounds = + (await folderContext.playgroundProvider?.getWorkspacePlaygrounds()) ?? []; + return playgrounds.flatMap( + playground => new PlaygroundNode(playground, folderContext, this.activeTasks) + ); + } } /* diff --git a/test/integration-tests/commands/runPlayground.test.ts b/test/integration-tests/commands/runPlayground.test.ts index edfce882b..b7ec9cbc0 100644 --- a/test/integration-tests/commands/runPlayground.test.ts +++ b/test/integration-tests/commands/runPlayground.test.ts @@ -19,8 +19,10 @@ import { FolderContext } from "@src/FolderContext"; import { WorkspaceContext } from "@src/WorkspaceContext"; import { Commands } from "@src/commands"; import { runPlayground } from "@src/commands/runPlayground"; +import { Playground } from "@src/sourcekit-lsp/extensions"; import { SwiftTask } from "@src/tasks/SwiftTaskProvider"; import { TaskManager } from "@src/tasks/TaskManager"; +import { PlaygroundNode } from "@src/ui/ProjectPanelProvider"; import { MockedObject, instance, mockObject } from "../../MockUtils"; import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities"; @@ -43,7 +45,7 @@ suite("Run Playground Command", function () { }); suite("Command", () => { - test("Succeeds", async () => { + test("Succeeds with PlaygroundItem", async () => { expect( await vscode.commands.executeCommand(Commands.PLAY, { id: "PackageLib/PackageLib.swift:3", @@ -51,6 +53,22 @@ suite("Run Playground Command", function () { ).to.be.true; }); + test("Succeeds with PlaygroundNode", async () => { + expect( + await vscode.commands.executeCommand( + Commands.PLAY, + new PlaygroundNode( + { + label: "foo", + id: "PackageLib/PackageLib.swift:3", + } as Playground, + folderContext, + new Set() + ) + ) + ).to.be.true; + }); + test("No playground item provided", async () => { expect(await vscode.commands.executeCommand(Commands.PLAY), undefined).to.be.false; }); diff --git a/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts b/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts index b3b2b9753..41b3140c0 100644 --- a/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts +++ b/test/unit-tests/sourcekit-lsp/LanguageClientManager.test.ts @@ -162,6 +162,7 @@ suite("LanguageClientManager Suite", () => { outputChannel: instance( mockObject({ dispose: mockFn(), + warn: mockFn(), }) ), initializeResult: { @@ -578,7 +579,11 @@ suite("LanguageClientManager Suite", () => { const middleware = languageClientFactoryMock.createLanguageClient.args[0][3].middleware!; expect(middleware).to.have.property("provideCodeLenses"); await expect( - middleware.provideCodeLenses!({} as any, {} as any, codelensesFromSourceKitLSP) + middleware.provideCodeLenses!( + { uri: vscode.Uri.file("/path/to/doc.swift") } as any, + {} as any, + codelensesFromSourceKitLSP + ) ).to.eventually.deep.equal([ { range: new vscode.Range(0, 0, 0, 0), From 75d15112408f00bb045c956ba98cb0c8af8cf352 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Wed, 10 Dec 2025 21:45:57 -0500 Subject: [PATCH 08/11] pin the swiftlang/github-workflows configurations to 0.0.2 (#1993) --- .github/workflows/nightly.yml | 4 ++-- .github/workflows/pull_request.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a434ef834..1b4363681 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -60,7 +60,7 @@ jobs: tests_release: name: Test Release needs: package - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: needs_token: true # Linux @@ -87,7 +87,7 @@ jobs: tests_insiders: name: Test Insiders needs: package - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: needs_token: true # Linux diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 00b679852..53810d1b0 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -48,7 +48,7 @@ jobs: tests: name: ${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && 'Full Test Run' || 'Test'}} needs: package - uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@0.0.2 with: needs_token: true # Linux @@ -76,7 +76,7 @@ jobs: soundness: name: Soundness - uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@0.0.2 with: # Pending https://github.com/swiftlang/vscode-swift/pull/1176 license_header_check_enabled: false From 649e1c0d41cf53ac47b57f305a116cbc454b4f40 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Thu, 11 Dec 2025 16:54:25 -0500 Subject: [PATCH 09/11] only attempt to run xcode-select on macOS (#1995) --- src/toolchain/toolchain.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/toolchain/toolchain.ts b/src/toolchain/toolchain.ts index 445aae608..e9dc6a128 100644 --- a/src/toolchain/toolchain.ts +++ b/src/toolchain/toolchain.ts @@ -566,7 +566,10 @@ export class SwiftToolchain { // swift may be a symbolic link const realSwiftBinaryPath = await fs.realpath(swiftBinaryPath); // Check if the swift binary is managed by xcrun - if (await this.isXcrunShim(realSwiftBinaryPath, logger)) { + if ( + process.platform === "darwin" && + (await this.isXcrunShim(realSwiftBinaryPath, logger)) + ) { const { stdout } = await execFile("xcrun", ["--find", "swift"], { env: configuration.swiftEnvironmentVariables, }); From 102ba05a192d3fa14a37a4d398d5404bcb1a95b9 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Fri, 12 Dec 2025 11:13:06 -0500 Subject: [PATCH 10/11] Always use xcrun as a fallback for finding binaries on macOS (#1998) --- CHANGELOG.md | 4 +++ src/toolchain/toolchain.ts | 38 ++++++++++---------- src/utilities/utilities.ts | 16 ++++----- test/unit-tests/toolchain/toolchain.test.ts | 39 +++++++++++++++++++-- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bab867d4d..63f379f97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - When editing .sourcekit-lsp/config.json use the JSON schema from the toolchain ([#1979](https://github.com/swiftlang/vscode-swift/pull/1979)) +### Fixed + +- Fix extension failing to find `lldb-dap` when `swift.path` points at an Xcode toolchain ([#1998](https://github.com/swiftlang/vscode-swift/pull/1998)) + ## 2.14.2 - 2025-12-07 ### Fixed diff --git a/src/toolchain/toolchain.ts b/src/toolchain/toolchain.ts index e9dc6a128..5061c03b3 100644 --- a/src/toolchain/toolchain.ts +++ b/src/toolchain/toolchain.ts @@ -436,25 +436,25 @@ export class SwiftToolchain { * Search for the supplied executable in the toolchain. */ private async findToolchainExecutable(executable: string): Promise { - if (process.platform === "win32") { - executable += ".exe"; - } - // First search the toolchain's 'bin' directory - const toolchainExecutablePath = path.join(this.toolchainPath, "bin", executable); - if (await pathExists(toolchainExecutablePath)) { - return toolchainExecutablePath; - } - // Fallback to xcrun if the active toolchain comes from Xcode/CommandLineTools - if ( - this.manager === "xcrun" || - (this.manager === "swiftly" && (await Swiftly.inUseVersion()) === "xcode") - ) { - const { stdout } = await execFile("xcrun", ["--find", executable]); - return stdout.trim(); - } - throw new Error( - `Failed to find ${executable} within Swift toolchain '${this.toolchainPath}'` - ); + let cause: unknown = undefined; + try { + if (process.platform === "win32") { + executable += ".exe"; + } + // First search the toolchain's 'bin' directory + const toolchainExecutablePath = path.join(this.toolchainPath, "bin", executable); + if (await pathExists(toolchainExecutablePath)) { + return toolchainExecutablePath; + } + // Fallback to using xcrun if we're on macOS + if (process.platform === "darwin") { + const { stdout } = await execFile("xcrun", ["--find", executable]); + return stdout.trim(); + } + } catch (error) { + cause = error; + } + throw new Error(`Failed to find ${executable} within Swift toolchain`, { cause }); } private basePlatformDeveloperPath(): string | undefined { diff --git a/src/utilities/utilities.ts b/src/utilities/utilities.ts index e8dadded2..a5314258a 100644 --- a/src/utilities/utilities.ts +++ b/src/utilities/utilities.ts @@ -153,6 +153,14 @@ export async function execFile( options.env = { ...(options.env ?? process.env), ...runtimeEnv }; } } + if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) { + // when adding environment vars we either combine with vars passed + // into the function or the process environment vars + options.env = { + ...(options.env ?? process.env), + ...configuration.swiftEnvironmentVariables, + }; + } options = { ...options, maxBuffer: options.maxBuffer ?? 1024 * 1024 * 64, // 64MB @@ -261,14 +269,6 @@ export async function execSwift( swift = toolchain.getToolchainExecutable("swift"); args = toolchain.buildFlags.withAdditionalFlags(args); } - if (Object.keys(configuration.swiftEnvironmentVariables).length > 0) { - // when adding environment vars we either combine with vars passed - // into the function or the process environment vars - options.env = { - ...(options.env ?? process.env), - ...configuration.swiftEnvironmentVariables, - }; - } options = { ...options, maxBuffer: options.maxBuffer ?? 1024 * 1024 * 64, // 64MB diff --git a/test/unit-tests/toolchain/toolchain.test.ts b/test/unit-tests/toolchain/toolchain.test.ts index 525dbe3dd..88204e1b6 100644 --- a/test/unit-tests/toolchain/toolchain.test.ts +++ b/test/unit-tests/toolchain/toolchain.test.ts @@ -99,7 +99,7 @@ suite("SwiftToolchain Unit Test Suite", () => { }); await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith( - "Failed to find lldb-dap within Swift toolchain '/Library/Developer/Toolchains/swift-6.0.1-RELEASE.xctoolchain/usr'" + "Failed to find lldb-dap within Swift toolchain" ); }); @@ -153,6 +153,39 @@ suite("SwiftToolchain Unit Test Suite", () => { "/Library/Developer/CommandLineTools/usr/bin/lldb-dap" ); }); + + test("returns the path to lldb-dap if it exists within an Xcode toolchain selected using swift.path", async () => { + mockFS({ + "/Applications/Xcode.app/Contents/Developer": { + Toolchains: { + "XcodeDefault.xctoolchain": {}, + }, + usr: { + bin: { + "lldb-dap": mockFS.file({ + content: "", + mode: 0o770, + }), + }, + }, + }, + }); + mockedUtilities.execFile.withArgs("xcrun", ["--find", "lldb-dap"]).resolves({ + stdout: "/Applications/Xcode.app/Contents/Developer/usr/bin/lldb-dap", + stderr: "", + }); + const sut = createSwiftToolchain({ + manager: "unknown", + swiftFolderPath: + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr", + toolchainPath: + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr", + }); + + await expect(sut.getLLDBDebugAdapter()).to.eventually.equalPath( + "/Applications/Xcode.app/Contents/Developer/usr/bin/lldb-dap" + ); + }); }); suite("Linux", () => { @@ -189,7 +222,7 @@ suite("SwiftToolchain Unit Test Suite", () => { }); await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith( - "Failed to find lldb-dap within Swift toolchain '/toolchains/swift-6.0.0/usr'" + "Failed to find lldb-dap within Swift toolchain" ); }); }); @@ -228,7 +261,7 @@ suite("SwiftToolchain Unit Test Suite", () => { }); await expect(sut.getLLDBDebugAdapter()).to.eventually.be.rejectedWith( - "Failed to find lldb-dap.exe within Swift toolchain '/toolchains/swift-6.0.0/usr'" + "Failed to find lldb-dap.exe within Swift toolchain" ); }); }); From 392c940db29ef376e85108ff6d7f72ac133c5127 Mon Sep 17 00:00:00 2001 From: award999 Date: Fri, 12 Dec 2025 11:35:50 -0500 Subject: [PATCH 11/11] Ignore new nightly jobs (#1999) --- .github/workflows/nightly.yml | 2 +- .github/workflows/pull_request.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1b4363681..888f720d6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -104,7 +104,7 @@ jobs: linux_pre_build_command: . .github/workflows/scripts/setup-linux.sh linux_build_command: ./scripts/test.sh # Windows - windows_exclude_swift_versions: '[{"swift_version": "5.9"}, {"swift_version": "6.0"}, {"swift_version": "6.1"}, {"swift_version": "nightly-6.1"}, {"swift_version": "nightly-6.2"}, {"swift_version": "nightly"}]' + windows_exclude_swift_versions: '[{"swift_version": "5.9"}, {"swift_version": "6.0"}, {"swift_version": "6.1"}, {"swift_version": "nightly-6.1"}, {"swift_version": "nightly-6.2"}, {"swift_version": "nightly-6.3"}, {"swift_version": "nightly"}, {"swift_version": "nightly-main"}]' windows_env_vars: | CI=1 VSCODE_VERSION=insiders diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 53810d1b0..03d52bcdf 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -52,7 +52,7 @@ jobs: with: needs_token: true # Linux - linux_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly-main\"}]' }}" + linux_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly-6.3\"},{\"swift_version\": \"nightly-main\"}]' }}" linux_env_vars: | NODE_VERSION=v20.19.0 NODE_PATH=/usr/local/nvm/versions/node/v20.19.0/bin @@ -64,7 +64,7 @@ jobs: linux_pre_build_command: . .github/workflows/scripts/setup-linux.sh linux_build_command: ./scripts/test.sh # Windows - windows_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly\"}]' }}" + windows_exclude_swift_versions: "${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly\"}]' || '[{\"swift_version\": \"nightly-6.1\"},{\"swift_version\": \"nightly-6.2\"},{\"swift_version\": \"nightly-6.3\"},{\"swift_version\": \"nightly\"}]' }}" windows_env_vars: | CI=1 FAST_TEST_RUN=${{ contains(github.event.pull_request.labels.*.name, 'full-test-run') && '0' || '1'}}