'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var node_fs = require('node:fs'); var node_path = require('node:path'); var node_module = require('node:module'); var vite = require('vite'); var importTransformation = require('quasar/dist/transforms/import-transformation.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var importTransformation__default = /*#__PURE__*/_interopDefaultLegacy(importTransformation); const require$1 = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.cjs', document.baseURI).href))); const quasarPath = node_path.dirname(require$1.resolve('quasar/package.json')); const { version } = JSON.parse( node_fs.readFileSync(node_path.join(quasarPath, 'package.json'), 'utf-8') ); function getViteConfig (runMode, viteMode, externalViteCfg) { const viteCfg = { define: { __QUASAR_VERSION__: `'${ version }'`, __QUASAR_SSR__: false, __QUASAR_SSR_SERVER__: false, __QUASAR_SSR_CLIENT__: false } }; // Set this to the default value only if it's not already set. // @quasar/app-vite configures this by itself when it needs it. if (!externalViteCfg.define || externalViteCfg.define.__QUASAR_SSR_PWA__ === void 0) { viteCfg.define.__QUASAR_SSR_PWA__ = false; } if (runMode === 'ssr-server') { Object.assign(viteCfg.define, { __QUASAR_SSR__: true, __QUASAR_SSR_SERVER__: true }); } else { // Alias "quasar" package to its dev file (which has flags) // to reduce the number of HTTP requests while in DEV mode if (viteMode !== 'production') { viteCfg.resolve = { alias: [ { find: /^quasar$/, replacement: 'quasar/dist/quasar.esm.js' } ] }; } else { viteCfg.optimizeDeps = { exclude: [ 'quasar' ] }; } if (runMode === 'ssr-client') { Object.assign(viteCfg.define, { __QUASAR_SSR__: true, __QUASAR_SSR_CLIENT__: true }); } } return viteCfg } const importQuasarRegex = /import\s*\{([\w,\s]+)\}\s*from\s*(['"])quasar\2;?/g; /** * Transforms JS code where importing from 'quasar' package * Example: * import { QBtn } from 'quasar' * -> import QBtn from 'quasar/src/components/QBtn.js' */ function mapQuasarImports (code, importMap = {}) { return code.replace( importQuasarRegex, (_, match) => match .split(',') .map(identifier => { const data = identifier.split(' as '); const importName = data[ 0 ].trim(); // might be an empty entry like below // (notice useQuasar is followed by a comma) // import { QTable, useQuasar, } from 'quasar' if (importName === '') { return '' } const importAs = data[ 1 ] !== void 0 ? data[ 1 ].trim() : importName; importMap[ importName ] = importAs; return `import ${ importAs } from '${ importTransformation__default["default"](importName) }';` }) .join('') ) } /** * Transforms JS code where importing from 'quasar' package * Example: * import { QBtn } from 'quasar' * -> add to importMap & importList & remove original import statement * (removing original is required so that the end file will have * only one import from Quasar statement) */ function removeQuasarImports (code, importMap, importSet, reverseMap) { return code.replace( importQuasarRegex, (_, match) => { match.split(',').forEach(identifier => { const data = identifier.split(' as '); const importName = data[ 0 ].trim(); // might be an empty entry like below // (notice useQuasar is followed by a comma) // import { QTable, useQuasar, } from 'quasar' if (importName !== '') { const importAs = data[ 1 ] !== void 0 ? data[ 1 ].trim() : importName; importSet.add(importName + (importAs !== importName ? ` as ${ importAs }` : '')); importMap[ importName ] = importAs; reverseMap[ importName.replace(/-/g, '_') ] = importAs; } }); // we registered the original import and we // remove this one to avoid duplicate imports from Quasar return '' } ) } const autoImportData = JSON.parse( node_fs.readFileSync(node_path.join(quasarPath, 'dist/transforms/auto-import.json'), 'utf-8') ); const compRegex = { kebab: new RegExp(`_resolveComponent\\("${ autoImportData.regex.kebabComponents }"\\)`, 'g'), pascal: new RegExp(`_resolveComponent\\("${ autoImportData.regex.pascalComponents }"\\)`, 'g'), combined: new RegExp(`_resolveComponent\\("${ autoImportData.regex.components }"\\)`, 'g') }; const dirRegex = new RegExp(`_resolveDirective\\("${ autoImportData.regex.directives.replace(/v-/g, '') }"\\)`, 'g'); const lengthSortFn = (a, b) => b.length - a.length; function vueTransform (content, autoImportComponentCase, useTreeshaking) { const importSet = new Set(); const importMap = {}; const compList = []; const dirList = []; const reverseMap = {}; const jsImportTransformed = useTreeshaking === true ? mapQuasarImports(content, importMap) : removeQuasarImports(content, importMap, importSet, reverseMap); let code = jsImportTransformed .replace(compRegex[ autoImportComponentCase ], (_, match) => { const name = autoImportData.importName[ match ]; const reverseName = match.replace(/-/g, '_'); if (importMap[ name ] === void 0) { importSet.add(name); reverseMap[ reverseName ] = name; } else { reverseMap[ reverseName ] = importMap[ name ]; } compList.push(reverseName); return '' }) .replace(dirRegex, (_, match) => { const name = autoImportData.importName[ 'v-' + match ]; const reverseName = match.replace(/-/g, '_'); if (importMap[ name ] === void 0) { importSet.add(name); reverseMap[ reverseName ] = name; } else { reverseMap[ reverseName ] = importMap[ name ]; } dirList.push(reverseName); return '' }); if (compList.length !== 0) { const list = compList.sort(lengthSortFn).join('|'); code = code .replace(new RegExp(`const _component_(${ list }) = `, 'g'), '') .replace(new RegExp(`_component_(${ list })`, 'g'), (_, match) => reverseMap[ match ]); } if (dirList.length !== 0) { const list = dirList.sort(lengthSortFn).join('|'); code = code .replace(new RegExp(`const _directive_(${ list }) = `, 'g'), '') .replace(new RegExp(`_directive_(${ list })`, 'g'), (_, match) => reverseMap[ match ]); } if (importSet.size === 0) { return code } const importList = [ ...importSet ]; const codePrefix = useTreeshaking === true ? importList.map(name => `import ${ name } from '${ importTransformation__default["default"](name) }'`).join(';') : `import {${ importList.join(',') }} from 'quasar'`; return codePrefix + ';' + code } function createScssTransform (fileExtension, sassVariables) { const sassImportCode = [ '@import \'quasar/src/css/variables.sass\'', '' ]; if (typeof sassVariables === 'string') { sassImportCode.unshift(`@import '${ sassVariables }'`); } const prefix = fileExtension === 'sass' ? sassImportCode.join('\n') : sassImportCode.join(';\n'); return content => { const useIndex = Math.max( content.lastIndexOf('@use '), content.lastIndexOf('@forward ') ); if (useIndex === -1) { return prefix + content } const newLineIndex = content.indexOf('\n', useIndex); if (newLineIndex !== -1) { const index = newLineIndex + 1; return content.substring(0, index) + prefix + content.substring(index) } return content + '\n' + prefix } } /** * @typedef {{ * vue: () => boolean; * template: () => boolean; * script: (extensions?: string | string[]) => boolean; * style: (extensions?: string | string[]) => boolean; * }} ViteQueryIs */ /** * @see https://github.com/vitejs/vite/blob/364aae13f0826169e8b1c5db41ac6b5bb2756958/packages/plugin-vue/src/utils/query.ts - source of inspiration * @example * '/absolute/path/src/App.vue' // Can contain combined template&script -> template: true, script: true, style: false * '/absolute/path/src/App.vue?vue&type=script&lang.js' // Only contains script -> template: false, script: true, style: false * '/absolute/path/src/App.vue?vue&type=style&lang.sass' // Only contains style -> template: false, script: false, style: true * '/absolute/path/src/script.js' // Only contains script -> template: false, script: true, style: false * '/absolute/path/src/index.scss' // Only contains style -> template: false, script: false, style: true * * @param {string} id * @returns {{ filename: string; query: { [key: string]: string; }; is: ViteQueryIs }} */ function parseViteRequest (id) { const [ filename, rawQuery ] = id.split('?', 2); const query = Object.fromEntries(new URLSearchParams(rawQuery)); const is = query.raw !== void 0 ? { // if it's a ?raw request, then don't touch it at all vue: () => false, template: () => false, script: () => false, style: () => false } : ( query.vue !== void 0 // is vue query? ? { // Almost all code might get merged into a single request with no 'type' (App.vue?vue) // or stay with their original 'type's (App.vue?vue&type=script&lang.ts) vue: () => true, template: () => ( query.type === void 0 || query.type === 'template' // On prod, TS code turns into a separate 'script' request. // See: https://github.com/vitejs/vite/pull/7909 || (query.type === 'script' && (query[ 'lang.ts' ] !== void 0 || query[ 'lang.tsx' ] !== void 0)) ), script: (extensions = scriptExt) => ( (query.type === void 0 || query.type === 'script') && isOfExt({ query, extensions }) === true ), style: (extensions = styleExt) => ( query.type === 'style' && isOfExt({ query, extensions }) === true ) } : { vue: () => isOfExt({ extensions: vueExt, filename }), template: () => isOfExt({ filename, extensions: vueExt }), script: (extensions = scriptExt) => isOfExt({ filename, extensions }), style: (extensions = styleExt) => isOfExt({ filename, extensions }) } ); return { filename, query, is } } const vueExt = [ '.vue' ]; const scriptExt = [ '.js', '.jsx', '.ts', '.tsx', '.vue' ]; const styleExt = [ '.css', '.scss', '.module.scss', '.sass', '.module.sass' ]; const isOfExt = ({ extensions, filename, query }) => extensions.some( ext => filename?.endsWith(ext) || query?.[ `lang${ ext }` ] !== void 0 ); const defaultOptions = { runMode: 'web-client', autoImportComponentCase: 'kebab', sassVariables: true, devTreeshaking: false }; function getConfigPlugin (opts) { return { name: 'vite:quasar:vite-conf', configResolved (viteConf) { const vueCfg = viteConf.plugins.find(entry => entry.name === 'vite:vue'); if (vueCfg === void 0) { console.error('\n\n[Quasar] Error: In your Vite config file, please add the Quasar plugin ** after ** the Vue one\n\n'); process.exit(1); } }, config (viteConf, { mode }) { return getViteConfig(opts.runMode, mode, viteConf) } } } function getScssTransformsPlugin (opts) { const sassVariables = typeof opts.sassVariables === 'string' ? vite.normalizePath(opts.sassVariables) : opts.sassVariables; const scssTransform = createScssTransform('scss', sassVariables); const sassTransform = createScssTransform('sass', sassVariables); const scssExt = [ '.scss', '.module.scss' ]; const sassExt = [ '.sass', '.module.sass' ]; return { name: 'vite:quasar:scss', enforce: 'pre', transform (src, id) { const { is } = parseViteRequest(id); if (is.style(scssExt) === true) { return { code: scssTransform(src), map: null } } if (is.style(sassExt) === true) { return { code: sassTransform(src), map: null } } return null } } } function getScriptTransformsPlugin (opts) { let useTreeshaking = true; return { name: 'vite:quasar:script', configResolved (resolvedConfig) { if (opts.devTreeshaking === false && resolvedConfig.mode !== 'production') { useTreeshaking = false; } }, transform (src, id) { const { is } = parseViteRequest(id); if (is.template() === true) { return { code: vueTransform(src, opts.autoImportComponentCase, useTreeshaking), map: null // provide source map if available } } if (useTreeshaking === true && is.script() === true) { return { code: mapQuasarImports(src), map: null // provide source map if available } } return null } } } function plugin (userOpts = {}) { const opts = { ...defaultOptions, ...userOpts }; const plugins = [ getConfigPlugin(opts) ]; if (opts.sassVariables) { plugins.push( getScssTransformsPlugin(opts) ); } if (opts.runMode !== 'ssr-server') { plugins.push( getScriptTransformsPlugin(opts) ); } return plugins } const transformAssetUrls = JSON.parse( node_fs.readFileSync(node_path.join(quasarPath, 'dist/transforms/loader-asset-urls.json'), 'utf-8') ); exports.quasar = plugin; exports.transformAssetUrls = transformAssetUrls;