From 0c990023517be9fa531f3c78bac1319d32360ca4 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 1 Mar 2022 03:21:03 +0800 Subject: [PATCH] fix: support sourcemap for `nuxt:pages-macros-transform` (#3429) --- packages/nuxt3/src/pages/macros.ts | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/nuxt3/src/pages/macros.ts b/packages/nuxt3/src/pages/macros.ts index 7b5b950c25..13334ba7c5 100644 --- a/packages/nuxt3/src/pages/macros.ts +++ b/packages/nuxt3/src/pages/macros.ts @@ -1,6 +1,7 @@ import { createUnplugin } from 'unplugin' import { parseQuery, parseURL, withQuery } from 'ufo' import { findStaticImports, findExports } from 'mlly' +import MagicString from 'magic-string-extra' export interface TransformMacroPluginOptions { macros: Record @@ -16,20 +17,20 @@ export const TransformMacroPlugin = createUnplugin((options: TransformMacroPlugi return pathname.endsWith('.vue') || !!parseQuery(search).macro }, transform (code, id) { - const originalCode = code + const s = new MagicString(code, { sourcemapOptions: { source: id, includeContent: true } }) const { search } = parseURL(id) // Tree-shake out any runtime references to the macro. // We do this first as it applies to all files, not just those with the query for (const macro in options.macros) { - const match = code.match(new RegExp(`\\b${macro}\\s*\\(\\s*`))?.[0] - if (match) { - code = code.replace(match, `/*#__PURE__*/ false && ${match}`) + const match = code.match(new RegExp(`\\b${macro}\\s*\\(\\s*`)) + if (match?.[0]) { + s.overwrite(match.index, match.index + match[0].length, `/*#__PURE__*/ false && ${match[0]}`) } } if (!parseQuery(search).macro) { - return originalCode === code ? undefined : code + return s.toRollupResult() } // [webpack] Re-export any imports from script blocks in the components @@ -37,33 +38,39 @@ export const TransformMacroPlugin = createUnplugin((options: TransformMacroPlugi const scriptImport = findStaticImports(code).find(i => parseQuery(i.specifier.replace('?macro=true', '')).type === 'script') if (scriptImport) { const specifier = withQuery(scriptImport.specifier.replace('?macro=true', ''), { macro: 'true' }) - return `export { meta } from "${specifier}"` + s.overwrite(0, code.length, `export { meta } from "${specifier}"`) + return s.toRollupResult() } const currentExports = findExports(code) for (const match of currentExports) { - if (match.type !== 'default') { continue } + if (match.type !== 'default') { + continue + } if (match.specifier && match._type === 'named') { // [webpack] Export named exports rather than the default (component) - return code.replace(match.code, `export {${Object.values(options.macros).join(', ')}} from "${match.specifier}"`) + s.overwrite(match.start, match.end, `export {${Object.values(options.macros).join(', ')}} from "${match.specifier}"`) + return s.toRollupResult() } else if (!options.dev) { // ensure we tree-shake any _other_ default exports out of the macro script - code = code.replace(match.code, '/*#__PURE__*/ false &&') - code += '\nexport default {}' + s.overwrite(match.start, match.end, '/*#__PURE__*/ false &&') + s.append('\nexport default {}') } } for (const macro in options.macros) { // Skip already-processed macros - if (currentExports.some(e => e.name === options.macros[macro])) { continue } + if (currentExports.some(e => e.name === options.macros[macro])) { + continue + } const { 0: match, index = 0 } = code.match(new RegExp(`\\b${macro}\\s*\\(\\s*`)) || {} as RegExpMatchArray const macroContent = match ? extractObject(code.slice(index + match.length)) : 'undefined' - code += `\nexport const ${options.macros[macro]} = ${macroContent}` + s.append(`\nexport const ${options.macros[macro]} = ${macroContent}`) } - return code + return s.toRollupResult() } } })