diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 1e1661289bb3..5e3eeb346694 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -90,6 +90,7 @@ "scule": "^1.0.0", "strip-literal": "^1.0.1", "ufo": "^1.1.2", + "ultrahtml": "^1.2.0", "unctx": "^2.3.0", "unenv": "^1.4.1", "unimport": "^3.0.6", diff --git a/packages/nuxt/src/core/plugins/dev-only.ts b/packages/nuxt/src/core/plugins/dev-only.ts index 92e94c085b2f..b14b4f6a7405 100644 --- a/packages/nuxt/src/core/plugins/dev-only.ts +++ b/packages/nuxt/src/core/plugins/dev-only.ts @@ -3,6 +3,7 @@ import { stripLiteral } from 'strip-literal' import { parseQuery, parseURL } from 'ufo' import MagicString from 'magic-string' import { createUnplugin } from 'unplugin' +import { type Node, parse } from 'ultrahtml' interface DevOnlyPluginOptions { sourcemap?: boolean @@ -10,7 +11,6 @@ interface DevOnlyPluginOptions { export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => { const DEVONLY_COMP_RE = /<(?:dev-only|DevOnly)>[\s\S]*?<\/(?:dev-only|DevOnly)>/g - const FALLBACK_SLOT_RE = /(?[\s\S]*?)<\/template>/ return { name: 'nuxt:server-devonly:transform', @@ -30,7 +30,10 @@ export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => { const s = new MagicString(code) const strippedCode = stripLiteral(code) for (const match of strippedCode.matchAll(DEVONLY_COMP_RE) || []) { - const replacement = match[0].match(FALLBACK_SLOT_RE)?.groups?.fallback || '' + const ast: Node = parse(match[0]).children[0] + const fallback: Node | undefined = ast.children?.find((n: Node) => n.name === 'template' && Object.values(n.attributes).includes('#fallback')) + const replacement = fallback ? match[0].slice(fallback.loc[0].end, fallback.loc[fallback.loc.length - 1].start) : '' + s.overwrite(match.index!, match.index! + match[0].length, replacement) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7638afa62ef..f7a1b9dd3ca1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -435,6 +435,9 @@ importers: ufo: specifier: ^1.1.2 version: 1.1.2 + ultrahtml: + specifier: ^1.2.0 + version: 1.2.0 unctx: specifier: ^2.3.0 version: 2.3.0 @@ -902,10 +905,10 @@ importers: version: 1.3.1 vitest: specifier: latest - version: 0.31.0(playwright@1.33.0) + version: 0.30.1(playwright@1.33.0) vue-router: specifier: latest - version: 4.2.0(vue@3.3.2) + version: 4.1.6(vue@3.3.2) test/fixtures/minimal: dependencies: @@ -2466,6 +2469,14 @@ packages: vite: 4.3.5(@types/node@18.16.8) vue: 3.3.2 + /@vitest/expect@0.30.1: + resolution: {integrity: sha512-c3kbEtN8XXJSeN81iDGq29bUzSjQhjES2WR3aColsS4lPGbivwLtas4DNUe0jD9gg/FYGIteqOenfU95EFituw==} + dependencies: + '@vitest/spy': 0.30.1 + '@vitest/utils': 0.30.1 + chai: 4.3.7 + dev: true + /@vitest/expect@0.31.0: resolution: {integrity: sha512-Jlm8ZTyp6vMY9iz9Ny9a0BHnCG4fqBa8neCF6Pk/c/6vkUk49Ls6UBlgGAU82QnzzoaUs9E/mUhq/eq9uMOv/g==} dependencies: @@ -2474,6 +2485,15 @@ packages: chai: 4.3.7 dev: true + /@vitest/runner@0.30.1: + resolution: {integrity: sha512-W62kT/8i0TF1UBCNMRtRMOBWJKRnNyv9RrjIgdUryEe0wNpGZvvwPDLuzYdxvgSckzjp54DSpv1xUbv4BQ0qVA==} + dependencies: + '@vitest/utils': 0.30.1 + concordance: 5.0.4 + p-limit: 4.0.0 + pathe: 1.1.0 + dev: true + /@vitest/runner@0.31.0: resolution: {integrity: sha512-H1OE+Ly7JFeBwnpHTrKyCNm/oZgr+16N4qIlzzqSG/YRQDATBYmJb/KUn3GrZaiQQyL7GwpNHVZxSQd6juLCgw==} dependencies: @@ -2483,6 +2503,14 @@ packages: pathe: 1.1.0 dev: true + /@vitest/snapshot@0.30.1: + resolution: {integrity: sha512-fJZqKrE99zo27uoZA/azgWyWbFvM1rw2APS05yB0JaLwUIg9aUtvvnBf4q7JWhEcAHmSwbrxKFgyBUga6tq9Tw==} + dependencies: + magic-string: 0.30.0 + pathe: 1.1.0 + pretty-format: 27.5.1 + dev: true + /@vitest/snapshot@0.31.0: resolution: {integrity: sha512-5dTXhbHnyUMTMOujZPB0wjFjQ6q5x9c8TvAsSPUNKjp1tVU7i9pbqcKPqntyu2oXtmVxKbuHCqrOd+Ft60r4tg==} dependencies: @@ -2491,12 +2519,26 @@ packages: pretty-format: 27.5.1 dev: true + /@vitest/spy@0.30.1: + resolution: {integrity: sha512-YfJeIf37GvTZe04ZKxzJfnNNuNSmTEGnla2OdL60C8od16f3zOfv9q9K0nNii0NfjDJRt/CVN/POuY5/zTS+BA==} + dependencies: + tinyspy: 2.1.0 + dev: true + /@vitest/spy@0.31.0: resolution: {integrity: sha512-IzCEQ85RN26GqjQNkYahgVLLkULOxOm5H/t364LG0JYb3Apg0PsYCHLBYGA006+SVRMWhQvHlBBCyuByAMFmkg==} dependencies: tinyspy: 2.1.0 dev: true + /@vitest/utils@0.30.1: + resolution: {integrity: sha512-/c8Xv2zUVc+rnNt84QF0Y0zkfxnaGhp87K2dYJMLtLOIckPzuxLVzAtFCicGFdB4NeBHNzTRr1tNn7rCtQcWFA==} + dependencies: + concordance: 5.0.4 + loupe: 2.3.6 + pretty-format: 27.5.1 + dev: true + /@vitest/utils@0.31.0: resolution: {integrity: sha512-kahaRyLX7GS1urekRXN2752X4gIgOGVX4Wo8eDUGUkTWlGpXzf5ZS6N9RUUS+Re3XEE8nVGqNyxkSxF5HXlGhQ==} dependencies: @@ -8115,6 +8157,11 @@ packages: resolution: {integrity: sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==} dev: true + /tinypool@0.4.0: + resolution: {integrity: sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA==} + engines: {node: '>=14.0.0'} + dev: true + /tinypool@0.5.0: resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==} engines: {node: '>=14.0.0'} @@ -8277,6 +8324,10 @@ packages: /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} + /ultrahtml@1.2.0: + resolution: {integrity: sha512-vxZM2yNvajRmCj/SknRYGNXk2tqiy6kRNvZjJLaleG3zJbSh/aNkOqD1/CVzypw8tyHyhpzYuwQgMMhUB4ZVNQ==} + dev: false + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -8537,6 +8588,27 @@ packages: extsprintf: 1.3.0 dev: true + /vite-node@0.30.1(@types/node@18.16.8): + resolution: {integrity: sha512-vTikpU/J7e6LU/8iM3dzBo8ZhEiKZEKRznEMm+mJh95XhWaPrJQraT/QsT2NWmuEf+zgAoMe64PKT7hfZ1Njmg==} + engines: {node: '>=v14.18.0'} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + mlly: 1.2.1 + pathe: 1.1.0 + picocolors: 1.0.0 + vite: 4.3.5(@types/node@18.16.8) + transitivePeerDependencies: + - '@types/node' + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-node@0.31.0(@types/node@18.16.8): resolution: {integrity: sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==} engines: {node: '>=v14.18.0'} @@ -8643,6 +8715,73 @@ packages: optionalDependencies: fsevents: 2.3.2 + /vitest@0.30.1(playwright@1.33.0): + resolution: {integrity: sha512-y35WTrSTlTxfMLttgQk4rHcaDkbHQwDP++SNwPb+7H8yb13Q3cu2EixrtHzF27iZ8v0XCciSsLg00RkPAzB/aA==} + engines: {node: '>=v14.18.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@types/chai': 4.3.4 + '@types/chai-subset': 1.3.3 + '@types/node': 18.16.8 + '@vitest/expect': 0.30.1 + '@vitest/runner': 0.30.1 + '@vitest/snapshot': 0.30.1 + '@vitest/spy': 0.30.1 + '@vitest/utils': 0.30.1 + acorn: 8.8.2 + acorn-walk: 8.2.0 + cac: 6.7.14 + chai: 4.3.7 + concordance: 5.0.4 + debug: 4.3.4 + local-pkg: 0.4.3 + magic-string: 0.30.0 + pathe: 1.1.0 + picocolors: 1.0.0 + playwright: 1.33.0 + source-map: 0.6.1 + std-env: 3.3.3 + strip-literal: 1.0.1 + tinybench: 2.4.0 + tinypool: 0.4.0 + vite: 4.3.5(@types/node@18.16.8) + vite-node: 0.30.1(@types/node@18.16.8) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vitest@0.31.0(playwright@1.33.0): resolution: {integrity: sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==} engines: {node: '>=v14.18.0'} @@ -8795,6 +8934,15 @@ packages: webpack: 5.82.1 dev: false + /vue-router@4.1.6(vue@3.3.2): + resolution: {integrity: sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.5.0 + vue: 3.3.2 + dev: true + /vue-router@4.2.0(vue@3.3.2): resolution: {integrity: sha512-c+usESa6ZoWsm4PPdzRSyenp5A4dsUtnDJnrI03fY1IpIihA9TK3x5ffgkFDpjhLJZewsXoKURapNLFdZjuqTg==} peerDependencies: