From 3a86f14bfa58172fe1e85934d97057d136674684 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 27 May 2025 22:15:56 -0600 Subject: [PATCH] Add symbol mapping & diff UI improvements --- package.json | 38 +- pnpm-lock.yaml | 1250 +++++++++++++++++++------ shared/messages.ts | 1 + tsconfig.json | 4 +- webview/App.css | 8 + webview/App.tsx | 113 ++- webview/common/ContextMenu.tsx | 25 +- webview/common/Header.module.css | 5 + webview/common/TooltipShared.tsx | 55 +- webview/diff.ts | 82 ++ webview/mock.ts | 80 +- webview/state.ts | 183 ++-- webview/views/DiffView.module.css | 23 + webview/views/DiffView.tsx | 822 ++++++++++++++++ webview/views/FunctionView.module.css | 2 - webview/views/FunctionView.tsx | 280 ++---- webview/views/SymbolsView.module.css | 55 +- webview/views/SymbolsView.tsx | 644 ++++++------- webview/views/TreeView.module.css | 42 + webview/views/TreeView.tsx | 215 +++++ webview/views/UnitsView.module.css | 49 +- webview/views/UnitsView.tsx | 226 +---- 22 files changed, 2872 insertions(+), 1330 deletions(-) create mode 100644 webview/diff.ts create mode 100644 webview/views/DiffView.module.css create mode 100644 webview/views/DiffView.tsx create mode 100644 webview/views/TreeView.module.css create mode 100644 webview/views/TreeView.tsx diff --git a/package.json b/package.json index 38354e5..91d6738 100644 --- a/package.json +++ b/package.json @@ -24,34 +24,34 @@ "@vscode/codicons": "^0.0.36", "clsx": "^2.1.1", "memoize-one": "^6.0.0", - "objdiff-wasm": "3.0.0-beta.8", + "objdiff-wasm": "3.0.0-beta.9", "picomatch": "^4.0.2", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-tooltip": "^5.28.0", - "react-virtualized-auto-sizer": "^1.0.24", - "react-window": "^1.8.10", - "shescape": "^2.1.1", - "zustand": "^5.0.2" + "react-tooltip": "^5.28.1", + "react-virtualized-auto-sizer": "^1.0.26", + "react-window": "^1.8.11", + "shescape": "^2.1.3", + "zustand": "^5.0.4" }, "devDependencies": { - "@biomejs/biome": "^1.9.3", - "@rsbuild/core": "^1.1.8", - "@rsbuild/plugin-react": "^1.0.7", - "@rsbuild/plugin-type-check": "^1.1.0", + "@biomejs/biome": "^1.9.4", + "@rsbuild/core": "^1.3.20", + "@rsbuild/plugin-react": "^1.3.1", + "@rsbuild/plugin-type-check": "^1.2.2", "@rsbuild/plugin-typed-css-modules": "^1.0.2", - "@types/node": "^22.10.2", - "@types/picomatch": "^3.0.1", - "@types/react": "^18.3.1", - "@types/react-dom": "^18.3.1", + "@types/node": "^22.15.18", + "@types/picomatch": "^3.0.2", + "@types/react": "^18.3.21", + "@types/react-dom": "^18.3.7", "@types/react-window": "^1.8.8", - "@types/vscode": "^1.96.0", + "@types/vscode": "^1.100.0", "@types/vscode-webview": "^1.57.5", "@vscode/test-cli": "^0.0.10", - "@vscode/test-electron": "^2.4.1", - "@vscode/vsce": "^3.2.2", - "tsx": "^4.19.2", - "typescript": "^5.7.2" + "@vscode/test-electron": "^2.5.2", + "@vscode/vsce": "^3.4.0", + "tsx": "^4.19.4", + "typescript": "^5.8.3" }, "main": "./dist/extension.js", "files": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7074f9d..0334d3d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^6.0.0 version: 6.0.0 objdiff-wasm: - specifier: 3.0.0-beta.8 - version: 3.0.0-beta.8 + specifier: 3.0.0-beta.9 + version: 3.0.0-beta.9 picomatch: specifier: ^4.0.2 version: 4.0.2 @@ -30,54 +30,54 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) react-tooltip: - specifier: ^5.28.0 - version: 5.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^5.28.1 + version: 5.28.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-virtualized-auto-sizer: - specifier: ^1.0.24 - version: 1.0.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.0.26 + version: 1.0.26(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-window: - specifier: ^1.8.10 + specifier: ^1.8.11 version: 1.8.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) shescape: - specifier: ^2.1.1 - version: 2.1.1 + specifier: ^2.1.3 + version: 2.1.3 zustand: - specifier: ^5.0.2 - version: 5.0.3(@types/react@18.3.18)(react@18.3.1) + specifier: ^5.0.4 + version: 5.0.5(@types/react@18.3.23)(react@18.3.1) devDependencies: '@biomejs/biome': - specifier: ^1.9.3 + specifier: ^1.9.4 version: 1.9.4 '@rsbuild/core': - specifier: ^1.1.8 - version: 1.2.14 + specifier: ^1.3.20 + version: 1.3.22 '@rsbuild/plugin-react': - specifier: ^1.0.7 - version: 1.1.1(@rsbuild/core@1.2.14) + specifier: ^1.3.1 + version: 1.3.1(@rsbuild/core@1.3.22) '@rsbuild/plugin-type-check': - specifier: ^1.1.0 - version: 1.2.1(@rsbuild/core@1.2.14)(@rspack/core@1.2.5(@swc/helpers@0.5.15))(typescript@5.8.2) + specifier: ^1.2.2 + version: 1.2.2(@rsbuild/core@1.3.22)(@rspack/core@1.3.12(@swc/helpers@0.5.17))(typescript@5.8.3) '@rsbuild/plugin-typed-css-modules': specifier: ^1.0.2 - version: 1.0.2(@rsbuild/core@1.2.14) + version: 1.0.2(@rsbuild/core@1.3.22) '@types/node': - specifier: ^22.10.2 - version: 22.13.8 + specifier: ^22.15.18 + version: 22.15.23 '@types/picomatch': - specifier: ^3.0.1 + specifier: ^3.0.2 version: 3.0.2 '@types/react': - specifier: ^18.3.1 - version: 18.3.18 + specifier: ^18.3.21 + version: 18.3.23 '@types/react-dom': - specifier: ^18.3.1 - version: 18.3.5(@types/react@18.3.18) + specifier: ^18.3.7 + version: 18.3.7(@types/react@18.3.23) '@types/react-window': specifier: ^1.8.8 version: 1.8.8 '@types/vscode': - specifier: ^1.96.0 - version: 1.97.0 + specifier: ^1.100.0 + version: 1.100.0 '@types/vscode-webview': specifier: ^1.57.5 version: 1.57.5 @@ -85,20 +85,26 @@ importers: specifier: ^0.0.10 version: 0.0.10 '@vscode/test-electron': - specifier: ^2.4.1 - version: 2.4.1 + specifier: ^2.5.2 + version: 2.5.2 '@vscode/vsce': - specifier: ^3.2.2 - version: 3.2.2 + specifier: ^3.4.0 + version: 3.4.2 tsx: - specifier: ^4.19.2 - version: 4.19.3 + specifier: ^4.19.4 + version: 4.19.4 typescript: - specifier: ^5.7.2 - version: 5.8.2 + specifier: ^5.8.3 + version: 5.8.3 packages: + '@azu/format-text@1.0.2': + resolution: {integrity: sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==} + + '@azu/style-format@1.0.1': + resolution: {integrity: sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==} + '@azure/abort-controller@2.1.2': resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} engines: {node: '>=18.0.0'} @@ -406,37 +412,52 @@ packages: peerDependencies: tslib: '2' - '@module-federation/error-codes@0.8.4': - resolution: {integrity: sha512-55LYmrDdKb4jt+qr8qE8U3al62ZANp3FhfVaNPOaAmdTh0jHdD8M3yf5HKFlr5xVkVO4eV/F/J2NCfpbh+pEXQ==} + '@module-federation/error-codes@0.14.0': + resolution: {integrity: sha512-GGk+EoeSACJikZZyShnLshtq9E2eCrDWbRiB4QAFXCX4oYmGgFfzXlx59vMNwqTKPJWxkEGnPYacJMcr2YYjag==} - '@module-federation/runtime-tools@0.8.4': - resolution: {integrity: sha512-fjVOsItJ1u5YY6E9FnS56UDwZgqEQUrWFnouRiPtK123LUuqUI9FH4redZoKWlE1PB0ir1Z3tnqy8eFYzPO38Q==} + '@module-federation/runtime-core@0.14.0': + resolution: {integrity: sha512-fGE1Ro55zIFDp/CxQuRhKQ1pJvG7P0qvRm2N+4i8z++2bgDjcxnCKUqDJ8lLD+JfJQvUJf0tuSsJPgevzueD4g==} - '@module-federation/runtime@0.8.4': - resolution: {integrity: sha512-yZeZ7z2Rx4gv/0E97oLTF3V6N25vglmwXGgoeju/W2YjsFvWzVtCDI7zRRb0mJhU6+jmSM8jP1DeQGbea/AiZQ==} + '@module-federation/runtime-tools@0.14.0': + resolution: {integrity: sha512-y/YN0c2DKsLETE+4EEbmYWjqF9G6ZwgZoDIPkaQ9p0pQu0V4YxzWfQagFFxR0RigYGuhJKmSU/rtNoHq+qF8jg==} - '@module-federation/sdk@0.8.4': - resolution: {integrity: sha512-waABomIjg/5m1rPDBWYG4KUhS5r7OUUY7S+avpaVIY/tkPWB3ibRDKy2dNLLAMaLKq0u+B1qIdEp4NIWkqhqpg==} + '@module-federation/runtime@0.14.0': + resolution: {integrity: sha512-kR3cyHw/Y64SEa7mh4CHXOEQYY32LKLK75kJOmBroLNLO7/W01hMNAvGBYTedS7hWpVuefPk1aFZioy3q2VLdQ==} - '@module-federation/webpack-bundler-runtime@0.8.4': - resolution: {integrity: sha512-HggROJhvHPUX7uqBD/XlajGygMNM1DG0+4OAkk8MBQe4a18QzrRNzZt6XQbRTSG4OaEoyRWhQHvYD3Yps405tQ==} + '@module-federation/sdk@0.14.0': + resolution: {integrity: sha512-lg/OWRsh18hsyTCamOOhEX546vbDiA2O4OggTxxH2wTGr156N6DdELGQlYIKfRdU/0StgtQS81Goc0BgDZlx9A==} + + '@module-federation/webpack-bundler-runtime@0.14.0': + resolution: {integrity: sha512-POWS6cKBicAAQ3DNY5X7XEUSfOfUsRaBNxbuwEfSGlrkTE9UcWheO06QP2ndHi8tHQuUKcIHi2navhPkJ+k5xg==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@rsbuild/core@1.2.14': - resolution: {integrity: sha512-G8AqvCHBhs8Yt7pOQuS5YYjdYozp436ohaLr1iAMB/Jw01VNFh4u1tpShudRnw3NPmHhJ82wBaEu1zNaJ0VsKg==} - engines: {node: '>=16.7.0'} + '@rsbuild/core@1.3.22': + resolution: {integrity: sha512-FGB7m8Tn/uiOhvqk0lw+NRMyD+VYJ+eBqVfpn0X11spkJDiPWn8UkMRvfzCX4XFcNZwRKYuuKJaZK1DNU8UG+w==} + engines: {node: '>=16.10.0'} hasBin: true - '@rsbuild/plugin-react@1.1.1': - resolution: {integrity: sha512-gkATKrOQauXMMtrYA5jbTQkhmYTE0VXoknPLtVpiXtwDbBUwgX23LFf1XJ51YOwqYpP7g5SfPEMgD2FENtCq0A==} + '@rsbuild/plugin-react@1.3.1': + resolution: {integrity: sha512-1PfE0CZDwiSIUFaMFOEprwsHK6oo29zU6DdtFH2D49uLcpUdOUvU1u2p00RCVO1CIgnAjRajLS7dnPdQUwFOuQ==} peerDependencies: '@rsbuild/core': 1.x - '@rsbuild/plugin-type-check@1.2.1': - resolution: {integrity: sha512-PtbjeMqDQy8IiPDTuaj8ZmvR42b0AsRq6RUF6wxa8dDsOzD0Dl1GcvemVGCto+/Dh8frLUmnlWF+T8riBw5rtA==} + '@rsbuild/plugin-type-check@1.2.2': + resolution: {integrity: sha512-7hRPT9Vi5uXLkvjy9gGHttpCvK7afGXS7bukyf0XCYAWj6XMPJvUQpXBatVVdNdNfeYt0ffHo5GqiPz/eeCorQ==} peerDependencies: '@rsbuild/core': 1.x peerDependenciesMeta: @@ -451,63 +472,60 @@ packages: '@rsbuild/core': optional: true - '@rspack/binding-darwin-arm64@1.2.5': - resolution: {integrity: sha512-ou0NXMLp6RxY9Bx8P9lA8ArVjz/WAI/gSu5kKrdKKtMs6WKutl4vvP9A4HHZnISd9Tn00dlvDwNeNSUR7fjoDQ==} + '@rspack/binding-darwin-arm64@1.3.12': + resolution: {integrity: sha512-8hKjVTBeWPqkMzFPNWIh72oU9O3vFy3e88wRjMPImDCXBiEYrKqGTTLd/J0SO+efdL3SBD1rX1IvdJpxCv6Yrw==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.2.5': - resolution: {integrity: sha512-RdvH9YongQlDE9+T2Xh5D2+dyiLHx2Gz38Af1uObyBRNWjF1qbuR51hOas0f2NFUdyA03j1+HWZCbE7yZrmI3w==} + '@rspack/binding-darwin-x64@1.3.12': + resolution: {integrity: sha512-Sj4m+mCUxL7oCpdu7OmWT7fpBM7hywk5CM9RDc3D7StaBZbvNtNftafCrTZzTYKuZrKmemTh5SFzT5Tz7tf6GA==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.2.5': - resolution: {integrity: sha512-jznk/CI/wN93fr8I1j3la/CAiGf8aG7ZHIpRBtT4CkNze0c5BcF3AaJVSBHVNQqgSv0qddxMt3SADpzV8rWZ6g==} + '@rspack/binding-linux-arm64-gnu@1.3.12': + resolution: {integrity: sha512-7MuOxf3/Mhv4mgFdLTvgnt/J+VouNR65DEhorth+RZm3LEWojgoFEphSAMAvpvAOpYSS68Sw4SqsOZi719ia2w==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.2.5': - resolution: {integrity: sha512-oYzcaJ0xjb1fWbbtPmjjPXeehExEgwJ8fEGYQ5TikB+p9oCLkAghnNjsz9evUhgjByxi+NTZ1YmUNwxRuQDY1Q==} + '@rspack/binding-linux-arm64-musl@1.3.12': + resolution: {integrity: sha512-s6KKj20T9Z1bA8caIjU6EzJbwyDo1URNFgBAlafCT2UC6yX7flstDJJ38CxZacA9A2P24RuQK2/jPSZpWrTUFA==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.2.5': - resolution: {integrity: sha512-dzEKs8oi86Vi+TFRCPpgmfF5ANL0VmlZN45e1An7HipeI2C5B1xrz/H8V43vPy8XEvQuMmkXO6Sp82A0zlHvIA==} + '@rspack/binding-linux-x64-gnu@1.3.12': + resolution: {integrity: sha512-0w/sRREYbRgHgWvs2uMEJSLfvzbZkPHUg6CMcYQGNVK6axYRot6jPyKetyFYA9pR5fB5rsXegpnFaZaVrRIK2g==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.2.5': - resolution: {integrity: sha512-4ENeVPVSD97rRRGr6kJSm4sIPf1tKJ8vlr9hJi4sSvF7eMLWipSwIVmqRXJ2riVMRjYD2einmJ9KzI8rqQ2OwA==} + '@rspack/binding-linux-x64-musl@1.3.12': + resolution: {integrity: sha512-jEdxkPymkRxbijDRsBGdhopcbGXiXDg59lXqIRkVklqbDmZ/O6DHm7gImmlx5q9FoWbz0gqJuOKBz4JqWxjWVA==} cpu: [x64] os: [linux] - '@rspack/binding-win32-arm64-msvc@1.2.5': - resolution: {integrity: sha512-WUoJvX/z43MWeW1JKAQIxdvqH02oLzbaGMCzIikvniZnakQovYLPH6tCYh7qD3p7uQsm+IafFddhFxTtogC3pg==} + '@rspack/binding-win32-arm64-msvc@1.3.12': + resolution: {integrity: sha512-ZRvUCb3TDLClAqcTsl/o9UdJf0B5CgzAxgdbnYJbldyuyMeTUB4jp20OfG55M3C2Nute2SNhu2bOOp9Se5Ongw==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.2.5': - resolution: {integrity: sha512-YzPvmt/gpiacE6aAacz4dxgEbNWwoKYPaT4WYy/oITobnAui++iCFXC4IICSmlpoA1y7O8K3Qb9jbaB/lLhbwA==} + '@rspack/binding-win32-ia32-msvc@1.3.12': + resolution: {integrity: sha512-1TKPjuXStPJr14f3ZHuv40Xc/87jUXx10pzVtrPnw+f3hckECHrbYU/fvbVzZyuXbsXtkXpYca6ygCDRJAoNeQ==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.2.5': - resolution: {integrity: sha512-QDDshfteMZiglllm7WUh/ITemFNuexwn1Yul7cHBFGQu6HqtqKNAR0kGR8J3e15MPMlinSaygVpfRE4A0KPmjQ==} + '@rspack/binding-win32-x64-msvc@1.3.12': + resolution: {integrity: sha512-lCR0JfnYKpV+a6r2A2FdxyUKUS4tajePgpPJN5uXDgMGwrDtRqvx+d0BHhwjFudQVJq9VVbRaL89s2MQ6u+xYw==} cpu: [x64] os: [win32] - '@rspack/binding@1.2.5': - resolution: {integrity: sha512-q9vQmGDFZyFVMULwOFL7488WNSgn4ue94R/njDLMMIPF4K0oEJP2QT02elfG4KVGv2CbP63D7vEFN4ZNreo/Rw==} + '@rspack/binding@1.3.12': + resolution: {integrity: sha512-4Ic8lV0+LCBfTlH5aIOujIRWZOtgmG223zC4L3o8WY/+ESAgpdnK6lSSMfcYgRanYLAy3HOmFIp20jwskMpbAg==} - '@rspack/core@1.2.5': - resolution: {integrity: sha512-x/riOl05gOVGgGQFimBqS5i8XbUpBxPIKUC+tDX4hmNNkzxRaGpspZfNtcL+1HBMyYuoM6fOWGyCp2R290Uy6g==} + '@rspack/core@1.3.12': + resolution: {integrity: sha512-mAPmV4LPPRgxpouUrGmAE4kpF1NEWJGyM5coebsjK/zaCMSjw3mkdxiU2b5cO44oIi0Ifv5iGkvwbdrZOvMyFA==} engines: {node: '>=16.0.0'} peerDependencies: - '@rspack/tracing': ^1.x '@swc/helpers': '>=0.5.1' peerDependenciesMeta: - '@rspack/tracing': - optional: true '@swc/helpers': optional: true @@ -515,16 +533,81 @@ packages: resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} - '@rspack/plugin-react-refresh@1.0.1': - resolution: {integrity: sha512-KSBc3bsr3mrAPViv7w9MpE9KEWm6q87EyRXyHlRfJ9PpQ56NbX9KZ7AXo7jPeECb0q5sfpM2PSEf+syBiMgLSw==} + '@rspack/plugin-react-refresh@1.4.3': + resolution: {integrity: sha512-wZx4vWgy5oMEvgyNGd/oUKcdnKaccYWHCRkOqTdAPJC3WcytxhTX+Kady8ERurSBiLyQpoMiU3Iyd+F1Y2Arbw==} peerDependencies: react-refresh: '>=0.10.0 <1.0.0' + webpack-hot-middleware: 2.x peerDependenciesMeta: - react-refresh: + webpack-hot-middleware: optional: true - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@secretlint/config-creator@9.3.3': + resolution: {integrity: sha512-USIKXtBIDPBt+uxssxFVqYBzSommdwXNDGwRZPGErnKWeIH58XuyqIjRTi99fYB0yAQZZ+Cv4sD2JVXCxevEew==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/config-loader@9.3.3': + resolution: {integrity: sha512-t0NGpVq7fFROr/UqfxSI09UI30U7rKSGXjfKNwR0O6fMlwx2AV9RWOvLS4hDLwxxKs+ywss6DZx/wcTdtBEWxA==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/core@9.3.3': + resolution: {integrity: sha512-XPpchOJz591E6bqMWkY6VxtaIbSI0gY0bUeVz1gkfT6FUI0fOfJrAMWe9RhxXWraMuxokTQA8R/LFJefiK+bXg==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/formatter@9.3.3': + resolution: {integrity: sha512-kqfnbhtxcH1Ew7pboM+jCZl8CuBzVuEKuHHSkT92iasxaaq1NK37h5IIfUDbFdXizmNFe3MwAnnVU8lqK2Dvyg==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/node@9.3.3': + resolution: {integrity: sha512-ZD1yXlzEJmFS/lq+BmgzUBB+2mQgj6kK6A//IhBop5xqAp+lXoq1vNgu7VSJ3DR+XrKrIK7YHFZXRh9aJvIjmA==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/profiler@9.3.3': + resolution: {integrity: sha512-wcVTByh+m9O1w2WAV08Po6trGsVjhRTV1UWuzVcQTTap9EjeKQLja6Xof/SIDGORD0KWooUIMAe7VPLQFPi1cQ==} + + '@secretlint/resolver@9.3.3': + resolution: {integrity: sha512-8N0lqD7OiI/aLK/PhKyiGh5xTlO/6TjHiOt72jnrvB9BK2QF45Mp5fivCARTKBypDiTZrOrS7blvqZ7qTnOTrA==} + + '@secretlint/secretlint-formatter-sarif@9.3.3': + resolution: {integrity: sha512-qH8726RFQLdD2iKXamSbBcRTSxbECDbvg0hS3aTGL0+XOmzWI7JL4tdNywMqeHzKCRLrcEJOLYWv/P/w2VdwkA==} + + '@secretlint/secretlint-rule-no-dotenv@9.3.3': + resolution: {integrity: sha512-Fm1uSlchskbIGuVEIYr1MnhTvUSd4GHqiRXVomH0Sli9Q0JMKElBlfS8cB165OaNGrCZ+TmmdrF/Q8sjwZYWyQ==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/secretlint-rule-preset-recommend@9.3.3': + resolution: {integrity: sha512-zT8zxh1z28Vzc9S5FVMbfWOITNikTYmajLTuX4D8lhGM3bx7xDopUJnsEtj1lAGc5WcCZ3baMJ3xCFZeDv/SAg==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/source-creator@9.3.3': + resolution: {integrity: sha512-2h6t9UfWQn7Sp6PUO+hvWK3i55tqE4H4YlmUBlL5VOjubADcO21OAtp7S05LgXE+VJfLDgUcb1hflkw0cPE1rw==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@secretlint/types@9.3.3': + resolution: {integrity: sha512-ehVGggPM23sHEkqQP/5HlGDK+8Xx2oRX8vF9C/fKh+TcTRWOfjCeC7QeoPxcEMXNDXfUsHK5P8DKqQEcpbiUZQ==} + engines: {node: ^14.13.1 || >=16.0.0} + + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@swc/helpers@0.5.17': + resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + + '@textlint/ast-node-types@14.7.2': + resolution: {integrity: sha512-3rZc9vD8y/DlcFe3Y/cyKRRVgBH4ElEUzVFYdRVDwoMSwV/cIyZgYzVG6ZuOItQt+cHSREuijuucZ4VqZynbtg==} + + '@textlint/linter-formatter@14.7.2': + resolution: {integrity: sha512-QZOqft5uK+o/UN8UcEF3cHgfbG1r3+OWqlJojyjGNkEBbBNPSyDfYlVxDjHqnOAwm7jBaeqVGlwvw/7PUFmsmw==} + + '@textlint/module-interop@14.7.2': + resolution: {integrity: sha512-rDQhFERa2+xMqhyrPFvAL9d5Tb4RpQGKQExwrezvtCTREh6Zsp/nKxtK0r6o0P9xn1+zq2sZHW9NZjpe7av3xw==} + + '@textlint/resolver@14.7.2': + resolution: {integrity: sha512-FCZa9XJx5KihK/4gxXLhS/KfOnBD6vD5UxAMtgrvbifn+JFrW9Kh17uZLCcuJDDJJCnZOHq8jdT7AU+rpmJZ+w==} + + '@textlint/types@14.7.2': + resolution: {integrity: sha512-VpsmtJf9+7cnIxmKtAVVGVzI6f2k09kBZnzjdTAO8JZ+HTmV46jeoVrotpSfQbWDpuQk2UFPfrsZL/LNf/99ew==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -532,8 +615,11 @@ packages: '@types/mocha@10.0.10': resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} - '@types/node@22.13.8': - resolution: {integrity: sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==} + '@types/node@22.15.23': + resolution: {integrity: sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} '@types/picomatch@3.0.2': resolution: {integrity: sha512-n0i8TD3UDB7paoMMxA3Y65vUncFJXjcUf7lQY7YyKGl6031FNjfsLs6pdLFCy2GNFxItPJG8GvvpbZc2skH7WA==} @@ -541,22 +627,25 @@ packages: '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - '@types/react-dom@18.3.5': - resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: '@types/react': ^18.0.0 '@types/react-window@1.8.8': resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==} - '@types/react@18.3.18': - resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==} + '@types/react@18.3.23': + resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} + + '@types/sarif@2.1.7': + resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} '@types/vscode-webview@1.57.5': resolution: {integrity: sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==} - '@types/vscode@1.97.0': - resolution: {integrity: sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w==} + '@types/vscode@1.100.0': + resolution: {integrity: sha512-4uNyvzHoraXEeCamR3+fzcBlh7Afs4Ifjs4epINyUX/jvdk0uzLnwiDY35UKDKnkCHP5Nu3dljl2H8lR6s+rQw==} '@vscode/codicons@0.0.36': resolution: {integrity: sha512-wsNOvNMMJ2BY8rC2N2MNBG7yOowV3ov8KlvUE/AiVUlHKTfWsw3OgAOQduX7h0Un6GssKD3aoTVH+TF3DSQwKQ==} @@ -566,8 +655,8 @@ packages: engines: {node: '>=18'} hasBin: true - '@vscode/test-electron@2.4.1': - resolution: {integrity: sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==} + '@vscode/test-electron@2.5.2': + resolution: {integrity: sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==} engines: {node: '>=16'} '@vscode/vsce-sign-alpine-arm64@2.0.2': @@ -618,8 +707,8 @@ packages: '@vscode/vsce-sign@2.0.5': resolution: {integrity: sha512-GfYWrsT/vypTMDMgWDm75iDmAOMe7F71sZECJ+Ws6/xyIfmB3ELVnVN+LwMFAvmXY+e6eWhR2EzNGF/zAhWY3Q==} - '@vscode/vsce@3.2.2': - resolution: {integrity: sha512-4TqdUq/yKlQTHcQMk/DamR632bq/+IJDomSbexOMee/UAYWqYm0XHWA6scGslsCpzY+sCWEhhl0nqdOB0XW1kw==} + '@vscode/vsce@3.4.2': + resolution: {integrity: sha512-U2gC7GiQc22nxRpWH4cdW16rRr5u9w+Bjsjm8g8mEjY4aeOG1U6/3XNGq+ElwdeoT8jAyhBmBAuYG7INcSe/6A==} engines: {node: '>= 20'} hasBin: true @@ -627,10 +716,21 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -655,9 +755,16 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -674,15 +781,19 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + binaryextensions@4.19.0: + resolution: {integrity: sha512-DRxnVbOi/1OgA5pA9EDiRT8gvVYeqfuN7TmPfLyt6cyho3KbHCi3EtDQf39TTmGDrR5dZ9CspdXhPkL/j/WGbg==} + engines: {node: '>=0.8'} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + boundary@2.0.0: + resolution: {integrity: sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -705,9 +816,6 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -729,8 +837,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001701: - resolution: {integrity: sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==} + caniuse-lite@1.0.30001718: + resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -761,9 +869,13 @@ packages: classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} @@ -811,8 +923,8 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js@3.40.0: - resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} + core-js@3.42.0: + resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -840,6 +952,15 @@ packages: supports-color: optional: true + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} engines: {node: '>=10'} @@ -926,6 +1047,9 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-stack-parser@2.1.4: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} @@ -962,6 +1086,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -970,6 +1099,19 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -996,6 +1138,10 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1011,6 +1157,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1047,6 +1197,10 @@ packages: engines: {node: '>=12'} deprecated: Glob versions prior to v9 are no longer supported + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1082,8 +1236,12 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -1110,9 +1268,17 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@7.0.4: + resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} + engines: {node: '>= 4'} + immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -1123,6 +1289,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1169,6 +1338,10 @@ packages: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} @@ -1179,10 +1352,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isomorphic-rslog@0.0.6: - resolution: {integrity: sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==} - engines: {node: '>=14.17.6'} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -1195,6 +1364,10 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} + istextorbinary@6.0.0: + resolution: {integrity: sha512-4j3UqQCa06GAf6QHlN3giz2EeFU7qc6Q5uB/aY7Gmb3xmLDLepDOtsZqkb4sCfJgFvTbLUinNw0kHgHs8XOHoQ==} + engines: {node: '>=10'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1209,10 +1382,21 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -1221,6 +1405,9 @@ packages: jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -1250,6 +1437,10 @@ packages: lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lines-and-columns@2.0.4: + resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} @@ -1278,13 +1469,19 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} @@ -1326,6 +1523,14 @@ packages: memoize-one@6.0.0: resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -1339,9 +1544,9 @@ packages: engines: {node: '>=4'} hasBin: true - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} @@ -1393,6 +1598,14 @@ packages: node-addon-api@4.3.0: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} + node-sarif-builder@2.0.3: + resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==} + engines: {node: '>=14'} + + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1400,8 +1613,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - objdiff-wasm@3.0.0-beta.8: - resolution: {integrity: sha512-qYvmBZllPMQKCwJtrj737ZKWVtvc8uJliIDQMzuxkiX4Qf2apcbpf4RN4md2y7Jibnr7pI2P1+CrZKyTFYubhw==} + objdiff-wasm@3.0.0-beta.9: + resolution: {integrity: sha512-vdmeVOBD2DHUeNAcg9zdcrohH/X4sWrRAE9USkq5EPZ7ECPWEhrIT+uc5O7t2pqlxRWqGfOGuY6DD8gt26PNHA==} object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} @@ -1410,17 +1623,17 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} open@10.1.0: resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} engines: {node: '>=18'} - ora@7.0.1: - resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} - engines: {node: '>=16'} + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} + engines: {node: '>=18'} p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} @@ -1430,12 +1643,20 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parse-json@7.1.1: + resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} + engines: {node: '>=16'} + parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} @@ -1468,6 +1689,10 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -1482,6 +1707,13 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pluralize@2.0.0: + resolution: {integrity: sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} @@ -1501,9 +1733,15 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + rc-config-loader@4.1.3: + resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -1513,18 +1751,18 @@ packages: peerDependencies: react: ^18.3.1 - react-refresh@0.16.0: - resolution: {integrity: sha512-FPvF2XxTSikpJxcr+bHut2H4gJ17+18Uy20D5/F+SKzFap62R3cM5wH6b8WN3LyGSYeQilLEcJcR1fjBSI2S1A==} + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} - react-tooltip@5.28.0: - resolution: {integrity: sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==} + react-tooltip@5.28.1: + resolution: {integrity: sha512-ZA4oHwoIIK09TS7PvSLFcRlje1wGZaxw6xHvfrzn6T82UcMEfEmHVCad16Gnr4NDNDh93HyN037VK4HDi5odfQ==} peerDependencies: react: '>=16.14.0' react-dom: '>=16.14.0' - react-virtualized-auto-sizer@1.0.25: - resolution: {integrity: sha512-YHsksEGDfsHbHuaBVDYwJmcktblcHGafz4ZVuYPQYuSHMUGjpwmUCrAOcvMSGMwwk1eFWj1M/1GwYpNPuyhaBg==} + react-virtualized-auto-sizer@1.0.26: + resolution: {integrity: sha512-CblNyiNVw2o+hsa5/49NH2ogGxZ+t+3aweRvNSq7TVjDIlwk7ir4lencEg5HxHeSzwNarSkNkiu0qJSOXtxm5A==} peerDependencies: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -1540,6 +1778,10 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + read-pkg@8.1.0: + resolution: {integrity: sha512-PORM8AgzXeskHO/WEv312k9U03B8K9JSiWF/8N9sUuFjBa+9SF2u6K7VClzXwDXab51jCd8Nd36CNM+zR97ScQ==} + engines: {node: '>=16'} + read@1.0.7: resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} engines: {node: '>=0.8'} @@ -1565,17 +1807,28 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -1591,6 +1844,11 @@ packages: scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + secretlint@9.3.3: + resolution: {integrity: sha512-JTIsI8BEon8Oo6P7YvGq3I3qCZuYgCvekU8qr4OYyvo6N/wHGg4JMruT5MVkxh3q0diX11xsqaptmeTP5/wNxQ==} + engines: {node: ^14.13.1 || >=16.0.0} + hasBin: true + semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -1614,9 +1872,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shescape@2.1.1: - resolution: {integrity: sha512-sAbmiCuXKxMGqPGe+nhwFJ/o++2D7Fzb8dwIO78Hnt/MGN5mbVvs4WNydZmxxVxkoJz4VuUBXDvhwsvqildYhA==} - engines: {node: ^14.18.0 || ^16.13.0 || ^18 || ^19 || ^20 || ^22} + shescape@2.1.3: + resolution: {integrity: sha512-WN/TCDjkmeOJklB0A2HzBe3tNSycodOXubHmhW8P8Af3cQkMraxx3ka5MoFJ2vkaOI+7nW/YujNWVoqHXnqRzA==} + engines: {node: ^14.18.0 || ^16.13.0 || ^18 || ^19 || ^20 || ^22 || ^24} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -1634,9 +1892,6 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -1647,12 +1902,35 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} @@ -1666,9 +1944,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string-width@6.1.0: - resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} - engines: {node: '>=16'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -1692,6 +1970,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + structured-source@4.0.0: + resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -1708,6 +1989,14 @@ packages: resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} engines: {node: '>=12'} + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} @@ -1719,10 +2008,21 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + textextensions@5.16.0: + resolution: {integrity: sha512-7D/r3s6uPZyU//MCYrX6I14nzauDwJ5CxazouuRGNuvSCihW87ufN6VLoROLCrHg6FblLuJrT6N2BVaPVzqElw==} + engines: {node: '>=0.8'} + thingies@1.21.0: resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} engines: {node: '>=10.18'} @@ -1743,8 +2043,8 @@ packages: peerDependencies: tslib: '2' - ts-checker-rspack-plugin@1.1.1: - resolution: {integrity: sha512-BlpPqnfAmV0TcDg58H+1qV8Zb57ilv0x+ajjnxrVQ6BWgC8HzAdc+TycqDOJ4sZZYIV+hywQGozZFGklzbCR6A==} + ts-checker-rspack-plugin@1.1.3: + resolution: {integrity: sha512-VpB+L+F330T484qGp5KqyoU00PRlUlz4kO1ifBpQ5CkKXEFXye8nmeXlZ5rvZAXjFAMRFiG+sI9OewO6Bd9UvA==} engines: {node: '>=16.0.0'} peerDependencies: '@rspack/core': ^1.0.0 @@ -1756,8 +2056,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.19.3: - resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} + tsx@4.19.4: + resolution: {integrity: sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==} engines: {node: '>=18.0.0'} hasBin: true @@ -1768,11 +2068,23 @@ packages: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} hasBin: true @@ -1782,13 +2094,21 @@ packages: underscore@1.13.7: resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==} - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} undici@6.21.1: resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} engines: {node: '>=18.17'} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} @@ -1803,6 +2123,9 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -1880,8 +2203,8 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zustand@5.0.3: - resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + zustand@5.0.5: + resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==} engines: {node: '>=12.20.0'} peerDependencies: '@types/react': '>=18.0.0' @@ -1900,6 +2223,12 @@ packages: snapshots: + '@azu/format-text@1.0.2': {} + + '@azu/style-format@1.0.1': + dependencies: + '@azu/format-text': 1.0.2 + '@azure/abort-controller@2.1.2': dependencies: tslib: 2.8.1 @@ -2150,151 +2479,275 @@ snapshots: dependencies: tslib: 2.8.1 - '@module-federation/error-codes@0.8.4': {} + '@module-federation/error-codes@0.14.0': {} - '@module-federation/runtime-tools@0.8.4': + '@module-federation/runtime-core@0.14.0': dependencies: - '@module-federation/runtime': 0.8.4 - '@module-federation/webpack-bundler-runtime': 0.8.4 + '@module-federation/error-codes': 0.14.0 + '@module-federation/sdk': 0.14.0 - '@module-federation/runtime@0.8.4': + '@module-federation/runtime-tools@0.14.0': dependencies: - '@module-federation/error-codes': 0.8.4 - '@module-federation/sdk': 0.8.4 + '@module-federation/runtime': 0.14.0 + '@module-federation/webpack-bundler-runtime': 0.14.0 - '@module-federation/sdk@0.8.4': + '@module-federation/runtime@0.14.0': dependencies: - isomorphic-rslog: 0.0.6 + '@module-federation/error-codes': 0.14.0 + '@module-federation/runtime-core': 0.14.0 + '@module-federation/sdk': 0.14.0 - '@module-federation/webpack-bundler-runtime@0.8.4': + '@module-federation/sdk@0.14.0': {} + + '@module-federation/webpack-bundler-runtime@0.14.0': dependencies: - '@module-federation/runtime': 0.8.4 - '@module-federation/sdk': 0.8.4 + '@module-federation/runtime': 0.14.0 + '@module-federation/sdk': 0.14.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 '@pkgjs/parseargs@0.11.0': optional: true - '@rsbuild/core@1.2.14': + '@rsbuild/core@1.3.22': dependencies: - '@rspack/core': 1.2.5(@swc/helpers@0.5.15) + '@rspack/core': 1.3.12(@swc/helpers@0.5.17) '@rspack/lite-tapable': 1.0.1 - '@swc/helpers': 0.5.15 - core-js: 3.40.0 + '@swc/helpers': 0.5.17 + core-js: 3.42.0 jiti: 2.4.2 - transitivePeerDependencies: - - '@rspack/tracing' - '@rsbuild/plugin-react@1.1.1(@rsbuild/core@1.2.14)': + '@rsbuild/plugin-react@1.3.1(@rsbuild/core@1.3.22)': dependencies: - '@rsbuild/core': 1.2.14 - '@rspack/plugin-react-refresh': 1.0.1(react-refresh@0.16.0) - react-refresh: 0.16.0 + '@rsbuild/core': 1.3.22 + '@rspack/plugin-react-refresh': 1.4.3(react-refresh@0.17.0) + react-refresh: 0.17.0 + transitivePeerDependencies: + - webpack-hot-middleware - '@rsbuild/plugin-type-check@1.2.1(@rsbuild/core@1.2.14)(@rspack/core@1.2.5(@swc/helpers@0.5.15))(typescript@5.8.2)': + '@rsbuild/plugin-type-check@1.2.2(@rsbuild/core@1.3.22)(@rspack/core@1.3.12(@swc/helpers@0.5.17))(typescript@5.8.3)': dependencies: deepmerge: 4.3.1 json5: 2.2.3 reduce-configs: 1.1.0 - ts-checker-rspack-plugin: 1.1.1(@rspack/core@1.2.5(@swc/helpers@0.5.15))(typescript@5.8.2) + ts-checker-rspack-plugin: 1.1.3(@rspack/core@1.3.12(@swc/helpers@0.5.17))(typescript@5.8.3) optionalDependencies: - '@rsbuild/core': 1.2.14 + '@rsbuild/core': 1.3.22 transitivePeerDependencies: - '@rspack/core' - typescript - '@rsbuild/plugin-typed-css-modules@1.0.2(@rsbuild/core@1.2.14)': + '@rsbuild/plugin-typed-css-modules@1.0.2(@rsbuild/core@1.3.22)': optionalDependencies: - '@rsbuild/core': 1.2.14 + '@rsbuild/core': 1.3.22 - '@rspack/binding-darwin-arm64@1.2.5': + '@rspack/binding-darwin-arm64@1.3.12': optional: true - '@rspack/binding-darwin-x64@1.2.5': + '@rspack/binding-darwin-x64@1.3.12': optional: true - '@rspack/binding-linux-arm64-gnu@1.2.5': + '@rspack/binding-linux-arm64-gnu@1.3.12': optional: true - '@rspack/binding-linux-arm64-musl@1.2.5': + '@rspack/binding-linux-arm64-musl@1.3.12': optional: true - '@rspack/binding-linux-x64-gnu@1.2.5': + '@rspack/binding-linux-x64-gnu@1.3.12': optional: true - '@rspack/binding-linux-x64-musl@1.2.5': + '@rspack/binding-linux-x64-musl@1.3.12': optional: true - '@rspack/binding-win32-arm64-msvc@1.2.5': + '@rspack/binding-win32-arm64-msvc@1.3.12': optional: true - '@rspack/binding-win32-ia32-msvc@1.2.5': + '@rspack/binding-win32-ia32-msvc@1.3.12': optional: true - '@rspack/binding-win32-x64-msvc@1.2.5': + '@rspack/binding-win32-x64-msvc@1.3.12': optional: true - '@rspack/binding@1.2.5': + '@rspack/binding@1.3.12': optionalDependencies: - '@rspack/binding-darwin-arm64': 1.2.5 - '@rspack/binding-darwin-x64': 1.2.5 - '@rspack/binding-linux-arm64-gnu': 1.2.5 - '@rspack/binding-linux-arm64-musl': 1.2.5 - '@rspack/binding-linux-x64-gnu': 1.2.5 - '@rspack/binding-linux-x64-musl': 1.2.5 - '@rspack/binding-win32-arm64-msvc': 1.2.5 - '@rspack/binding-win32-ia32-msvc': 1.2.5 - '@rspack/binding-win32-x64-msvc': 1.2.5 + '@rspack/binding-darwin-arm64': 1.3.12 + '@rspack/binding-darwin-x64': 1.3.12 + '@rspack/binding-linux-arm64-gnu': 1.3.12 + '@rspack/binding-linux-arm64-musl': 1.3.12 + '@rspack/binding-linux-x64-gnu': 1.3.12 + '@rspack/binding-linux-x64-musl': 1.3.12 + '@rspack/binding-win32-arm64-msvc': 1.3.12 + '@rspack/binding-win32-ia32-msvc': 1.3.12 + '@rspack/binding-win32-x64-msvc': 1.3.12 - '@rspack/core@1.2.5(@swc/helpers@0.5.15)': + '@rspack/core@1.3.12(@swc/helpers@0.5.17)': dependencies: - '@module-federation/runtime-tools': 0.8.4 - '@rspack/binding': 1.2.5 + '@module-federation/runtime-tools': 0.14.0 + '@rspack/binding': 1.3.12 '@rspack/lite-tapable': 1.0.1 - caniuse-lite: 1.0.30001701 + caniuse-lite: 1.0.30001718 optionalDependencies: - '@swc/helpers': 0.5.15 + '@swc/helpers': 0.5.17 '@rspack/lite-tapable@1.0.1': {} - '@rspack/plugin-react-refresh@1.0.1(react-refresh@0.16.0)': + '@rspack/plugin-react-refresh@1.4.3(react-refresh@0.17.0)': dependencies: error-stack-parser: 2.1.4 - html-entities: 2.5.2 - optionalDependencies: - react-refresh: 0.16.0 + html-entities: 2.6.0 + react-refresh: 0.17.0 - '@swc/helpers@0.5.15': + '@secretlint/config-creator@9.3.3': + dependencies: + '@secretlint/types': 9.3.3 + + '@secretlint/config-loader@9.3.3': + dependencies: + '@secretlint/profiler': 9.3.3 + '@secretlint/resolver': 9.3.3 + '@secretlint/types': 9.3.3 + ajv: 8.17.1 + debug: 4.4.1 + rc-config-loader: 4.1.3 + transitivePeerDependencies: + - supports-color + + '@secretlint/core@9.3.3': + dependencies: + '@secretlint/profiler': 9.3.3 + '@secretlint/types': 9.3.3 + debug: 4.4.1 + structured-source: 4.0.0 + transitivePeerDependencies: + - supports-color + + '@secretlint/formatter@9.3.3': + dependencies: + '@secretlint/resolver': 9.3.3 + '@secretlint/types': 9.3.3 + '@textlint/linter-formatter': 14.7.2 + '@textlint/module-interop': 14.7.2 + '@textlint/types': 14.7.2 + chalk: 4.1.2 + debug: 4.4.1 + pluralize: 8.0.0 + strip-ansi: 6.0.1 + table: 6.9.0 + terminal-link: 2.1.1 + transitivePeerDependencies: + - supports-color + + '@secretlint/node@9.3.3': + dependencies: + '@secretlint/config-loader': 9.3.3 + '@secretlint/core': 9.3.3 + '@secretlint/formatter': 9.3.3 + '@secretlint/profiler': 9.3.3 + '@secretlint/source-creator': 9.3.3 + '@secretlint/types': 9.3.3 + debug: 4.4.1 + p-map: 4.0.0 + transitivePeerDependencies: + - supports-color + + '@secretlint/profiler@9.3.3': {} + + '@secretlint/resolver@9.3.3': {} + + '@secretlint/secretlint-formatter-sarif@9.3.3': + dependencies: + node-sarif-builder: 2.0.3 + + '@secretlint/secretlint-rule-no-dotenv@9.3.3': + dependencies: + '@secretlint/types': 9.3.3 + + '@secretlint/secretlint-rule-preset-recommend@9.3.3': {} + + '@secretlint/source-creator@9.3.3': + dependencies: + '@secretlint/types': 9.3.3 + istextorbinary: 6.0.0 + + '@secretlint/types@9.3.3': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 + '@textlint/ast-node-types@14.7.2': {} + + '@textlint/linter-formatter@14.7.2': + dependencies: + '@azu/format-text': 1.0.2 + '@azu/style-format': 1.0.1 + '@textlint/module-interop': 14.7.2 + '@textlint/resolver': 14.7.2 + '@textlint/types': 14.7.2 + chalk: 4.1.2 + debug: 4.4.1 + js-yaml: 3.14.1 + lodash: 4.17.21 + pluralize: 2.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + table: 6.9.0 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + '@textlint/module-interop@14.7.2': {} + + '@textlint/resolver@14.7.2': {} + + '@textlint/types@14.7.2': + dependencies: + '@textlint/ast-node-types': 14.7.2 + '@types/istanbul-lib-coverage@2.0.6': {} '@types/mocha@10.0.10': {} - '@types/node@22.13.8': + '@types/node@22.15.23': dependencies: - undici-types: 6.20.0 + undici-types: 6.21.0 + + '@types/normalize-package-data@2.4.4': {} '@types/picomatch@3.0.2': {} '@types/prop-types@15.7.14': {} - '@types/react-dom@18.3.5(@types/react@18.3.18)': + '@types/react-dom@18.3.7(@types/react@18.3.23)': dependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.23 '@types/react-window@1.8.8': dependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.23 - '@types/react@18.3.18': + '@types/react@18.3.23': dependencies: '@types/prop-types': 15.7.14 csstype: 3.1.3 + '@types/sarif@2.1.7': {} + '@types/vscode-webview@1.57.5': {} - '@types/vscode@1.97.0': {} + '@types/vscode@1.100.0': {} '@vscode/codicons@0.0.36': {} @@ -2310,12 +2763,12 @@ snapshots: supports-color: 9.4.0 yargs: 17.7.2 - '@vscode/test-electron@2.4.1': + '@vscode/test-electron@2.5.2': dependencies: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 jszip: 3.10.1 - ora: 7.0.1 + ora: 8.2.0 semver: 7.7.1 transitivePeerDependencies: - supports-color @@ -2359,9 +2812,13 @@ snapshots: '@vscode/vsce-sign-win32-arm64': 2.0.2 '@vscode/vsce-sign-win32-x64': 2.0.2 - '@vscode/vsce@3.2.2': + '@vscode/vsce@3.4.2': dependencies: '@azure/identity': 4.7.0 + '@secretlint/node': 9.3.3 + '@secretlint/secretlint-formatter-sarif': 9.3.3 + '@secretlint/secretlint-rule-no-dotenv': 9.3.3 + '@secretlint/secretlint-rule-preset-recommend': 9.3.3 '@vscode/vsce-sign': 2.0.5 azure-devops-node-api: 12.5.0 chalk: 2.4.2 @@ -2378,6 +2835,7 @@ snapshots: minimatch: 3.1.2 parse-semver: 1.1.1 read: 1.0.7 + secretlint: 9.3.3 semver: 7.7.1 tmp: 0.2.3 typed-rest-client: 1.8.11 @@ -2392,8 +2850,24 @@ snapshots: agent-base@7.1.3: {} + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -2413,8 +2887,14 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} + astral-regex@2.0.0: {} + asynckit@0.4.0: {} azure-devops-node-api@12.5.0: @@ -2424,10 +2904,13 @@ snapshots: balanced-match@1.0.2: {} - base64-js@1.5.1: {} + base64-js@1.5.1: + optional: true binary-extensions@2.3.0: {} + binaryextensions@4.19.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -2435,14 +2918,10 @@ snapshots: readable-stream: 3.6.2 optional: true - bl@5.1.0: - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - boolbase@1.0.0: {} + boundary@2.0.0: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -2468,11 +2947,6 @@ snapshots: ieee754: 1.2.1 optional: true - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 @@ -2503,7 +2977,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001701: {} + caniuse-lite@1.0.30001718: {} chalk@2.4.2: dependencies: @@ -2558,9 +3032,11 @@ snapshots: classnames@2.5.1: {} - cli-cursor@4.0.0: + clean-stack@2.2.0: {} + + cli-cursor@5.0.0: dependencies: - restore-cursor: 4.0.0 + restore-cursor: 5.1.0 cli-spinners@2.9.2: {} @@ -2602,7 +3078,7 @@ snapshots: convert-source-map@2.0.0: {} - core-js@3.40.0: {} + core-js@3.42.0: {} core-util-is@1.0.3: {} @@ -2630,6 +3106,10 @@ snapshots: optionalDependencies: supports-color: 8.1.1 + debug@4.4.1: + dependencies: + ms: 2.1.3 + decamelize@4.0.0: {} decompress-response@6.0.0: @@ -2711,6 +3191,10 @@ snapshots: entities@4.5.0: {} + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + error-stack-parser@2.1.4: dependencies: stackframe: 1.3.4 @@ -2764,11 +3248,29 @@ snapshots: escape-string-regexp@4.0.0: {} + esprima@4.0.1: {} + events@3.3.0: {} expand-template@2.0.3: optional: true + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-uri@3.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + fd-slicer@1.1.0: dependencies: pend: 1.2.0 @@ -2799,6 +3301,12 @@ snapshots: fs-constants@1.0.0: optional: true + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -2808,6 +3316,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2872,6 +3382,15 @@ snapshots: minimatch: 5.1.6 once: 1.4.0 + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.4 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -2896,7 +3415,11 @@ snapshots: dependencies: lru-cache: 6.0.0 - html-entities@2.5.2: {} + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + html-entities@2.6.0: {} html-escaper@2.0.2: {} @@ -2927,10 +3450,15 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ieee754@1.2.1: {} + ieee754@1.2.1: + optional: true + + ignore@7.0.4: {} immediate@3.0.6: {} + indent-string@4.0.0: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -2941,6 +3469,8 @@ snapshots: ini@1.3.8: optional: true + is-arrayish@0.2.1: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -2969,6 +3499,8 @@ snapshots: is-unicode-supported@1.3.0: {} + is-unicode-supported@2.1.0: {} + is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 @@ -2977,8 +3509,6 @@ snapshots: isexe@2.0.0: {} - isomorphic-rslog@0.0.6: {} - istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -2992,6 +3522,11 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + istextorbinary@6.0.0: + dependencies: + binaryextensions: 4.19.0 + textextensions: 5.16.0 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -3006,14 +3541,29 @@ snapshots: js-tokens@4.0.0: {} + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 + json-parse-even-better-errors@3.0.2: {} + + json-schema-traverse@1.0.0: {} + json5@2.2.3: {} jsonc-parser@3.3.1: {} + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + jsonwebtoken@9.0.2: dependencies: jws: 3.2.2 @@ -3068,6 +3618,8 @@ snapshots: dependencies: immediate: 3.0.6 + lines-and-columns@2.0.4: {} + linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 @@ -3090,12 +3642,16 @@ snapshots: lodash.once@4.1.1: {} + lodash.truncate@4.4.2: {} + + lodash@4.17.21: {} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-symbols@5.1.0: + log-symbols@6.0.0: dependencies: chalk: 5.4.1 is-unicode-supported: 1.3.0 @@ -3140,6 +3696,13 @@ snapshots: memoize-one@6.0.0: {} + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + mime-db@1.52.0: {} mime-types@2.1.35: @@ -3148,7 +3711,7 @@ snapshots: mime@1.6.0: {} - mimic-fn@2.1.0: {} + mimic-function@5.0.1: {} mimic-response@3.1.0: optional: true @@ -3215,13 +3778,24 @@ snapshots: node-addon-api@4.3.0: optional: true + node-sarif-builder@2.0.3: + dependencies: + '@types/sarif': 2.1.7 + fs-extra: 10.1.0 + + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.1 + validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} nth-check@2.1.1: dependencies: boolbase: 1.0.0 - objdiff-wasm@3.0.0-beta.8: {} + objdiff-wasm@3.0.0-beta.9: {} object-inspect@1.13.4: {} @@ -3229,9 +3803,9 @@ snapshots: dependencies: wrappy: 1.0.2 - onetime@5.1.2: + onetime@7.0.0: dependencies: - mimic-fn: 2.1.0 + mimic-function: 5.0.1 open@10.1.0: dependencies: @@ -3240,16 +3814,16 @@ snapshots: is-inside-container: 1.0.0 is-wsl: 3.1.0 - ora@7.0.1: + ora@8.2.0: dependencies: chalk: 5.4.1 - cli-cursor: 4.0.0 + cli-cursor: 5.0.0 cli-spinners: 2.9.2 is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - string-width: 6.1.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 strip-ansi: 7.1.0 p-limit@3.1.0: @@ -3260,10 +3834,22 @@ snapshots: dependencies: p-limit: 3.1.0 + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + package-json-from-dist@1.0.1: {} pako@1.0.11: {} + parse-json@7.1.1: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 3.0.2 + lines-and-columns: 2.0.4 + type-fest: 3.13.1 + parse-semver@1.1.1: dependencies: semver: 5.7.2 @@ -3297,6 +3883,8 @@ snapshots: lru-cache: 11.0.2 minipass: 7.1.2 + path-type@6.0.0: {} + pend@1.2.0: {} picocolors@1.1.1: {} @@ -3305,6 +3893,10 @@ snapshots: picomatch@4.0.2: {} + pluralize@2.0.0: {} + + pluralize@8.0.0: {} + prebuild-install@7.1.3: dependencies: detect-libc: 2.0.3 @@ -3335,10 +3927,21 @@ snapshots: dependencies: side-channel: 1.1.0 + queue-microtask@1.2.3: {} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 + rc-config-loader@4.1.3: + dependencies: + debug: 4.4.1 + js-yaml: 4.1.0 + json5: 2.2.3 + require-from-string: 2.0.2 + transitivePeerDependencies: + - supports-color + rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -3353,16 +3956,16 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-refresh@0.16.0: {} + react-refresh@0.17.0: {} - react-tooltip@5.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-tooltip@5.28.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@floating-ui/dom': 1.6.13 classnames: 2.5.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-virtualized-auto-sizer@1.0.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-virtualized-auto-sizer@1.0.26(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3378,6 +3981,13 @@ snapshots: dependencies: loose-envify: 1.4.0 + read-pkg@8.1.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.2 + parse-json: 7.1.1 + type-fest: 4.41.0 + read@1.0.7: dependencies: mute-stream: 0.0.8 @@ -3397,6 +4007,7 @@ snapshots: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + optional: true readdirp@3.6.0: dependencies: @@ -3408,15 +4019,23 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + resolve-pkg-maps@1.0.0: {} - restore-cursor@4.0.0: + restore-cursor@5.1.0: dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.1.0: {} run-applescript@7.0.0: {} + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -3429,6 +4048,18 @@ snapshots: dependencies: loose-envify: 1.4.0 + secretlint@9.3.3: + dependencies: + '@secretlint/config-creator': 9.3.3 + '@secretlint/formatter': 9.3.3 + '@secretlint/node': 9.3.3 + '@secretlint/profiler': 9.3.3 + debug: 4.4.1 + globby: 14.1.0 + read-pkg: 8.1.0 + transitivePeerDependencies: + - supports-color + semver@5.7.2: {} semver@7.7.1: {} @@ -3445,7 +4076,7 @@ snapshots: shebang-regex@3.0.0: {} - shescape@2.1.1: + shescape@2.1.3: dependencies: which: 3.0.1 @@ -3477,8 +4108,6 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - signal-exit@3.0.7: {} - signal-exit@4.1.0: {} simple-concat@1.0.1: @@ -3491,11 +4120,33 @@ snapshots: simple-concat: 1.0.1 optional: true + slash@5.1.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-license-ids@3.0.21: {} + + sprintf-js@1.0.3: {} + stackframe@1.3.4: {} - stdin-discarder@0.1.0: - dependencies: - bl: 5.1.0 + stdin-discarder@0.2.2: {} stoppable@1.1.0: {} @@ -3511,10 +4162,10 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - string-width@6.1.0: + string-width@7.2.0: dependencies: - eastasianwidth: 0.2.0 emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 string_decoder@1.1.1: @@ -3524,6 +4175,7 @@ snapshots: string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 + optional: true strip-ansi@6.0.1: dependencies: @@ -3538,6 +4190,10 @@ snapshots: strip-json-comments@3.1.1: {} + structured-source@4.0.0: + dependencies: + boundary: 2.0.0 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -3552,6 +4208,19 @@ snapshots: supports-color@9.4.0: {} + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + tapable@2.2.1: {} tar-fs@2.1.2: @@ -3571,12 +4240,21 @@ snapshots: readable-stream: 3.6.2 optional: true + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + test-exclude@6.0.0: dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.3 minimatch: 3.1.2 + text-table@0.2.0: {} + + textextensions@5.16.0: {} + thingies@1.21.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -3591,21 +4269,22 @@ snapshots: dependencies: tslib: 2.8.1 - ts-checker-rspack-plugin@1.1.1(@rspack/core@1.2.5(@swc/helpers@0.5.15))(typescript@5.8.2): + ts-checker-rspack-plugin@1.1.3(@rspack/core@1.3.12(@swc/helpers@0.5.17))(typescript@5.8.3): dependencies: '@babel/code-frame': 7.26.2 '@rspack/lite-tapable': 1.0.1 chokidar: 3.6.0 + is-glob: 4.0.3 memfs: 4.17.0 minimatch: 9.0.5 picocolors: 1.1.1 - typescript: 5.8.2 + typescript: 5.8.3 optionalDependencies: - '@rspack/core': 1.2.5(@swc/helpers@0.5.15) + '@rspack/core': 1.3.12(@swc/helpers@0.5.17) tslib@2.8.1: {} - tsx@4.19.3: + tsx@4.19.4: dependencies: esbuild: 0.25.0 get-tsconfig: 4.10.0 @@ -3619,22 +4298,32 @@ snapshots: tunnel@0.0.6: {} + type-fest@0.21.3: {} + + type-fest@3.13.1: {} + + type-fest@4.41.0: {} + typed-rest-client@1.8.11: dependencies: qs: 6.14.0 tunnel: 0.0.6 underscore: 1.13.7 - typescript@5.8.2: {} + typescript@5.8.3: {} uc.micro@2.1.0: {} underscore@1.13.7: {} - undici-types@6.20.0: {} + undici-types@6.21.0: {} undici@6.21.1: {} + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + url-join@4.0.1: {} util-deprecate@1.0.2: {} @@ -3647,6 +4336,11 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -3730,7 +4424,7 @@ snapshots: yocto-queue@0.1.0: {} - zustand@5.0.3(@types/react@18.3.18)(react@18.3.1): + zustand@5.0.5(@types/react@18.3.23)(react@18.3.1): optionalDependencies: - '@types/react': 18.3.18 + '@types/react': 18.3.23 react: 18.3.1 diff --git a/shared/messages.ts b/shared/messages.ts index 1ccbd01..c29f065 100644 --- a/shared/messages.ts +++ b/shared/messages.ts @@ -27,6 +27,7 @@ export type StateMessage = { leftObject?: ArrayBuffer | null; rightObject?: ArrayBuffer | null; projectConfig?: ProjectConfig | null; + diffLabel?: string | null; }; // decomp.me colors diff --git a/tsconfig.json b/tsconfig.json index 4373529..c23d9fd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,9 +15,7 @@ "allowImportingTsExtensions": true, /* type checking */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true + "strict": true }, "include": ["src", "webview", "shared"] } diff --git a/webview/App.css b/webview/App.css index a4e9386..2a050f0 100644 --- a/webview/App.css +++ b/webview/App.css @@ -49,6 +49,14 @@ --vscode-list-hoverBackground, light-dark(#f2f2f2, #2a2d2e) ); + --list-row-selection-background: var( + --vscode-list-inactiveSelectionBackground, + light-dark(#e4e6f1, #37373d) + ); + --list-row-highlight-background: var( + --vscode-list-activeSelectionBackground, + light-dark(#e8e8e8, #04395e) + ); --line-number-foreground: var(--vscode-editorLineNumber-foreground, #6e7681); diff --git a/webview/App.tsx b/webview/App.tsx index a9d9a74..27dc464 100644 --- a/webview/App.tsx +++ b/webview/App.tsx @@ -1,50 +1,77 @@ import './App.css'; -import type { diff, display } from 'objdiff-wasm'; +import type { diff } from 'objdiff-wasm'; +import { useMemo } from 'react'; import { useShallow } from 'zustand/react/shallow'; +import { useDiff } from './diff'; import { useAppStore, useExtensionStore } from './state'; -import type { SymbolRefByName } from './state'; -import FunctionView from './views/FunctionView'; +import DiffView from './views/DiffView'; import SettingsView from './views/SettingsView'; -import SymbolsView from './views/SymbolsView'; import UnitsView from './views/UnitsView'; -const findSymbol = ( - obj: diff.ObjectDiff | undefined, - symbolRef: SymbolRefByName | null, -): display.SectionDisplaySymbol | null => { - if (!obj || !symbolRef) { - return null; - } - const idx = obj.findSymbol( - symbolRef.symbolName, - symbolRef.sectionName ?? undefined, - ); - if (idx !== undefined) { - return { - symbol: idx, - isMappingSymbol: false, - }; - } - return null; -}; - const App = () => { - const { buildRunning, result, config, ready } = useExtensionStore( + const { + buildRunning, + configProperties, + currentUnit, + leftStatus, + rightStatus, + leftObject, + rightObject, + config, + ready, + } = useExtensionStore( useShallow((state) => ({ buildRunning: state.buildRunning, - result: state.result, + configProperties: state.configProperties, + currentUnit: state.currentUnit, + leftStatus: state.leftStatus, + rightStatus: state.rightStatus, + leftObject: state.leftObject, + rightObject: state.rightObject, config: state.projectConfig, ready: state.ready, })), ); - const { leftSymbolRef, rightSymbolRef, currentView } = useAppStore( - useShallow((state) => ({ - leftSymbolRef: state.leftSymbol, - rightSymbolRef: state.rightSymbol, - currentView: state.currentView, - })), + const { leftSymbolRef, rightSymbolRef, currentView, mappings } = useAppStore( + useShallow((state) => { + const unitState = state.getUnitState(currentUnit?.name ?? ''); + return { + leftSymbolRef: state.leftSymbol, + rightSymbolRef: state.rightSymbol, + currentView: state.currentView, + mappings: unitState?.mappings, + }; + }), ); + const mappingConfig = useMemo(() => { + const result: diff.MappingConfig = { + mappings: mappings == null ? [] : Object.entries(mappings), + selectingLeft: undefined, + selectingRight: undefined, + }; + if (leftSymbolRef && !rightSymbolRef) { + result.selectingRight = leftSymbolRef.symbolName; + result.mappings = result.mappings.filter( + ([left, _]) => left !== leftSymbolRef.symbolName, + ); + } + if (!leftSymbolRef && rightSymbolRef) { + result.selectingLeft = rightSymbolRef.symbolName; + result.mappings = result.mappings.filter( + ([_, right]) => right !== rightSymbolRef.symbolName, + ); + } + return result; + }, [leftSymbolRef, rightSymbolRef, mappings]); + const result = useDiff({ + leftStatus, + rightStatus, + leftObject, + rightObject, + configProperties, + mappingConfig, + }); if (!ready) { // Uses panel background color to avoid flashing @@ -53,15 +80,19 @@ const App = () => { switch (currentView) { case 'main': - if (result) { - const leftSymbol = findSymbol(result.left, leftSymbolRef); - const rightSymbol = findSymbol(result.right, rightSymbolRef); - if (leftSymbol || rightSymbol) { - return ( - - ); - } - return ; + if ( + result.leftStatus || + result.rightStatus || + result.diff.left || + result.diff.right + ) { + return ( + + ); } if (buildRunning) { diff --git a/webview/common/ContextMenu.tsx b/webview/common/ContextMenu.tsx index 146828f..0ea9670 100644 --- a/webview/common/ContextMenu.tsx +++ b/webview/common/ContextMenu.tsx @@ -23,9 +23,14 @@ export type ContextMenuState = Readonly<{ data: T; }>; -type ContextMenuProps = React.PropsWithChildren<{ +export type ContextMenuRender = ( + state: ContextMenuState, + close: () => void, +) => React.ReactNode; + +export type ContextMenuProps = React.PropsWithChildren<{ className?: string; - render?: (state: ContextMenuState, close: () => void) => React.ReactNode; + render?: ContextMenuRender; }>; export function createContextMenu(): { @@ -55,9 +60,7 @@ export function createContextMenu(): { }); }, []); - const close = useCallback(() => { - setState(null); - }, []); + const close = useCallback(() => setState(null), []); const closeIfOutside = useCallback( (e: Event) => { @@ -108,9 +111,7 @@ export function createContextMenu(): { observer.observe(state.target.parentNode, { childList: true, }); - return () => { - observer.disconnect(); - }; + return () => observer.disconnect(); } }, [state?.target, close]); @@ -186,12 +187,8 @@ export function renderContextItems( className={styles.contextMenuItem} onClick={() => { navigator.clipboard.writeText(item.val.value).then( - () => { - close(); - }, - (e) => { - console.warn('Failed to copy:', e); - }, + () => close(), + (e) => console.warn('Failed to copy:', e), ); }} > diff --git a/webview/common/Header.module.css b/webview/common/Header.module.css index 260135a..d3d2d6a 100644 --- a/webview/common/Header.module.css +++ b/webview/common/Header.module.css @@ -42,3 +42,8 @@ .spacer { flex: 1 1 0; } + +.input { + display: flex; + align-items: center; +} diff --git a/webview/common/TooltipShared.tsx b/webview/common/TooltipShared.tsx index d95687e..d1435a2 100644 --- a/webview/common/TooltipShared.tsx +++ b/webview/common/TooltipShared.tsx @@ -1,9 +1,52 @@ import styles from './TooltipShared.module.css'; import type { display } from 'objdiff-wasm'; -import React, { useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Tooltip } from 'react-tooltip'; +type TooltipProps = { + 'data-tooltip-id': string; + 'data-tooltip-content': string; +}; + +export type TooltipCallback = (content: T) => display.HoverItem[] | null; + +export function createTooltip(): { + Tooltip: React.FC<{ + callback: TooltipCallback; + }>; + useTooltip: (content: T) => TooltipProps; +} { + const id = generateRandomString(10); + return { + Tooltip: ({ callback }) => { + const callbackMemo = useCallback( + (content: string) => { + if (!content) { + return null; + } + const parsedContent = JSON.parse(content) as T; + return callback(parsedContent); + }, + [callback], + ); + return ; + }, + useTooltip: (content: T) => + // useMemo( + // () => ({ + // 'data-tooltip-id': id, + // 'data-tooltip-content': JSON.stringify(content), + // }), + // [content], + // ), + ({ + 'data-tooltip-id': id, + 'data-tooltip-content': JSON.stringify(content), + }), + }; +} + const TooltipShared = ({ id, callback, @@ -74,4 +117,12 @@ const TooltipContent = ({ items }: { items: display.HoverItem[] }) => { const TooltipContentMemo = React.memo(TooltipContent); -export default TooltipShared; +function generateRandomString(length: number): string { + const characters = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} diff --git a/webview/diff.ts b/webview/diff.ts new file mode 100644 index 0000000..cab1208 --- /dev/null +++ b/webview/diff.ts @@ -0,0 +1,82 @@ +import { diff } from 'objdiff-wasm'; +import { useMemo } from 'react'; +import type { ConfigProperties } from '../shared/config'; +import type { BuildStatus } from '../shared/messages'; +import { buildDiffConfig } from './state'; + +export type DiffInput = { + leftStatus: BuildStatus | null; + rightStatus: BuildStatus | null; + leftObject: ArrayBuffer | null; + rightObject: ArrayBuffer | null; + configProperties: ConfigProperties; + mappingConfig: diff.MappingConfig; +}; + +export type DiffOutput = { + leftStatus: BuildStatus | null; + rightStatus: BuildStatus | null; + diff: diff.DiffResult | null; + lastBuilt: number | null; + isMapping: boolean; +}; + +export const useDiff = ({ + leftStatus, + rightStatus, + leftObject, + rightObject, + configProperties, + mappingConfig, +}: DiffInput) => + useMemo(() => { + const start = performance.now(); + const diffConfig = buildDiffConfig(configProperties); + let left: diff.Object | undefined; + let right: diff.Object | undefined; + try { + left = + leftObject?.byteLength && leftStatus?.success + ? diff.Object.parse(new Uint8Array(leftObject), diffConfig) + : undefined; + } catch (e) { + leftStatus = { + success: false, + cmdline: leftStatus?.cmdline ?? '', + stdout: '', + stderr: `Failed to parse left object: ${e}`, + }; + } + try { + right = + rightObject?.byteLength && rightStatus?.success + ? diff.Object.parse(new Uint8Array(rightObject), diffConfig) + : undefined; + } catch (e) { + rightStatus = { + success: false, + cmdline: rightStatus?.cmdline ?? '', + stdout: '', + stderr: `Failed to parse right object: ${e}`, + }; + } + const result = diff.runDiff(left, right, diffConfig, mappingConfig); + const end = performance.now(); + console.debug('Diff time:', end - start, 'ms'); + return { + leftStatus, + rightStatus, + diff: result, + lastBuilt: Date.now(), + isMapping: + mappingConfig.selectingLeft != null || + mappingConfig.selectingRight != null, + }; + }, [ + leftStatus, + rightStatus, + leftObject, + rightObject, + configProperties, + mappingConfig, + ]); diff --git a/webview/mock.ts b/webview/mock.ts index 285fd9e..91b6c8c 100644 --- a/webview/mock.ts +++ b/webview/mock.ts @@ -36,6 +36,11 @@ function sendMessage(data: InboundMessage) { let resolvedProjectConfig: ProjectConfig | null = null; async function fetchFile(path: string): Promise { + if (!path) { + return Promise.resolve( + new Response(null, { status: 404, statusText: 'Not Found' }), + ); + } const search = new URLSearchParams(); search.set('path', path); const response = await fetch(`/api/get?${search.toString()}`); @@ -59,6 +64,54 @@ if (serializedConfigProperties) { configProperties = JSON.parse(serializedConfigProperties); } +async function fetchUnitFiles(unit: Unit, out: StateMessage): Promise { + const leftPromise = fetchFile(unit.target_path ?? '') + .then((r) => r.arrayBuffer()) + .then( + (o) => { + out.leftObject = o; + out.leftStatus = { + success: true, + cmdline: '', + stdout: '', + stderr: '', + }; + }, + (e) => { + out.leftObject = null; + out.leftStatus = { + success: false, + cmdline: '', + stdout: '', + stderr: `Failed to fetch object: ${e}`, + }; + }, + ); + const rightPromise = fetchFile(unit.base_path ?? '') + .then((r) => r.arrayBuffer()) + .then( + (o) => { + out.rightObject = o; + out.rightStatus = { + success: true, + cmdline: '', + stdout: '', + stderr: '', + }; + }, + (e) => { + out.rightObject = null; + out.rightStatus = { + success: false, + cmdline: '', + stdout: '', + stderr: `Failed to fetch object: ${e}`, + }; + }, + ); + await Promise.all([leftPromise, rightPromise]); +} + async function handleMessage(msg: OutboundMessage): Promise { switch (msg.type) { case 'ready': { @@ -70,17 +123,14 @@ async function handleMessage(msg: OutboundMessage): Promise { buildRunning: false, configProperties, currentUnit: null, + leftStatus: null, + rightStatus: null, leftObject: null, rightObject: null, projectConfig: resolvedProjectConfig, }; if (lastUnit) { - out.leftObject = await fetchFile(lastUnit.target_path ?? '').then((r) => - r.arrayBuffer(), - ); - out.rightObject = await fetchFile(lastUnit.base_path ?? '').then((r) => - r.arrayBuffer(), - ); + await fetchUnitFiles(lastUnit, out); } sendMessage(out); break; @@ -90,16 +140,13 @@ async function handleMessage(msg: OutboundMessage): Promise { const out: StateMessage = { type: 'state', buildRunning: false, + leftStatus: null, + rightStatus: null, leftObject: null, rightObject: null, }; if (lastUnit) { - out.leftObject = await fetchFile(lastUnit.target_path ?? '').then((r) => - r.arrayBuffer(), - ); - out.rightObject = await fetchFile(lastUnit.base_path ?? '').then((r) => - r.arrayBuffer(), - ); + await fetchUnitFiles(lastUnit, out); } sendMessage(out); break; @@ -115,17 +162,14 @@ async function handleMessage(msg: OutboundMessage): Promise { type: 'state', buildRunning: false, currentUnit: unit, + leftStatus: null, + rightStatus: null, leftObject: null, rightObject: null, }; if (unit) { sendMessage({ type: 'state', buildRunning: true }); - out.leftObject = await fetchFile(unit.target_path ?? '').then((r) => - r.arrayBuffer(), - ); - out.rightObject = await fetchFile(unit.base_path ?? '').then((r) => - r.arrayBuffer(), - ); + await fetchUnitFiles(unit, out); } lastUnit = unit; localStorage.setItem('lastUnit', JSON.stringify(unit)); diff --git a/webview/state.ts b/webview/state.ts index 015ec3e..eb99901 100644 --- a/webview/state.ts +++ b/webview/state.ts @@ -33,20 +33,16 @@ export type SymbolRefByName = { sectionName: string | null; }; -export type UnitScrollOffsets = { - left: number; - right: number; -}; -export type UnitCollapsedSections = { - left: Record; - right: Record; -}; +export type Side = 'left' | 'right'; +export type UnitScrollOffsets = { [key in Side]: number }; +export type UnitCollapsedSections = { [key in Side]: Record }; export type UnitState = { scrollOffsets: UnitScrollOffsets; symbolScrollOffsets: Record; collapsedSections: UnitCollapsedSections; search: string | null; + mappings: Record; }; const defaultUnitState: UnitState = { scrollOffsets: { left: 0, right: 0 }, @@ -56,6 +52,7 @@ const defaultUnitState: UnitState = { right: {}, }, search: null, + mappings: {}, }; export type CurrentView = 'main' | 'settings'; @@ -68,7 +65,7 @@ export interface AppState { currentView: CurrentView; collapsedUnits: Record; - getUnitState(unit: string): UnitState; + getUnitState(unit: string | null | undefined): UnitState; setSelectedSymbol: ( leftSymbol: SymbolRefByName | null, rightSymbol: SymbolRefByName | null, @@ -91,6 +88,11 @@ export interface AppState { ) => void; setUnitSearch: (unit: string, search: string | null) => void; setUnitsScrollOffset: (offset: number) => void; + setUnitMapping: ( + unit: string, + left: string | null | undefined, + right: string | null | undefined, + ) => void; setHighlight: (highlight: HighlightState) => void; setCurrentView: (view: CurrentView) => void; setCollapsedUnit: (unit: string, collapsed: boolean) => void; @@ -123,7 +125,9 @@ export const useAppStore = create((set) => { collapsedUnits: {}, getUnitState(unit) { - return this.unitStates[unit] ?? defaultUnitState; + return unit == null + ? defaultUnitState + : (this.unitStates[unit] ?? defaultUnitState); }, setSelectedSymbol: (leftSymbol, rightSymbol) => set({ leftSymbol, rightSymbol }), @@ -160,6 +164,23 @@ export const useAppStore = create((set) => { search, })), setUnitsScrollOffset: (offset) => set({ unitsScrollOffset: offset }), + setUnitMapping: (unit, left, right) => + setUnitState(unit, (state) => { + const newMappings = Object.fromEntries( + Object.entries(state.mappings || {}).filter( + ([k, v]) => + (left == null || k !== left) && (right == null || v !== right), + ), + ); + if (left != null && right != null && left !== right) { + // Only add new mapping if both sides are defined and different + newMappings[left] = right; + } + return { + ...state, + mappings: newMappings, + }; + }), setHighlight: (highlight: HighlightState) => set({ highlight }), setCurrentView: (currentView) => set({ currentView }), setCollapsedUnit: (unit, collapsed) => @@ -178,14 +199,11 @@ export type ExtensionState = { currentUnit: Unit | null; leftStatus: BuildStatus | null; rightStatus: BuildStatus | null; - leftObject: diff.Object | null; - rightObject: diff.Object | null; - result: diff.DiffResult | null; - lastBuilt: number | null; + leftObject: ArrayBuffer | null; + rightObject: ArrayBuffer | null; projectConfig: ProjectConfig | null; + diffLabel: string | null; ready: boolean; - - setResult: (result: diff.DiffResult | null | undefined) => void; }; export const useExtensionStore = create( subscribeWithSelector((set) => ({ @@ -197,18 +215,9 @@ export const useExtensionStore = create( rightStatus: null, leftObject: null, rightObject: null, - result: null, - lastBuilt: null, projectConfig: null, + diffLabel: null, ready: false, - - setResult: (result: diff.DiffResult | null | undefined) => { - if (result === undefined) { - set({ lastBuilt: Date.now() }); - } else { - set({ result, lastBuilt: Date.now() }); - } - }, })), ); @@ -275,7 +284,8 @@ subscriptions.push( k !== 'setUnitsScrollOffset' && k !== 'setHighlight' && k !== 'setCurrentView' && - k !== 'setCollapsedUnit' + k !== 'setCollapsedUnit' && + k !== 'setUnitMapping' ) { serialized[k] = state[k] as any; } @@ -330,117 +340,30 @@ export function buildDiffConfig( return config; } -// Run diff when objects or config properties change -subscriptions.push( - useExtensionStore.subscribe( - (state) => ({ - leftObject: state.leftObject, - rightObject: state.rightObject, - configProperties: state.configProperties, - setResult: state.setResult, - }), - ( - { leftObject, rightObject, configProperties, setResult }, - { - leftObject: prevLeftObject, - rightObject: prevRightObject, - configProperties: prevConfigProperties, - }, - ) => { - if (leftObject == null && rightObject == null) { - setResult(null); - } else if ( - configProperties === prevConfigProperties && - leftObject?.hash() === prevLeftObject?.hash() && - rightObject?.hash() === prevRightObject?.hash() - ) { - // Nothing changed, but update build time - setResult(undefined); - } else { - const start = performance.now(); - const diffConfig = buildDiffConfig(configProperties); - const result = diff.runDiff( - leftObject ?? undefined, - rightObject ?? undefined, - diffConfig, - ); - const end = performance.now(); - console.debug('Diff time:', end - start, 'ms'); - setResult(result); - } - }, - { equalityFn: shallow }, - ), -); - const handleMessage = (event: MessageEvent) => { const message = event.data as InboundMessage; if (message.type === 'state') { + console.log('Received state message', message); const newState: Partial = { ...message, - leftObject: undefined, - rightObject: undefined, - result: undefined, ready: true, }; - let diffConfig: diff.DiffConfig | null = null; - if (message.leftObject !== undefined) { - if (message.leftObject == null) { - newState.leftObject = null; - } else { - if (diffConfig == null) { - diffConfig = buildDiffConfig(message.configProperties); - } - try { - newState.leftObject = diff.Object.parse( - new Uint8Array(message.leftObject), - diffConfig, - ); - newState.leftStatus = { - success: true, - cmdline: '', - stdout: '', - stderr: '', - }; - } catch (e) { - newState.leftObject = null; - newState.leftStatus = { - success: false, - cmdline: '', - stdout: 'Failed to parse object', - stderr: e instanceof Error ? e.message : String(e), - }; - } - } + // Backwards compatibility for decomp.me + if (message.leftObject && !message.leftStatus) { + newState.leftStatus = { + success: true, + cmdline: '', + stdout: '', + stderr: '', + }; } - if (message.rightObject !== undefined) { - if (message.rightObject == null) { - newState.rightObject = null; - } else { - if (diffConfig == null) { - diffConfig = buildDiffConfig(message.configProperties); - } - try { - newState.rightObject = diff.Object.parse( - new Uint8Array(message.rightObject), - diffConfig, - ); - newState.rightStatus = { - success: true, - cmdline: '', - stdout: '', - stderr: '', - }; - } catch (e) { - newState.rightObject = null; - newState.rightStatus = { - success: false, - cmdline: '', - stdout: 'Failed to parse object', - stderr: e instanceof Error ? e.message : String(e), - }; - } - } + if (message.rightObject && !message.rightStatus) { + newState.rightStatus = { + success: true, + cmdline: '', + stdout: '', + stderr: '', + }; } for (const k in newState) { const key = k as keyof typeof newState; diff --git a/webview/views/DiffView.module.css b/webview/views/DiffView.module.css new file mode 100644 index 0000000..0ba7712 --- /dev/null +++ b/webview/views/DiffView.module.css @@ -0,0 +1,23 @@ +.content { + flex: 1 1 0; + display: flex; + flex-flow: row; +} + +.column { + flex: 1 1 0; + margin: 0; + padding: 0; + overflow: auto; +} + +.no-object { + color: var(--color-blue); + + font-family: var(--code-font-family); + font-weight: var(--code-font-weight); + font-size: var(--code-font-size); + font-variant-ligatures: var(--code-font-variant-ligatures); + text-wrap: nowrap; + white-space: pre; +} diff --git a/webview/views/DiffView.tsx b/webview/views/DiffView.tsx new file mode 100644 index 0000000..a23d0c9 --- /dev/null +++ b/webview/views/DiffView.tsx @@ -0,0 +1,822 @@ +import headerStyles from '../common/Header.module.css'; +import styles from './DiffView.module.css'; + +import clsx from 'clsx'; +import { type diff, display } from 'objdiff-wasm'; +import { useCallback, useMemo, useState } from 'react'; +import AutoSizer from 'react-virtualized-auto-sizer'; +import { useShallow } from 'zustand/react/shallow'; +import type { BuildStatus } from '../../shared/messages'; +import { + type ContextMenuRender, + renderContextItems, +} from '../common/ContextMenu'; +import type { TooltipCallback } from '../common/TooltipShared'; +import type { DiffOutput } from '../diff'; +import { + type Side, + type SymbolRefByName, + buildDiffConfig, + runBuild, + setCurrentUnit, + useAppStore, + useExtensionStore, +} from '../state'; +import { percentClass } from '../util/util'; +import { + InstructionContextMenuProvider, + InstructionList, + InstructionTooltip, + type InstructionTooltipContent, +} from './FunctionView'; +import { + SymbolContextMenuProvider, + SymbolList, + SymbolTooltip, + type SymbolTooltipContent, +} from './SymbolsView'; + +type ColumnViewBuildStatus = { + type: 'buildStatus'; + status: BuildStatus; +}; + +type ColumnViewAsm = { + type: 'asm'; + obj: diff.ObjectDiff; + symbol: display.SymbolDisplay; +}; + +type ColumnViewSymbols = { + type: 'symbols'; + mappingSymbol: number | null; +}; + +type ColumnViewNone = { + type: 'none'; +}; + +type ColumnView = + | ColumnViewNone + | ColumnViewBuildStatus + | ColumnViewAsm + | ColumnViewSymbols; + +export const resolveSymbol = ( + obj: diff.ObjectDiff | undefined, + symbolRef: SymbolRefByName | null, +): display.SymbolDisplay | null => { + if (!symbolRef || !obj) { + return null; + } + const leftSymbol = obj?.findSymbol( + symbolRef.symbolName, + symbolRef.sectionName ?? undefined, + ); + if (leftSymbol === undefined) { + return null; + } + return display.displaySymbol(obj, leftSymbol.id); +}; + +const DiffView = ({ + result, + leftSymbolRef, + rightSymbolRef, +}: { + result: DiffOutput; + leftSymbolRef: SymbolRefByName | null; + rightSymbolRef: SymbolRefByName | null; +}) => { + const { configProperties } = useExtensionStore( + useShallow((state) => ({ + configProperties: state.configProperties, + })), + ); + const leftSymbol = useMemo( + () => resolveSymbol(result.diff?.left, leftSymbolRef), + [result.diff?.left, leftSymbolRef], + ); + const rightSymbol = useMemo( + () => resolveSymbol(result.diff?.right, rightSymbolRef), + [result.diff?.right, rightSymbolRef], + ); + const diffConfig = useMemo( + () => buildDiffConfig(configProperties), + [configProperties], + ); + + let leftColumnView: ColumnView = { + type: 'symbols', + mappingSymbol: null, + }; + let rightColumnView: ColumnView = { + type: 'symbols', + mappingSymbol: null, + }; + + const leftSuccess = result.leftStatus?.success ?? false; + const rightSuccess = result.rightStatus?.success ?? false; + if (!leftSuccess) { + if (result.leftStatus) { + leftColumnView = { + type: 'buildStatus', + status: result.leftStatus, + }; + } else { + leftColumnView = { + type: 'none', + }; + } + } + if (!rightSuccess) { + if (result.rightStatus) { + rightColumnView = { + type: 'buildStatus', + status: result.rightStatus, + }; + } else { + rightColumnView = { + type: 'none', + }; + } + } + + if (leftSymbol && rightSymbol) { + // Joint function view + leftColumnView = { + type: 'asm', + obj: result.diff!.left!, + symbol: leftSymbol, + }; + rightColumnView = { + type: 'asm', + obj: result.diff!.right!, + symbol: rightSymbol, + }; + } else if (leftSymbol) { + // Left function view only + leftColumnView = { + type: 'asm', + obj: result.diff!.left!, + symbol: leftSymbol, + }; + if (rightSuccess) { + // Mapping view + rightColumnView = { + type: 'symbols', + mappingSymbol: leftSymbol.info.id, + }; + } + } else if (rightSymbol) { + // Right function view only + rightColumnView = { + type: 'asm', + obj: result.diff!.right!, + symbol: rightSymbol, + }; + if (leftSuccess) { + // Mapping view + leftColumnView = { + type: 'symbols', + mappingSymbol: rightSymbol.info.id, + }; + } + } + + const symbolContextMenuRender: ContextMenuRender = + useCallback( + ({ data }, close) => { + let obj: diff.ObjectDiff | undefined; + switch (data.side) { + case 'left': + obj = result.diff?.left; + break; + case 'right': + obj = result.diff?.right; + break; + default: + break; + } + if (!obj) { + return null; + } + const items = display.symbolContext(obj, data.symbolRef); + return renderContextItems(items, close); + }, + [result.diff], + ); + + const symbolTooltipCallback: TooltipCallback = + useCallback( + (data) => { + let obj: diff.ObjectDiff | undefined; + switch (data.side) { + case 'left': + obj = result.diff?.left; + break; + case 'right': + obj = result.diff?.right; + break; + default: + break; + } + if (!obj) { + return null; + } + return display.symbolHover(obj, data.symbolRef); + }, + [result.diff], + ); + + const instructionContextMenuRender: ContextMenuRender = + useCallback( + ({ data }, close) => { + let obj: diff.ObjectDiff | undefined; + let symbol: number | undefined; + switch (data.column) { + case 0: + obj = result.diff?.left; + symbol = leftSymbol?.info.id; + break; + case 1: + obj = result.diff?.right; + symbol = rightSymbol?.info.id; + break; + default: + break; + } + if (!obj || symbol === undefined) { + return null; + } + const items = display.instructionContext( + obj, + symbol, + data.row, + diffConfig, + ); + return renderContextItems(items, close); + }, + [result.diff, leftSymbol, rightSymbol, diffConfig], + ); + + const instructionTooltipCallback: TooltipCallback = + useCallback( + (data) => { + let obj: diff.ObjectDiff | undefined; + let symbol: number | undefined; + switch (data.column) { + case 0: + obj = result.diff?.left; + symbol = leftSymbol?.info.id; + break; + case 1: + obj = result.diff?.right; + symbol = rightSymbol?.info.id; + break; + default: + break; + } + if (!obj || symbol === undefined) { + return null; + } + return display.instructionHover(obj, symbol, data.row, diffConfig); + }, + [result.diff, leftSymbol, rightSymbol, diffConfig], + ); + + const [showMappedSymbols, setShowMappedSymbols] = useState(false); + + return ( + <> + +
+ + + + {({ height, width }) => ( + + )} + + + +
+ + + + ); +}; + +const DiffViewHeader = ({ + result, + leftSymbolRef, + rightSymbolRef, + leftColumnView, + rightColumnView, + showMappedSymbols, + setShowMappedSymbols, +}: { + result: DiffOutput; + leftSymbolRef: SymbolRefByName | null; + rightSymbolRef: SymbolRefByName | null; + leftColumnView: ColumnView; + rightColumnView: ColumnView; + showMappedSymbols: boolean; + setShowMappedSymbols: (value: boolean) => void; +}) => { + const { buildRunning, currentUnit, hasProjectConfig } = useExtensionStore( + useShallow((state) => ({ + buildRunning: state.buildRunning, + currentUnit: state.currentUnit, + hasProjectConfig: state.projectConfig != null, + })), + ); + const currentUnitName = currentUnit?.name || ''; + const { + search, + setUnitSectionCollapsed, + setUnitSearch, + setCurrentView, + setSelectedSymbol, + setUnitMapping, + } = useAppStore( + useShallow((state) => { + const unit = state.getUnitState(currentUnitName); + return { + search: unit.search, + setUnitSectionCollapsed: state.setUnitSectionCollapsed, + setUnitSearch: state.setUnitSearch, + setCurrentView: state.setCurrentView, + setSelectedSymbol: state.setSelectedSymbol, + setUnitMapping: state.setUnitMapping, + }; + }), + ); + + const onBackClick = useCallback(() => { + if (leftSymbolRef || rightSymbolRef) { + setSelectedSymbol(null, null); + } else if (hasProjectConfig) { + setCurrentUnit(null); + } + }, [leftSymbolRef, rightSymbolRef, setSelectedSymbol, hasProjectConfig]); + + const setAllSections = (side: Side, value: boolean) => { + if (side === 'left') { + if (result.diff?.left) { + const displaySections = display.displaySections( + result.diff.left, + { + mapping: undefined, + regex: undefined, + }, + { + showHiddenSymbols: false, + showMappedSymbols: false, + reverseFnOrder: false, + }, + ); + for (const section of displaySections) { + setUnitSectionCollapsed(currentUnitName, section.id, 'left', value); + } + } + } else if (result.diff?.right) { + const displaySections = display.displaySections( + result.diff.right, + { + mapping: undefined, + regex: undefined, + }, + { + showHiddenSymbols: false, + showMappedSymbols: false, + reverseFnOrder: false, + }, + ); + for (const section of displaySections) { + setUnitSectionCollapsed(currentUnitName, section.id, 'right', value); + } + } + }; + + const expandCollapse = (side: Side) => ( + <> +
+ + + + ); + + const onSearchChange = useCallback( + (e: React.ChangeEvent) => + setUnitSearch(currentUnitName, e.target.value), + [currentUnitName, setUnitSearch], + ); + + const onSettingsClick = useCallback(() => { + setCurrentView('settings'); + }, [setCurrentView]); + + const changeBase = useCallback(() => { + setUnitMapping(currentUnitName, leftSymbolRef?.symbolName, null); + setSelectedSymbol(leftSymbolRef, null); + }, [currentUnitName, leftSymbolRef, setUnitMapping, setSelectedSymbol]); + + const changeTarget = useCallback(() => { + setUnitMapping(currentUnitName, null, rightSymbolRef?.symbolName); + setSelectedSymbol(null, rightSymbolRef); + }, [currentUnitName, rightSymbolRef, setUnitMapping, setSelectedSymbol]); + + const onShowMappedSymbolsChange = useCallback( + (e: React.ChangeEvent) => + setShowMappedSymbols(e.target.checked), + [setShowMappedSymbols], + ); + + const showMappedSymbolsInput = ( +
+ + +
+ ); + + const filterRow = ( + + ); + + if (leftColumnView.type !== 'asm' && rightColumnView.type !== 'asm') { + const unitNameRow = ( + + {currentUnitName} + + ); + + const settingsRow = ( + + ); + + return ( +
+
+
+ {hasProjectConfig ? ( + + ) : null} + Target object +
+
+ {currentUnitName ? unitNameRow : filterRow} + {expandCollapse('left')} +
+
+
+
+ {hasProjectConfig && ( + + )} + Base object +
+
+ {currentUnitName ? filterRow : settingsRow} + {expandCollapse('right')} +
+
+
+ ); + } + + const matchPercent = + leftColumnView.type === 'asm' + ? leftColumnView.symbol.matchPercent + : undefined; + + return ( +
+
+
+ +
+
+ +
+
+ {result.isMapping ? ( + showMappedSymbolsInput + ) : ( + + )} +
+
+
+
+ {hasProjectConfig && ( + + )} + {result.lastBuilt && ( + + Last built:{' '} + {new Date(result.lastBuilt).toLocaleTimeString('en-US')} + + )} +
+
+ {matchPercent !== undefined && ( + <> + + {Math.floor(matchPercent).toFixed(0)}% + + {' | '} + + )} + +
+
+ {result.isMapping ? ( + filterRow + ) : ( + + )} +
+
+
+ ); +}; + +const SymbolLabel = ({ + view, + side, + isMapping, + currentUnitName, +}: { + view: ColumnView; + side: Side; + isMapping: boolean; + currentUnitName: string; +}) => { + switch (view.type) { + case 'asm': { + const displayName = + view.symbol.info.demangledName || view.symbol.info.name; + return ( + + {displayName} + + ); + } + case 'buildStatus': + return ( + + Build failed + + ); + case 'symbols': { + if (isMapping) { + switch (side) { + case 'left': + return ( + + Choose target symbol + + ); + case 'right': + return ( + + Choose base symbol + + ); + } + } + return ( + + {currentUnitName} + + ); + } + default: + return ( + + Missing + + ); + } +}; + +const DiffViewContent = ({ + result, + height, + width, + leftColumnView, + rightColumnView, + showMappedSymbols, + showHiddenSymbols, +}: { + result: DiffOutput; + height: number; + width: number; + leftColumnView: ColumnView; + rightColumnView: ColumnView; + showMappedSymbols: boolean; + showHiddenSymbols: boolean; +}) => { + // Shared symbols view state + const [highlightedPath, setHighlightedPath] = useState(null); + const [hoverSymbols, setHoverSymbols] = useState< + [number | null, number | null] + >([null, null]); + + if (leftColumnView.type === 'asm' && rightColumnView.type === 'asm') { + // Render joint function view + return ( + + ); + } + + let leftColumn = null; + let rightColumn = null; + if (leftColumnView.type === 'symbols') { + leftColumn = ( + + ); + } else if (leftColumnView.type === 'asm') { + leftColumn = ( + + ); + } else if (leftColumnView.type === 'buildStatus') { + leftColumn = ( + + ); + } else if (leftColumnView.type === 'none') { + leftColumn = ; + } + + if (rightColumnView.type === 'symbols') { + rightColumn = ( + + ); + } else if (rightColumnView.type === 'asm') { + rightColumn = ( + + ); + } else if (rightColumnView.type === 'buildStatus') { + rightColumn = ( + + ); + } else if (rightColumnView.type === 'none') { + rightColumn = ; + } + + return ( + <> + {leftColumn} + {rightColumn} + + ); +}; + +const NoObjectView = ({ + height, + width, +}: { + height: number; + width: number; +}) => ( +
+ No object configured +
+); + +const BuildStatusView = ({ + status, + height, + width, +}: { + status: BuildStatus; + height: number; + width: number; +}) => ( +
+
{status.cmdline}
+
{status.stdout}
+
{status.stderr}
+
+); + +export default DiffView; diff --git a/webview/views/FunctionView.module.css b/webview/views/FunctionView.module.css index c40238c..dc6423d 100644 --- a/webview/views/FunctionView.module.css +++ b/webview/views/FunctionView.module.css @@ -5,8 +5,6 @@ .instruction-row { display: flex; flex-direction: row; - gap: 0.5em; - height: var(--list-row-height); } .instruction-cell { diff --git a/webview/views/FunctionView.tsx b/webview/views/FunctionView.tsx index e2a7026..9725c4a 100644 --- a/webview/views/FunctionView.tsx +++ b/webview/views/FunctionView.tsx @@ -4,26 +4,20 @@ import styles from './FunctionView.module.css'; import clsx from 'clsx'; import memoizeOne from 'memoize-one'; import { type diff, display } from 'objdiff-wasm'; -import { memo, useMemo } from 'react'; -import AutoSizer from 'react-virtualized-auto-sizer'; +import { memo, useCallback, useMemo } from 'react'; import { FixedSizeList, areEqual } from 'react-window'; import type { ListChildComponentProps } from 'react-window'; import { useShallow } from 'zustand/react/shallow'; import { createContextMenu, renderContextItems } from '../common/ContextMenu'; -import TooltipShared from '../common/TooltipShared'; -import { - buildDiffConfig, - runBuild, - useAppStore, - useExtensionStore, -} from '../state'; +import { createTooltip } from '../common/TooltipShared'; +import { buildDiffConfig, useAppStore, useExtensionStore } from '../state'; import { type HighlightState, highlightColumn, highlightMatches, updateHighlight, } from '../util/highlight'; -import { percentClass, useFontSize } from '../util/util'; +import { useFontSize } from '../util/util'; const ROTATION_CLASSES = [ styles.rotation0, @@ -37,10 +31,20 @@ const ROTATION_CLASSES = [ styles.rotation8, ]; -const { ContextMenuProvider, useContextMenu } = createContextMenu<{ +export type InstructionTooltipContent = { column: number; row: number; -}>(); +}; + +export const { + Tooltip: InstructionTooltip, + useTooltip: useInstructionTooltip, +} = createTooltip(); + +export const { + ContextMenuProvider: InstructionContextMenuProvider, + useContextMenu: useInstructionContextMenu, +} = createContextMenu(); const AsmCell = ({ obj, @@ -53,15 +57,28 @@ const AsmCell = ({ }: { obj: diff.ObjectDiff | undefined; config: diff.DiffConfig; - symbol: display.SectionDisplaySymbol | null; + symbol: display.SymbolRef | null; row: number; column: number; highlight: HighlightState; setHighlight: (highlight: HighlightState) => void; }) => { - const onContextMenu = useContextMenu(); + const onContextMenu = useInstructionContextMenu(); + const tooltipContent: InstructionTooltipContent = useMemo( + () => ({ + column, + row, + }), + [column, row], + ); + const tooltipProps = useInstructionTooltip(tooltipContent); + const onContextMenuMemo = useCallback( + (e: React.MouseEvent) => onContextMenu(e, tooltipContent), + [onContextMenu, tooltipContent], + ); + if (!obj || !symbol) { - return
; + return null; } const highlight = highlightColumn(highlightState, column); @@ -198,33 +215,24 @@ const AsmCell = ({ return
; } - const tooltipContent: InstructionTooltipContent = { column, row }; return (
onContextMenu(e, { column, row })} + onContextMenu={onContextMenuMemo} + {...tooltipProps} > {out}
); }; -type InstructionTooltipContent = { - column: number; - row: number; -}; - type ItemData = { itemCount: number; symbolName: string; result: diff.DiffResult; config: diff.DiffConfig; matchPercent?: number; - left: display.SectionDisplaySymbol | null; leftSymbol: display.SymbolDisplay | null; - right: display.SectionDisplaySymbol | null; rightSymbol: display.SymbolDisplay | null; highlight: HighlightState; setHighlight: (highlight: HighlightState) => void; @@ -234,7 +242,7 @@ const AsmRow = memo( ({ index, style, - data: { result, config, left, right, highlight, setHighlight }, + data: { result, config, leftSymbol, rightSymbol, highlight, setHighlight }, }: ListChildComponentProps) => { return (
void, ): ItemData => { - const leftSymbol = left ? display.displaySymbol(result.left!, left) : null; - const rightSymbol = right - ? display.displaySymbol(result.right!, right) - : null; const itemCount = Math.max( leftSymbol?.rowCount || 0, rightSymbol?.rowCount || 0, ); - const symbolName = leftSymbol?.name || rightSymbol?.name || ''; + const symbolName = leftSymbol?.info.name || rightSymbol?.info.name || ''; const config = buildDiffConfig(null); const matchPercent = rightSymbol?.matchPercent; return { @@ -300,9 +304,7 @@ const createItemData = memoizeOne( result, config, matchPercent, - left, leftSymbol, - right, rightSymbol, highlight, setHighlight, @@ -322,7 +324,7 @@ const SymbolLabel = ({ ); } - const displayName = symbol.demangledName || symbol.name; + const displayName = symbol.info.demangledName || symbol.info.name; return ( { - const { buildRunning, currentUnit, lastBuilt, hasProjectConfig } = - useExtensionStore( - useShallow((state) => ({ - buildRunning: state.buildRunning, - currentUnit: state.currentUnit, - lastBuilt: state.lastBuilt, - hasProjectConfig: state.projectConfig != null, - })), - ); + const currentUnit = useExtensionStore((state) => state.currentUnit); + const { highlight, setSymbolScrollOffset, setHighlight } = useAppStore( + useShallow((state) => ({ + highlight: state.highlight, + setSymbolScrollOffset: state.setSymbolScrollOffset, + setHighlight: state.setHighlight, + })), + ); + const itemData = createItemData( + diff, + leftSymbol, + rightSymbol, + highlight, + setHighlight, + ); const currentUnitName = currentUnit?.name || ''; - const { highlight, setSelectedSymbol, setSymbolScrollOffset, setHighlight } = - useAppStore( - useShallow((state) => ({ - highlight: state.highlight, - setSelectedSymbol: state.setSelectedSymbol, - setSymbolScrollOffset: state.setSymbolScrollOffset, - setHighlight: state.setHighlight, - })), - ); - - const itemData = createItemData(diff, left, right, highlight, setHighlight); const initialScrollOffset = useMemo( () => useAppStore.getState().getUnitState(currentUnitName).symbolScrollOffsets[ @@ -370,140 +371,25 @@ const FunctionView = ({ ] || 0, [currentUnitName, itemData.symbolName], ); - const itemSize = useFontSize() * 1.33; return ( - <> -
-
-
- -
-
- -
-
-
-
- {hasProjectConfig && ( - - )} - {lastBuilt && ( - - Last built: {new Date(lastBuilt).toLocaleTimeString('en-US')} - - )} -
-
- {itemData.matchPercent !== undefined && ( - <> - - {Math.floor(itemData.matchPercent).toFixed(0)}% - - {' | '} - - )} - -
-
-
-
- { - let obj: diff.ObjectDiff | undefined; - let symbol: display.SectionDisplaySymbol | undefined; - switch (data.column) { - case 0: - obj = diff.left; - symbol = itemData.left ?? undefined; - break; - case 1: - obj = diff.right; - symbol = itemData.right ?? undefined; - break; - default: - break; - } - if (!obj || !symbol) { - return null; - } - const items = display.instructionContext( - obj, - symbol, - data.row, - itemData.config, - ); - return renderContextItems(items, close); - }} - > - - {({ height, width }) => ( - { - setSymbolScrollOffset( - currentUnitName, - itemData.symbolName, - e.scrollOffset, - ); - }} - initialScrollOffset={initialScrollOffset} - > - {AsmRow} - - )} - - -
- { - const data: InstructionTooltipContent = JSON.parse(content); - let obj: diff.ObjectDiff | undefined; - let symbol: display.SectionDisplaySymbol | undefined; - switch (data.column) { - case 0: - obj = diff.left; - symbol = itemData.left ?? undefined; - break; - case 1: - obj = diff.right; - symbol = itemData.right ?? undefined; - break; - default: - break; - } - if (!obj || !symbol) { - return null; - } - return display.instructionHover( - obj, - symbol, - data.row, - itemData.config, - ); - }} - /> - + { + setSymbolScrollOffset( + currentUnitName, + itemData.symbolName, + e.scrollOffset, + ); + }} + initialScrollOffset={initialScrollOffset} + > + {AsmRow} + ); }; - -export default FunctionView; diff --git a/webview/views/SymbolsView.module.css b/webview/views/SymbolsView.module.css index 76098d8..f596446 100644 --- a/webview/views/SymbolsView.module.css +++ b/webview/views/SymbolsView.module.css @@ -11,41 +11,6 @@ padding: 0; } -.symbol-list-row { - cursor: pointer; - user-select: none; - height: var(--list-row-height); - - font-family: var(--code-font-family); - font-weight: var(--code-font-weight); - font-size: var(--code-font-size); - font-variant-ligatures: var(--code-font-variant-ligatures); - text-wrap: nowrap; - white-space: pre; - - &:hover { - background-color: var(--list-row-hover-background); - } -} - -.section { - padding-left: 0.5em; - - &::before { - content: "▼ "; - } - &.collapsed { - opacity: 0.75; - &::before { - content: "▶ "; - } - } -} - -.symbol { - padding-left: 2em; -} - .flag-local { color: inherit; } @@ -62,6 +27,10 @@ color: var(--color-blue); } +.flag-hidden { + color: var(--color-muted); +} + .symbol-name { color: var(--color-bright); } @@ -76,3 +45,19 @@ text-wrap: nowrap; white-space: pre; } + +.selected { + background-color: var(--list-row-selection-background) !important; +} + +.highlighted { + background-color: var(--list-row-highlight-background) !important; +} + +.selected.highlighted { + background-color: color-mix( + in srgb, + var(--list-row-selection-background) 50%, + var(--list-row-highlight-background) 50% + ) !important; +} diff --git a/webview/views/SymbolsView.tsx b/webview/views/SymbolsView.tsx index 5a9c4cc..a19788c 100644 --- a/webview/views/SymbolsView.tsx +++ b/webview/views/SymbolsView.tsx @@ -1,47 +1,44 @@ -import headerStyles from '../common/Header.module.css'; import styles from './SymbolsView.module.css'; -import clsx from 'clsx'; import memoizeOne from 'memoize-one'; import { type diff, display } from 'objdiff-wasm'; -import { memo, useCallback, useMemo } from 'react'; -import AutoSizer from 'react-virtualized-auto-sizer'; +import { memo, useCallback, useMemo, useState } from 'react'; import { FixedSizeList, type ListChildComponentProps, areEqual, } from 'react-window'; import { useShallow } from 'zustand/react/shallow'; -import type { BuildStatus } from '../../shared/messages'; -import { createContextMenu, renderContextItems } from '../common/ContextMenu'; -import TooltipShared from '../common/TooltipShared'; +import type { Unit } from '../../shared/config'; +import { createContextMenu } from '../common/ContextMenu'; +import { createTooltip } from '../common/TooltipShared'; +import type { DiffOutput } from '../diff'; import { - type UnitScrollOffsets, - runBuild, - setCurrentUnit, + type Side, + type SymbolRefByName, useAppStore, useExtensionStore, } from '../state'; import { percentClass, useFontSize } from '../util/util'; +import { type TreeData, TreeRow } from './TreeView'; -type Side = keyof UnitScrollOffsets; - -type SymbolTooltipContent = { - symbolRef: display.SectionDisplaySymbol; +export type SymbolTooltipContent = { + symbolRef: display.SymbolRef; side: Side; }; -const { ContextMenuProvider, useContextMenu } = - createContextMenu(); +export const { Tooltip: SymbolTooltip, useTooltip: useSymbolTooltip } = + createTooltip(); + +export const { + ContextMenuProvider: SymbolContextMenuProvider, + useContextMenu: useSymbolContextMenu, +} = createContextMenu(); const SectionRow = ({ section, - style, - onClick, }: { - section: SectionData; - style?: React.CSSProperties; - onClick?: React.MouseEventHandler; + section: display.SectionDisplay; }) => { let percentElem = null; if (section.matchPercent != null) { @@ -56,63 +53,53 @@ const SectionRow = ({ ); } return ( -
+ {section.name} ({section.size.toString(16)}){percentElem} -
+
); }; const SymbolRow = ({ - obj, - section, - symbolRef, - side, - style, + symbol, }: { - obj: diff.ObjectDiff; - section: SectionData; - symbolRef: display.SectionDisplaySymbol; - side: Side; - style?: React.CSSProperties; + symbol: display.SymbolDisplay; }) => { - const setSelectedSymbol = useAppStore((state) => state.setSelectedSymbol); - const onContextMenu = useContextMenu(); - const symbol = display.displaySymbol(obj, symbolRef); const flags = []; - if (symbol.flags.global) { + if (symbol.info.flags.global) { flags.push( g , ); } - if (symbol.flags.weak) { + if (symbol.info.flags.weak) { flags.push( w , ); } - if (symbol.flags.local) { + if (symbol.info.flags.local) { flags.push( l , ); } - if (symbol.flags.common) { + if (symbol.info.flags.common) { flags.push( c , ); } + if (symbol.info.flags.hidden) { + flags.push( + + h + , + ); + } let flagsElem = null; if (flags.length > 0) { flagsElem = <>[{flags}] ; @@ -129,172 +116,286 @@ const SymbolRow = ({ ); } - const tooltipContent: SymbolTooltipContent = { - symbolRef, - side, - }; return ( -
{ - setSelectedSymbol( - { - symbolName: symbol.name, - sectionName: section.name, - }, - { - symbolName: symbol.name, - sectionName: section.name, - }, - ); - }} - data-tooltip-id="symbol-tooltip" - data-tooltip-content={JSON.stringify(tooltipContent)} - onContextMenu={(e) => { - onContextMenu(e, tooltipContent); - }} - > + <> {flagsElem} {percentElem} - {symbol.demangledName || symbol.name} + {symbol.info.demangledName || symbol.info.name} -
+ ); }; -type SectionData = display.SectionDisplay & { collapsed: boolean }; +type SymbolData = { + section: display.SectionDisplay; + symbolRef: display.SymbolRef; + selected: boolean; + highlighted: boolean; +}; type ItemData = { - status: BuildStatus | null; obj: diff.ObjectDiff | undefined; - itemCount: number; - sections: SectionData[]; + otherObj?: diff.ObjectDiff | undefined; + sections: display.SectionDisplay[]; + treeData: TreeData; side: Side; + isMapping: boolean; + currentUnitName: string; setSectionCollapsed: (section: string, collapsed: boolean) => void; + setHoverSymbols: (value: [number | null, number | null]) => void; }; const SymbolListRow = memo( ({ index, style, - data: { obj, sections, side, setSectionCollapsed }, + data: { + obj, + otherObj, + treeData, + side, + isMapping, + currentUnitName, + setSectionCollapsed, + setHoverSymbols, + }, }: ListChildComponentProps) => { + const { setSelectedSymbol, setUnitMapping } = useAppStore( + useShallow((state) => ({ + setSelectedSymbol: state.setSelectedSymbol, + setUnitMapping: state.setUnitMapping, + })), + ); + const onContextMenu = useSymbolContextMenu(); if (!obj) { return null; } - let currentIndex = 0; - for (const section of sections) { - if (currentIndex === index) { - return ( - setSectionCollapsed(section.id, !section.collapsed)} - /> - ); - } - currentIndex++; - if (section.collapsed) { - continue; - } - if (index < currentIndex + section.symbols.length) { - const symbolRef = section.symbols[index - currentIndex]; - return ( - - ); - } - currentIndex += section.symbols.length; + const node = treeData.nodes[index]; + if (node.type === 'leaf') { + const { symbolRef, section, selected, highlighted } = node.data; + const symbol = display.displaySymbol(obj, symbolRef); + const tooltipContent: SymbolTooltipContent = { + symbolRef, + side, + }; + const tooltipProps = useSymbolTooltip(tooltipContent); + return ( + } + getClasses={() => { + const classes = []; + if (selected) { + classes.push(styles.selected); + } + if (highlighted) { + classes.push(styles.highlighted); + } + return classes; + }} + onLeafClick={() => { + const symbolRefByName: SymbolRefByName = { + symbolName: symbol.info.name, + sectionName: section.name, + }; + let otherSymbolRefByName: SymbolRefByName | null = null; + if (symbol.targetSymbol !== undefined && otherObj) { + const targetSymbol = otherObj.getSymbol(symbol.targetSymbol); + if (targetSymbol) { + otherSymbolRefByName = { + symbolName: targetSymbol.name, + sectionName: targetSymbol.sectionName ?? null, + }; + } + } + if (isMapping) { + if (side === 'left') { + setUnitMapping( + currentUnitName, + symbolRefByName.symbolName, + otherSymbolRefByName?.symbolName, + ); + } else { + setUnitMapping( + currentUnitName, + otherSymbolRefByName?.symbolName, + symbolRefByName.symbolName, + ); + } + } + if (side === 'left') { + setSelectedSymbol(symbolRefByName, otherSymbolRefByName); + } else { + setSelectedSymbol(otherSymbolRefByName, symbolRefByName); + } + }} + onHover={() => { + const targetSymbol = symbol.targetSymbol ?? null; + if (side === 'left') { + setHoverSymbols([symbolRef, targetSymbol]); + } else { + setHoverSymbols([targetSymbol, symbolRef]); + } + }} + rowProps={{ + ...tooltipProps, + onContextMenu: (e) => onContextMenu(e, tooltipContent), + }} + /> + ); } - return null; + return ( + } + setBranchCollapsed={setSectionCollapsed} + onHover={() => setHoverSymbols([null, null])} + /> + ); }, areEqual, ); const createItemDataFn = ( - status: BuildStatus | null, obj: diff.ObjectDiff | undefined, + otherObj: diff.ObjectDiff | undefined, collapsedSections: Record, search: string | null, side: Side, + isMapping: boolean, setSectionCollapsed: (section: string, collapsed: boolean) => void, + highlightedPath: string | null, + setHighlightedPath: (id: string | null) => void, + hoverSymbol: number | null, + setHoverSymbols: (value: [number | null, number | null]) => void, + mappingSymbol: number | null, + currentUnit: Unit | null, + showMappedSymbols: boolean, + showHiddenSymbols: boolean, + diffLabel: string | null, ): ItemData => { + const currentUnitName = currentUnit?.name || ''; if (!obj) { return { - status, obj, - itemCount: 0, + otherObj, sections: [], + treeData: { + leafCount: 0, + nodes: [], + highlightedPath, + setHighlightedPath, + }, side, + isMapping, + currentUnitName, setSectionCollapsed, + setHoverSymbols, }; } - const displaySections = display.displaySections( + const reverseFnOrder = + currentUnit?.metadata?.reverse_fn_order ?? + currentUnit?.reverse_fn_order ?? + false; + const sections = display.displaySections( obj, { - mapping: undefined, + mapping: mappingSymbol ?? undefined, regex: search ?? undefined, }, { - showHiddenSymbols: false, - showMappedSymbols: false, - reverseFnOrder: false, + showHiddenSymbols, + showMappedSymbols, + reverseFnOrder, }, ); - let itemCount = 0; - const sections: SectionData[] = []; - for (const section of displaySections) { - itemCount++; + const treeData: ItemData['treeData'] = { + leafCount: 0, + nodes: [], + highlightedPath, + setHighlightedPath, + }; + for (const section of sections) { if (search !== null && section.symbols.length === 0) { continue; } - if (collapsedSections[section.id]) { - sections.push({ - ...section, - symbols: [], - collapsed: true, - }); - continue; - } - itemCount += section.symbols.length; - sections.push({ - ...section, - collapsed: false, + treeData.leafCount += section.symbols.length; + const collapsed = collapsedSections[section.id]; + treeData.nodes.push({ + type: 'branch', + id: section.id, + indent: 0, + path: [], + data: section, + collapsed, }); + if (!collapsed) { + for (const symbolRef of section.symbols) { + const symbol = display.displaySymbol(obj, symbolRef); + treeData.nodes.push({ + type: 'leaf', + id: `symbol-${symbolRef}`, + indent: 1, + path: [section.id], + data: { + section, + symbolRef, + selected: hoverSymbol === symbolRef, + highlighted: diffLabel !== null && diffLabel === symbol.info.name, + }, + }); + } + } } return { - status, obj, - itemCount, + otherObj, sections, + treeData, side, + isMapping, + currentUnitName, setSectionCollapsed, + setHoverSymbols, }; }; const createItemDataLeft = memoizeOne(createItemDataFn); const createItemDataRight = memoizeOne(createItemDataFn); -const SymbolsView = ({ diff }: { diff: diff.DiffResult }) => { - const { - buildRunning, - currentUnit, - hasProjectConfig, - leftStatus, - rightStatus, - } = useExtensionStore( +export const SymbolList = ({ + height, + width, + side, + result, + mappingSymbol, + showMappedSymbols, + showHiddenSymbols, + highlightedPath, + setHighlightedPath, + hoverSymbols, + setHoverSymbols, +}: { + height: number; + width: number; + side: Side; + result: DiffOutput; + mappingSymbol: number | null; + showMappedSymbols: boolean; + showHiddenSymbols: boolean; + highlightedPath: string | null; + setHighlightedPath: (id: string | null) => void; + hoverSymbols: [number | null, number | null]; + setHoverSymbols: (value: [number | null, number | null]) => void; +}) => { + const { currentUnit, diffLabel } = useExtensionStore( useShallow((state) => ({ - buildRunning: state.buildRunning, currentUnit: state.currentUnit, - hasProjectConfig: state.projectConfig != null, - leftStatus: state.leftStatus, - rightStatus: state.rightStatus, + diffLabel: state.diffLabel, })), ); const currentUnitName = currentUnit?.name || ''; @@ -303,8 +404,6 @@ const SymbolsView = ({ diff }: { diff: diff.DiffResult }) => { search, setUnitSectionCollapsed, setUnitScrollOffset, - setUnitSearch, - setCurrentView, } = useAppStore( useShallow((state) => { const unit = state.getUnitState(currentUnitName); @@ -313,8 +412,6 @@ const SymbolsView = ({ diff }: { diff: diff.DiffResult }) => { search: unit.search, setUnitSectionCollapsed: state.setUnitSectionCollapsed, setUnitScrollOffset: state.setUnitScrollOffset, - setUnitSearch: state.setUnitSearch, - setCurrentView: state.setCurrentView, }; }), ); @@ -322,220 +419,51 @@ const SymbolsView = ({ diff }: { diff: diff.DiffResult }) => { () => useAppStore.getState().getUnitState(currentUnitName).scrollOffsets, [currentUnitName], ); - const setLeftSectionCollapsed = useCallback( + + const setSectionCollapsed = useCallback( (section: string, collapsed: boolean) => { - setUnitSectionCollapsed(currentUnitName, section, 'left', collapsed); + setUnitSectionCollapsed(currentUnitName, section, side, collapsed); }, - [currentUnitName, setUnitSectionCollapsed], - ); - const setRightSectionCollapsed = useCallback( - (section: string, collapsed: boolean) => { - setUnitSectionCollapsed(currentUnitName, section, 'right', collapsed); - }, - [currentUnitName, setUnitSectionCollapsed], + [currentUnitName, setUnitSectionCollapsed, side], ); - const renderList = ( - height: number, - width: number, - itemData: ItemData, - side: Side, - ) => { - if (!itemData.obj) { - if (!itemData.status || itemData.status.success) { - return ( -
- No object configured -
- ); - } - return ( -
-
{itemData.status.cmdline}
-
{itemData.status.stdout}
-
{itemData.status.stderr}
-
- ); - } - return ( - { - if (currentUnitName) { - setUnitScrollOffset(currentUnitName, side, e.scrollOffset); - } - }} - initialScrollOffset={initialScrollOffsets[side]} - > - {SymbolListRow} - - ); - }; - + const itemData = (side === 'left' ? createItemDataLeft : createItemDataRight)( + side === 'left' ? result.diff?.left : result.diff?.right, + side === 'left' ? result.diff?.right : result.diff?.left, + collapsedSections[side], + search, + side, + result.isMapping, + setSectionCollapsed, + highlightedPath, + setHighlightedPath, + side === 'left' ? hoverSymbols[0] : hoverSymbols[1], + setHoverSymbols, + mappingSymbol, + currentUnit, + showMappedSymbols, + showHiddenSymbols, + diffLabel, + ); const itemSize = useFontSize() * 1.33; - const leftItemData = createItemDataLeft( - leftStatus, - diff.left, - collapsedSections.left, - search, - 'left', - setLeftSectionCollapsed, - ); - const rightItemData = createItemDataRight( - rightStatus, - diff.right, - collapsedSections.right, - search, - 'right', - setRightSectionCollapsed, - ); - - const setAllSections = (side: Side, value: boolean) => { - if (side === 'left') { - for (const section of leftItemData.sections) { - setUnitSectionCollapsed(currentUnitName, section.id, 'left', value); - } - } else { - for (const section of rightItemData.sections) { - setUnitSectionCollapsed(currentUnitName, section.id, 'right', value); - } - } - }; - - const expandCollapse = (side: Side) => ( - <> -
- - - - ); - - const unitNameRow = ( - - {currentUnitName} - - ); - - const filterRow = ( - setUnitSearch(currentUnitName, e.target.value)} - /> - ); - - const settingsRow = ( - - ); - return ( - <> -
-
-
- {hasProjectConfig ? ( - - ) : null} - Target object -
-
- {currentUnitName ? unitNameRow : filterRow} - {expandCollapse('left')} -
-
-
-
- {hasProjectConfig && ( - - )} - Base object -
-
- {currentUnitName ? filterRow : settingsRow} - {expandCollapse('right')} -
-
-
-
- { - let obj: diff.ObjectDiff | undefined; - switch (data.side) { - case 'left': - obj = diff.left; - break; - case 'right': - obj = diff.right; - break; - default: - break; - } - if (!obj) { - return null; - } - const items = display.symbolContext(obj, data.symbolRef); - return renderContextItems(items, close); - }} - > - - {({ height, width }) => ( - <> - {renderList(height, width, leftItemData, 'left')} - {renderList(height, width, rightItemData, 'right')} - - )} - - -
- { - const data: SymbolTooltipContent = JSON.parse(content); - let obj: diff.ObjectDiff | undefined; - switch (data.side) { - case 'left': - obj = diff.left; - break; - case 'right': - obj = diff.right; - break; - default: - break; - } - if (!obj) { - return null; - } - return display.symbolHover(obj, data.symbolRef); - }} - /> - + { + if (currentUnitName) { + setUnitScrollOffset(currentUnitName, side, e.scrollOffset); + } + }} + initialScrollOffset={initialScrollOffsets[side]} + > + {SymbolListRow} + ); }; - -export default SymbolsView; diff --git a/webview/views/TreeView.module.css b/webview/views/TreeView.module.css new file mode 100644 index 0000000..5ab4bd7 --- /dev/null +++ b/webview/views/TreeView.module.css @@ -0,0 +1,42 @@ +.row { + display: flex; + cursor: pointer; + user-select: none; + height: var(--list-row-height); + padding-left: 0.5em; + + font-family: var(--code-font-family); + font-weight: var(--code-font-weight); + font-size: var(--code-font-size); + font-variant-ligatures: var(--code-font-variant-ligatures); + text-wrap: nowrap; + white-space: pre; + + &:hover { + background-color: var(--list-row-hover-background); + } +} + +.indent { + display: inline-block; + height: var(--list-row-height); + width: 0; + border-right: 1px solid var(--panel-separator); + margin-left: 0.5em; + margin-right: 0.5em; +} + +.indent-highlighted { + border-right-color: var(--color-muted); +} + +.toggle { + display: inline-block; + height: var(--list-row-height); + width: 1em; + margin-right: 0.25em; +} + +.collapsed { + color: color-mix(in srgb, var(--foreground) 75%, transparent); +} diff --git a/webview/views/TreeView.tsx b/webview/views/TreeView.tsx new file mode 100644 index 0000000..4973378 --- /dev/null +++ b/webview/views/TreeView.tsx @@ -0,0 +1,215 @@ +import clsx from 'clsx'; +import type { ListChildComponentProps } from 'react-window'; +import styles from './TreeView.module.css'; + +export type NodeInner = { + id: string; + indent: number; + path: string[]; + data: T; +}; + +export type BranchNode = NodeInner & { + type: 'branch'; + collapsed: boolean; +}; + +export type LeafNode = NodeInner & { + type: 'leaf'; +}; + +export type Node = BranchNode | LeafNode; + +export type TreeData = { + leafCount: number; + nodes: Node[]; + highlightedPath: string | null; + setHighlightedPath: (id: string | null) => void; +}; + +export type TreeRowProps = ListChildComponentProps> & { + rowProps?: React.HTMLProps | null; + render: (item: Node) => React.ReactNode; + getClasses?: (item: Node) => string[]; + onLeafClick?: (item: LeafNode) => void; + onHover?: (item: Node) => void; + setBranchCollapsed?: (id: string, collapsed: boolean) => void; +}; + +export function TreeRow({ + index, + style, + data: { nodes, highlightedPath, setHighlightedPath }, + rowProps, + render, + getClasses, + onLeafClick, + onHover, + setBranchCollapsed, +}: TreeRowProps) { + const node = nodes[index]; + const classes = [styles.row]; + if (node.type === 'branch' && node.collapsed) { + classes.push(styles.collapsed); + } + classes.push(...(getClasses?.(node) ?? [])); + const indentItems = []; + for (let i = 0; i < node.indent; i++) { + indentItems.push( + , + ); + } + if (node.type === 'branch') { + indentItems.push( + , + ); + } + return ( +
{ + if (node.type === 'leaf') { + onLeafClick?.(node); + } else { + const collapsed = !node.collapsed; + setBranchCollapsed?.(node.id, collapsed); + setHighlightedPath( + collapsed ? node.path[node.path.length - 1] : node.id, + ); + } + }} + onMouseEnter={() => { + onHover?.(node); + setHighlightedPath( + node.type === 'leaf' || node.collapsed + ? node.path[node.path.length - 1] + : node.id, + ); + }} + > + {indentItems} + {render(node)} +
+ ); +} + +type NodeWithChildren = BranchNode & { + children: (NodeWithChildren | LeafNode)[]; +}; + +export type SimpleTreeNodeData = { label: string }; +export type SimpleTreeData = TreeData< + SimpleTreeNodeData, + L & SimpleTreeNodeData +>; + +// Build a simple tree structure by splitting the path of each item +// into components (splitting on '/') and creating a tree node for +// each component. +export function buildSimpleTree( + items: L[], + getPath: (item: L) => string, + collapsed: Record, + highlightedPath: string | null, + setHighlightedPath: (id: string | null) => void, +): SimpleTreeData { + type SimpleTreeNode = NodeWithChildren< + SimpleTreeNodeData, + L & SimpleTreeNodeData + >; + const map = new Map(); + const rootNodes = []; + for (const item of items) { + const path = getPath(item); + const split = path.split('/'); + let parent: SimpleTreeNode | null = null; + for (let i = 0; i < split.length - 1; i++) { + const name = split[i]; + const dirPath = split.slice(0, i + 1); + const key = dirPath.join('/'); + let node = map.get(key); + if (!node) { + node = { + type: 'branch', + id: key, + indent: i, + collapsed: !!collapsed[key], + children: [], + path: buildPath(dirPath), + data: { label: name }, + }; + if (parent) { + parent.children.push(node); + } else { + rootNodes.push(node); + } + map.set(key, node); + } + parent = node; + } + const node: LeafNode = { + type: 'leaf', + id: path, + indent: split.length - 1, + path: buildPath(split), + data: { + ...item, + label: split[split.length - 1], + }, + }; + if (parent) { + parent.children.push(node); + } else { + rootNodes.push(node); + } + } + const nodes: SimpleTreeData['nodes'] = []; + for (const node of rootNodes) { + pushNodes(node, nodes); + } + return { + leafCount: items.length, + nodes, + highlightedPath, + setHighlightedPath, + }; +} + +function pushNodes( + item: NodeWithChildren | LeafNode, + out: Node[], +) { + if (item.type === 'branch') { + out.push(item); + if (!item.collapsed) { + for (const child of item.children) { + pushNodes(child, out); + } + } + } else if (item.type === 'leaf') { + out.push(item); + } +} + +function buildPath(split: string[]) { + const path = []; + for (let i = 0; i < split.length - 1; i++) { + path.push(split.slice(0, i + 1).join('/')); + } + return path; +} diff --git a/webview/views/UnitsView.module.css b/webview/views/UnitsView.module.css index 180d18c..1849c56 100644 --- a/webview/views/UnitsView.module.css +++ b/webview/views/UnitsView.module.css @@ -5,49 +5,8 @@ overflow: hidden; } -.row { - display: flex; - cursor: pointer; - user-select: none; - height: var(--list-row-height); - padding-left: 0.5em; - - font-family: var(--code-font-family); - font-weight: var(--code-font-weight); - font-size: var(--code-font-size); - font-variant-ligatures: var(--code-font-variant-ligatures); - text-wrap: nowrap; - white-space: pre; - - &:hover { - background-color: var(--list-row-hover-background); - } -} - -.indent { - display: inline-block; - height: var(--list-row-height); - width: 0; - border-right: 1px solid var(--panel-separator); - margin-left: 0.5em; - margin-right: 0.5em; -} - -.indent-highlighted { - border-right-color: var(--color-muted); -} - -.toggle { - display: inline-block; - height: var(--list-row-height); - width: 1em; - margin-right: 0.25em; -} - -.unit { - .label { - margin-left: 0.4em; - } +.unit-label { + margin-left: 0.4em; } .complete { @@ -57,7 +16,3 @@ .incomplete { color: var(--color-red); } - -.collapsed { - color: color-mix(in srgb, var(--foreground) 75%, transparent); -} diff --git a/webview/views/UnitsView.tsx b/webview/views/UnitsView.tsx index ee035ca..8eedbed 100644 --- a/webview/views/UnitsView.tsx +++ b/webview/views/UnitsView.tsx @@ -1,6 +1,3 @@ -import styles from './UnitsView.module.css'; - -import clsx from 'clsx'; import memoizeOne from 'memoize-one'; import { memo, useMemo, useState } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -19,135 +16,40 @@ import { useExtensionStore, } from '../state'; import { useFontSize } from '../util/util'; +import { type SimpleTreeData, TreeRow, buildSimpleTree } from './TreeView'; +import styles from './UnitsView.module.css'; -type DirectoryItem = { - type: 'directory'; - indent: number; - label: string; - id: string; - collapsed: boolean; - path: string[]; -}; - -type UnitItem = { - type: 'unit'; - indent: number; - label: string; - id: string; - unit: Unit; - path: string[]; -}; - -type Item = DirectoryItem | UnitItem; - -type ItemData = { - unitsCount: number; - items: Item[]; - highlightedPath: string | null; - setHighlightedPath: (id: string | null) => void; -}; - -const UnitRow = memo( - ({ - index, - style, - data: { items, highlightedPath, setHighlightedPath }, - }: ListChildComponentProps) => { - const setCollapsedUnit = useAppStore((state) => state.setCollapsedUnit); - const item = items[index]; - const classes = [styles.row]; - if (item.type === 'unit') { - classes.push(styles.unit); - if (item.unit.metadata?.complete !== undefined) { - if (item.unit.metadata.complete) { - classes.push(styles.complete); - } else { - classes.push(styles.incomplete); - } - } - } else { - // classes.push(styles.directory); - if (item.collapsed) { - classes.push(styles.collapsed); - } - } - const indentItems = []; - for (let i = 0; i < item.indent; i++) { - indentItems.push( - , - ); - } - if (item.type === 'directory') { - indentItems.push( - , - ); - } - return ( -
{ - if (item.type === 'unit') { - setCurrentUnit(item.unit); - } else { - const collapsed = !item.collapsed; - setCollapsedUnit(item.id, collapsed); - setHighlightedPath( - collapsed ? item.path[item.path.length - 1] : item.id, - ); +const UnitRow = memo((props: ListChildComponentProps>) => { + const setCollapsedUnit = useAppStore((state) => state.setCollapsedUnit); + return ( + { + if ( + item.type === 'leaf' && + item.data.metadata?.complete !== undefined + ) { + if (item.data.metadata.complete) { + return [styles.complete]; } - }} - onMouseEnter={() => { - setHighlightedPath( - item.type === 'unit' || item.collapsed - ? item.path[item.path.length - 1] - : item.id, - ); - }} - > - {indentItems} - {item.label} -
- ); - }, - areEqual, -); - -type TreeItem = DirectoryItem & { children: (TreeItem | UnitItem)[] }; - -function pushTreeItems(item: TreeItem | UnitItem, out: Item[]) { - if (item.type === 'directory') { - out.push(item); - if (!item.collapsed) { - for (const child of item.children) { - pushTreeItems(child, out); - } - } - } else if (item.type === 'unit') { - out.push(item); - } -} - -const buildPath = (split: string[]) => { - const path = []; - for (let i = 0; i < split.length - 1; i++) { - path.push(split.slice(0, i + 1).join('/')); - } - return path; -}; + return [styles.incomplete]; + } + return []; + }} + onLeafClick={(item) => { + setCurrentUnit(item.data); + }} + setBranchCollapsed={setCollapsedUnit} + render={(item) => { + return ( + + {item.data.label} + + ); + }} + /> + ); +}, areEqual); const createItemData = memoizeOne( ( @@ -155,62 +57,14 @@ const createItemData = memoizeOne( collapsedUnits: Record, highlightedPath: string | null, setHighlightedPath: (id: string | null) => void, - ): ItemData => { - const units = config?.units ?? []; - const map = new Map(); - const rootItems = []; - for (const unit of units) { - const path = unit.name || ''; - const split = path.split('/'); - let parent: TreeItem | null = null; - for (let i = 0; i < split.length - 1; i++) { - const name = split[i]; - const dirPath = split.slice(0, i + 1); - const key = dirPath.join('/'); - let item = map.get(key); - if (!item) { - item = { - type: 'directory', - indent: i, - label: name, - id: key, - collapsed: !!collapsedUnits[key], - children: [], - path: buildPath(dirPath), - }; - if (parent) { - parent.children.push(item); - } else { - rootItems.push(item); - } - map.set(key, item); - } - parent = item; - } - const unitItem: UnitItem = { - type: 'unit', - indent: split.length - 1, - label: split[split.length - 1], - id: path, - unit, - path: buildPath(split), - }; - if (parent) { - parent.children.push(unitItem); - } else { - rootItems.push(unitItem); - } - } - const items: Item[] = []; - for (const item of rootItems) { - pushTreeItems(item, items); - } - return { - unitsCount: units.length, - items, + ): SimpleTreeData => { + return buildSimpleTree( + config?.units ?? [], + (unit) => unit.name || '', + collapsedUnits, highlightedPath, setHighlightedPath, - }; + ); }, ); @@ -250,7 +104,7 @@ const UnitsView = () => {
- {itemData.unitsCount} unit{itemData.unitsCount === 1 ? '' : 's'} + {itemData.leafCount} unit{itemData.leafCount === 1 ? '' : 's'}
@@ -260,7 +114,7 @@ const UnitsView = () => { {({ height, width }) => (