jsv-compiler
Version:
use vue3 template in .js
1,199 lines • 84.9 kB
JavaScript
'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