UNPKG

jsv-compiler

Version:
1,199 lines 84.9 kB
'use strict'; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, '__esModule', { value: true }); var CompilerDOM = require('./compiler-dom.cjs'); var sourceMap = require('source-map'); var path = require('path'); var compilerCore = require('./compiler-core.cjs'); var url = require('url'); var shared = require('@vue/shared'); var CompilerSSR = require('@vue/compiler-ssr'); var postcss = require('postcss'); var selectorParser = require('postcss-selector-parser'); var merge = require('merge-source-map'); var MagicString = require('magic-string'); var parser = require('@babel/parser'); var estreeWalker = require('estree-walker'); function _interopDefaultLegacy(e) { return e && typeof e === 'object' && 'default' in e ? e['default'] : e; } function _interopNamespace(e) { if (e && e.__esModule) { return e; } else { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { n[k] = e[k]; }); } n['default'] = e; return Object.freeze(n); } } var CompilerDOM__namespace = /*#__PURE__*/ _interopNamespace(CompilerDOM); var path__default = /*#__PURE__*/ _interopDefaultLegacy(path); var CompilerSSR__namespace = /*#__PURE__*/ _interopNamespace(CompilerSSR); var postcss__default = /*#__PURE__*/ _interopDefaultLegacy(postcss); var selectorParser__default = /*#__PURE__*/ _interopDefaultLegacy(selectorParser); var merge__default = /*#__PURE__*/ _interopDefaultLegacy(merge); var MagicString__default = /*#__PURE__*/ _interopDefaultLegacy(MagicString); var SFC_CACHE_MAX_SIZE = 500; var sourceToSFC = new (require('lru-cache'))(SFC_CACHE_MAX_SIZE); function parse(source, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.sourceMap, sourceMap = _c === void 0 ? true : _c, _d = _b.filename, filename = _d === void 0 ? 'component.vue' : _d, _e = _b.sourceRoot, sourceRoot = _e === void 0 ? '' : _e, _f = _b.pad, pad = _f === void 0 ? false : _f, _g = _b.compiler, compiler = _g === void 0 ? CompilerDOM__namespace : _g; var sourceKey = source + sourceMap + filename + sourceRoot + pad + compiler.parse; var cache = sourceToSFC.get(sourceKey); if (cache) { return cache; } var descriptor = { filename: filename, source: source, templates: [], script: null, scriptSetup: null, styles: [], customBlocks: [] }; var errors = []; var ast = compiler.parse(source, { // there are no components at SFC parsing level isNativeTag: function () { return true; }, // preserve all whitespaces isPreTag: function () { return true; }, getTextMode: function (_a, parent) { var tag = _a.tag, props = _a.props; // all top level elements except <template> are parsed as raw text // containers if ((!parent && tag !== 'template') || // <template lang="xxx"> should also be treated as raw text props.some(function (p) { return p.type === 6 /* ATTRIBUTE */ && p.name === 'lang' && p.value && p.value.content !== 'html'; })) { return 2 /* RAWTEXT */; } else { return 0 /* DATA */; } }, onError: function (e) { errors.push(e); } }); ast.children.forEach(function (node) { if (node.type !== 1 /* ELEMENT */) { return; } if (!node.children.length && !hasSrc(node)) { return; } switch (node.tag) { case 'template': descriptor.templates.push(createBlock(node, source, false)); // if (!descriptor.template) { // descriptor.template = createBlock( // node, // source, // false // ) as SFCTemplateBlock // } else { // errors.push(createDuplicateBlockError(node)) // } break; case 'script': var block = createBlock(node, source, pad); var isSetup = !!block.attrs.setup; if (isSetup && !descriptor.scriptSetup) { descriptor.scriptSetup = block; break; } if (!isSetup && !descriptor.script) { descriptor.script = block; break; } errors.push(createDuplicateBlockError(node, isSetup)); break; case 'style': descriptor.styles.push(createBlock(node, source, pad)); break; default: descriptor.customBlocks.push(createBlock(node, source, pad)); break; } }); if (descriptor.scriptSetup) { if (descriptor.scriptSetup.src) { errors.push(new SyntaxError("<script setup> cannot use the \"src\" attribute because " + "its syntax will be ambiguous outside of the component.")); descriptor.scriptSetup = null; } if (descriptor.script && descriptor.script.src) { errors.push(new SyntaxError("<script> cannot use the \"src\" attribute when <script setup> is " + "also present because they must be processed together.")); descriptor.script = null; } } if (sourceMap) { var genMap = function (block) { if (block && !block.src) { block.map = generateSourceMap(filename, source, block.content, sourceRoot, !pad || block.type === 'template' ? block.loc.start.line - 1 : 0); } }; // genMap(descriptor.template) descriptor.templates.forEach(genMap); genMap(descriptor.script); descriptor.styles.forEach(genMap); descriptor.customBlocks.forEach(genMap); } var result = { ast: ast, descriptor: descriptor, errors: errors }; sourceToSFC.set(sourceKey, result); return result; } function createDuplicateBlockError(node, isScriptSetup) { if (isScriptSetup === void 0) { isScriptSetup = false; } var err = new SyntaxError("Single file component can contain only one <" + node.tag + (isScriptSetup ? " setup" : "") + "> element"); err.loc = node.loc; return err; } function createBlock(node, source, pad) { var type = node.tag; var _a = node.loc, start = _a.start, end = _a.end; var content = ''; if (node.children.length) { start = node.children[0].loc.start; end = node.children[node.children.length - 1].loc.end; content = source.slice(start.offset, end.offset); } var loc = { source: content, start: start, end: end }; var attrs = {}; var block = { type: type, content: content, loc: loc, attrs: attrs }; if (pad) { block.content = padContent(source, block, pad) + block.content; } node.props.forEach(function (p) { if (p.type === 6 /* ATTRIBUTE */) { attrs[p.name] = p.value ? p.value.content || true : true; if (p.name === 'lang') { block.lang = p.value && p.value.content; } else if (p.name === 'src') { block.src = p.value && p.value.content; } else if (type === 'style') { if (p.name === 'scoped') { block.scoped = true; } else if (p.name === 'vars' && typeof attrs.vars === 'string') { block.vars = attrs.vars; } else if (p.name === 'module') { block.module = attrs[p.name]; } } else if (type === 'template' && p.name === 'functional') { block.functional = true; } else if (type === 'script' && p.name === 'setup') { block.setup = attrs.setup; } } }); return block; } var splitRE = /\r?\n/g; var emptyRE = /^(?:\/\/)?\s*$/; var replaceRE = /./g; function generateSourceMap(filename, source, generated, sourceRoot, lineOffset) { var map = new sourceMap.SourceMapGenerator({ file: filename.replace(/\\/g, '/'), sourceRoot: sourceRoot.replace(/\\/g, '/') }); map.setSourceContent(filename, source); generated.split(splitRE).forEach(function (line, index) { if (!emptyRE.test(line)) { var originalLine = index + 1 + lineOffset; var generatedLine = index + 1; for (var i = 0; i < line.length; i++) { if (!/\s/.test(line[i])) { map.addMapping({ source: filename, original: { line: originalLine, column: i }, generated: { line: generatedLine, column: i } }); } } } }); return JSON.parse(map.toString()); } function padContent(content, block, pad) { content = content.slice(0, block.loc.start.offset); if (pad === 'space') { return content.replace(replaceRE, ' '); } else { var offset = content.split(splitRE).length; var padChar = block.type === 'script' && !block.lang ? '//\n' : '\n'; return Array(offset).join(padChar); } } function hasSrc(node) { return node.props.some(function (p) { if (p.type !== 6 /* ATTRIBUTE */) { return false; } return p.name === 'src'; }); } function isRelativeUrl(url) { var firstChar = url.charAt(0); return firstChar === '.' || firstChar === '~' || firstChar === '@'; } var externalRE = /^https?:\/\//; function isExternalUrl(url) { return externalRE.test(url); } var dataUrlRE = /^\s*data:/i; function isDataUrl(url) { return dataUrlRE.test(url); } /** * Parses string url into URL object. */ function parseUrl(url) { var firstChar = url.charAt(0); if (firstChar === '~') { var secondChar = url.charAt(1); url = url.slice(secondChar === '/' ? 2 : 1); } return parseUriParts(url); } /** * vuejs/component-compiler-utils#22 Support uri fragment in transformed require * @param urlString an url as a string */ function parseUriParts(urlString) { // A TypeError is thrown if urlString is not a string // @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost return url.parse(shared.isString(urlString) ? urlString : ''); } var defaultAssetUrlOptions = { base: null, includeAbsolute: false, tags: { video: ['src', 'poster'], source: ['src'], img: ['src'], image: ['xlink:href', 'href'], use: ['xlink:href', 'href'] } }; var normalizeOptions = function (options) { if (Object.keys(options).some(function (key) { return shared.isArray(options[key]); })) { // legacy option format which directly passes in tags config return __assign(__assign({}, defaultAssetUrlOptions), { tags: options }); } return __assign(__assign({}, defaultAssetUrlOptions), options); }; var createAssetUrlTransformWithOptions = function (options) { return function (node, context) { return transformAssetUrl(node, context, options); }; }; /** * A `@vue/compiler-core` plugin that transforms relative asset urls into * either imports or absolute urls. * * ``` js * // Before * createVNode('img', { src: './logo.png' }) * * // After * import _imports_0 from './logo.png' * createVNode('img', { src: _imports_0 }) * ``` */ var transformAssetUrl = function (node, context, options) { if (options === void 0) { options = defaultAssetUrlOptions; } if (node.type === 1 /* ELEMENT */) { if (!node.props.length) { return; } var tags = options.tags || defaultAssetUrlOptions.tags; var attrs = tags[node.tag]; var wildCardAttrs = tags['*']; if (!attrs && !wildCardAttrs) { return; } var assetAttrs_1 = (attrs || []).concat(wildCardAttrs || []); node.props.forEach(function (attr, index) { if (attr.type !== 6 /* ATTRIBUTE */ || !assetAttrs_1.includes(attr.name) || !attr.value || isExternalUrl(attr.value.content) || isDataUrl(attr.value.content) || attr.value.content[0] === '#' || (!options.includeAbsolute && !isRelativeUrl(attr.value.content))) { return; } var url = parseUrl(attr.value.content); if (options.base) { // explicit base - directly rewrite the url into absolute url // does not apply to absolute urls or urls that start with `@` // since they are aliases if (attr.value.content[0] !== '@' && isRelativeUrl(attr.value.content)) { // when packaged in the browser, path will be using the posix- // only version provided by rollup-plugin-node-builtins. attr.value.content = (path__default.posix || path__default).join(options.base, url.path + (url.hash || '')); } return; } // otherwise, transform the url into an import. // this assumes a bundler will resolve the import into the correct // absolute url (e.g. webpack file-loader) var exp = getImportsExpressionExp(url.path, url.hash, attr.loc, context); node.props[index] = { type: 7 /* DIRECTIVE */, name: 'bind', arg: compilerCore.createSimpleExpression(attr.name, true, attr.loc), exp: exp, modifiers: [], loc: attr.loc }; }); } }; function getImportsExpressionExp(path, hash, loc, context) { if (path) { var importsArray = Array.from(context.imports); var existing = importsArray.find(function (i) { return i.path === path; }); if (existing) { return existing.exp; } var name_1 = "_imports_" + importsArray.length; var exp = compilerCore.createSimpleExpression(name_1, false, loc, true); exp.isRuntimeConstant = true; context.imports.add({ exp: exp, path: path }); if (hash && path) { var ret = context.hoist(compilerCore.createSimpleExpression(name_1 + " + '" + hash + "'", false, loc, true)); ret.isRuntimeConstant = true; return ret; } else { return exp; } } else { return compilerCore.createSimpleExpression("''", false, loc, true); } } var srcsetTags = ['img', 'source']; // http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5 var escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g; var createSrcsetTransformWithOptions = function (options) { return function (node, context) { return transformSrcset(node, context, options); }; }; var transformSrcset = function (node, context, options) { if (options === void 0) { options = defaultAssetUrlOptions; } if (node.type === 1 /* ELEMENT */) { if (srcsetTags.includes(node.tag) && node.props.length) { node.props.forEach(function (attr, index) { if (attr.name === 'srcset' && attr.type === 6 /* ATTRIBUTE */) { if (!attr.value) return; var value = attr.value.content; var imageCandidates_1 = value.split(',').map(function (s) { // The attribute value arrives here with all whitespace, except // normal spaces, represented by escape sequences var _a = s .replace(escapedSpaceCharacters, ' ') .trim() .split(' ', 2), url = _a[0], descriptor = _a[1]; return { url: url, descriptor: descriptor }; }); // for data url need recheck url for (var i = 0; i < imageCandidates_1.length; i++) { if (imageCandidates_1[i].url.trim().startsWith('data:')) { imageCandidates_1[i + 1].url = imageCandidates_1[i].url + ',' + imageCandidates_1[i + 1].url; imageCandidates_1.splice(i, 1); } } // When srcset does not contain any relative URLs, skip transforming if (!options.includeAbsolute && !imageCandidates_1.some(function (_a) { var url = _a.url; return isRelativeUrl(url); })) { return; } if (options.base) { var base_1 = options.base; var set_1 = []; imageCandidates_1.forEach(function (_a) { var url = _a.url, descriptor = _a.descriptor; descriptor = descriptor ? " " + descriptor : ""; if (isRelativeUrl(url)) { set_1.push((path__default.posix || path__default).join(base_1, url) + descriptor); } else { set_1.push(url + descriptor); } }); attr.value.content = set_1.join(', '); return; } var compoundExpression_1 = compilerCore.createCompoundExpression([], attr.loc); imageCandidates_1.forEach(function (_a, index) { var url = _a.url, descriptor = _a.descriptor; if (!isExternalUrl(url) && !isDataUrl(url) && (options.includeAbsolute || isRelativeUrl(url))) { var path_1 = parseUrl(url).path; var exp = void 0; if (path_1) { var importsArray = Array.from(context.imports); var existingImportsIndex = importsArray.findIndex(function (i) { return i.path === path_1; }); if (existingImportsIndex > -1) { exp = compilerCore.createSimpleExpression("_imports_" + existingImportsIndex, false, attr.loc, true); } else { exp = compilerCore.createSimpleExpression("_imports_" + importsArray.length, false, attr.loc, true); context.imports.add({ exp: exp, path: path_1 }); } compoundExpression_1.children.push(exp); } } else { var exp = compilerCore.createSimpleExpression("\"" + url + "\"", false, attr.loc, true); compoundExpression_1.children.push(exp); } var isNotLast = imageCandidates_1.length - 1 > index; if (descriptor && isNotLast) { compoundExpression_1.children.push(" + '" + descriptor + ", ' + "); } else if (descriptor) { compoundExpression_1.children.push(" + '" + descriptor + "'"); } else if (isNotLast) { compoundExpression_1.children.push(" + ', ' + "); } }); var hoisted = context.hoist(compoundExpression_1); hoisted.isRuntimeConstant = true; node.props[index] = { type: 7 /* DIRECTIVE */, name: 'bind', arg: compilerCore.createSimpleExpression('srcset', true, attr.loc), exp: hoisted, modifiers: [], loc: attr.loc }; } }); } } }; function preprocess(_a, preprocessor) { var source = _a.source, filename = _a.filename, preprocessOptions = _a.preprocessOptions; // Consolidate exposes a callback based API, but the callback is in fact // called synchronously for most templating engines. In our case, we have to // expose a synchronous API so that it is usable in Jest transforms (which // have to be sync because they are applied via Node.js require hooks) var res = ''; var err = null; preprocessor.render(source, __assign({ filename: filename }, preprocessOptions), function (_err, _res) { if (_err) err = _err; res = _res; }); if (err) throw err; return res; } function compileTemplate(options) { var preprocessLang = options.preprocessLang, preprocessCustomRequire = options.preprocessCustomRequire; var preprocessor = preprocessLang ? preprocessCustomRequire ? preprocessCustomRequire(preprocessLang) : require('consolidate')[preprocessLang] : false; if (preprocessor) { try { return doCompileTemplate(__assign(__assign({}, options), { source: preprocess(options, preprocessor) })); } catch (e) { return { code: "export default function render() {}", source: options.source, tips: [], errors: [e] }; } } else if (preprocessLang) { return { code: "export default function render() {}", source: options.source, tips: [ "Component " + options.filename + " uses lang " + preprocessLang + " for template. Please install the language preprocessor." ], errors: [ "Component " + options.filename + " uses lang " + preprocessLang + " for template, however it is not installed." ] }; } else { return doCompileTemplate(options); } } function doCompileTemplate(_a) { var filename = _a.filename, inMap = _a.inMap, source = _a.source, _b = _a.ssr, ssr = _b === void 0 ? false : _b, _c = _a.compiler, compiler = _c === void 0 ? ssr ? CompilerSSR__namespace : CompilerDOM__namespace : _c, _d = _a.compilerOptions, compilerOptions = _d === void 0 ? {} : _d, transformAssetUrls = _a.transformAssetUrls; var errors = []; var nodeTransforms = []; if (shared.isObject(transformAssetUrls)) { var assetOptions = normalizeOptions(transformAssetUrls); nodeTransforms = [ createAssetUrlTransformWithOptions(assetOptions), createSrcsetTransformWithOptions(assetOptions) ]; } else if (transformAssetUrls !== false) { nodeTransforms = [transformAssetUrl, transformSrcset]; } var _e = compiler.compile(source, __assign(__assign({ mode: 'module', prefixIdentifiers: true, hoistStatic: true, cacheHandlers: true }, compilerOptions), { nodeTransforms: nodeTransforms.concat(compilerOptions.nodeTransforms || []), filename: filename, sourceMap: true, onError: function (e) { return errors.push(e); } })), code = _e.code, map = _e.map, ast = _e.ast; // inMap should be the map produced by ./parse.ts which is a simple line-only // mapping. If it is present, we need to adjust the final map and errors to // reflect the original line numbers. if (inMap) { if (map) { map = mapLines(inMap, map); } if (errors.length) { patchErrors(errors, source, inMap); } } return { code: code, source: source, errors: errors, tips: [], map: map, ast: ast }; } function mapLines(oldMap, newMap) { if (!oldMap) return newMap; if (!newMap) return oldMap; var oldMapConsumer = new sourceMap.SourceMapConsumer(oldMap); var newMapConsumer = new sourceMap.SourceMapConsumer(newMap); var mergedMapGenerator = new sourceMap.SourceMapGenerator(); newMapConsumer.eachMapping(function (m) { if (m.originalLine == null) { return; } var origPosInOldMap = oldMapConsumer.originalPositionFor({ line: m.originalLine, column: m.originalColumn }); if (origPosInOldMap.source == null) { return; } mergedMapGenerator.addMapping({ generated: { line: m.generatedLine, column: m.generatedColumn }, original: { line: origPosInOldMap.line, // use current column, since the oldMap produced by @vue/compiler-sfc // does not column: m.originalColumn }, source: origPosInOldMap.source, name: origPosInOldMap.name }); }); // source-map's type definition is incomplete var generator = mergedMapGenerator; oldMapConsumer.sources.forEach(function (sourceFile) { generator._sources.add(sourceFile); var sourceContent = oldMapConsumer.sourceContentFor(sourceFile); if (sourceContent != null) { mergedMapGenerator.setSourceContent(sourceFile, sourceContent); } }); generator._sourceRoot = oldMap.sourceRoot; generator._file = oldMap.file; return generator.toJSON(); } function patchErrors(errors, source, inMap) { var originalSource = inMap.sourcesContent[0]; var offset = originalSource.indexOf(source); var lineOffset = originalSource.slice(0, offset).split(/\r?\n/).length - 1; errors.forEach(function (err) { if (err.loc) { err.loc.start.line += lineOffset; err.loc.start.offset += offset; if (err.loc.end !== err.loc.start) { err.loc.end.line += lineOffset; err.loc.end.offset += offset; } } }); } var trimPlugin = postcss__default.plugin('trim', function () { return function (css) { css.walk(function (_a) { var type = _a.type, raws = _a.raws; if (type === 'rule' || type === 'atrule') { if (raws.before) raws.before = '\n'; if (raws.after) raws.after = '\n'; } }); }; }); var animationNameRE = /^(-\w+-)?animation-name$/; var animationRE = /^(-\w+-)?animation$/; var scopedPlugin = postcss__default.plugin('vue-scoped', function (id) { return function (root) { var keyframes = Object.create(null); var shortId = id.replace(/^data-v-/, ''); root.each(function rewriteSelectors(node) { if (node.type !== 'rule') { // handle media queries if (node.type === 'atrule') { if (node.name === 'media' || node.name === 'supports') { node.each(rewriteSelectors); } else if (/-?keyframes$/.test(node.name)) { // register keyframes keyframes[node.params] = node.params = node.params + '-' + shortId; } } return; } node.selector = selectorParser__default(function (selectors) { function rewriteSelector(selector, slotted) { var node = null; var shouldInject = true; // find the last child node to insert attribute selector selector.each(function (n) { // DEPRECATED ">>>" and "/deep/" combinator if (n.type === 'combinator' && (n.value === '>>>' || n.value === '/deep/')) { n.value = ' '; n.spaces.before = n.spaces.after = ''; console.warn("[@vue/compiler-sfc] the >>> and /deep/ combinators have " + "been deprecated. Use ::v-deep instead."); return false; } if (n.type === 'pseudo') { var value = n.value; // deep: inject [id] attribute at the node before the ::v-deep // combinator. if (value === ':deep' || value === '::v-deep') { if (n.nodes.length) { // .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar // replace the current node with ::v-deep's inner selector selector.insertAfter(n, n.nodes[0]); // insert a space combinator before if it doesn't already have one var prev = selector.at(selector.index(n) - 1); if (!prev || !isSpaceCombinator(prev)) { selector.insertAfter(n, selectorParser__default.combinator({ value: ' ' })); } selector.removeChild(n); } else { // DEPRECATED usage // .foo ::v-deep .bar -> .foo[xxxxxxx] .bar console.warn("[@vue/compiler-sfc] ::v-deep usage as a combinator has " + "been deprecated. Use ::v-deep(<inner-selector>) instead."); var prev = selector.at(selector.index(n) - 1); if (prev && isSpaceCombinator(prev)) { selector.removeChild(prev); } selector.removeChild(n); } return false; } // slot: use selector inside `::v-slotted` and inject [id + '-s'] // instead. // ::v-slotted(.foo) -> .foo[xxxxxxx-s] if (value === ':slotted' || value === '::v-slotted') { rewriteSelector(n.nodes[0], true /* slotted */); selector.insertAfter(n, n.nodes[0]); selector.removeChild(n); // since slotted attribute already scopes the selector there's no // need for the non-slot attribute. shouldInject = false; return false; } // global: replace with inner selector and do not inject [id]. // ::v-global(.foo) -> .foo if (value === ':global' || value === '::v-global') { selectors.insertAfter(selector, n.nodes[0]); selectors.removeChild(selector); return false; } } if (n.type !== 'pseudo' && n.type !== 'combinator') { node = n; } }); if (node) { node.spaces.after = ''; } else { // For deep selectors & standalone pseudo selectors, // the attribute selectors are prepended rather than appended. // So all leading spaces must be eliminated to avoid problems. selector.first.spaces.before = ''; } if (shouldInject) { var idToAdd = slotted ? id + '-s' : id; selector.insertAfter( // If node is null it means we need to inject [id] at the start // insertAfter can handle `null` here node, selectorParser__default.attribute({ attribute: idToAdd, value: idToAdd, raws: {}, quoteMark: "\"" })); } } selectors.each(function (selector) { return rewriteSelector(selector); }); }).processSync(node.selector); }); if (Object.keys(keyframes).length) { // If keyframes are found in this <style>, find and rewrite animation names // in declarations. // Caveat: this only works for keyframes and animation rules in the same // <style> element. // individual animation-name declaration root.walkDecls(function (decl) { if (animationNameRE.test(decl.prop)) { decl.value = decl.value .split(',') .map(function (v) { return keyframes[v.trim()] || v.trim(); }) .join(','); } // shorthand if (animationRE.test(decl.prop)) { decl.value = decl.value .split(',') .map(function (v) { var vals = v.trim().split(/\s+/); var i = vals.findIndex(function (val) { return keyframes[val]; }); if (i !== -1) { vals.splice(i, 1, keyframes[vals[i]]); return vals.join(' '); } else { return v; } }) .join(','); } }); } }; }); function isSpaceCombinator(node) { return node.type === 'combinator' && /^\s+$/.test(node.value); } var cssVarRE = /\bvar\(--(global:)?([^)]+)\)/g; var scopedVarsPlugin = postcss__default.plugin('vue-scoped', function (id) { return function (root) { var shortId = id.replace(/^data-v-/, ''); root.walkDecls(function (decl) { // rewrite CSS variables if (cssVarRE.test(decl.value)) { decl.value = decl.value.replace(cssVarRE, function (_, $1, $2) { return $1 ? "var(--" + $2 + ")" : "var(--" + shortId + "-" + $2 + ")"; }); } }); }; }); // .scss/.sass processor var scss = function (source, map, options, load) { if (load === void 0) { load = require; } var nodeSass = load('sass'); var finalOptions = __assign(__assign({}, options), { data: getSource(source, options.filename, options.additionalData), file: options.filename, outFile: options.filename, sourceMap: !!map }); try { var result = nodeSass.renderSync(finalOptions); var dependencies = result.stats.includedFiles; if (map) { return { code: result.css.toString(), map: merge__default(map, JSON.parse(result.map.toString())), errors: [], dependencies: dependencies }; } return { code: result.css.toString(), errors: [], dependencies: dependencies }; } catch (e) { return { code: '', errors: [e], dependencies: [] }; } }; var sass = function (source, map, options, load) { return scss(source, map, __assign(__assign({}, options), { indentedSyntax: true }), load); }; // .less var less = function (source, map, options, load) { if (load === void 0) { load = require; } var nodeLess = load('less'); var result; var error = null; nodeLess.render(getSource(source, options.filename, options.additionalData), __assign(__assign({}, options), { syncImport: true }), function (err, output) { error = err; result = output; }); if (error) return { code: '', errors: [error], dependencies: [] }; var dependencies = result.imports; if (map) { return { code: result.css.toString(), map: merge__default(map, result.map), errors: [], dependencies: dependencies }; } return { code: result.css.toString(), errors: [], dependencies: dependencies }; }; // .styl var styl = function (source, map, options, load) { if (load === void 0) { load = require; } var nodeStylus = load('stylus'); try { var ref_1 = nodeStylus(source); Object.keys(options).forEach(function (key) { return ref_1.set(key, options[key]); }); if (map) ref_1.set('sourcemap', { inline: false, comment: false }); var result = ref_1.render(); var dependencies = ref_1.deps(); if (map) { return { code: result, map: merge__default(map, ref_1.sourcemap), errors: [], dependencies: dependencies }; } return { code: result, errors: [], dependencies: dependencies }; } catch (e) { return { code: '', errors: [e], dependencies: [] }; } }; function getSource(source, filename, additionalData) { if (!additionalData) return source; if (shared.isFunction(additionalData)) { return additionalData(source, filename); } return additionalData + source; } var processors = { less: less, sass: sass, scss: scss, styl: styl, stylus: styl }; function compileStyle(options) { return doCompileStyle(__assign(__assign({}, options), { isAsync: false })); } function compileStyleAsync(options) { return doCompileStyle(__assign(__assign({}, options), { isAsync: true })); } function doCompileStyle(options) { var filename = options.filename, id = options.id, _a = options.scoped, scoped = _a === void 0 ? false : _a, _b = options.vars, vars = _b === void 0 ? false : _b, _c = options.trim, trim = _c === void 0 ? true : _c, _d = options.modules, modules = _d === void 0 ? false : _d, _e = options.modulesOptions, modulesOptions = _e === void 0 ? {} : _e, preprocessLang = options.preprocessLang, postcssOptions = options.postcssOptions, postcssPlugins = options.postcssPlugins; var preprocessor = preprocessLang && processors[preprocessLang]; var preProcessedSource = preprocessor && preprocess$1(options, preprocessor); var map = preProcessedSource ? preProcessedSource.map : options.map; var source = preProcessedSource ? preProcessedSource.code : options.source; var plugins = (postcssPlugins || []).slice(); if (vars && scoped) { // vars + scoped, only applies to raw source before other transforms // #1623 plugins.unshift(scopedVarsPlugin(id)); } if (trim) { plugins.push(trimPlugin()); } if (scoped) { plugins.push(scopedPlugin(id)); } var cssModules; if (modules) { if (!options.isAsync) { throw new Error('[@vue/compiler-sfc] `modules` option can only be used with compileStyleAsync().'); } plugins.push(require('postcss-modules')(__assign(__assign({}, modulesOptions), { getJSON: function (_cssFileName, json) { cssModules = json; } }))); } var postCSSOptions = __assign(__assign({}, postcssOptions), { to: filename, from: filename }); if (map) { postCSSOptions.map = { inline: false, annotation: false, prev: map }; } var result; var code; var outMap; // stylus output include plain css. so need remove the repeat item var dependencies = new Set(preProcessedSource ? preProcessedSource.dependencies : []); // sass has filename self when provided filename option dependencies.delete(filename); var errors = []; if (preProcessedSource && preProcessedSource.errors.length) { errors.push.apply(errors, preProcessedSource.errors); } var recordPlainCssDependencies = function (messages) { messages.forEach(function (msg) { if (msg.type === 'dependency') { // postcss output path is absolute position path dependencies.add(msg.file); } }); return dependencies; }; try { result = postcss__default(plugins).process(source, postCSSOptions); // In async mode, return a promise. if (options.isAsync) { return result .then(function (result) { return ({ code: result.css || '', map: result.map && result.map.toJSON(), errors: errors, modules: cssModules, rawResult: result, dependencies: recordPlainCssDependencies(result.messages) }); }) .catch(function (error) { return ({ code: '', map: undefined, errors: __spreadArrays(errors, [error]), rawResult: undefined, dependencies: dependencies }); }); } recordPlainCssDependencies(result.messages); // force synchronous transform (we know we only have sync plugins) code = result.css; outMap = result.map; } catch (e) { errors.push(e); } return { code: code || "", map: outMap && outMap.toJSON(), errors: errors, rawResult: result, dependencies: dependencies }; } function preprocess$1(options, preprocessor) { return preprocessor(options.source, options.map, __assign({ filename: options.filename }, options.preprocessOptions), options.preprocessCustomRequire); } var defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/; var namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/; /** * Utility for rewriting `export default` in a script block into a variable * declaration so that we can inject things into it */ function rewriteDefault(input, as, parserPlugins) { if (!hasDefaultExport(input)) { return input + ("\nconst " + as + " = {}"); } var replaced = input.replace(defaultExportRE, "$1const " + as + " ="); if (!hasDefaultExport(replaced)) { return replaced; } // if the script somehow still contains `default export`, it probably has // multi-line comments or template strings. fallback to a full parse. var s = new MagicString__default(input); var ast = parser.parse(input, { sourceType: 'module', plugins: parserPlugins }).program.body; ast.forEach(function (node) { if (node.type === 'ExportDefaultDeclaration') { s.overwrite(node.start, node.declaration.start, "const " + as + " = "); } if (node.type === 'ExportNamedDeclaration') { node.specifiers.forEach(function (specifier) { if (specifier.type === 'ExportSpecifier' && specifier.exported.name === 'default') { var end = specifier.end; s.overwrite(specifier.start, input.charAt(end) === ',' ? end + 1 : end, ""); s.append("\nconst " + as + " = " + specifier.local.name); } }); } }); return s.toString(); } function hasDefaultExport(input) { return defaultExportRE.test(input) || namedDefaultExportRE.test(input); } function genCssVarsCode(varsExp, scoped, knownBindings) { var exp = CompilerDOM.createSimpleExpression(varsExp, false); var context = CompilerDOM.createTransformContext(CompilerDOM.createRoot([]), { prefixIdentifiers: true }); if (knownBindings) { // when compiling <script setup> we already know what bindings are exposed // so we can avoid prefixing them from the ctx. for (var key in knownBindings) { context.identifiers[key] = 1; } } var transformed = CompilerDOM.processExpression(exp, context); var transformedString = transformed.type === 4 /* SIMPLE_EXPRESSION */ ? transformed.content : transformed.children .map(function (c) { return typeof c === 'string' ? c : c.content; }) .join(''); return "__useCssVars__(_ctx => (" + transformedString + ")" + (scoped ? ", true" : "") + ")"; } // <script setup> already gets the calls injected as part of the transform // this is only for single normal <script> function injectCssVarsCalls(sfc, parserPlugins) { var script = rewriteDefault(sfc.script.content, "__default__", parserPlugins); var calls = ""; for (var _i = 0, _a = sfc.styles; _i < _a.length; _i++) { var style = _a[_i]; var vars = style.attrs.vars; if (typeof vars === 'string') { calls += genCssVarsCode(vars, !!style.scoped) + '\n'; } } return (script + "\nimport { useCssVars as __useCssVars__ } from 'vue'\n" + ("const __injectCSSVars__ = () => {\n" + calls + "}\n") + "const __setup__ = __default__.setup\n" + "__default__.setup = __setup__\n" + " ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n" + " : __injectCSSVars__\n" + "export default __default__"); } var hasWarned = false; /** * Compile `<script setup>` * It requires the whole SFC descriptor because we need to handle and merge * normal `<script>` + `<script setup>` if both are present. */ function compileScript(sfc, options) { if (options === void 0) { options = {}; } var script = sfc.script, scriptSetup = sfc.scriptSetup, styles = sfc.styles, source = sfc.source, filename = sfc.filename; if (!hasWarned && scriptSetup) { hasWarned = true; // @ts-ignore `console.info` cannot be null error console[console.info ? 'info' : 'log']("\n[@vue/compiler-sfc] <script setup> is still an experimental proposal.\n" + "Follow https://github.com/vuejs/rfcs/pull/182 for its status.\n"); } var hasCssVars = styles.some(function (s) { return typeof s.attrs.vars === 'string'; }); var scriptLang = script && script.lang; var scriptSetupLang = scriptSetup && scriptSetup.lang; var isTS = scriptLang === 'ts' || scriptSetupLang === 'ts'; var plugins = __spreadArrays(shared.babelParserDefaultPlugins, ['jsx']); if (options.babelParserPlugins) plugins.push.apply(plugins, options.babelParserPlugins); if (isTS) plugins.push('typescript', 'decorators-legacy'); if (!scriptSetup) { if (!script) { throw new Error("SFC contains no <script> tags."); } if (scriptLang && scriptLang !== 'ts') { // do not process non js/ts script blocks return script; } try { var scriptAst_2 = parser.parse(script.content, { plugins: plugins, sourceType: 'module' }).program.body; return __assign(__assign({}, script), { content: hasCssVars ? injectCssVarsCalls(sfc, plugins) : script.content, bindings: analyzeScriptBindings(scriptAst_2), scriptAst: scriptAst_2 }); } catch (e) { // silently fallback if parse fails since user may be using custom // babel syntax return script; } } if (script && scriptLang !== scriptSetupLang) { throw new Error("<script> and <script setup> must have the same language type."); } if (scriptSetupLang && scriptSetupLang !== 'ts') { // do not process non js/ts script blocks return scriptSetup; } var defaultTempVar = "__default__"; var bindings = {}; var imports = {}; var setupScopeVars = {}; var setupExports = {}; var exportAllIndex = 0; var defaultExport; var needDefaultExportRefCheck = false; var hasAwait = false; var checkDuplicateDefaultExport = function (node) { if (defaultExport) { // <script> already has export default throw new Error("Default export is already declared in normal <script>.\n\n" + shared.generateCodeFrame(source, node.start + startOffset, node.start + startOffset + "export default".length)); } }; var s = new MagicString__default(source); var startOffset = scriptSetup.loc.start.offset; var endOffset = scriptSetup.loc.end.offset; var scriptStartOffset = script && script.loc.start.offset; var scriptEndOffset = script && script.loc.end.offset; var