| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- try {
- require.resolve('@vue/compiler-sfc');
- }
- catch (e) {
- throw new Error('rollup-plugin-vue requires @vue/compiler-sfc to be present in the dependency ' +
- 'tree.');
- }
- const compiler_sfc_1 = require("@vue/compiler-sfc");
- const fs_1 = __importDefault(require("fs"));
- const debug_1 = __importDefault(require("debug"));
- const hash_sum_1 = __importDefault(require("hash-sum"));
- const path_1 = require("path");
- const querystring_1 = __importDefault(require("querystring"));
- const rollup_pluginutils_1 = require("rollup-pluginutils");
- const debug = debug_1.default('rollup-plugin-vue');
- const defaultOptions = {
- include: /\.vue$/,
- exclude: [],
- target: 'browser',
- exposeFilename: false,
- customBlocks: [],
- };
- function PluginVue(userOptions = {}) {
- const options = {
- ...defaultOptions,
- ...userOptions,
- };
- const isServer = options.target === 'node';
- const isProduction = process.env.NODE_ENV === 'production' || process.env.BUILD === 'production';
- const rootContext = process.cwd();
- const filter = rollup_pluginutils_1.createFilter(options.include, options.exclude);
- const filterCustomBlock = createCustomBlockFilter(options.customBlocks);
- return {
- name: 'vue',
- async resolveId(id, importer) {
- const query = parseVuePartRequest(id);
- if (query.vue) {
- if (query.src) {
- const resolved = await this.resolve(query.filename, importer, {
- skipSelf: true,
- });
- if (resolved) {
- cache.set(resolved.id, getDescriptor(importer));
- const [, originalQuery] = id.split('?', 2);
- resolved.id += `?${originalQuery}`;
- return resolved;
- }
- }
- else if (!filter(query.filename)) {
- return undefined;
- }
- debug(`resolveId(${id})`);
- return id;
- }
- return undefined;
- },
- load(id) {
- const query = parseVuePartRequest(id);
- if (query.vue) {
- if (query.src) {
- return fs_1.default.readFileSync(query.filename, 'utf-8');
- }
- const descriptor = getDescriptor(query.filename);
- if (descriptor) {
- const block = query.type === 'template'
- ? descriptor.template
- : query.type === 'script'
- ? descriptor.script
- : query.type === 'style'
- ? descriptor.styles[query.index]
- : typeof query.index === 'number'
- ? descriptor.customBlocks[query.index]
- : null;
- if (block) {
- return {
- code: block.content,
- map: normalizeSourceMap(block.map, id),
- };
- }
- }
- }
- return undefined;
- },
- async transform(code, id) {
- const query = parseVuePartRequest(id);
- if (query.vue) {
- if (!query.src && !filter(query.filename))
- return null;
- const descriptor = getDescriptor(query.filename);
- const hasScoped = descriptor.styles.some((s) => s.scoped);
- if (query.src) {
- this.addWatchFile(query.filename);
- }
- if (query.type === 'template') {
- debug(`transform(${id})`);
- const block = descriptor.template;
- const preprocessLang = block.lang;
- const preprocessOptions = preprocessLang &&
- options.templatePreprocessOptions &&
- options.templatePreprocessOptions[preprocessLang];
- const result = compiler_sfc_1.compileTemplate({
- filename: query.filename,
- source: code,
- inMap: query.src ? undefined : block.map,
- preprocessLang,
- preprocessOptions,
- preprocessCustomRequire: options.preprocessCustomRequire,
- compiler: options.compiler,
- ssr: isServer,
- compilerOptions: {
- ...options.compilerOptions,
- scopeId: hasScoped ? `data-v-${query.id}` : undefined,
- bindingMetadata: descriptor.script
- ? descriptor.script.bindings
- : undefined,
- },
- transformAssetUrls: options.transformAssetUrls,
- });
- if (result.errors.length) {
- result.errors.forEach((error) => this.error(typeof error === 'string'
- ? { id: query.filename, message: error }
- : createRollupError(query.filename, error)));
- return null;
- }
- if (result.tips.length) {
- result.tips.forEach((tip) => this.warn({
- id: query.filename,
- message: tip,
- }));
- }
- return {
- code: result.code,
- map: normalizeSourceMap(result.map, id),
- };
- }
- else if (query.type === 'style') {
- debug(`transform(${id})`);
- const block = descriptor.styles[query.index];
- let preprocessOptions = options.preprocessOptions || {};
- const preprocessLang = (options.preprocessStyles
- ? block.lang
- : undefined);
- if (preprocessLang) {
- preprocessOptions =
- preprocessOptions[preprocessLang] || preprocessOptions;
- // include node_modules for imports by default
- switch (preprocessLang) {
- case 'scss':
- case 'sass':
- preprocessOptions = {
- includePaths: ['node_modules'],
- ...preprocessOptions,
- };
- break;
- case 'less':
- case 'stylus':
- preprocessOptions = {
- paths: ['node_modules'],
- ...preprocessOptions,
- };
- }
- }
- else {
- preprocessOptions = {};
- }
- const result = await compiler_sfc_1.compileStyleAsync({
- filename: query.filename,
- id: `data-v-${query.id}`,
- source: code,
- scoped: block.scoped,
- vars: !!block.vars,
- modules: !!block.module,
- postcssOptions: options.postcssOptions,
- postcssPlugins: options.postcssPlugins,
- modulesOptions: options.cssModulesOptions,
- preprocessLang,
- preprocessCustomRequire: options.preprocessCustomRequire,
- preprocessOptions,
- });
- if (result.errors.length) {
- result.errors.forEach((error) => this.error({
- id: query.filename,
- message: error.message,
- }));
- return null;
- }
- if (query.module) {
- return {
- code: `export default ${_(result.modules)}`,
- map: null,
- };
- }
- else {
- return {
- code: result.code,
- map: normalizeSourceMap(result.map, id),
- };
- }
- }
- return null;
- }
- else if (filter(id)) {
- debug(`transform(${id})`);
- const { descriptor, errors } = parseSFC(code, id, rootContext);
- if (errors.length) {
- errors.forEach((error) => this.error(createRollupError(id, error)));
- return null;
- }
- // module id for scoped CSS & hot-reload
- const output = transformVueSFC(code, id, descriptor, { rootContext, isProduction, isServer, filterCustomBlock }, options);
- debug('transient .vue file:', '\n' + output + '\n');
- return {
- code: output,
- map: {
- mappings: '',
- },
- };
- }
- else {
- return null;
- }
- },
- };
- }
- exports.default = PluginVue;
- function createCustomBlockFilter(queries) {
- if (!queries || queries.length === 0)
- return () => false;
- const allowed = new Set(queries.filter((query) => /^[a-z]/i.test(query)));
- const disallowed = new Set(queries
- .filter((query) => /^![a-z]/i.test(query))
- .map((query) => query.substr(1)));
- const allowAll = queries.includes('*') || !queries.includes('!*');
- return (type) => {
- if (allowed.has(type))
- return true;
- if (disallowed.has(type))
- return true;
- return allowAll;
- };
- }
- function parseVuePartRequest(id) {
- const [filename, query] = id.split('?', 2);
- if (!query)
- return { vue: false, filename };
- const raw = querystring_1.default.parse(query);
- if ('vue' in raw) {
- return {
- ...raw,
- filename,
- vue: true,
- index: Number(raw.index),
- src: 'src' in raw,
- scoped: 'scoped' in raw,
- };
- }
- return { vue: false, filename };
- }
- const cache = new Map();
- function getDescriptor(id) {
- if (cache.has(id)) {
- return cache.get(id);
- }
- throw new Error(`${id} is not parsed yet`);
- }
- function parseSFC(code, id, sourceRoot) {
- const { descriptor, errors } = compiler_sfc_1.parse(code, {
- sourceMap: true,
- filename: id,
- sourceRoot: sourceRoot,
- });
- cache.set(id, descriptor);
- return { descriptor, errors: errors };
- }
- function transformVueSFC(code, resourcePath, descriptor, { rootContext, isProduction, isServer, filterCustomBlock, }, options) {
- const shortFilePath = path_1.relative(rootContext, resourcePath)
- .replace(/^(\.\.[\/\\])+/, '')
- .replace(/\\/g, '/');
- const id = hash_sum_1.default(isProduction ? shortFilePath + '\n' + code : shortFilePath);
- // feature information
- const hasScoped = descriptor.styles.some((s) => s.scoped);
- const templateImport = !descriptor.template
- ? ''
- : getTemplateCode(descriptor, resourcePath, id, hasScoped, isServer);
- const renderReplace = !descriptor.template
- ? ''
- : isServer
- ? `script.ssrRender = ssrRender`
- : `script.render = render`;
- const scriptImport = getScriptCode(descriptor, resourcePath);
- const stylesCode = getStyleCode(descriptor, resourcePath, id, options.preprocessStyles);
- const customBlocksCode = getCustomBlock(descriptor, resourcePath, filterCustomBlock);
- const output = [
- scriptImport,
- templateImport,
- stylesCode,
- customBlocksCode,
- renderReplace,
- ];
- if (hasScoped) {
- output.push(`script.__scopeId = ${_(`data-v-${id}`)}`);
- }
- if (!isProduction) {
- output.push(`script.__file = ${_(shortFilePath)}`);
- }
- else if (options.exposeFilename) {
- output.push(`script.__file = ${_(path_1.basename(shortFilePath))}`);
- }
- output.push('export default script');
- return output.join('\n');
- }
- function getTemplateCode(descriptor, resourcePath, id, hasScoped, isServer) {
- const renderFnName = isServer ? 'ssrRender' : 'render';
- let templateImport = `const ${renderFnName} = () => {}`;
- let templateRequest;
- if (descriptor.template) {
- const src = descriptor.template.src || resourcePath;
- const idQuery = `&id=${id}`;
- const scopedQuery = hasScoped ? `&scoped=true` : ``;
- const srcQuery = descriptor.template.src ? `&src` : ``;
- const attrsQuery = attrsToQuery(descriptor.template.attrs, 'js', true);
- const query = `?vue&type=template${idQuery}${srcQuery}${scopedQuery}${attrsQuery}`;
- templateRequest = _(src + query);
- templateImport = `import { ${renderFnName} } from ${templateRequest}`;
- }
- return templateImport;
- }
- function getScriptCode(descriptor, resourcePath) {
- let scriptImport = `const script = {}`;
- if (descriptor.script || descriptor.scriptSetup) {
- if (compiler_sfc_1.compileScript) {
- descriptor.script = compiler_sfc_1.compileScript(descriptor);
- }
- if (descriptor.script) {
- const src = descriptor.script.src || resourcePath;
- const attrsQuery = attrsToQuery(descriptor.script.attrs, 'js');
- const srcQuery = descriptor.script.src ? `&src` : ``;
- const query = `?vue&type=script${srcQuery}${attrsQuery}`;
- const scriptRequest = _(src + query);
- scriptImport =
- `import script from ${scriptRequest}\n` +
- `export * from ${scriptRequest}`; // support named exports
- }
- }
- return scriptImport;
- }
- function getStyleCode(descriptor, resourcePath, id, preprocessStyles) {
- let stylesCode = ``;
- let hasCSSModules = false;
- if (descriptor.styles.length) {
- descriptor.styles.forEach((style, i) => {
- const src = style.src || resourcePath;
- // do not include module in default query, since we use it to indicate
- // that the module needs to export the modules json
- const attrsQuery = attrsToQuery(style.attrs, 'css', preprocessStyles);
- const attrsQueryWithoutModule = attrsQuery.replace(/&module(=true|=[^&]+)?/, '');
- // make sure to only pass id when necessary so that we don't inject
- // duplicate tags when multiple components import the same css file
- const idQuery = style.scoped ? `&id=${id}` : ``;
- const srcQuery = style.src ? `&src` : ``;
- const query = `?vue&type=style&index=${i}${srcQuery}${idQuery}`;
- const styleRequest = src + query + attrsQuery;
- const styleRequestWithoutModule = src + query + attrsQueryWithoutModule;
- if (style.module) {
- if (!hasCSSModules) {
- stylesCode += `\nconst cssModules = script.__cssModules = {}`;
- hasCSSModules = true;
- }
- stylesCode += genCSSModulesCode(id, i, styleRequest, styleRequestWithoutModule, style.module);
- }
- else {
- stylesCode += `\nimport ${_(styleRequest)}`;
- }
- // TODO SSR critical CSS collection
- });
- }
- return stylesCode;
- }
- function getCustomBlock(descriptor, resourcePath, filter) {
- let code = '';
- descriptor.customBlocks.forEach((block, index) => {
- if (filter(block.type)) {
- const src = block.src || resourcePath;
- const attrsQuery = attrsToQuery(block.attrs, block.type);
- const srcQuery = block.src ? `&src` : ``;
- const query = `?vue&type=${block.type}&index=${index}${srcQuery}${attrsQuery}`;
- const request = _(src + query);
- code += `import block${index} from ${request}\n`;
- code += `if (typeof block${index} === 'function') block${index}(script)\n`;
- }
- });
- return code;
- }
- function createRollupError(id, error) {
- if ('code' in error) {
- return {
- id,
- plugin: 'vue',
- pluginCode: String(error.code),
- message: error.message,
- frame: error.loc.source,
- parserError: error,
- loc: error.loc
- ? {
- file: id,
- line: error.loc.start.line,
- column: error.loc.start.column,
- }
- : undefined,
- };
- }
- else {
- return {
- id,
- plugin: 'vue',
- message: error.message,
- parserError: error,
- };
- }
- }
- // these are built-in query parameters so should be ignored
- // if the user happen to add them as attrs
- const ignoreList = ['id', 'index', 'src', 'type', 'lang'];
- function attrsToQuery(attrs, langFallback, forceLangFallback = false) {
- let query = ``;
- for (const name in attrs) {
- const value = attrs[name];
- if (!ignoreList.includes(name)) {
- query += `&${querystring_1.default.escape(name)}${value ? `=${querystring_1.default.escape(String(value))}` : ``}`;
- }
- }
- if (langFallback || attrs.lang) {
- query +=
- `lang` in attrs
- ? forceLangFallback
- ? `&lang.${langFallback}`
- : `&lang.${attrs.lang}`
- : `&lang.${langFallback}`;
- }
- return query;
- }
- function _(any) {
- return JSON.stringify(any);
- }
- function normalizeSourceMap(map, id) {
- if (!map)
- return null;
- if (!id.includes('type=script')) {
- map.file = id;
- map.sources[0] = id;
- }
- return {
- ...map,
- version: Number(map.version),
- mappings: typeof map.mappings === 'string' ? map.mappings : '',
- };
- }
- function genCSSModulesCode(
- // @ts-ignore
- id, index, request, requestWithoutModule, moduleName) {
- const styleVar = `style${index}`;
- let code =
- // first import the CSS for extraction
- `\nimport ${_(requestWithoutModule)}` +
- // then import the json file to expose to component...
- `\nimport ${styleVar} from ${_(request + '.js')}`;
- // inject variable
- const name = typeof moduleName === 'string' ? moduleName : '$style';
- code += `\ncssModules["${name}"] = ${styleVar}`;
- return code;
- }
- // overwrite for cjs require('rollup-plugin-vue')() usage
- module.exports = PluginVue;
|