Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export interface Options {
autoImport?: ImportPluginOptions,
styles?: true | 'none' | 'sass' | {
configFile: string,
/**
* Enable this flag when using Vite >= 5.4.3.
*
* @see https://github.com/vitejs/vite/pull/17909
* @default false
*/
useViteFileImport?: boolean,
},
}

Expand Down
77 changes: 32 additions & 45 deletions packages/vite-plugin/src/stylesPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
import path from 'upath'
import { resolveVuetifyBase, normalizePath, isObject } from '@vuetify/loader-shared'

import type { Plugin } from 'vite'
import type { Options } from '@vuetify/loader-shared'

function isSubdir (root: string, test: string) {
const relative = path.relative(root, test)
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
}

const PLUGIN_VIRTUAL_PREFIX = "virtual:"
const PLUGIN_VIRTUAL_NAME = "plugin-vuetify"
const VIRTUAL_MODULE_ID = `${PLUGIN_VIRTUAL_PREFIX}${PLUGIN_VIRTUAL_NAME}`
import { pathToFileURL } from 'node:url'

export function stylesPlugin (options: Options): Plugin {
const vuetifyBase = resolveVuetifyBase()

let configFile: string
let configFile: string | undefined
const tempFiles = new Map<string, string>()
const isNone = options.styles === 'none'
const sassVariables = isNone ? false : isObject(options.styles)
let useFileImport = false

return {
name: 'vuetify:styles',
enforce: 'pre',
configResolved (config) {
if (isObject(options.styles)) {
useFileImport = options.styles.useViteFileImport === true
if (path.isAbsolute(options.styles.configFile)) {
configFile = options.styles.configFile
configFile = path.resolve(options.styles.configFile)
} else {
configFile = path.join(config.root || process.cwd(), options.styles.configFile)
configFile = path.resolve(path.join(config.root || process.cwd(), options.styles.configFile))
}
configFile = useFileImport
? pathToFileURL(configFile).href
: normalizePath(configFile)
}
},
async resolveId (source, importer, { custom }) {
Expand All @@ -39,48 +37,37 @@ export function stylesPlugin (options: Options): Plugin {
isSubdir(vuetifyBase, path.isAbsolute(source) ? source : importer)
)
) {
if (options.styles === 'none') {
return `${PLUGIN_VIRTUAL_PREFIX}__void__`
} else if (options.styles === 'sass') {
if (options.styles === 'sass') {
const target = source.replace(/\.css$/, '.sass')
return this.resolve(target, importer, { skipSelf: true, custom })
} else if (isObject(options.styles)) {
const resolution = await this.resolve(source, importer, { skipSelf: true, custom })
}

if (!resolution) return null
const resolution = await this.resolve(source, importer, { skipSelf: true, custom })

const target = resolution.id.replace(/\.css$/, '.sass')
const file = path.relative(path.join(vuetifyBase, 'lib'), target)
const contents = `@use "${normalizePath(configFile)}"\n@use "${normalizePath(target)}"`
if (!resolution) {
return undefined
}

tempFiles.set(file, contents)
const target = resolution.id.replace(/\.css$/, '.sass')
tempFiles.set(target, isNone
? '' :
useFileImport
? `@use "${configFile}"\n@use "${pathToFileURL(target).href}"`
: `@use "${configFile}"\n@use "${normalizePath(target)}"`
)

return `${VIRTUAL_MODULE_ID}:${file}`
}
} else if (source.startsWith(`/${PLUGIN_VIRTUAL_NAME}:`)) {
return PLUGIN_VIRTUAL_PREFIX + source.slice(1)
} else if (source.startsWith(`/@id/__x00__${PLUGIN_VIRTUAL_NAME}:`)) {
return PLUGIN_VIRTUAL_PREFIX + source.slice(12)
} else if (source.startsWith(`/${VIRTUAL_MODULE_ID}:`)) {
return source.slice(1)
return target
}

return null
return undefined
},
load (id) {
// When Vite is configured with `optimizeDeps.exclude: ['vuetify']`, the
// received id contains a version hash (e.g. \0__void__?v=893fa859).
if (new RegExp(`^${PLUGIN_VIRTUAL_PREFIX}__void__(\\?.*)?$`).test(id)) {
return ''
}

if (id.startsWith(`${VIRTUAL_MODULE_ID}`)) {
const file = new RegExp(`^${VIRTUAL_MODULE_ID}:(.*?)(\\?.*)?$`).exec(id)![1]

return tempFiles.get(file)
}

return null
return isNone || sassVariables ? tempFiles.get(id) : undefined
},
}
}

function isSubdir (root: string, test: string) {
const relative = path.relative(root, test)
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
}