diff --git a/tools/vscode-config-extension/.gitignore b/tools/vscode-config-extension/.gitignore deleted file mode 100644 index 40b878d..0000000 --- a/tools/vscode-config-extension/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ \ No newline at end of file diff --git a/tools/vscode-config-extension/.vscodeignore b/tools/vscode-config-extension/.vscodeignore deleted file mode 100644 index 917dd95..0000000 --- a/tools/vscode-config-extension/.vscodeignore +++ /dev/null @@ -1,7 +0,0 @@ -.github/** -.vscode/** -.vscode-test/** -test/** -*.log -.gitignore -.vscodeignore diff --git a/tools/vscode-config-extension/LICENSE b/tools/vscode-config-extension/LICENSE deleted file mode 100644 index 946080c..0000000 --- a/tools/vscode-config-extension/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets.) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2025 GeWuYou - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/tools/vscode-config-extension/README.md b/tools/vscode-config-extension/README.md deleted file mode 100644 index ffa850d..0000000 --- a/tools/vscode-config-extension/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# GFramework Config Tool - -VS Code extension for the GFramework AI-First config workflow. - -## Current MVP - -- Browse config files from the workspace `config/` directory -- Open raw YAML files -- Open matching schema files from `schemas/` -- Run lightweight schema validation for nested required fields, unknown nested fields, scalar types, scalar arrays, and - arrays of objects -- Open a lightweight form preview for nested object fields, object arrays, top-level scalar fields, and scalar arrays -- Batch edit one config domain across multiple files for top-level scalar and scalar-array fields -- Surface schema metadata such as `title`, `description`, `default`, `enum`, and `x-gframework-ref-table` in the - lightweight editors - -## Validation Coverage - -The extension currently validates the repository's minimal config-schema subset: - -- required properties in nested objects -- unknown properties in nested objects -- scalar compatibility for `integer`, `number`, `boolean`, and `string` -- scalar arrays with scalar item type checks -- arrays of objects whose items use the same supported subset recursively -- scalar `enum` constraints and scalar-array item `enum` constraints - -## Local Testing - -```bash -cd tools/vscode-config-extension -bun install -bun run test -``` - -## Packaging And Publishing - -```bash -cd tools/vscode-config-extension -bun install -bun run package:vsix -VSCE_PAT=your_marketplace_pat bun run publish:marketplace -``` - -## Current Constraints - -- Multi-root workspaces use the first workspace folder -- Validation only covers a minimal subset of JSON Schema -- Form preview supports object-array editing, but nested object arrays inside array items still fall back to raw YAML -- Batch editing remains limited to top-level scalar fields and top-level scalar arrays - -## Workspace Settings - -- `gframeworkConfig.configPath` -- `gframeworkConfig.schemasPath` diff --git a/tools/vscode-config-extension/bun.lock b/tools/vscode-config-extension/bun.lock deleted file mode 100644 index 7bc1c78..0000000 --- a/tools/vscode-config-extension/bun.lock +++ /dev/null @@ -1,627 +0,0 @@ -{ - "lockfileVersion": 1, - "configVersion": 1, - "workspaces": { - "": { - "name": "gframework-config-tool", - "devDependencies": { - "@vscode/vsce": "^3.7.1", - }, - }, - }, - "packages": { - "@azu/format-text": ["@azu/format-text@1.0.2", "", {}, "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg=="], - - "@azu/style-format": ["@azu/style-format@1.0.1", "", { "dependencies": { "@azu/format-text": "^1.0.1" } }, "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g=="], - - "@azure/abort-controller": ["@azure/abort-controller@2.1.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA=="], - - "@azure/core-auth": ["@azure/core-auth@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", "tslib": "^2.6.2" } }, "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg=="], - - "@azure/core-client": ["@azure/core-client@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w=="], - - "@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.23.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" } }, "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ=="], - - "@azure/core-tracing": ["@azure/core-tracing@1.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ=="], - - "@azure/core-util": ["@azure/core-util@1.13.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A=="], - - "@azure/identity": ["@azure/identity@4.13.1", "", { "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.2", "@azure/core-rest-pipeline": "^1.17.0", "@azure/core-tracing": "^1.0.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", "@azure/msal-browser": "^5.5.0", "@azure/msal-node": "^5.1.0", "open": "^10.1.0", "tslib": "^2.2.0" } }, "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw=="], - - "@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="], - - "@azure/msal-browser": ["@azure/msal-browser@5.6.2", "", { "dependencies": { "@azure/msal-common": "16.4.0" } }, "sha512-ZgcN9ToRJ80f+wNPBBKYJ+DG0jlW7ktEjYtSNkNsTrlHVMhKB8tKMdI1yIG1I9BJtykkXtqnuOjlJaEMC7J6aw=="], - - "@azure/msal-common": ["@azure/msal-common@16.4.0", "", {}, "sha512-twXt09PYtj1PffNNIAzQlrBd0DS91cdA6i1gAfzJ6BnPM4xNk5k9q/5xna7jLIjU3Jnp0slKYtucshGM8OGNAw=="], - - "@azure/msal-node": ["@azure/msal-node@5.1.1", "", { "dependencies": { "@azure/msal-common": "16.4.0", "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" } }, "sha512-71grXU6+5hl+3CL3joOxlj/AW6rmhthuTlG0fRqsTrhPArQBpZuUFzCIlKOGdcafLUa/i1hBdV78ZxJdlvRA+g=="], - - "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], - - "@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="], - - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - - "@secretlint/config-creator": ["@secretlint/config-creator@10.2.2", "", { "dependencies": { "@secretlint/types": "^10.2.2" } }, "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ=="], - - "@secretlint/config-loader": ["@secretlint/config-loader@10.2.2", "", { "dependencies": { "@secretlint/profiler": "^10.2.2", "@secretlint/resolver": "^10.2.2", "@secretlint/types": "^10.2.2", "ajv": "^8.17.1", "debug": "^4.4.1", "rc-config-loader": "^4.1.3" } }, "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ=="], - - "@secretlint/core": ["@secretlint/core@10.2.2", "", { "dependencies": { "@secretlint/profiler": "^10.2.2", "@secretlint/types": "^10.2.2", "debug": "^4.4.1", "structured-source": "^4.0.0" } }, "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw=="], - - "@secretlint/formatter": ["@secretlint/formatter@10.2.2", "", { "dependencies": { "@secretlint/resolver": "^10.2.2", "@secretlint/types": "^10.2.2", "@textlint/linter-formatter": "^15.2.0", "@textlint/module-interop": "^15.2.0", "@textlint/types": "^15.2.0", "chalk": "^5.4.1", "debug": "^4.4.1", "pluralize": "^8.0.0", "strip-ansi": "^7.1.0", "table": "^6.9.0", "terminal-link": "^4.0.0" } }, "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA=="], - - "@secretlint/node": ["@secretlint/node@10.2.2", "", { "dependencies": { "@secretlint/config-loader": "^10.2.2", "@secretlint/core": "^10.2.2", "@secretlint/formatter": "^10.2.2", "@secretlint/profiler": "^10.2.2", "@secretlint/source-creator": "^10.2.2", "@secretlint/types": "^10.2.2", "debug": "^4.4.1", "p-map": "^7.0.3" } }, "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ=="], - - "@secretlint/profiler": ["@secretlint/profiler@10.2.2", "", {}, "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig=="], - - "@secretlint/resolver": ["@secretlint/resolver@10.2.2", "", {}, "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w=="], - - "@secretlint/secretlint-formatter-sarif": ["@secretlint/secretlint-formatter-sarif@10.2.2", "", { "dependencies": { "node-sarif-builder": "^3.2.0" } }, "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ=="], - - "@secretlint/secretlint-rule-no-dotenv": ["@secretlint/secretlint-rule-no-dotenv@10.2.2", "", { "dependencies": { "@secretlint/types": "^10.2.2" } }, "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg=="], - - "@secretlint/secretlint-rule-preset-recommend": ["@secretlint/secretlint-rule-preset-recommend@10.2.2", "", {}, "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA=="], - - "@secretlint/source-creator": ["@secretlint/source-creator@10.2.2", "", { "dependencies": { "@secretlint/types": "^10.2.2", "istextorbinary": "^9.5.0" } }, "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw=="], - - "@secretlint/types": ["@secretlint/types@10.2.2", "", {}, "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg=="], - - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@2.3.0", "", {}, "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg=="], - - "@textlint/ast-node-types": ["@textlint/ast-node-types@15.5.2", "", {}, "sha512-fCaOxoup5LIyBEo7R1oYWE7V4bSX0KQeHh66twon9e9usaLE3ijgF8QjYsR6joCssdeCHVd0wHm7ppsEyTr6vg=="], - - "@textlint/linter-formatter": ["@textlint/linter-formatter@15.5.2", "", { "dependencies": { "@azu/format-text": "^1.0.2", "@azu/style-format": "^1.0.1", "@textlint/module-interop": "15.5.2", "@textlint/resolver": "15.5.2", "@textlint/types": "15.5.2", "chalk": "^4.1.2", "debug": "^4.4.3", "js-yaml": "^4.1.1", "lodash": "^4.17.23", "pluralize": "^2.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "table": "^6.9.0", "text-table": "^0.2.0" } }, "sha512-jAw7jWM8+wU9cG6Uu31jGyD1B+PAVePCvnPKC/oov+2iBPKk3ao30zc/Itmi7FvXo4oPaL9PmzPPQhyniPVgVg=="], - - "@textlint/module-interop": ["@textlint/module-interop@15.5.2", "", {}, "sha512-mg6rMQ3+YjwiXCYoQXbyVfDucpTa1q5mhspd/9qHBxUq4uY6W8GU42rmT3GW0V1yOfQ9z/iRrgPtkp71s8JzXg=="], - - "@textlint/resolver": ["@textlint/resolver@15.5.2", "", {}, "sha512-YEITdjRiJaQrGLUWxWXl4TEg+d2C7+TNNjbGPHPH7V7CCnXm+S9GTjGAL7Q2WSGJyFEKt88Jvx6XdJffRv4HEA=="], - - "@textlint/types": ["@textlint/types@15.5.2", "", { "dependencies": { "@textlint/ast-node-types": "15.5.2" } }, "sha512-sJOrlVLLXp4/EZtiWKWq9y2fWyZlI8GP+24rnU5avtPWBIMm/1w97yzKrAqYF8czx2MqR391z5akhnfhj2f/AQ=="], - - "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="], - - "@types/sarif": ["@types/sarif@2.1.7", "", {}, "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ=="], - - "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.4", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-CI0NhTrz4EBaa0U+HaaUZrJhPoso8sG7ZFya8uQoBA57fjzrjRSv87ekCjLZOFExN+gXE/z0xuN2QfH4H2HrLQ=="], - - "@vscode/vsce": ["@vscode/vsce@3.7.1", "", { "dependencies": { "@azure/identity": "^4.1.0", "@secretlint/node": "^10.1.2", "@secretlint/secretlint-formatter-sarif": "^10.1.2", "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", "@vscode/vsce-sign": "^2.0.0", "azure-devops-node-api": "^12.5.0", "chalk": "^4.1.2", "cheerio": "^1.0.0-rc.9", "cockatiel": "^3.1.2", "commander": "^12.1.0", "form-data": "^4.0.0", "glob": "^11.0.0", "hosted-git-info": "^4.0.2", "jsonc-parser": "^3.2.0", "leven": "^3.1.0", "markdown-it": "^14.1.0", "mime": "^1.3.4", "minimatch": "^3.0.3", "parse-semver": "^1.1.1", "read": "^1.0.7", "secretlint": "^10.1.2", "semver": "^7.5.2", "tmp": "^0.2.3", "typed-rest-client": "^1.8.4", "url-join": "^4.0.1", "xml2js": "^0.5.0", "yauzl": "^2.3.1", "yazl": "^2.2.2" }, "optionalDependencies": { "keytar": "^7.7.0" }, "bin": { "vsce": "vsce" } }, "sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g=="], - - "@vscode/vsce-sign": ["@vscode/vsce-sign@2.0.9", "", { "optionalDependencies": { "@vscode/vsce-sign-alpine-arm64": "2.0.6", "@vscode/vsce-sign-alpine-x64": "2.0.6", "@vscode/vsce-sign-darwin-arm64": "2.0.6", "@vscode/vsce-sign-darwin-x64": "2.0.6", "@vscode/vsce-sign-linux-arm": "2.0.6", "@vscode/vsce-sign-linux-arm64": "2.0.6", "@vscode/vsce-sign-linux-x64": "2.0.6", "@vscode/vsce-sign-win32-arm64": "2.0.6", "@vscode/vsce-sign-win32-x64": "2.0.6" } }, "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g=="], - - "@vscode/vsce-sign-alpine-arm64": ["@vscode/vsce-sign-alpine-arm64@2.0.6", "", { "os": "none", "cpu": "arm64" }, "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q=="], - - "@vscode/vsce-sign-alpine-x64": ["@vscode/vsce-sign-alpine-x64@2.0.6", "", { "os": "none", "cpu": "x64" }, "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w=="], - - "@vscode/vsce-sign-darwin-arm64": ["@vscode/vsce-sign-darwin-arm64@2.0.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ=="], - - "@vscode/vsce-sign-darwin-x64": ["@vscode/vsce-sign-darwin-x64@2.0.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw=="], - - "@vscode/vsce-sign-linux-arm": ["@vscode/vsce-sign-linux-arm@2.0.6", "", { "os": "linux", "cpu": "arm" }, "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA=="], - - "@vscode/vsce-sign-linux-arm64": ["@vscode/vsce-sign-linux-arm64@2.0.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA=="], - - "@vscode/vsce-sign-linux-x64": ["@vscode/vsce-sign-linux-x64@2.0.6", "", { "os": "linux", "cpu": "x64" }, "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA=="], - - "@vscode/vsce-sign-win32-arm64": ["@vscode/vsce-sign-win32-arm64@2.0.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg=="], - - "@vscode/vsce-sign-win32-x64": ["@vscode/vsce-sign-win32-x64@2.0.6", "", { "os": "win32", "cpu": "x64" }, "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ=="], - - "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - - "ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], - - "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], - - "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], - - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], - - "azure-devops-node-api": ["azure-devops-node-api@12.5.0", "", { "dependencies": { "tunnel": "0.0.6", "typed-rest-client": "^1.8.4" } }, "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - - "binaryextensions": ["binaryextensions@6.11.0", "", { "dependencies": { "editions": "^6.21.0" } }, "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw=="], - - "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], - - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - - "boundary": ["boundary@2.0.0", "", {}, "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA=="], - - "brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], - - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - - "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], - - "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - - "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], - - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], - - "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="], - - "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="], - - "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="], - - "cockatiel": ["cockatiel@3.2.1", "", {}, "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], - - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], - - "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], - - "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], - - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], - - "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], - - "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="], - - "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], - - "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], - - "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], - - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], - - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], - - "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], - - "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], - - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], - - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - - "editions": ["editions@6.22.0", "", { "dependencies": { "version-range": "^4.15.0" } }, "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ=="], - - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="], - - "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - - "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], - - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], - - "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - - "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], - - "fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - - "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - - "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], - - "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], - - "fs-extra": ["fs-extra@11.3.4", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], - - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], - - "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - - "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], - - "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], - - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "globby": ["globby@14.1.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.3", "ignore": "^7.0.3", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - - "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], - - "htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="], - - "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], - - "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - - "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], - - "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], - - "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - - "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "istextorbinary": ["istextorbinary@9.5.0", "", { "dependencies": { "binaryextensions": "^6.11.0", "editions": "^6.21.0", "textextensions": "^6.11.0" } }, "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw=="], - - "jackspeak": ["jackspeak@4.2.3", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - - "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], - - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], - - "jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="], - - "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], - - "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], - - "keytar": ["keytar@7.9.0", "", { "dependencies": { "node-addon-api": "^4.3.0", "prebuild-install": "^7.0.1" } }, "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ=="], - - "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], - - "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], - - "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], - - "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], - - "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], - - "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], - - "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], - - "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], - - "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], - - "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], - - "lodash.truncate": ["lodash.truncate@4.4.2", "", {}, "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw=="], - - "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="], - - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - - "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="], - - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - - "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], - - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - - "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], - - "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], - - "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "mute-stream": ["mute-stream@0.0.8", "", {}, "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="], - - "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], - - "node-abi": ["node-abi@3.89.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA=="], - - "node-addon-api": ["node-addon-api@4.3.0", "", {}, "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="], - - "node-sarif-builder": ["node-sarif-builder@3.4.0", "", { "dependencies": { "@types/sarif": "^2.1.7", "fs-extra": "^11.1.1" } }, "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg=="], - - "normalize-package-data": ["normalize-package-data@6.0.2", "", { "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g=="], - - "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - - "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], - - "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], - - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - - "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], - - "parse-semver": ["parse-semver@1.1.1", "", { "dependencies": { "semver": "^5.1.0" } }, "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ=="], - - "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], - - "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="], - - "parse5-parser-stream": ["parse5-parser-stream@7.1.2", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - - "path-type": ["path-type@6.0.0", "", {}, "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ=="], - - "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - - "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], - - "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="], - - "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - - "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], - - "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], - - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], - - "rc-config-loader": ["rc-config-loader@4.1.4", "", { "dependencies": { "debug": "^4.4.3", "js-yaml": "^4.1.1", "json5": "^2.2.3", "require-from-string": "^2.0.2" } }, "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ=="], - - "read": ["read@1.0.7", "", { "dependencies": { "mute-stream": "~0.0.4" } }, "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ=="], - - "read-pkg": ["read-pkg@9.0.1", "", { "dependencies": { "@types/normalize-package-data": "^2.4.3", "normalize-package-data": "^6.0.0", "parse-json": "^8.0.0", "type-fest": "^4.6.0", "unicorn-magic": "^0.1.0" } }, "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA=="], - - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], - - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], - - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - - "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], - - "secretlint": ["secretlint@10.2.2", "", { "dependencies": { "@secretlint/config-creator": "^10.2.2", "@secretlint/formatter": "^10.2.2", "@secretlint/node": "^10.2.2", "@secretlint/profiler": "^10.2.2", "debug": "^4.4.1", "globby": "^14.1.0", "read-pkg": "^9.0.1" }, "bin": "./bin/secretlint.js" }, "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg=="], - - "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], - - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], - - "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], - - "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="], - - "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="], - - "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], - - "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="], - - "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], - - "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], - - "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], - - "spdx-license-ids": ["spdx-license-ids@3.0.23", "", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="], - - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - - "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - - "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], - - "structured-source": ["structured-source@4.0.0", "", { "dependencies": { "boundary": "^2.0.0" } }, "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="], - - "table": ["table@6.9.0", "", { "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1" } }, "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A=="], - - "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="], - - "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], - - "terminal-link": ["terminal-link@4.0.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "supports-hyperlinks": "^3.2.0" } }, "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA=="], - - "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], - - "textextensions": ["textextensions@6.11.0", "", { "dependencies": { "editions": "^6.21.0" } }, "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ=="], - - "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], - - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], - - "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], - - "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], - - "typed-rest-client": ["typed-rest-client@1.8.11", "", { "dependencies": { "qs": "^6.9.1", "tunnel": "0.0.6", "underscore": "^1.12.1" } }, "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA=="], - - "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], - - "underscore": ["underscore@1.13.8", "", {}, "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ=="], - - "undici": ["undici@7.24.7", "", {}, "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ=="], - - "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], - - "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - - "url-join": ["url-join@4.0.1", "", {}, "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="], - - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - - "uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - - "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], - - "version-range": ["version-range@4.15.0", "", {}, "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg=="], - - "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="], - - "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], - - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], - - "xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], - - "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], - - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], - - "yazl": ["yazl@2.5.1", "", { "dependencies": { "buffer-crc32": "~0.2.3" } }, "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw=="], - - "@secretlint/formatter/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - - "@textlint/linter-formatter/pluralize": ["pluralize@2.0.0", "", {}, "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw=="], - - "@textlint/linter-formatter/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "glob/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], - - "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], - - "normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], - - "parse-semver/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - - "path-scurry/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], - - "read-pkg/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="], - - "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "table/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@textlint/linter-formatter/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], - - "normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - - "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "table/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - } -} diff --git a/tools/vscode-config-extension/package.json b/tools/vscode-config-extension/package.json deleted file mode 100644 index 71588e3..0000000 --- a/tools/vscode-config-extension/package.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "name": "gframework-config-tool", - "displayName": "GFramework Config Tool", - "description": "VS Code tooling for browsing, validating, and editing AI-First config files in GFramework projects.", - "version": "0.0.1", - "publisher": "GeWuYou", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/GeWuYou/GFramework.git", - "directory": "tools/vscode-config-extension" - }, - "homepage": "https://github.com/GeWuYou/GFramework/tree/main/tools/gframework-config-tool", - "bugs": { - "url": "https://github.com/GeWuYou/GFramework/issues" - }, - "packageManager": "bun@1.2.15", - "keywords": [ - "gframework", - "config", - "yaml", - "json-schema", - "game-dev" - ], - "engines": { - "vscode": "^1.90.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [ - "onView:gframeworkConfigExplorer", - "onCommand:gframeworkConfig.refresh", - "onCommand:gframeworkConfig.openRaw", - "onCommand:gframeworkConfig.openSchema", - "onCommand:gframeworkConfig.openFormPreview", - "onCommand:gframeworkConfig.batchEditDomain", - "onCommand:gframeworkConfig.validateAll" - ], - "main": "./src/extension.js", - "scripts": { - "test": "node --test ./test/*.test.js", - "package:vsix": "vsce package", - "publish:marketplace": "vsce publish" - }, - "devDependencies": { - "@vscode/vsce": "^3.7.1" - }, - "vsce": { - "yarn": false - }, - "contributes": { - "views": { - "explorer": [ - { - "id": "gframeworkConfigExplorer", - "name": "GFramework Config" - } - ] - }, - "commands": [ - { - "command": "gframeworkConfig.refresh", - "title": "GFramework Config: Refresh" - }, - { - "command": "gframeworkConfig.openRaw", - "title": "GFramework Config: Open Raw File" - }, - { - "command": "gframeworkConfig.openSchema", - "title": "GFramework Config: Open Schema" - }, - { - "command": "gframeworkConfig.openFormPreview", - "title": "GFramework Config: Open Form Preview" - }, - { - "command": "gframeworkConfig.batchEditDomain", - "title": "GFramework Config: Batch Edit Domain" - }, - { - "command": "gframeworkConfig.validateAll", - "title": "GFramework Config: Validate All" - } - ], - "menus": { - "view/title": [ - { - "command": "gframeworkConfig.refresh", - "when": "view == gframeworkConfigExplorer", - "group": "navigation" - }, - { - "command": "gframeworkConfig.validateAll", - "when": "view == gframeworkConfigExplorer", - "group": "navigation" - } - ], - "view/item/context": [ - { - "command": "gframeworkConfig.openRaw", - "when": "view == gframeworkConfigExplorer && viewItem == gframeworkConfigFile", - "group": "inline" - }, - { - "command": "gframeworkConfig.openSchema", - "when": "view == gframeworkConfigExplorer && viewItem == gframeworkConfigFile", - "group": "navigation" - }, - { - "command": "gframeworkConfig.openFormPreview", - "when": "view == gframeworkConfigExplorer && viewItem == gframeworkConfigFile", - "group": "navigation" - }, - { - "command": "gframeworkConfig.batchEditDomain", - "when": "view == gframeworkConfigExplorer && viewItem == domain", - "group": "navigation" - } - ] - }, - "configuration": { - "title": "GFramework Config", - "properties": { - "gframeworkConfig.configPath": { - "type": "string", - "default": "config", - "description": "Relative path from the workspace root to the config directory." - }, - "gframeworkConfig.schemasPath": { - "type": "string", - "default": "schemas", - "description": "Relative path from the workspace root to the schema directory." - } - } - } - } -} diff --git a/tools/vscode-config-extension/src/configValidation.js b/tools/vscode-config-extension/src/configValidation.js deleted file mode 100644 index 301e3d6..0000000 --- a/tools/vscode-config-extension/src/configValidation.js +++ /dev/null @@ -1,842 +0,0 @@ -/** - * Parse the repository's minimal config-schema subset into a recursive tree. - * The parser intentionally mirrors the same high-level contract used by the - * runtime validator and source generator so tooling diagnostics stay aligned. - * - * @param {string} content Raw schema JSON text. - * @returns {{ - * type: "object", - * required: string[], - * properties: Record - * }} Parsed schema info. - */ -function parseSchemaContent(content) { - const parsed = JSON.parse(content); - return parseSchemaNode(parsed, ""); -} - -/** - * Collect top-level schema fields that the current batch editor can update - * safely. Batch editing intentionally remains conservative even though the form - * preview can now navigate nested object structures. - * - * @param {{type: "object", required: string[], properties: Record}} schemaInfo Parsed schema. - * @returns {Array<{ - * key: string, - * path: string, - * type: string, - * itemType?: string, - * title?: string, - * description?: string, - * defaultValue?: string, - * enumValues?: string[], - * itemEnumValues?: string[], - * refTable?: string, - * inputKind: "scalar" | "array", - * required: boolean - * }>} Editable field descriptors. - */ -function getEditableSchemaFields(schemaInfo) { - const editableFields = []; - const requiredSet = new Set(Array.isArray(schemaInfo.required) ? schemaInfo.required : []); - - for (const [key, property] of Object.entries(schemaInfo.properties || {})) { - if (isEditableScalarType(property.type)) { - editableFields.push({ - key, - path: key, - type: property.type, - title: property.title, - description: property.description, - defaultValue: property.defaultValue, - enumValues: property.enumValues, - refTable: property.refTable, - inputKind: "scalar", - required: requiredSet.has(key) - }); - continue; - } - - if (property.type === "array" && property.items && isEditableScalarType(property.items.type)) { - editableFields.push({ - key, - path: key, - type: property.type, - itemType: property.items.type, - title: property.title, - description: property.description, - defaultValue: property.defaultValue, - itemEnumValues: property.items.enumValues, - refTable: property.refTable, - inputKind: "array", - required: requiredSet.has(key) - }); - } - } - - return editableFields.sort((left, right) => left.key.localeCompare(right.key)); -} - -/** - * Parse YAML into a recursive object/array/scalar tree. - * The parser covers the config system's intended subset: root mappings, - * indentation-based nested objects, scalar arrays, and arrays of objects. - * - * @param {string} text YAML text. - * @returns {YamlNode} Parsed YAML tree. - */ -function parseTopLevelYaml(text) { - const tokens = tokenizeYaml(text); - if (tokens.length === 0) { - return createObjectNode(); - } - - const state = {index: 0}; - return parseBlock(tokens, state, tokens[0].indent); -} - -/** - * Produce extension-facing validation diagnostics from schema and parsed YAML. - * - * @param {{type: "object", required: string[], properties: Record}} schemaInfo Parsed schema. - * @param {YamlNode} parsedYaml Parsed YAML tree. - * @returns {Array<{severity: "error" | "warning", message: string}>} Validation diagnostics. - */ -function validateParsedConfig(schemaInfo, parsedYaml) { - const diagnostics = []; - validateNode(schemaInfo, parsedYaml, "", diagnostics); - return diagnostics; -} - -/** - * Determine whether the current schema type can be edited through the batch - * editor. The richer form preview handles nested objects separately. - * - * @param {string} schemaType Schema type. - * @returns {boolean} True when the type is batch-editable. - */ -function isEditableScalarType(schemaType) { - return schemaType === "string" || - schemaType === "integer" || - schemaType === "number" || - schemaType === "boolean"; -} - -/** - * Determine whether a scalar value matches a minimal schema type. - * - * @param {string} expectedType Schema type. - * @param {string} scalarValue YAML scalar value. - * @returns {boolean} True when compatible. - */ -function isScalarCompatible(expectedType, scalarValue) { - const value = unquoteScalar(String(scalarValue)); - switch (expectedType) { - case "integer": - return /^-?\d+$/u.test(value); - case "number": - return /^-?\d+(?:\.\d+)?$/u.test(value); - case "boolean": - return /^(true|false)$/iu.test(value); - case "string": - return true; - default: - return true; - } -} - -/** - * Apply form updates back into YAML. The implementation rewrites the YAML tree - * from the parsed structure so nested object edits can be saved safely. - * - * @param {string} originalYaml Original YAML content. - * @param {{scalars?: Record, arrays?: Record, objectArrays?: Record>>}} updates Updated form values. - * @returns {string} Updated YAML content. - */ -function applyFormUpdates(originalYaml, updates) { - const root = normalizeRootNode(parseTopLevelYaml(originalYaml)); - const scalarUpdates = updates.scalars || {}; - const arrayUpdates = updates.arrays || {}; - const objectArrayUpdates = updates.objectArrays || {}; - - for (const [path, value] of Object.entries(scalarUpdates)) { - setNodeAtPath(root, path.split("."), createScalarNode(String(value))); - } - - for (const [path, values] of Object.entries(arrayUpdates)) { - setNodeAtPath(root, path.split("."), createArrayNode( - (values || []).map((item) => createScalarNode(String(item))))); - } - - for (const [path, items] of Object.entries(objectArrayUpdates)) { - setNodeAtPath(root, path.split("."), createArrayNode( - (items || []).map((item) => createNodeFromFormValue(item)))); - } - - return renderYaml(root).join("\n"); -} - -/** - * Apply only scalar updates back into YAML. - * - * @param {string} originalYaml Original YAML content. - * @param {Record} updates Updated scalar values. - * @returns {string} Updated YAML content. - */ -function applyScalarUpdates(originalYaml, updates) { - return applyFormUpdates(originalYaml, {scalars: updates}); -} - -/** - * Parse the batch editor's comma-separated array input. - * - * @param {string} value Raw input value. - * @returns {string[]} Parsed array items. - */ -function parseBatchArrayValue(value) { - return String(value) - .split(",") - .map((item) => item.trim()) - .filter((item) => item.length > 0); -} - -/** - * Normalize a schema enum array into string values that can be shown in UI - * hints and compared against parsed YAML scalar content. - * - * @param {unknown} value Raw schema enum value. - * @returns {string[] | undefined} Normalized enum values. - */ -function normalizeSchemaEnumValues(value) { - if (!Array.isArray(value)) { - return undefined; - } - - const normalized = value - .filter((item) => ["string", "number", "boolean"].includes(typeof item)) - .map((item) => String(item)); - - return normalized.length > 0 ? normalized : undefined; -} - -/** - * Convert a schema default value into a compact string that can be shown in UI - * metadata hints. - * - * @param {unknown} value Raw schema default value. - * @returns {string | undefined} Display string for the default value. - */ -function formatSchemaDefaultValue(value) { - if (value === null || value === undefined) { - return undefined; - } - - if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { - return String(value); - } - - if (Array.isArray(value)) { - const normalized = value - .filter((item) => ["string", "number", "boolean"].includes(typeof item)) - .map((item) => String(item)); - - return normalized.length > 0 ? normalized.join(", ") : undefined; - } - - if (typeof value === "object") { - return JSON.stringify(value); - } - - return undefined; -} - -/** - * Format a scalar value for YAML output. - * - * @param {string} value Scalar value. - * @returns {string} YAML-ready scalar. - */ -function formatYamlScalar(value) { - if (/^-?\d+(?:\.\d+)?$/u.test(value) || /^(true|false)$/iu.test(value)) { - return value; - } - - if (value.length === 0 || /[:#\[\]\{\},]|^\s|\s$/u.test(value)) { - return JSON.stringify(value); - } - - return value; -} - -/** - * Remove a simple YAML string quote wrapper. - * - * @param {string} value Scalar value. - * @returns {string} Unquoted value. - */ -function unquoteScalar(value) { - if ((value.startsWith("\"") && value.endsWith("\"")) || - (value.startsWith("'") && value.endsWith("'"))) { - return value.slice(1, -1); - } - - return value; -} - -/** - * Parse one schema node recursively. - * - * @param {unknown} rawNode Raw schema node. - * @param {string} displayPath Logical property path. - * @returns {SchemaNode} Parsed schema node. - */ -function parseSchemaNode(rawNode, displayPath) { - const value = rawNode && typeof rawNode === "object" ? rawNode : {}; - const type = typeof value.type === "string" ? value.type : "object"; - const metadata = { - title: typeof value.title === "string" ? value.title : undefined, - description: typeof value.description === "string" ? value.description : undefined, - defaultValue: formatSchemaDefaultValue(value.default), - refTable: typeof value["x-gframework-ref-table"] === "string" - ? value["x-gframework-ref-table"] - : undefined - }; - - if (type === "object") { - const required = Array.isArray(value.required) - ? value.required.filter((item) => typeof item === "string") - : []; - const properties = {}; - for (const [key, propertyNode] of Object.entries(value.properties || {})) { - properties[key] = parseSchemaNode(propertyNode, combinePath(displayPath, key)); - } - - return { - type: "object", - displayPath, - required, - properties, - title: metadata.title, - description: metadata.description, - defaultValue: metadata.defaultValue - }; - } - - if (type === "array") { - const itemNode = parseSchemaNode(value.items || {}, `${displayPath}[]`); - return { - type: "array", - displayPath, - title: metadata.title, - description: metadata.description, - defaultValue: metadata.defaultValue, - refTable: metadata.refTable, - items: itemNode - }; - } - - return { - type, - displayPath, - title: metadata.title, - description: metadata.description, - defaultValue: metadata.defaultValue, - enumValues: normalizeSchemaEnumValues(value.enum), - refTable: metadata.refTable - }; -} - -/** - * Validate one schema node against one YAML node. - * - * @param {SchemaNode} schemaNode Schema node. - * @param {YamlNode} yamlNode YAML node. - * @param {string} displayPath Current logical path. - * @param {Array<{severity: "error" | "warning", message: string}>} diagnostics Diagnostic sink. - */ -function validateNode(schemaNode, yamlNode, displayPath, diagnostics) { - if (schemaNode.type === "object") { - validateObjectNode(schemaNode, yamlNode, displayPath, diagnostics); - return; - } - - if (schemaNode.type === "array") { - if (!yamlNode || yamlNode.kind !== "array") { - diagnostics.push({ - severity: "error", - message: `Property '${displayPath}' is expected to be an array.` - }); - return; - } - - for (let index = 0; index < yamlNode.items.length; index += 1) { - validateNode(schemaNode.items, yamlNode.items[index], `${displayPath}[${index}]`, diagnostics); - } - return; - } - - if (!yamlNode || yamlNode.kind !== "scalar") { - diagnostics.push({ - severity: "error", - message: `Property '${displayPath}' is expected to be '${schemaNode.type}', but the current YAML shape is '${yamlNode ? yamlNode.kind : "missing"}'.` - }); - return; - } - - if (!isScalarCompatible(schemaNode.type, yamlNode.value)) { - diagnostics.push({ - severity: "error", - message: `Property '${displayPath}' is expected to be '${schemaNode.type}', but the current scalar value is incompatible.` - }); - return; - } - - if (Array.isArray(schemaNode.enumValues) && - schemaNode.enumValues.length > 0 && - !schemaNode.enumValues.includes(unquoteScalar(yamlNode.value))) { - diagnostics.push({ - severity: "error", - message: `Property '${displayPath}' must be one of: ${schemaNode.enumValues.join(", ")}.` - }); - } -} - -/** - * Validate an object node recursively. - * - * @param {Extract} schemaNode Object schema node. - * @param {YamlNode} yamlNode YAML node. - * @param {string} displayPath Current logical path. - * @param {Array<{severity: "error" | "warning", message: string}>} diagnostics Diagnostic sink. - */ -function validateObjectNode(schemaNode, yamlNode, displayPath, diagnostics) { - if (!yamlNode || yamlNode.kind !== "object") { - const subject = displayPath.length === 0 ? "Root object" : `Property '${displayPath}'`; - diagnostics.push({ - severity: "error", - message: `${subject} is expected to be an object.` - }); - return; - } - - for (const requiredProperty of schemaNode.required) { - if (!yamlNode.map.has(requiredProperty)) { - diagnostics.push({ - severity: "error", - message: `Required property '${combinePath(displayPath, requiredProperty)}' is missing.` - }); - } - } - - for (const entry of yamlNode.entries) { - if (!Object.prototype.hasOwnProperty.call(schemaNode.properties, entry.key)) { - diagnostics.push({ - severity: "error", - message: `Property '${combinePath(displayPath, entry.key)}' is not declared in the matching schema.` - }); - continue; - } - - validateNode( - schemaNode.properties[entry.key], - entry.node, - combinePath(displayPath, entry.key), - diagnostics); - } -} - -/** - * Tokenize YAML lines into indentation-aware units. - * - * @param {string} text YAML text. - * @returns {Array<{indent: number, text: string}>} Tokens. - */ -function tokenizeYaml(text) { - const tokens = []; - const lines = String(text).split(/\r?\n/u); - - for (const line of lines) { - if (!line || line.trim().length === 0 || line.trimStart().startsWith("#")) { - continue; - } - - const indentMatch = /^(\s*)/u.exec(line); - const indent = indentMatch ? indentMatch[1].length : 0; - const trimmed = line.slice(indent); - tokens.push({indent, text: trimmed}); - } - - return tokens; -} - -/** - * Parse the next YAML block from the token stream. - * - * @param {Array<{indent: number, text: string}>} tokens Token array. - * @param {{index: number}} state Mutable parser state. - * @param {number} indent Expected indentation. - * @returns {YamlNode} Parsed node. - */ -function parseBlock(tokens, state, indent) { - if (state.index >= tokens.length) { - return createObjectNode(); - } - - const token = tokens[state.index]; - if (token.text.startsWith("-")) { - return parseSequence(tokens, state, indent); - } - - return parseMapping(tokens, state, indent); -} - -/** - * Parse a mapping block. - * - * @param {Array<{indent: number, text: string}>} tokens Token array. - * @param {{index: number}} state Mutable parser state. - * @param {number} indent Expected indentation. - * @returns {YamlNode} Parsed object node. - */ -function parseMapping(tokens, state, indent) { - const entries = []; - const map = new Map(); - - while (state.index < tokens.length) { - const token = tokens[state.index]; - if (token.indent < indent || token.text.startsWith("-")) { - break; - } - - if (token.indent > indent) { - state.index += 1; - continue; - } - - const match = /^([A-Za-z0-9_]+):(.*)$/u.exec(token.text); - if (!match) { - state.index += 1; - continue; - } - - const key = match[1]; - const rawValue = match[2].trim(); - state.index += 1; - - let node; - if (rawValue.length > 0 && !rawValue.startsWith("|") && !rawValue.startsWith(">")) { - node = createScalarNode(rawValue); - } else if (state.index < tokens.length && tokens[state.index].indent > indent) { - node = parseBlock(tokens, state, tokens[state.index].indent); - } else { - node = createScalarNode(""); - } - - entries.push({key, node}); - map.set(key, node); - } - - return {kind: "object", entries, map}; -} - -/** - * Parse a sequence block. - * - * @param {Array<{indent: number, text: string}>} tokens Token array. - * @param {{index: number}} state Mutable parser state. - * @param {number} indent Expected indentation. - * @returns {YamlNode} Parsed array node. - */ -function parseSequence(tokens, state, indent) { - const items = []; - - while (state.index < tokens.length) { - const token = tokens[state.index]; - if (token.indent !== indent || !token.text.startsWith("-")) { - break; - } - - const rest = token.text.slice(1).trim(); - state.index += 1; - - if (rest.length === 0) { - if (state.index < tokens.length && tokens[state.index].indent > indent) { - items.push(parseBlock(tokens, state, tokens[state.index].indent)); - } else { - items.push(createScalarNode("")); - } - continue; - } - - if (/^[A-Za-z0-9_]+:/u.test(rest)) { - items.push(parseInlineObjectItem(tokens, state, indent, rest)); - continue; - } - - items.push(createScalarNode(rest)); - } - - return createArrayNode(items); -} - -/** - * Parse an array item written as an inline mapping head followed by nested - * child lines, for example `- wave: 1`. - * - * @param {Array<{indent: number, text: string}>} tokens Token array. - * @param {{index: number}} state Mutable parser state. - * @param {number} parentIndent Array indentation. - * @param {string} firstEntry Inline first entry text. - * @returns {YamlNode} Parsed object node. - */ -function parseInlineObjectItem(tokens, state, parentIndent, firstEntry) { - const syntheticTokens = [{indent: parentIndent + 2, text: firstEntry}]; - while (state.index < tokens.length && tokens[state.index].indent > parentIndent) { - syntheticTokens.push(tokens[state.index]); - state.index += 1; - } - - return parseBlock(syntheticTokens, {index: 0}, parentIndent + 2); -} - -/** - * Ensure the root node is an object, creating one if the YAML was empty or not - * object-shaped enough for structured edits. - * - * @param {YamlNode} node Parsed node. - * @returns {YamlObjectNode} Root object node. - */ -function normalizeRootNode(node) { - return node && node.kind === "object" ? node : createObjectNode(); -} - -/** - * Replace or create a node at a dot-separated object path. - * - * @param {YamlObjectNode} root Root object node. - * @param {string[]} segments Path segments. - * @param {YamlNode} valueNode Value node. - */ -function setNodeAtPath(root, segments, valueNode) { - let current = root; - - for (let index = 0; index < segments.length; index += 1) { - const segment = segments[index]; - if (!segment) { - continue; - } - - if (index === segments.length - 1) { - setObjectEntry(current, segment, valueNode); - return; - } - - let nextNode = current.map.get(segment); - if (!nextNode || nextNode.kind !== "object") { - nextNode = createObjectNode(); - setObjectEntry(current, segment, nextNode); - } - - current = nextNode; - } -} - -/** - * Insert or replace one mapping entry while preserving insertion order. - * - * @param {YamlObjectNode} objectNode Target object node. - * @param {string} key Mapping key. - * @param {YamlNode} valueNode Value node. - */ -function setObjectEntry(objectNode, key, valueNode) { - const existingIndex = objectNode.entries.findIndex((entry) => entry.key === key); - if (existingIndex >= 0) { - objectNode.entries[existingIndex] = {key, node: valueNode}; - } else { - objectNode.entries.push({key, node: valueNode}); - } - - objectNode.map.set(key, valueNode); -} - -/** - * Render a YAML node back to text lines. - * - * @param {YamlNode} node YAML node. - * @param {number} indent Current indentation. - * @returns {string[]} YAML lines. - */ -function renderYaml(node, indent = 0) { - if (node.kind === "object") { - return renderObjectNode(node, indent); - } - - if (node.kind === "array") { - return renderArrayNode(node, indent); - } - - return [`${" ".repeat(indent)}${formatYamlScalar(node.value)}`]; -} - -/** - * Render an object node. - * - * @param {YamlObjectNode} node Object node. - * @param {number} indent Current indentation. - * @returns {string[]} YAML lines. - */ -function renderObjectNode(node, indent) { - const lines = []; - for (const entry of node.entries) { - if (entry.node.kind === "scalar") { - lines.push(`${" ".repeat(indent)}${entry.key}: ${formatYamlScalar(entry.node.value)}`); - continue; - } - - if (entry.node.kind === "array" && entry.node.items.length === 0) { - lines.push(`${" ".repeat(indent)}${entry.key}: []`); - continue; - } - - lines.push(`${" ".repeat(indent)}${entry.key}:`); - lines.push(...renderYaml(entry.node, indent + 2)); - } - - return lines; -} - -/** - * Render an array node. - * - * @param {YamlArrayNode} node Array node. - * @param {number} indent Current indentation. - * @returns {string[]} YAML lines. - */ -function renderArrayNode(node, indent) { - const lines = []; - for (const item of node.items) { - if (item.kind === "scalar") { - lines.push(`${" ".repeat(indent)}- ${formatYamlScalar(item.value)}`); - continue; - } - - lines.push(`${" ".repeat(indent)}-`); - lines.push(...renderYaml(item, indent + 2)); - } - - return lines; -} - -/** - * Create a scalar node. - * - * @param {string} value Scalar value. - * @returns {YamlScalarNode} Scalar node. - */ -function createScalarNode(value) { - return {kind: "scalar", value}; -} - -/** - * Create an array node. - * - * @param {YamlNode[]} items Array items. - * @returns {YamlArrayNode} Array node. - */ -function createArrayNode(items) { - return {kind: "array", items}; -} - -/** - * Convert one structured form value back into a YAML node tree. - * Object-array editors submit plain JavaScript objects so the writer can - * rebuild the full array deterministically instead of patching item paths - * one by one. - * - * @param {unknown} value Structured form value. - * @returns {YamlNode} YAML node. - */ -function createNodeFromFormValue(value) { - if (Array.isArray(value)) { - return createArrayNode(value.map((item) => createNodeFromFormValue(item))); - } - - if (value && typeof value === "object") { - const objectNode = createObjectNode(); - for (const [key, childValue] of Object.entries(value)) { - setObjectEntry(objectNode, key, createNodeFromFormValue(childValue)); - } - - return objectNode; - } - - return createScalarNode(String(value ?? "")); -} - -/** - * Create an object node. - * - * @returns {YamlObjectNode} Object node. - */ -function createObjectNode() { - return {kind: "object", entries: [], map: new Map()}; -} - -/** - * Combine a parent path with one child segment. - * - * @param {string} parentPath Parent path. - * @param {string} key Child key. - * @returns {string} Combined path. - */ -function combinePath(parentPath, key) { - return parentPath && parentPath !== "" ? `${parentPath}.${key}` : key; -} - -module.exports = { - applyFormUpdates, - applyScalarUpdates, - getEditableSchemaFields, - isEditableScalarType, - isScalarCompatible, - parseBatchArrayValue, - parseSchemaContent, - parseTopLevelYaml, - unquoteScalar, - validateParsedConfig -}; - -/** - * @typedef {{ - * type: "object", - * displayPath: string, - * required: string[], - * properties: Record, - * title?: string, - * description?: string, - * defaultValue?: string - * } | { - * type: "array", - * displayPath: string, - * title?: string, - * description?: string, - * defaultValue?: string, - * refTable?: string, - * items: SchemaNode - * } | { - * type: "string" | "integer" | "number" | "boolean", - * displayPath: string, - * title?: string, - * description?: string, - * defaultValue?: string, - * enumValues?: string[], - * refTable?: string - * }} SchemaNode - */ - -/** - * @typedef {{kind: "scalar", value: string}} YamlScalarNode - * @typedef {{kind: "array", items: YamlNode[]}} YamlArrayNode - * @typedef {{kind: "object", entries: Array<{key: string, node: YamlNode}>, map: Map}} YamlObjectNode - * @typedef {YamlScalarNode | YamlArrayNode | YamlObjectNode} YamlNode - */ diff --git a/tools/vscode-config-extension/src/extension.js b/tools/vscode-config-extension/src/extension.js deleted file mode 100644 index 22fceb8..0000000 --- a/tools/vscode-config-extension/src/extension.js +++ /dev/null @@ -1,1482 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const vscode = require("vscode"); -const { - applyFormUpdates, - getEditableSchemaFields, - parseBatchArrayValue, - parseSchemaContent, - parseTopLevelYaml, - unquoteScalar, - validateParsedConfig -} = require("./configValidation"); - -/** - * Activate the GFramework config extension. - * The current tool focuses on workspace file navigation, lightweight - * validation, and a schema-aware form preview for common editing workflows. - * - * @param {vscode.ExtensionContext} context Extension context. - */ -function activate(context) { - const diagnostics = vscode.languages.createDiagnosticCollection("gframeworkConfig"); - const provider = new ConfigTreeDataProvider(); - - context.subscriptions.push(diagnostics); - context.subscriptions.push( - vscode.window.registerTreeDataProvider("gframeworkConfigExplorer", provider), - vscode.commands.registerCommand("gframeworkConfig.refresh", async () => { - provider.refresh(); - await validateAllConfigs(diagnostics); - }), - vscode.commands.registerCommand("gframeworkConfig.openRaw", async (item) => { - await openRawFile(item); - }), - vscode.commands.registerCommand("gframeworkConfig.openSchema", async (item) => { - await openSchemaFile(item); - }), - vscode.commands.registerCommand("gframeworkConfig.openFormPreview", async (item) => { - await openFormPreview(item, diagnostics); - }), - vscode.commands.registerCommand("gframeworkConfig.batchEditDomain", async (item) => { - await openBatchEdit(item, diagnostics, provider); - }), - vscode.commands.registerCommand("gframeworkConfig.validateAll", async () => { - await validateAllConfigs(diagnostics); - }), - vscode.workspace.onDidSaveTextDocument(async (document) => { - const workspaceRoot = getWorkspaceRoot(); - if (!workspaceRoot) { - return; - } - - if (!isConfigFile(document.uri, workspaceRoot)) { - return; - } - - await validateConfigFile(document.uri, diagnostics); - provider.refresh(); - }), - vscode.workspace.onDidChangeWorkspaceFolders(async () => { - provider.refresh(); - await validateAllConfigs(diagnostics); - }) - ); - - void validateAllConfigs(diagnostics); -} - -/** - * Deactivate the extension. - */ -function deactivate() { -} - -/** - * Tree provider for the GFramework config explorer view. - */ -class ConfigTreeDataProvider { - constructor() { - this._emitter = new vscode.EventEmitter(); - this.onDidChangeTreeData = this._emitter.event; - } - - /** - * Refresh the tree view. - */ - refresh() { - this._emitter.fire(undefined); - } - - /** - * Resolve a tree item. - * - * @param {ConfigTreeItem} element Tree element. - * @returns {vscode.TreeItem} Tree item. - */ - getTreeItem(element) { - return element; - } - - /** - * Resolve child elements. - * - * @param {ConfigTreeItem | undefined} element Parent element. - * @returns {Thenable} Child items. - */ - async getChildren(element) { - const workspaceRoot = getWorkspaceRoot(); - if (!workspaceRoot) { - return []; - } - - if (!element) { - return this.getRootItems(workspaceRoot); - } - - if (element.kind !== "domain" || !element.resourceUri) { - return []; - } - - return this.getFileItems(workspaceRoot, element.resourceUri); - } - - /** - * Build root domain items from the config directory. - * - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {Promise} Root items. - */ - async getRootItems(workspaceRoot) { - const configRoot = getConfigRoot(workspaceRoot); - if (!configRoot || !fs.existsSync(configRoot.fsPath)) { - return [ - new ConfigTreeItem( - "No config directory", - "info", - vscode.TreeItemCollapsibleState.None, - undefined, - "Set gframeworkConfig.configPath or create the directory.") - ]; - } - - const entries = fs.readdirSync(configRoot.fsPath, {withFileTypes: true}) - .filter((entry) => entry.isDirectory()) - .sort((left, right) => left.name.localeCompare(right.name)); - - return entries.map((entry) => { - const domainUri = vscode.Uri.joinPath(configRoot, entry.name); - return new ConfigTreeItem( - entry.name, - "domain", - vscode.TreeItemCollapsibleState.Collapsed, - domainUri, - undefined); - }); - } - - /** - * Build file items for a config domain directory. - * - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @param {vscode.Uri} domainUri Domain directory URI. - * @returns {Promise} File items. - */ - async getFileItems(workspaceRoot, domainUri) { - const entries = fs.readdirSync(domainUri.fsPath, {withFileTypes: true}) - .filter((entry) => entry.isFile() && isYamlPath(entry.name)) - .sort((left, right) => left.name.localeCompare(right.name)); - - return entries.map((entry) => { - const fileUri = vscode.Uri.joinPath(domainUri, entry.name); - const schemaUri = getSchemaUriForConfigFile(fileUri, workspaceRoot); - const description = schemaUri && fs.existsSync(schemaUri.fsPath) - ? "schema" - : "schema missing"; - const item = new ConfigTreeItem( - entry.name, - "file", - vscode.TreeItemCollapsibleState.None, - fileUri, - description); - - item.contextValue = "gframeworkConfigFile"; - item.command = { - command: "gframeworkConfig.openRaw", - title: "Open Raw", - arguments: [item] - }; - - return item; - }); - } -} - -/** - * Tree item used by the config explorer. - */ -class ConfigTreeItem extends vscode.TreeItem { - /** - * @param {string} label Display label. - * @param {"domain" | "file" | "info"} kind Item kind. - * @param {vscode.TreeItemCollapsibleState} collapsibleState Collapsible state. - * @param {vscode.Uri | undefined} resourceUri Resource URI. - * @param {string | undefined} description Description. - */ - constructor(label, kind, collapsibleState, resourceUri, description) { - super(label, collapsibleState); - this.kind = kind; - this.resourceUri = resourceUri; - this.description = description; - this.contextValue = kind === "file" ? "gframeworkConfigFile" : kind; - } -} - -/** - * Open the selected raw config file. - * - * @param {ConfigTreeItem | { resourceUri?: vscode.Uri }} item Tree item. - * @returns {Promise} Async task. - */ -async function openRawFile(item) { - const uri = item && item.resourceUri; - if (!uri) { - return; - } - - const document = await vscode.workspace.openTextDocument(uri); - await vscode.window.showTextDocument(document, {preview: false}); -} - -/** - * Open the matching schema file for a selected config item. - * - * @param {ConfigTreeItem | { resourceUri?: vscode.Uri }} item Tree item. - * @returns {Promise} Async task. - */ -async function openSchemaFile(item) { - const workspaceRoot = getWorkspaceRoot(); - const configUri = item && item.resourceUri; - if (!workspaceRoot || !configUri) { - return; - } - - const schemaUri = getSchemaUriForConfigFile(configUri, workspaceRoot); - if (!schemaUri || !fs.existsSync(schemaUri.fsPath)) { - void vscode.window.showWarningMessage("Matching schema file was not found."); - return; - } - - const document = await vscode.workspace.openTextDocument(schemaUri); - await vscode.window.showTextDocument(document, {preview: false}); -} - -/** - * Open a lightweight form preview for schema-bound config fields. - * The preview walks nested object structures recursively and now supports - * object-array editing for the repository's supported schema subset. - * - * @param {ConfigTreeItem | { resourceUri?: vscode.Uri }} item Tree item. - * @param {vscode.DiagnosticCollection} diagnostics Diagnostic collection. - * @returns {Promise} Async task. - */ -async function openFormPreview(item, diagnostics) { - const workspaceRoot = getWorkspaceRoot(); - const configUri = item && item.resourceUri; - if (!workspaceRoot || !configUri) { - return; - } - - const yamlText = await fs.promises.readFile(configUri.fsPath, "utf8"); - const parsedYaml = parseTopLevelYaml(yamlText); - const schemaInfo = await loadSchemaInfoForConfig(configUri, workspaceRoot); - - const panel = vscode.window.createWebviewPanel( - "gframeworkConfigFormPreview", - `Config Form: ${path.basename(configUri.fsPath)}`, - vscode.ViewColumn.Beside, - {enableScripts: true}); - - panel.webview.html = renderFormHtml( - path.basename(configUri.fsPath), - schemaInfo, - parsedYaml); - - panel.webview.onDidReceiveMessage(async (message) => { - if (message.type === "save") { - const latestYamlText = await fs.promises.readFile(configUri.fsPath, "utf8"); - const updatedYaml = applyFormUpdates(latestYamlText, { - scalars: message.scalars || {}, - arrays: parseArrayFieldPayload(message.arrays || {}), - objectArrays: message.objectArrays || {} - }); - await fs.promises.writeFile(configUri.fsPath, updatedYaml, "utf8"); - const document = await vscode.workspace.openTextDocument(configUri); - await document.save(); - await validateConfigFile(configUri, diagnostics); - void vscode.window.showInformationMessage("Config file saved from form preview."); - } - - if (message.type === "openRaw") { - await openRawFile({resourceUri: configUri}); - } - }); -} - -/** - * Validate all config files in the configured config directory. - * - * @param {vscode.DiagnosticCollection} diagnostics Diagnostic collection. - * @returns {Promise} Async task. - */ -async function validateAllConfigs(diagnostics) { - diagnostics.clear(); - - const workspaceRoot = getWorkspaceRoot(); - if (!workspaceRoot) { - return; - } - - const configRoot = getConfigRoot(workspaceRoot); - if (!configRoot || !fs.existsSync(configRoot.fsPath)) { - return; - } - - const files = enumerateYamlFiles(configRoot.fsPath); - for (const filePath of files) { - await validateConfigFile(vscode.Uri.file(filePath), diagnostics); - } -} - -/** - * Validate a single config file against its matching schema. - * - * @param {vscode.Uri} configUri Config file URI. - * @param {vscode.DiagnosticCollection} diagnostics Diagnostic collection. - * @returns {Promise} Async task. - */ -async function validateConfigFile(configUri, diagnostics) { - const workspaceRoot = getWorkspaceRoot(); - if (!workspaceRoot) { - return; - } - - if (!isConfigFile(configUri, workspaceRoot)) { - return; - } - - const yamlText = await fs.promises.readFile(configUri.fsPath, "utf8"); - const parsedYaml = parseTopLevelYaml(yamlText); - const schemaInfo = await loadSchemaInfoForConfig(configUri, workspaceRoot); - const fileDiagnostics = []; - - if (!schemaInfo.exists) { - fileDiagnostics.push(new vscode.Diagnostic( - new vscode.Range(0, 0, 0, 1), - `Matching schema file not found: ${schemaInfo.schemaPath}`, - vscode.DiagnosticSeverity.Warning)); - diagnostics.set(configUri, fileDiagnostics); - return; - } - - for (const diagnostic of validateParsedConfig(schemaInfo, parsedYaml)) { - fileDiagnostics.push(new vscode.Diagnostic( - new vscode.Range(0, 0, 0, 1), - diagnostic.message, - diagnostic.severity === "error" - ? vscode.DiagnosticSeverity.Error - : vscode.DiagnosticSeverity.Warning)); - } - - diagnostics.set(configUri, fileDiagnostics); -} - -/** - * Open a minimal batch editor for one config domain. - * The workflow intentionally focuses on one schema-bound directory at a time - * so designers can apply the same top-level scalar or scalar-array values - * across multiple files without dropping down to repetitive raw-YAML edits. - * - * @param {ConfigTreeItem | { kind?: string, resourceUri?: vscode.Uri }} item Tree item. - * @param {vscode.DiagnosticCollection} diagnostics Diagnostic collection. - * @param {ConfigTreeDataProvider} provider Tree provider. - * @returns {Promise} Async task. - */ -async function openBatchEdit(item, diagnostics, provider) { - const workspaceRoot = getWorkspaceRoot(); - const domainUri = item && item.resourceUri; - if (!workspaceRoot || !domainUri || item.kind !== "domain") { - return; - } - - const fileItems = fs.readdirSync(domainUri.fsPath, {withFileTypes: true}) - .filter((entry) => entry.isFile() && isYamlPath(entry.name)) - .sort((left, right) => left.name.localeCompare(right.name)) - .map((entry) => { - const fileUri = vscode.Uri.joinPath(domainUri, entry.name); - return { - label: entry.name, - description: path.relative(workspaceRoot.uri.fsPath, fileUri.fsPath), - fileUri, - picked: true - }; - }); - - if (fileItems.length === 0) { - void vscode.window.showWarningMessage("No YAML config files were found in the selected domain."); - return; - } - - const selectedFiles = await vscode.window.showQuickPick(fileItems, { - canPickMany: true, - title: `Batch Edit: ${path.basename(domainUri.fsPath)}`, - placeHolder: "Select the config files to update." - }); - if (!selectedFiles || selectedFiles.length === 0) { - return; - } - - const schemaInfo = await loadSchemaInfoForConfig(selectedFiles[0].fileUri, workspaceRoot); - if (!schemaInfo.exists) { - void vscode.window.showWarningMessage("Batch edit requires a matching schema file for the selected domain."); - return; - } - - const editableFields = getEditableSchemaFields(schemaInfo); - if (editableFields.length === 0) { - void vscode.window.showWarningMessage( - "No top-level scalar or scalar-array fields were found in the matching schema."); - return; - } - - const selectedFields = await vscode.window.showQuickPick( - editableFields.map((field) => ({ - label: field.title || field.key, - description: field.inputKind === "array" - ? `array<${field.itemType}>` - : field.type, - detail: [ - field.required ? "required" : "", - field.description || "", - field.refTable ? `ref: ${field.refTable}` : "" - ].filter((part) => part.length > 0).join(" · ") || undefined, - field - })), - { - canPickMany: true, - title: `Batch Edit Fields: ${path.basename(domainUri.fsPath)}`, - placeHolder: "Select the fields to apply across the chosen files." - }); - if (!selectedFields || selectedFields.length === 0) { - return; - } - - const updates = { - scalars: {}, - arrays: {} - }; - - for (const selectedField of selectedFields) { - const field = selectedField.field; - const rawValue = await promptBatchFieldValue(field); - if (rawValue === undefined) { - return; - } - - if (field.inputKind === "array") { - updates.arrays[field.key] = parseBatchArrayValue(rawValue); - continue; - } - - updates.scalars[field.key] = rawValue; - } - - const edit = new vscode.WorkspaceEdit(); - const touchedDocuments = []; - let changedFileCount = 0; - - for (const fileItem of selectedFiles) { - const document = await vscode.workspace.openTextDocument(fileItem.fileUri); - const originalYaml = document.getText(); - const updatedYaml = applyFormUpdates(originalYaml, updates); - if (updatedYaml === originalYaml) { - continue; - } - - const fullRange = new vscode.Range( - document.positionAt(0), - document.positionAt(originalYaml.length)); - edit.replace(fileItem.fileUri, fullRange, updatedYaml); - touchedDocuments.push(document); - changedFileCount += 1; - } - - if (changedFileCount === 0) { - void vscode.window.showInformationMessage("Batch edit did not change any selected config files."); - return; - } - - const applied = await vscode.workspace.applyEdit(edit); - if (!applied) { - throw new Error("VS Code rejected the batch edit workspace update."); - } - - for (const document of touchedDocuments) { - await document.save(); - await validateConfigFile(document.uri, diagnostics); - } - - provider.refresh(); - void vscode.window.showInformationMessage( - `Batch updated ${changedFileCount} config file(s) in '${path.basename(domainUri.fsPath)}'.`); -} - -/** - * Load schema info for a config file. - * - * @param {vscode.Uri} configUri Config file URI. - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {Promise<{exists: boolean, schemaPath: string, required: string[], properties: Record}>} Schema info. - */ -async function loadSchemaInfoForConfig(configUri, workspaceRoot) { - const schemaUri = getSchemaUriForConfigFile(configUri, workspaceRoot); - const schemaPath = schemaUri ? schemaUri.fsPath : ""; - if (!schemaUri || !fs.existsSync(schemaUri.fsPath)) { - return { - exists: false, - schemaPath, - required: [], - properties: {} - }; - } - - const content = await fs.promises.readFile(schemaUri.fsPath, "utf8"); - try { - const parsed = parseSchemaContent(content); - - return { - exists: true, - schemaPath, - type: parsed.type, - required: parsed.required, - properties: parsed.properties - }; - } catch (error) { - return { - exists: false, - schemaPath, - required: [], - properties: {} - }; - } -} - -/** - * Render the form-preview webview HTML. - * - * @param {string} fileName File name. - * @param {{exists: boolean, schemaPath: string, required: string[], properties: Record, type?: string}} schemaInfo Schema info. - * @param {unknown} parsedYaml Parsed YAML data. - * @returns {string} HTML string. - */ -function renderFormHtml(fileName, schemaInfo, parsedYaml) { - const formModel = buildFormModel(schemaInfo, parsedYaml); - const renderedFields = formModel.fields - .map((field) => renderFormField(field)) - .join("\n"); - - const unsupportedFields = formModel.unsupported - .map((field) => ` -
- ${escapeHtml(field.path)}: ${escapeHtml(field.message)} -
- `) - .join("\n"); - - const schemaStatus = schemaInfo.exists - ? `Schema: ${escapeHtml(schemaInfo.schemaPath)}` - : `Schema missing: ${escapeHtml(schemaInfo.schemaPath)}`; - - const editableContent = renderedFields; - const unsupportedSection = unsupportedFields.length > 0 - ? `
${unsupportedFields}
` - : ""; - const emptyState = editableContent.length > 0 - ? `${editableContent}${unsupportedSection}` - : "

No editable schema-bound fields were detected. Use raw YAML for unsupported shapes.

"; - - return ` - - - - - - - -
- - -
-
-
File: ${escapeHtml(fileName)}
-
${schemaStatus}
-
-
${emptyState}
- - -`; -} - -/** - * Render one form field. - * - * @param {Record} field Form field descriptor. - * @returns {string} HTML fragment. - */ -function renderFormField(field) { - if (field.kind === "section") { - return ` -
-
${escapeHtml(field.label)} ${field.required ? "required" : ""}
-
${escapeHtml(field.displayPath || field.path)}
- ${field.description ? `${escapeHtml(field.description)}` : ""} -
- `; - } - - if (field.kind === "objectArray") { - const renderedItems = field.items - .map((item) => renderObjectArrayItem(item)) - .join("\n"); - const renderedTemplate = renderObjectArrayItem({ - title: "Item", - fields: field.templateFields - }); - return ` -
-
${escapeHtml(field.label)} ${field.required ? "required" : ""}
-
${escapeHtml(field.displayPath || field.path)}
- Each item uses the object schema below. - ${renderFieldHint(field.schema, true)} -
${renderedItems}
- - -
- `; - } - - if (field.kind === "array") { - const itemType = field.itemType - ? `array<${escapeHtml(field.itemType)}>` - : "array"; - const dataAttribute = field.itemMode - ? `data-item-array-path="${escapeHtml(field.path)}"` - : `data-array-path="${escapeHtml(field.path)}"`; - return ` - - `; - } - - const enumValues = Array.isArray(field.schema.enumValues) ? field.schema.enumValues : []; - const dataAttribute = field.itemMode - ? `data-item-local-path="${escapeHtml(field.path)}"` - : `data-path="${escapeHtml(field.path)}"`; - const inputControl = enumValues.length > 0 - ? ` - - ` - : ``; - - return ` - - `; -} - -/** - * Render one object-array item editor block. - * - * @param {{title: string, fields: Array>}} item Item model. - * @returns {string} HTML fragment. - */ -function renderObjectArrayItem(item) { - return ` -
-
- ${escapeHtml(item.title)} - -
- ${item.fields.map((field) => renderFormField(field)).join("\n")} -
- `; -} - -/** - * Build a recursive form model from schema and parsed YAML. - * - * @param {{exists: boolean, schemaPath: string, required: string[], properties: Record, type?: string}} schemaInfo Schema info. - * @param {unknown} parsedYaml Parsed YAML data. - * @returns {{fields: Array>, unsupported: Array<{path: string, message: string}>}} Form model. - */ -function buildFormModel(schemaInfo, parsedYaml) { - if (!schemaInfo || schemaInfo.type !== "object") { - return {fields: [], unsupported: []}; - } - - const fields = []; - const unsupported = []; - collectFormFields(schemaInfo, parsedYaml, "", 0, fields, unsupported); - return {fields, unsupported}; -} - -/** - * Recursively collect top-level form-editable fields. - * - * @param {{type: string, required?: string[], properties?: Record, title?: string, description?: string}} schemaNode Schema node. - * @param {unknown} yamlNode YAML node. - * @param {string} currentPath Current logical path. - * @param {number} depth Current depth. - * @param {Array>} fields Field sink. - * @param {Array<{path: string, message: string}>} unsupported Unsupported sink. - */ -function collectFormFields(schemaNode, yamlNode, currentPath, depth, fields, unsupported) { - if (!schemaNode || schemaNode.type !== "object") { - return; - } - - const yamlMap = getYamlObjectMap(yamlNode); - const requiredSet = new Set(Array.isArray(schemaNode.required) ? schemaNode.required : []); - - for (const [key, propertySchema] of Object.entries(schemaNode.properties || {})) { - const propertyPath = currentPath ? `${currentPath}.${key}` : key; - const label = propertySchema.title || key; - const propertyValue = yamlMap.get(key); - - if (propertySchema.type === "object") { - fields.push({ - kind: "section", - path: propertyPath, - label, - description: propertySchema.description, - required: requiredSet.has(key), - depth - }); - collectFormFields(propertySchema, propertyValue, propertyPath, depth + 1, fields, unsupported); - continue; - } - - if (propertySchema.type === "array" && - propertySchema.items && - ["string", "integer", "number", "boolean"].includes(propertySchema.items.type)) { - fields.push({ - kind: "array", - path: propertyPath, - displayPath: propertyPath, - label, - required: requiredSet.has(key), - depth, - itemType: propertySchema.items.type, - value: getScalarArrayValue(propertyValue), - schema: propertySchema - }); - continue; - } - - if (propertySchema.type === "array" && - propertySchema.items && - propertySchema.items.type === "object") { - const itemFieldsTemplate = []; - collectObjectArrayItemFields( - propertySchema.items, - undefined, - "", - `${propertyPath}[]`, - depth + 1, - itemFieldsTemplate, - unsupported); - fields.push({ - kind: "objectArray", - path: propertyPath, - displayPath: propertyPath, - label, - required: requiredSet.has(key), - depth, - schema: propertySchema, - items: buildObjectArrayItemModels(propertySchema.items, propertyValue, propertyPath, depth + 1, unsupported), - templateFields: itemFieldsTemplate - }); - continue; - } - - if (["string", "integer", "number", "boolean"].includes(propertySchema.type)) { - fields.push({ - kind: "scalar", - path: propertyPath, - displayPath: propertyPath, - label, - required: requiredSet.has(key), - depth, - value: getScalarFieldValue(propertyValue, propertySchema.defaultValue), - schema: propertySchema - }); - continue; - } - - unsupported.push({ - path: propertyPath, - message: propertySchema.type === "array" - ? "Unsupported array shapes are currently raw-YAML-only in the form preview." - : `${propertySchema.type} fields are currently raw-YAML-only.` - }); - } -} - -/** - * Build object-array item models from the current YAML array value. - * - * @param {{type: string, required?: string[], properties?: Record}} itemSchema Array item schema. - * @param {unknown} yamlNode YAML node. - * @param {string} propertyPath Top-level object-array path. - * @param {number} depth Current depth. - * @param {Array<{path: string, message: string}>} unsupported Unsupported sink. - * @returns {Array<{title: string, fields: Array>}>} Item models. - */ -function buildObjectArrayItemModels(itemSchema, yamlNode, propertyPath, depth, unsupported) { - if (!yamlNode || yamlNode.kind !== "array") { - return []; - } - - const items = []; - for (let index = 0; index < yamlNode.items.length; index += 1) { - const itemNode = yamlNode.items[index]; - const itemPath = `${propertyPath}[${index}]`; - if (!itemNode || itemNode.kind !== "object") { - unsupported.push({ - path: itemPath, - message: "Object-array items must be mappings. Use raw YAML if the current file mixes scalar and object items." - }); - continue; - } - - const fields = []; - collectObjectArrayItemFields( - itemSchema, - itemNode, - "", - itemPath, - depth, - fields, - unsupported); - items.push({ - title: `Item ${index + 1}`, - fields - }); - } - - return items; -} - -/** - * Recursively collect editable fields inside one object-array item. - * Nested objects remain editable, while nested object arrays still fall back - * to raw YAML until a deeper editor model is added. - * - * @param {{type: string, required?: string[], properties?: Record, title?: string, description?: string}} schemaNode Schema node. - * @param {unknown} yamlNode YAML node. - * @param {string} localPath Path inside the current array item. - * @param {string} displayPath Full logical path for UI display. - * @param {number} depth Current depth. - * @param {Array>} fields Field sink. - * @param {Array<{path: string, message: string}>} unsupported Unsupported sink. - */ -function collectObjectArrayItemFields(schemaNode, yamlNode, localPath, displayPath, depth, fields, unsupported) { - if (!schemaNode || schemaNode.type !== "object") { - return; - } - - const yamlMap = getYamlObjectMap(yamlNode); - const requiredSet = new Set(Array.isArray(schemaNode.required) ? schemaNode.required : []); - - for (const [key, propertySchema] of Object.entries(schemaNode.properties || {})) { - const itemLocalPath = localPath ? `${localPath}.${key}` : key; - const itemDisplayPath = `${displayPath}.${key}`; - const label = propertySchema.title || key; - const propertyValue = yamlMap.get(key); - - if (propertySchema.type === "object") { - fields.push({ - kind: "section", - path: itemLocalPath, - displayPath: itemDisplayPath, - label, - description: propertySchema.description, - required: requiredSet.has(key), - depth - }); - collectObjectArrayItemFields( - propertySchema, - propertyValue, - itemLocalPath, - itemDisplayPath, - depth + 1, - fields, - unsupported); - continue; - } - - if (propertySchema.type === "array" && - propertySchema.items && - ["string", "integer", "number", "boolean"].includes(propertySchema.items.type)) { - fields.push({ - kind: "array", - path: itemLocalPath, - displayPath: itemDisplayPath, - label, - required: requiredSet.has(key), - depth, - itemType: propertySchema.items.type, - value: getScalarArrayValue(propertyValue), - schema: propertySchema, - itemMode: true - }); - continue; - } - - if (["string", "integer", "number", "boolean"].includes(propertySchema.type)) { - fields.push({ - kind: "scalar", - path: itemLocalPath, - displayPath: itemDisplayPath, - label, - required: requiredSet.has(key), - depth, - value: getScalarFieldValue(propertyValue, propertySchema.defaultValue), - schema: propertySchema, - itemMode: true - }); - continue; - } - - unsupported.push({ - path: itemDisplayPath, - message: propertySchema.type === "array" - ? "Nested object-array fields are currently raw-YAML-only inside the object-array editor." - : `${propertySchema.type} fields are currently raw-YAML-only.` - }); - } -} - -/** - * Get the mapping lookup for one parsed YAML object node. - * - * @param {unknown} yamlNode YAML node. - * @returns {Map} Mapping lookup. - */ -function getYamlObjectMap(yamlNode) { - return yamlNode && yamlNode.kind === "object" && yamlNode.map instanceof Map - ? yamlNode.map - : new Map(); -} - -/** - * Extract a scalar field value from a parsed YAML node. - * - * @param {unknown} yamlNode YAML node. - * @param {string | undefined} defaultValue Default value from schema metadata. - * @returns {string} Scalar display value. - */ -function getScalarFieldValue(yamlNode, defaultValue) { - if (yamlNode && yamlNode.kind === "scalar") { - return unquoteScalar(yamlNode.value || ""); - } - - return defaultValue || ""; -} - -/** - * Extract a scalar-array value list from a parsed YAML node. - * - * @param {unknown} yamlNode YAML node. - * @returns {string[]} Scalar array value list. - */ -function getScalarArrayValue(yamlNode) { - if (!yamlNode || yamlNode.kind !== "array") { - return []; - } - - return yamlNode.items - .filter((item) => item && item.kind === "scalar") - .map((item) => unquoteScalar(item.value || "")); -} - -/** - * Render human-facing metadata hints for one schema field. - * - * @param {{description?: string, defaultValue?: string, enumValues?: string[], items?: {enumValues?: string[]}, refTable?: string}} propertySchema Property schema metadata. - * @param {boolean} isArrayField Whether the field is an array. - * @returns {string} HTML fragment. - */ -function renderFieldHint(propertySchema, isArrayField) { - const hints = []; - - if (propertySchema.description) { - hints.push(escapeHtml(propertySchema.description)); - } - - if (propertySchema.defaultValue) { - hints.push(`Default: ${escapeHtml(propertySchema.defaultValue)}`); - } - - const enumValues = isArrayField - ? propertySchema.items && Array.isArray(propertySchema.items.enumValues) - ? propertySchema.items.enumValues - : [] - : propertySchema.enumValues; - if (Array.isArray(enumValues) && enumValues.length > 0) { - hints.push(`Allowed: ${escapeHtml(enumValues.join(", "))}`); - } - - if (propertySchema.refTable) { - hints.push(`Ref table: ${escapeHtml(propertySchema.refTable)}`); - } - - if (hints.length === 0) { - return ""; - } - - return `${hints.join(" · ")}`; -} - -/** - * Prompt for one batch-edit field value. - * - * @param {{key: string, type: string, itemType?: string, title?: string, description?: string, defaultValue?: string, enumValues?: string[], itemEnumValues?: string[], refTable?: string, inputKind: "scalar" | "array", required: boolean}} field Editable field descriptor. - * @returns {Promise} User input, or undefined when cancelled. - */ -async function promptBatchFieldValue(field) { - if (field.inputKind === "array") { - const hintParts = []; - if (field.itemEnumValues && field.itemEnumValues.length > 0) { - hintParts.push(`Allowed items: ${field.itemEnumValues.join(", ")}`); - } - - if (field.defaultValue) { - hintParts.push(`Default: ${field.defaultValue}`); - } - - return vscode.window.showInputBox({ - title: `Batch Edit Array: ${field.title || field.key}`, - prompt: `Enter comma-separated items for '${field.key}' (expected array<${field.itemType}>). Leave empty to clear the array.`, - placeHolder: hintParts.join(" | "), - ignoreFocusOut: true - }); - } - - if (field.enumValues && field.enumValues.length > 0) { - const picked = await vscode.window.showQuickPick( - field.enumValues.map((value) => ({ - label: value, - description: value === field.defaultValue ? "default" : undefined - })), - { - title: `Batch Edit Field: ${field.title || field.key}`, - placeHolder: `Select a value for '${field.key}'.` - }); - return picked ? picked.label : undefined; - } - - return vscode.window.showInputBox({ - title: `Batch Edit Field: ${field.title || field.key}`, - prompt: `Enter the new value for '${field.key}' (expected ${field.type}).`, - placeHolder: [ - field.description || "", - field.defaultValue ? `Default: ${field.defaultValue}` : "", - field.refTable ? `Ref table: ${field.refTable}` : "" - ].filter((part) => part.length > 0).join(" | ") || undefined, - ignoreFocusOut: true - }); -} - -/** - * Enumerate all YAML files recursively. - * - * @param {string} rootPath Root path. - * @returns {string[]} YAML file paths. - */ -function enumerateYamlFiles(rootPath) { - const results = []; - - for (const entry of fs.readdirSync(rootPath, {withFileTypes: true})) { - const fullPath = path.join(rootPath, entry.name); - if (entry.isDirectory()) { - results.push(...enumerateYamlFiles(fullPath)); - continue; - } - - if (entry.isFile() && isYamlPath(entry.name)) { - results.push(fullPath); - } - } - - return results; -} - -/** - * Check whether a path is a YAML file. - * - * @param {string} filePath File path. - * @returns {boolean} True for YAML files. - */ -function isYamlPath(filePath) { - return filePath.endsWith(".yaml") || filePath.endsWith(".yml"); -} - -/** - * Resolve the first workspace root. - * - * @returns {vscode.WorkspaceFolder | undefined} Workspace root. - */ -function getWorkspaceRoot() { - const folders = vscode.workspace.workspaceFolders; - return folders && folders.length > 0 ? folders[0] : undefined; -} - -/** - * Resolve the configured config root. - * - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {vscode.Uri | undefined} Config root URI. - */ -function getConfigRoot(workspaceRoot) { - const relativePath = vscode.workspace.getConfiguration("gframeworkConfig") - .get("configPath", "config"); - return vscode.Uri.joinPath(workspaceRoot.uri, relativePath); -} - -/** - * Resolve the configured schemas root. - * - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {vscode.Uri | undefined} Schema root URI. - */ -function getSchemasRoot(workspaceRoot) { - const relativePath = vscode.workspace.getConfiguration("gframeworkConfig") - .get("schemasPath", "schemas"); - return vscode.Uri.joinPath(workspaceRoot.uri, relativePath); -} - -/** - * Resolve the matching schema URI for a config file. - * - * @param {vscode.Uri} configUri Config file URI. - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {vscode.Uri | undefined} Schema URI. - */ -function getSchemaUriForConfigFile(configUri, workspaceRoot) { - const configRoot = getConfigRoot(workspaceRoot); - const schemaRoot = getSchemasRoot(workspaceRoot); - if (!configRoot || !schemaRoot) { - return undefined; - } - - const relativePath = path.relative(configRoot.fsPath, configUri.fsPath); - const segments = relativePath.split(path.sep); - if (segments.length === 0 || !segments[0]) { - return undefined; - } - - return vscode.Uri.joinPath(schemaRoot, `${segments[0]}.schema.json`); -} - -/** - * Check whether a URI is inside the configured config root. - * - * @param {vscode.Uri} uri File URI. - * @param {vscode.WorkspaceFolder} workspaceRoot Workspace root. - * @returns {boolean} True when the file belongs to the config tree. - */ -function isConfigFile(uri, workspaceRoot) { - const configRoot = getConfigRoot(workspaceRoot); - if (!configRoot) { - return false; - } - - const relativePath = path.relative(configRoot.fsPath, uri.fsPath); - return !relativePath.startsWith("..") && !path.isAbsolute(relativePath) && isYamlPath(uri.fsPath); -} - -/** - * Escape HTML text. - * - * @param {string} value Raw string. - * @returns {string} Escaped string. - */ -function escapeHtml(value) { - return String(value) - .replace(/&/gu, "&") - .replace(//gu, ">") - .replace(/"/gu, """) - .replace(/'/gu, "'"); -} - -/** - * Convert raw textarea payloads into scalar-array items. - * - * @param {Record} arrays Raw array editor payload. - * @returns {Record} Parsed array updates. - */ -function parseArrayFieldPayload(arrays) { - const parsed = {}; - - for (const [key, value] of Object.entries(arrays)) { - parsed[key] = String(value) - .split(/\r?\n/u) - .map((item) => item.trim()) - .filter((item) => item.length > 0); - } - - return parsed; -} - -module.exports = { - activate, - deactivate -}; diff --git a/tools/vscode-config-extension/test/configValidation.test.js b/tools/vscode-config-extension/test/configValidation.test.js deleted file mode 100644 index ae8a272..0000000 --- a/tools/vscode-config-extension/test/configValidation.test.js +++ /dev/null @@ -1,369 +0,0 @@ -const test = require("node:test"); -const assert = require("node:assert/strict"); -const { - applyFormUpdates, - applyScalarUpdates, - getEditableSchemaFields, - parseBatchArrayValue, - parseSchemaContent, - parseTopLevelYaml, - validateParsedConfig -} = require("../src/configValidation"); - -test("parseSchemaContent should capture nested objects and object-array metadata", () => { - const schema = parseSchemaContent(` - { - "type": "object", - "required": ["id", "reward", "phases"], - "properties": { - "id": { - "type": "integer", - "title": "Monster Id", - "description": "Primary monster key.", - "default": 1 - }, - "reward": { - "type": "object", - "required": ["gold"], - "properties": { - "gold": { - "type": "integer", - "default": 10 - }, - "currency": { - "type": "string", - "enum": ["coin", "gem"] - } - } - }, - "phases": { - "type": "array", - "description": "Encounter phases.", - "items": { - "type": "object", - "required": ["wave"], - "properties": { - "wave": { "type": "integer" }, - "monsterId": { "type": "string" } - } - } - } - } - } - `); - - assert.equal(schema.type, "object"); - assert.deepEqual(schema.required, ["id", "reward", "phases"]); - assert.equal(schema.properties.id.defaultValue, "1"); - assert.equal(schema.properties.reward.type, "object"); - assert.deepEqual(schema.properties.reward.required, ["gold"]); - assert.equal(schema.properties.reward.properties.currency.enumValues[1], "gem"); - assert.equal(schema.properties.phases.type, "array"); - assert.equal(schema.properties.phases.items.type, "object"); - assert.equal(schema.properties.phases.items.properties.wave.type, "integer"); -}); - -test("parseTopLevelYaml should parse nested mappings and object arrays", () => { - const yaml = parseTopLevelYaml(` -id: 1 -reward: - gold: 10 - currency: coin -phases: - - - wave: 1 - monsterId: slime -`); - - assert.equal(yaml.kind, "object"); - assert.equal(yaml.map.get("reward").kind, "object"); - assert.equal(yaml.map.get("reward").map.get("currency").value, "coin"); - assert.equal(yaml.map.get("phases").kind, "array"); - assert.equal(yaml.map.get("phases").items[0].kind, "object"); - assert.equal(yaml.map.get("phases").items[0].map.get("wave").value, "1"); -}); - -test("validateParsedConfig should report missing and unknown nested properties", () => { - const schema = parseSchemaContent(` - { - "type": "object", - "required": ["reward"], - "properties": { - "reward": { - "type": "object", - "required": ["gold", "currency"], - "properties": { - "gold": { "type": "integer" }, - "currency": { "type": "string" } - } - } - } - } - `); - const yaml = parseTopLevelYaml(` -reward: - gold: 10 - rarity: epic -`); - - const diagnostics = validateParsedConfig(schema, yaml); - - assert.equal(diagnostics.length, 2); - assert.match(diagnostics[0].message, /reward\.currency/u); - assert.match(diagnostics[1].message, /reward\.rarity/u); -}); - -test("validateParsedConfig should report object-array item issues", () => { - const schema = parseSchemaContent(` - { - "type": "object", - "properties": { - "phases": { - "type": "array", - "items": { - "type": "object", - "required": ["wave", "monsterId"], - "properties": { - "wave": { "type": "integer" }, - "monsterId": { "type": "string" } - } - } - } - } - } - `); - const yaml = parseTopLevelYaml(` -phases: - - - wave: 1 - hpScale: 1.5 -`); - - const diagnostics = validateParsedConfig(schema, yaml); - - assert.equal(diagnostics.length, 2); - assert.match(diagnostics[0].message, /phases\[0\]\.monsterId/u); - assert.match(diagnostics[1].message, /phases\[0\]\.hpScale/u); -}); - -test("validateParsedConfig should report deep enum mismatches", () => { - const schema = parseSchemaContent(` - { - "type": "object", - "properties": { - "reward": { - "type": "object", - "properties": { - "currency": { - "type": "string", - "enum": ["coin", "gem"] - } - } - } - } - } - `); - const yaml = parseTopLevelYaml(` -reward: - currency: ticket -`); - - const diagnostics = validateParsedConfig(schema, yaml); - - assert.equal(diagnostics.length, 1); - assert.match(diagnostics[0].message, /coin, gem/u); -}); - -test("applyFormUpdates should update nested scalar and scalar-array paths", () => { - const updated = applyFormUpdates( - [ - "id: 1", - "reward:", - " gold: 10", - "phases:", - " -", - " wave: 1" - ].join("\n"), - { - scalars: { - "reward.currency": "coin", - name: "Slime" - }, - arrays: { - dropItems: ["potion", "hi potion"] - } - }); - - assert.match(updated, /^name: Slime$/mu); - assert.match(updated, /^reward:$/mu); - assert.match(updated, /^ currency: coin$/mu); - assert.match(updated, /^dropItems:$/mu); - assert.match(updated, /^ - potion$/mu); - assert.match(updated, /^ - hi potion$/mu); - assert.match(updated, /^phases:$/mu); -}); - -test("applyFormUpdates should rewrite object-array items from structured form payloads", () => { - const updated = applyFormUpdates( - [ - "id: 1", - "name: Slime", - "phases:", - " -", - " wave: 1", - " monsterId: slime" - ].join("\n"), - { - objectArrays: { - phases: [ - { - wave: "1", - monsterId: "slime", - tags: ["starter", "melee"], - reward: { - gold: "10", - currency: "coin" - } - }, - { - wave: "2", - monsterId: "goblin" - } - ] - } - }); - - assert.match(updated, /^id: 1$/mu); - assert.match(updated, /^name: Slime$/mu); - assert.match(updated, /^phases:$/mu); - assert.match(updated, /^ -$/mu); - assert.match(updated, /^ wave: 1$/mu); - assert.match(updated, /^ monsterId: slime$/mu); - assert.match(updated, /^ tags:$/mu); - assert.match(updated, /^ - starter$/mu); - assert.match(updated, /^ - melee$/mu); - assert.match(updated, /^ reward:$/mu); - assert.match(updated, /^ gold: 10$/mu); - assert.match(updated, /^ currency: coin$/mu); - assert.match(updated, /^ monsterId: goblin$/mu); -}); - -test("applyFormUpdates should clear object arrays when the form removes all items", () => { - const updated = applyFormUpdates( - [ - "id: 1", - "phases:", - " -", - " wave: 1", - " monsterId: slime" - ].join("\n"), - { - objectArrays: { - phases: [] - } - }); - - assert.equal(updated, [ - "id: 1", - "phases: []" - ].join("\n")); -}); - -test("applyScalarUpdates should preserve the scalar-only compatibility wrapper", () => { - const updated = applyScalarUpdates( - [ - "id: 1", - "name: Slime" - ].join("\n"), - { - name: "Goblin", - hp: "25" - }); - - assert.match(updated, /^name: Goblin$/mu); - assert.match(updated, /^hp: 25$/mu); -}); - -test("getEditableSchemaFields should keep batch editing limited to top-level scalar and scalar-array properties", () => { - const schema = parseSchemaContent(` - { - "type": "object", - "required": ["id", "dropItems"], - "properties": { - "id": { "type": "integer" }, - "name": { - "type": "string", - "title": "Monster Name", - "description": "Display name." - }, - "reward": { - "type": "object", - "properties": { - "gold": { "type": "integer" } - } - }, - "dropItems": { - "type": "array", - "description": "Drop ids.", - "items": { - "type": "string", - "enum": ["potion", "bomb"] - } - }, - "waypoints": { - "type": "array", - "items": { - "type": "object", - "properties": { - "x": { "type": "integer" } - } - } - } - } - } - `); - - assert.deepEqual(getEditableSchemaFields(schema), [ - { - key: "dropItems", - path: "dropItems", - type: "array", - itemType: "string", - title: undefined, - description: "Drop ids.", - defaultValue: undefined, - itemEnumValues: ["potion", "bomb"], - refTable: undefined, - inputKind: "array", - required: true - }, - { - key: "id", - path: "id", - type: "integer", - title: undefined, - description: undefined, - defaultValue: undefined, - enumValues: undefined, - refTable: undefined, - inputKind: "scalar", - required: true - }, - { - key: "name", - path: "name", - type: "string", - title: "Monster Name", - description: "Display name.", - defaultValue: undefined, - enumValues: undefined, - refTable: undefined, - inputKind: "scalar", - required: false - } - ]); -}); - -test("parseBatchArrayValue should keep comma-separated batch editing behavior", () => { - assert.deepEqual(parseBatchArrayValue(" potion, bomb , ,elixir "), ["potion", "bomb", "elixir"]); -});