From f9cf1913ead2eda82bca5f18658fae6f2209943e Mon Sep 17 00:00:00 2001 From: Romain Hamel Date: Wed, 15 Jul 2026 22:20:25 +0200 Subject: [PATCH] feat(devtools): render prop description as markdown --- .../app/components/ComponentPropInput.vue | 41 ++++- packages/devtools/nuxt.config.ts | 2 +- packages/devtools/package.json | 1 + packages/nuxt/test/basic.nuxt.test.ts | 2 +- .../test/fixtures/basic/app/types/props.ts | 6 + pnpm-lock.yaml | 165 ++++++++++++++++++ 6 files changed, 207 insertions(+), 10 deletions(-) diff --git a/packages/devtools/app/components/ComponentPropInput.vue b/packages/devtools/app/components/ComponentPropInput.vue index a98556ed..8a9dc572 100644 --- a/packages/devtools/app/components/ComponentPropInput.vue +++ b/packages/devtools/app/components/ComponentPropInput.vue @@ -10,6 +10,7 @@ import PrimitiveArrayInput from '../components/inputs/PrimitiveArrayInput.vue' import DateInput from '../components/inputs/DateInput.vue' import IconInput from '../components/inputs/IconInput.vue' import { createReusableTemplate } from '@vueuse/core' +import security from '@comark/nuxt/plugins/security' const inputTypes: Record = { icon: IconInput, @@ -62,10 +63,6 @@ function clearValue() { modelValue.value = undefined } -const description = computed(() => { - return props.description?.replace(/`([^`]+)`/g, '$1') -}) - const isArray = computed(() => currentInput.value?.inputType === 'array') const [DefineSelect, ReuseSelect] = createReusableTemplate() @@ -123,11 +120,12 @@ const [DefineDescription, ReuseDescription] = createReusableTemplate() - -

@@ -179,3 +177,30 @@ const [DefineDescription, ReuseDescription] = createReusableTemplate() + + diff --git a/packages/devtools/nuxt.config.ts b/packages/devtools/nuxt.config.ts index 3fbbdd3a..ac7bc7b7 100644 --- a/packages/devtools/nuxt.config.ts +++ b/packages/devtools/nuxt.config.ts @@ -1,7 +1,7 @@ import { resolve } from 'pathe' export default defineNuxtConfig({ - modules: ['@nuxt/ui'], + modules: ['@comark/nuxt', '@nuxt/ui'], ssr: false, components: { diff --git a/packages/devtools/package.json b/packages/devtools/package.json index e0b601e1..a4d522fb 100644 --- a/packages/devtools/package.json +++ b/packages/devtools/package.json @@ -9,6 +9,7 @@ "generate": "nuxt generate" }, "dependencies": { + "@comark/nuxt": "0.5.1", "@nuxt/ui": "catalog:", "@vueuse/core": "^14.3.0", "@vueuse/integrations": "^14.3.0", diff --git a/packages/nuxt/test/basic.nuxt.test.ts b/packages/nuxt/test/basic.nuxt.test.ts index 0939a488..1512ea71 100644 --- a/packages/nuxt/test/basic.nuxt.test.ts +++ b/packages/nuxt/test/basic.nuxt.test.ts @@ -81,7 +81,7 @@ describe('basic', async () => { expect(component).toEqual(expect.objectContaining({ props: [ { - description: '', + description: 'Configures the **primary** label.\n\n- Supports `inline code`\n- See [the guide](https://example.com/docs).', global: false, name: 'foo', required: true, diff --git a/packages/nuxt/test/fixtures/basic/app/types/props.ts b/packages/nuxt/test/fixtures/basic/app/types/props.ts index a56616b4..518c2ef0 100644 --- a/packages/nuxt/test/fixtures/basic/app/types/props.ts +++ b/packages/nuxt/test/fixtures/basic/app/types/props.ts @@ -1,3 +1,9 @@ export type BasicComponentProps = { + /** + * Configures the **primary** label. + * + * - Supports `inline code` + * - See [the guide](https://example.com/docs). + */ foo: string } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06ed15a5..5ad3ff3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,6 +177,9 @@ importers: packages/devtools: dependencies: + '@comark/nuxt': + specifier: 0.5.1 + version: 0.5.1(magicast@0.5.3)(nuxt@4.4.8(@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.29.0))(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@26.1.1)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.11.1)(cac@6.7.14)(db0@0.3.4(better-sqlite3@12.11.1))(esbuild@0.28.1)(eslint@10.7.0(jiti@2.7.0))(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1(rolldown@1.1.4)(rollup@4.61.1))(rollup@4.61.1)(srvx@0.11.15)(terser@5.47.1)(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.0))(vue-tsc@3.3.6(typescript@6.0.3))(yaml@2.9.0))(shiki@4.3.1)(vue@3.5.39(typescript@6.0.3)) '@nuxt/ui': specifier: 'catalog:' version: 4.9.0(e78c506334925a3ee357dadc00409e75) @@ -662,6 +665,26 @@ packages: '@colordx/core@5.4.3': resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==} + '@comark/nuxt@0.5.1': + resolution: {integrity: sha512-BvXUbzasGRqQ6bWGuRMO0E6KhWXXpv8FpursPHTixTwJxYVa7BFHUVqvq4cfjj5/6VgbXwofvHiawVQV2k33og==} + peerDependencies: + nuxt: ^4.0.0 + + '@comark/vue@0.5.1': + resolution: {integrity: sha512-uz5Oirzg7ruuJJItceWRswAftuMoY17Omge9bsUampmAL/XdI77YrBOozA5DlId+OCX0VXnt1tCCe4c1IrcJ7w==} + peerDependencies: + beautiful-mermaid: ^1.1.3 + katex: ^0.17.0 + shiki: ^4.3.1 + vue: ^3.5.0 + peerDependenciesMeta: + beautiful-mermaid: + optional: true + katex: + optional: true + shiki: + optional: true + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -3908,9 +3931,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/methods@1.1.4': resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} @@ -4738,6 +4767,20 @@ packages: colortranslator@5.0.0: resolution: {integrity: sha512-Z3UPUKasUVDFCDYAjP2fmlVRf1jFHJv1izAmPjiOa0OCIw1W7iC8PZ2GsoDa8uZv+mKyWopxxStT9q05+27h7w==} + comark@0.5.1: + resolution: {integrity: sha512-RRRmUaEc6tokYJhgIGHrl8+pUt3kY1BxMnbRrxMxkCk2RcPcrilq9OmmPWIO7zuUIF7qLLRCCQz+wPuMg7Vz9w==} + peerDependencies: + beautiful-mermaid: ^1.1.3 + katex: ^0.17.0 + shiki: ^4.3.1 + peerDependenciesMeta: + beautiful-mermaid: + optional: true + katex: + optional: true + shiki: + optional: true + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -5058,16 +5101,32 @@ packages: dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-serializer@3.1.1: + resolution: {integrity: sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==} + engines: {node: '>=20.19.0'} + domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + domelementtype@3.0.0: + resolution: {integrity: sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==} + engines: {node: '>=20.19.0'} + domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + domhandler@6.0.1: + resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==} + engines: {node: '>=20.19.0'} + domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + domutils@4.0.2: + resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==} + engines: {node: '>=20.19.0'} + dot-prop@10.1.0: resolution: {integrity: sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==} engines: {node: '>=20'} @@ -5798,6 +5857,10 @@ packages: html-whitespace-sensitive-tag-names@3.0.1: resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} + htmlparser2@12.0.0: + resolution: {integrity: sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==} + engines: {node: '>=20.19.0'} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -6038,6 +6101,10 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + js-yaml@5.2.1: + resolution: {integrity: sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==} + hasBin: true + jsdoc-type-pratt-parser@7.2.0: resolution: {integrity: sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==} engines: {node: '>=20.0.0'} @@ -6206,6 +6273,9 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + linkifyjs@4.3.3: resolution: {integrity: sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==} @@ -6275,6 +6345,9 @@ packages: magicast@0.5.3: resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} + markdown-exit@1.1.0-beta.2: + resolution: {integrity: sha512-8CzMGVlFZ4DEfnc8KU+4ycUW2SIOuiXqCHD7z51ecVEi/weyc0f2ylQbCm4KoKuVlTZSuMUMnWT0hTyquZ7anQ==} + markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} @@ -6332,6 +6405,9 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + memoize-one@6.0.0: resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} @@ -7365,6 +7441,10 @@ packages: pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -8074,6 +8154,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -9134,6 +9217,26 @@ snapshots: '@colordx/core@5.4.3': {} + '@comark/nuxt@0.5.1(magicast@0.5.3)(nuxt@4.4.8(@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.29.0))(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@26.1.1)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.11.1)(cac@6.7.14)(db0@0.3.4(better-sqlite3@12.11.1))(esbuild@0.28.1)(eslint@10.7.0(jiti@2.7.0))(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1(rolldown@1.1.4)(rollup@4.61.1))(rollup@4.61.1)(srvx@0.11.15)(terser@5.47.1)(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.0))(vue-tsc@3.3.6(typescript@6.0.3))(yaml@2.9.0))(shiki@4.3.1)(vue@3.5.39(typescript@6.0.3))': + dependencies: + '@comark/vue': 0.5.1(shiki@4.3.1)(vue@3.5.39(typescript@6.0.3)) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + comark: 0.5.1(shiki@4.3.1) + nuxt: 4.4.8(@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.29.0))(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@types/node@26.1.1)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.11.1)(cac@6.7.14)(db0@0.3.4(better-sqlite3@12.11.1))(esbuild@0.28.1)(eslint@10.7.0(jiti@2.7.0))(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rolldown@1.1.4)(rollup-plugin-visualizer@7.0.1(rolldown@1.1.4)(rollup@4.61.1))(rollup@4.61.1)(srvx@0.11.15)(terser@5.47.1)(typescript@6.0.3)(vite@8.0.16(@types/node@26.1.1)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.47.1)(yaml@2.9.0))(vue-tsc@3.3.6(typescript@6.0.3))(yaml@2.9.0) + transitivePeerDependencies: + - beautiful-mermaid + - katex + - magicast + - shiki + - vue + + '@comark/vue@0.5.1(shiki@4.3.1)(vue@3.5.39(typescript@6.0.3))': + dependencies: + comark: 0.5.1(shiki@4.3.1) + vue: 3.5.39(typescript@6.0.3) + optionalDependencies: + shiki: 4.3.1 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -12303,10 +12406,14 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/linkify-it@5.0.0': {} + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 + '@types/mdurl@2.0.0': {} + '@types/methods@1.1.4': {} '@types/ms@2.1.0': {} @@ -13237,6 +13344,15 @@ snapshots: colortranslator@5.0.0: {} + comark@0.5.1(shiki@4.3.1): + dependencies: + entities: 8.0.0 + htmlparser2: 12.0.0 + js-yaml: 5.2.1 + markdown-exit: 1.1.0-beta.2 + optionalDependencies: + shiki: 4.3.1 + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -13526,18 +13642,36 @@ snapshots: domhandler: 5.0.3 entities: 4.5.0 + dom-serializer@3.1.1: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + entities: 8.0.0 + domelementtype@2.3.0: {} + domelementtype@3.0.0: {} + domhandler@5.0.3: dependencies: domelementtype: 2.3.0 + domhandler@6.0.1: + dependencies: + domelementtype: 3.0.0 + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 + domutils@4.0.2: + dependencies: + dom-serializer: 3.1.1 + domelementtype: 3.0.0 + domhandler: 6.0.1 + dot-prop@10.1.0: dependencies: type-fest: 5.6.0 @@ -14486,6 +14620,13 @@ snapshots: html-whitespace-sensitive-tag-names@3.0.1: {} + htmlparser2@12.0.0: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + domutils: 4.0.2 + entities: 8.0.0 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -14756,6 +14897,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@5.2.1: + dependencies: + argparse: 2.0.1 + jsdoc-type-pratt-parser@7.2.0: {} jsep@1.4.0: {} @@ -14881,6 +15026,10 @@ snapshots: lilconfig@3.1.3: {} + linkify-it@5.0.2: + dependencies: + uc.micro: 2.1.0 + linkifyjs@4.3.3: {} listhen@1.10.0(srvx@0.11.15): @@ -15002,6 +15151,16 @@ snapshots: '@babel/types': 7.29.7 source-map-js: 1.2.1 + markdown-exit@1.1.0-beta.2: + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + entities: 7.0.1 + linkify-it: 5.0.2 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + markdown-table@3.0.4: {} marked@17.0.6: {} @@ -15128,6 +15287,8 @@ snapshots: mdn-data@2.27.1: {} + mdurl@2.0.0: {} + memoize-one@6.0.0: {} merge-stream@2.0.0: {} @@ -17026,6 +17187,8 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 + punycode.js@2.3.1: {} + punycode@2.3.1: {} qs@6.15.3: @@ -17987,6 +18150,8 @@ snapshots: typescript@6.0.3: {} + uc.micro@2.1.0: {} + ufo@1.6.4: {} ultrahtml@1.6.0: {}