diff --git a/packages/playground/vue/PreProcessors.vue b/packages/playground/vue/PreProcessors.vue index ddb636678e8cdd..79df8ba3e5f33e 100644 --- a/packages/playground/vue/PreProcessors.vue +++ b/packages/playground/vue/PreProcessors.vue @@ -9,6 +9,12 @@ p.pug-less p.pug-stylus | This is rendered from <template lang="pug"> | and styled with <style lang="stylus">. It should be orange. +p.pug-sass-import + | This is rendered from <template lang="pug"> + | and styled with <style lang="sass"> which has import. It should be blue. +p.pug-sass-non-import + | This is rendered from <template lang="pug"> + | and styled with <style lang="sass"> which has import. It should be yellow. SlotComponent template(v-slot:test-slot) div.pug-slot slot content @@ -42,3 +48,10 @@ color = orange .pug-stylus color: color + + diff --git a/packages/playground/vue/import.sass b/packages/playground/vue/import.sass new file mode 100644 index 00000000000000..e35f9085000fe1 --- /dev/null +++ b/packages/playground/vue/import.sass @@ -0,0 +1,2 @@ +.pug-sass-import + color: blue diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts index fb1bce3cd61132..28a15996363285 100644 --- a/packages/plugin-vue/src/index.ts +++ b/packages/plugin-vue/src/index.ts @@ -235,7 +235,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { descriptor, Number(query.index), options, - this + this, + filename ) } } diff --git a/packages/plugin-vue/src/style.ts b/packages/plugin-vue/src/style.ts index ad9d981412f52d..5dba59e627922f 100644 --- a/packages/plugin-vue/src/style.ts +++ b/packages/plugin-vue/src/style.ts @@ -1,6 +1,7 @@ import type { SFCDescriptor } from 'vue/compiler-sfc' import type { TransformPluginContext } from 'rollup' import type { ResolvedOptions } from '.' +import { formatPostcssSourceMap } from 'vite' // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function transformStyle( @@ -8,7 +9,8 @@ export async function transformStyle( descriptor: SFCDescriptor, index: number, options: ResolvedOptions, - pluginContext: TransformPluginContext + pluginContext: TransformPluginContext, + filename: string ) { const block = descriptor.styles[index] // vite already handles pre-processors and CSS module so this is only @@ -19,7 +21,14 @@ export async function transformStyle( id: `data-v-${descriptor.id}`, isProd: options.isProduction, source: code, - scoped: block.scoped + scoped: block.scoped, + postcssOptions: { + map: { + from: filename, + inline: false, + annotation: false + } + } }) if (result.errors.length) { @@ -36,8 +45,12 @@ export async function transformStyle( return null } + const map = result.map + ? formatPostcssSourceMap(result.map, filename) + : ({ mappings: '' } as any) + return { code: result.code, - map: result.map || ({ mappings: '' } as any) + map: map } } diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index aea96d14d758be..3286e9dffcbf04 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -5,6 +5,7 @@ export { build } from './build' export { optimizeDeps } from './optimizer' export { send } from './server/send' export { createLogger, printHttpServerUrls } from './logger' +export { formatPostcssSourceMap } from './plugins/css' export { transformWithEsbuild } from './plugins/esbuild' export { resolvePackageEntry } from './plugins/resolve' export { resolvePackageData } from './packages' diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 4a46477de03f44..96e8ac87129d89 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -761,8 +761,8 @@ async function compileCSS( .default(postcssPlugins) .process(code, { ...postcssOptions, - to: id, - from: id, + to: cleanUrl(id), + from: cleanUrl(id), map: { inline: false, annotation: false, @@ -812,9 +812,12 @@ async function compileCSS( } } - const postcssMap = formatPostcssSourceMap(postcssResult.map.toJSON(), id) + const postcssMap = formatPostcssSourceMap( + postcssResult.map.toJSON(), + cleanUrl(id) + ) const combinedMap = preprocessorMap - ? combineSourcemaps(id, [ + ? combineSourcemaps(cleanUrl(id), [ { ...postcssMap, version: 3 }, { ...preprocessorMap, version: 3 } ]) @@ -829,7 +832,7 @@ async function compileCSS( } } -function formatPostcssSourceMap( +export function formatPostcssSourceMap( rawMap: RawSourceMap, file: string ): ExistingRawSourceMap { diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index b5eca4b58dbf75..9828a0d5602ef8 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -50,7 +50,7 @@ import type { } from 'rollup' import * as acorn from 'acorn' import type { RawSourceMap } from '@ampproject/remapping/dist/types/types' -import { combineSourcemaps } from '../utils' +import { cleanUrl, combineSourcemaps } from '../utils' import MagicString from 'magic-string' import type { FSWatcher } from 'chokidar' import { @@ -420,7 +420,7 @@ export async function createPluginContainer( if (!combinedMap) { combinedMap = m as SourceMap } else { - combinedMap = combineSourcemaps(this.filename, [ + combinedMap = combineSourcemaps(cleanUrl(this.filename), [ { ...(m as RawSourceMap), sourcesContent: combinedMap.sourcesContent diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 37d5c447d38868..c9fa06a4b408df 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -551,6 +551,20 @@ export function combineSourcemaps( }) filename = filename.replace(/@/g, '____atmark____') + // FIXME: hack for @ parse broken with normalized absolute paths with windows (C:/path/to/something) + const base = normalizePath(path.dirname(filename)) + sourcemapList.forEach((sourcemap) => { + sourcemap.sources = sourcemap.sources.map((source) => { + if (!source) return null + if (sourcemap.sourceRoot) { + source = path.resolve(sourcemap.sourceRoot, source) + } + return normalizePath(path.relative(base, source)) + }) + sourcemap.sourceRoot = undefined + }) + const baseFilename = path.basename(filename) + // We don't declare type here so we can convert/fake/map as RawSourceMap let map //: SourceMap let mapIndex = 1 @@ -562,10 +576,10 @@ export function combineSourcemaps( map = remapping( sourcemapList[0], function loader(sourcefile) { - if (sourcefile === filename && sourcemapList[mapIndex]) { + if (sourcefile === baseFilename && sourcemapList[mapIndex]) { return sourcemapList[mapIndex++] } else { - return { ...nullSourceMap } + return null } }, true @@ -580,6 +594,11 @@ export function combineSourcemaps( (source) => source?.replace(/____atmark____/g, '@') ?? null ) + map.sources = map.sources.map((source) => + source ? normalizePath(path.resolve(base, source)) : null + ) + map.file = filename + return map as RawSourceMap }