@vue-jsx-vapor/compiler
Version:
Vue JSX Vapor Compiler
1,419 lines (1,399 loc) • 107 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const __babel_parser = __toESM(require("@babel/parser"));
const __vue_shared = __toESM(require("@vue/shared"));
const source_map_js = __toESM(require("source-map-js"));
const ast_kit = __toESM(require("ast-kit"));
//#region src/utils/error.ts
let ErrorCodes = /* @__PURE__ */ function(ErrorCodes$1) {
ErrorCodes$1[ErrorCodes$1["X_V_IF_NO_EXPRESSION"] = 28] = "X_V_IF_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_ELSE_NO_ADJACENT_IF"] = 30] = "X_V_ELSE_NO_ADJACENT_IF";
ErrorCodes$1[ErrorCodes$1["X_V_FOR_NO_EXPRESSION"] = 31] = "X_V_FOR_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_FOR_MALFORMED_EXPRESSION"] = 32] = "X_V_FOR_MALFORMED_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_ON_NO_EXPRESSION"] = 35] = "X_V_ON_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_MIXED_SLOT_USAGE"] = 37] = "X_V_SLOT_MIXED_SLOT_USAGE";
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_DUPLICATE_SLOT_NAMES"] = 38] = "X_V_SLOT_DUPLICATE_SLOT_NAMES";
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN"] = 39] = "X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN";
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_MISPLACED"] = 40] = "X_V_SLOT_MISPLACED";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_NO_EXPRESSION"] = 41] = "X_V_MODEL_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_MALFORMED_EXPRESSION"] = 42] = "X_V_MODEL_MALFORMED_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_HTML_NO_EXPRESSION"] = 53] = "X_V_HTML_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_HTML_WITH_CHILDREN"] = 54] = "X_V_HTML_WITH_CHILDREN";
ErrorCodes$1[ErrorCodes$1["X_V_TEXT_NO_EXPRESSION"] = 55] = "X_V_TEXT_NO_EXPRESSION";
ErrorCodes$1[ErrorCodes$1["X_V_TEXT_WITH_CHILDREN"] = 56] = "X_V_TEXT_WITH_CHILDREN";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ON_INVALID_ELEMENT"] = 57] = "X_V_MODEL_ON_INVALID_ELEMENT";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ARG_ON_ELEMENT"] = 58] = "X_V_MODEL_ARG_ON_ELEMENT";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ON_FILE_INPUT_ELEMENT"] = 59] = "X_V_MODEL_ON_FILE_INPUT_ELEMENT";
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_UNNECESSARY_VALUE"] = 60] = "X_V_MODEL_UNNECESSARY_VALUE";
ErrorCodes$1[ErrorCodes$1["X_V_SHOW_NO_EXPRESSION"] = 61] = "X_V_SHOW_NO_EXPRESSION";
return ErrorCodes$1;
}({});
const errorMessages = {
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
[ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,
[ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,
[ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,
[ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression.`,
[ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE]: "Mixed v-slot usage on both the component and nested <template>. When there are multiple named slots, all slots should use <template> syntax to avoid scope ambiguity.",
[ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES]: `Duplicate slot names found. `,
[ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN]: "Extraneous children found when component already has explicitly named default slot. These children will be ignored.",
[ErrorCodes.X_V_MODEL_NO_EXPRESSION]: `v-model is missing expression.`,
[ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`,
[ErrorCodes.X_V_SLOT_MISPLACED]: `v-slot can only be used on components or <template> tags.`,
[ErrorCodes.X_V_HTML_NO_EXPRESSION]: `v-html is missing expression.`,
[ErrorCodes.X_V_HTML_WITH_CHILDREN]: `v-html will override element children.`,
[ErrorCodes.X_V_TEXT_NO_EXPRESSION]: `v-text is missing expression.`,
[ErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`,
[ErrorCodes.X_V_MODEL_ARG_ON_ELEMENT]: `v-model argument is not supported on plain elements.`,
[ErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
[ErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,
[ErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
[ErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`
};
function createCompilerError(code, loc, messages, additionalMessage) {
const msg = (messages || errorMessages)[code] + (additionalMessage || ``);
const error = new SyntaxError(String(msg));
error.code = code;
error.loc = loc;
return error;
}
//#endregion
//#region src/ir/component.ts
let IRDynamicPropsKind = /* @__PURE__ */ function(IRDynamicPropsKind$1) {
IRDynamicPropsKind$1[IRDynamicPropsKind$1["EXPRESSION"] = 0] = "EXPRESSION";
IRDynamicPropsKind$1[IRDynamicPropsKind$1["ATTRIBUTE"] = 1] = "ATTRIBUTE";
return IRDynamicPropsKind$1;
}({});
let IRSlotType = /* @__PURE__ */ function(IRSlotType$1) {
IRSlotType$1[IRSlotType$1["STATIC"] = 0] = "STATIC";
IRSlotType$1[IRSlotType$1["DYNAMIC"] = 1] = "DYNAMIC";
IRSlotType$1[IRSlotType$1["LOOP"] = 2] = "LOOP";
IRSlotType$1[IRSlotType$1["CONDITIONAL"] = 3] = "CONDITIONAL";
IRSlotType$1[IRSlotType$1["EXPRESSION"] = 4] = "EXPRESSION";
return IRSlotType$1;
}({});
//#endregion
//#region src/ir/index.ts
let IRNodeTypes = /* @__PURE__ */ function(IRNodeTypes$1) {
IRNodeTypes$1[IRNodeTypes$1["ROOT"] = 0] = "ROOT";
IRNodeTypes$1[IRNodeTypes$1["BLOCK"] = 1] = "BLOCK";
IRNodeTypes$1[IRNodeTypes$1["SET_PROP"] = 2] = "SET_PROP";
IRNodeTypes$1[IRNodeTypes$1["SET_DYNAMIC_PROPS"] = 3] = "SET_DYNAMIC_PROPS";
IRNodeTypes$1[IRNodeTypes$1["SET_TEXT"] = 4] = "SET_TEXT";
IRNodeTypes$1[IRNodeTypes$1["SET_EVENT"] = 5] = "SET_EVENT";
IRNodeTypes$1[IRNodeTypes$1["SET_DYNAMIC_EVENTS"] = 6] = "SET_DYNAMIC_EVENTS";
IRNodeTypes$1[IRNodeTypes$1["SET_HTML"] = 7] = "SET_HTML";
IRNodeTypes$1[IRNodeTypes$1["SET_TEMPLATE_REF"] = 8] = "SET_TEMPLATE_REF";
IRNodeTypes$1[IRNodeTypes$1["INSERT_NODE"] = 9] = "INSERT_NODE";
IRNodeTypes$1[IRNodeTypes$1["PREPEND_NODE"] = 10] = "PREPEND_NODE";
IRNodeTypes$1[IRNodeTypes$1["CREATE_COMPONENT_NODE"] = 11] = "CREATE_COMPONENT_NODE";
IRNodeTypes$1[IRNodeTypes$1["SLOT_OUTLET_NODE"] = 12] = "SLOT_OUTLET_NODE";
IRNodeTypes$1[IRNodeTypes$1["DIRECTIVE"] = 13] = "DIRECTIVE";
IRNodeTypes$1[IRNodeTypes$1["DECLARE_OLD_REF"] = 14] = "DECLARE_OLD_REF";
IRNodeTypes$1[IRNodeTypes$1["IF"] = 15] = "IF";
IRNodeTypes$1[IRNodeTypes$1["FOR"] = 16] = "FOR";
IRNodeTypes$1[IRNodeTypes$1["GET_TEXT_CHILD"] = 17] = "GET_TEXT_CHILD";
IRNodeTypes$1[IRNodeTypes$1["CREATE_NODES"] = 18] = "CREATE_NODES";
IRNodeTypes$1[IRNodeTypes$1["SET_NODES"] = 19] = "SET_NODES";
return IRNodeTypes$1;
}({});
let DynamicFlag = /* @__PURE__ */ function(DynamicFlag$1) {
DynamicFlag$1[DynamicFlag$1["NONE"] = 0] = "NONE";
/**
* This node is referenced and needs to be saved as a variable.
*/
DynamicFlag$1[DynamicFlag$1["REFERENCED"] = 1] = "REFERENCED";
/**
* This node is not generated from template, but is generated dynamically.
*/
DynamicFlag$1[DynamicFlag$1["NON_TEMPLATE"] = 2] = "NON_TEMPLATE";
/**
* This node needs to be inserted back into the template.
*/
DynamicFlag$1[DynamicFlag$1["INSERT"] = 4] = "INSERT";
return DynamicFlag$1;
}({});
function isBlockOperation(op) {
const type = op.type;
return type === IRNodeTypes.CREATE_COMPONENT_NODE || type === IRNodeTypes.SLOT_OUTLET_NODE || type === IRNodeTypes.IF || type === IRNodeTypes.FOR;
}
//#endregion
//#region src/utils/ast.ts
function findProp(expression, key) {
if (expression?.type === "JSXElement") for (const attr of expression.openingElement.attributes) {
const name = attr.type === "JSXAttribute" && (attr.name.type === "JSXIdentifier" ? attr.name.name : attr.name.type === "JSXNamespacedName" ? attr.name.namespace.name : "").split("_")[0];
if (name && ((0, __vue_shared.isString)(key) ? name === key : key.test(name))) return attr;
}
}
const TS_NODE_TYPES = [
"TSAsExpression",
"TSTypeAssertion",
"TSNonNullExpression",
"TSInstantiationExpression",
"TSSatisfiesExpression"
];
function unwrapTSNode(node) {
if (TS_NODE_TYPES.includes(node.type)) return unwrapTSNode(node.expression);
else return node;
}
function isJSXComponent(node) {
if (node.type !== "JSXElement") return false;
const { openingElement } = node;
if (openingElement.name.type === "JSXIdentifier") {
const name = openingElement.name.name;
return !(0, __vue_shared.isHTMLTag)(name) && !(0, __vue_shared.isSVGTag)(name);
} else return openingElement.name.type === "JSXMemberExpression";
}
function isMemberExpression(exp) {
if (!exp.ast) return;
const ret = unwrapTSNode(exp.ast);
return ret.type === "MemberExpression" || ret.type === "OptionalMemberExpression" || ret.type === "Identifier" && ret.name !== "undefined";
}
function isTemplate(node) {
if (node.type === "JSXElement" && node.openingElement.name.type === "JSXIdentifier") return node.openingElement.name.name === "template";
}
function isStaticNode(node) {
node = unwrapTSNode(node);
switch (node.type) {
case "UnaryExpression": return isStaticNode(node.argument);
case "LogicalExpression":
case "BinaryExpression": return isStaticNode(node.left) && isStaticNode(node.right);
case "ConditionalExpression": return isStaticNode(node.test) && isStaticNode(node.consequent) && isStaticNode(node.alternate);
case "SequenceExpression":
case "TemplateLiteral": return node.expressions.every((expr) => isStaticNode(expr));
case "ParenthesizedExpression": return isStaticNode(node.expression);
case "StringLiteral":
case "NumericLiteral":
case "BooleanLiteral":
case "NullLiteral":
case "BigIntLiteral": return true;
}
return false;
}
function isConstantNode(node) {
if (isStaticNode(node)) return true;
node = unwrapTSNode(node);
switch (node.type) {
case "Identifier": return node.name === "undefined" || (0, __vue_shared.isGloballyAllowed)(node.name);
case "RegExpLiteral": return true;
case "ObjectExpression": return node.properties.every((prop) => {
if (prop.type === "ObjectMethod") return false;
if (prop.type === "SpreadElement") return isConstantNode(prop.argument);
return (!prop.computed || isConstantNode(prop.key)) && isConstantNode(prop.value);
});
case "ArrayExpression": return node.elements.every((element) => {
if (element === null) return true;
if (element.type === "SpreadElement") return isConstantNode(element.argument);
return isConstantNode(element);
});
}
return false;
}
const isFnExpression = (exp) => {
try {
if (!exp.ast) return false;
let ret = exp.ast;
if (ret.type === "Program") {
ret = ret.body[0];
if (ret.type === "ExpressionStatement") ret = ret.expression;
}
ret = unwrapTSNode(ret);
return ret.type === "FunctionExpression" || ret.type === "ArrowFunctionExpression";
} catch {
return false;
}
};
const isFragmentNode = (node) => node.type === IRNodeTypes.ROOT || node.type === "JSXFragment" || node.type === "JSXElement" && !!isTemplate(node);
const isStaticProperty = (node) => !!node && (node.type === "ObjectProperty" || node.type === "ObjectMethod") && !node.computed;
const nonIdentifierRE = /^$|^\d|[^$\w\u00A0-\uFFFF]/;
const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
function getTextLikeValue(node, excludeNumber) {
node = node.type === "JSXExpressionContainer" ? node.expression : node;
if (node.type === "StringLiteral") return node.value;
else if (!excludeNumber && (node.type === "NumericLiteral" || node.type === "BigIntLiteral")) return String(node.value);
else if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis[0].value.cooked;
}
//#endregion
//#region src/utils/text.ts
const EMPTY_TEXT_REGEX = /^[\t\v\f \u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[\n\r]\s*$/;
const START_EMPTY_TEXT_REGEX = /^\s*[\n\r]/;
const END_EMPTY_TEXT_REGEX = /[\n\r]\s*$/;
function resolveJSXText(node) {
if (EMPTY_TEXT_REGEX.test(String(node.extra?.raw))) return "";
let value = node.value;
if (START_EMPTY_TEXT_REGEX.test(value)) value = value.trimStart();
if (END_EMPTY_TEXT_REGEX.test(value)) value = value.trimEnd();
return value;
}
function isEmptyText(node) {
return node.type === "JSXText" && EMPTY_TEXT_REGEX.test(String(node.extra?.raw)) || node.type === "JSXExpressionContainer" && node.expression.type === "JSXEmptyExpression";
}
function getText(node, content) {
return content.ir.source.slice(node.start, node.end);
}
//#endregion
//#region src/utils/expression.ts
const locStub = {
start: {
line: 1,
column: 0,
index: 0
},
end: {
line: 1,
column: 0,
index: 0
},
filename: "",
identifierName: void 0
};
function createSimpleExpression(content, isStatic = false, ast) {
return {
loc: ast ? ast.loc : locStub,
content,
isStatic,
ast
};
}
const isLiteralWhitelisted = /* @__PURE__ */ (0, __vue_shared.makeMap)("true,false,null,this");
function isConstantExpression(exp) {
return isLiteralWhitelisted(exp.content) || (0, __vue_shared.isGloballyAllowed)(exp.content) || getLiteralExpressionValue(exp) !== null;
}
function getLiteralExpressionValue(exp) {
if (exp.ast) {
const res = getTextLikeValue(exp.ast);
if (res != null) return res;
}
return exp.isStatic ? exp.content : null;
}
const EMPTY_EXPRESSION = createSimpleExpression("", true);
function resolveExpression(node, context) {
if (!node) return EMPTY_EXPRESSION;
node = unwrapTSNode(node.type === "JSXExpressionContainer" ? node.expression : node);
const isStatic = node.type === "StringLiteral" || node.type === "JSXText" || node.type === "JSXIdentifier";
const source = node.type === "JSXEmptyExpression" ? "" : node.type === "JSXIdentifier" ? node.name : node.type === "StringLiteral" ? node.value : node.type === "JSXText" ? resolveJSXText(node) : node.type === "Identifier" ? node.name : context.ir.source.slice(node.start, node.end);
return createSimpleExpression(source, isStatic, node);
}
function propToExpression(prop, context) {
return prop.type === "JSXAttribute" && prop.value?.type === "JSXExpressionContainer" ? resolveExpression(prop.value.expression, context) : EMPTY_EXPRESSION;
}
//#endregion
//#region src/utils/directive.ts
const namespaceRE = /^(?:\$([\w-]+)\$)?([\w-]+)?/;
function resolveDirective(node, context) {
const { value, name } = node;
let nameString = name.type === "JSXNamespacedName" ? name.namespace.name : name.type === "JSXIdentifier" ? name.name : "";
const isDirective = nameString.startsWith("v-");
let modifiers = [];
let isStatic = true;
let argString = name.type === "JSXNamespacedName" ? name.name.name : "";
if (name.type !== "JSXNamespacedName" && !argString) [nameString, ...modifiers] = nameString.split("_");
else {
const result = argString.match(namespaceRE);
if (result) {
let modifierString = "";
[, argString, modifierString] = result;
if (argString) {
argString = argString.replaceAll("_", ".");
isStatic = false;
if (modifierString && modifierString.startsWith("_")) modifiers = modifierString.slice(1).split("_");
} else if (modifierString) [argString, ...modifiers] = modifierString.split("_");
}
}
const arg = isDirective ? argString && name.type === "JSXNamespacedName" ? createSimpleExpression(argString, isStatic, name.name) : void 0 : createSimpleExpression(nameString, true, name);
const exp = value ? resolveExpression(value, context) : void 0;
return {
name: isDirective ? nameString.slice(2) : "bind",
rawName: getText(name, context),
exp,
arg,
loc: node.loc,
modifiers: modifiers.map((modifier) => createSimpleExpression(modifier))
};
}
//#endregion
//#region src/utils/transform.ts
function newDynamic() {
return {
flags: DynamicFlag.REFERENCED,
children: []
};
}
function newBlock(node) {
return {
type: 1,
node,
dynamic: newDynamic(),
effect: [],
operation: [],
returns: [],
tempId: 0
};
}
function createBranch(node, context, isVFor) {
context.node = node = wrapFragment(node);
const branch = newBlock(node);
const exitBlock = context.enterBlock(branch, isVFor);
context.reference();
return [branch, exitBlock];
}
function wrapFragment(node) {
if (node.type === "JSXFragment" || isTemplate(node)) return node;
return {
type: "JSXFragment",
openingFragment: { type: "JSXOpeningFragment" },
closingFragment: { type: "JSXClosingFragment" },
children: [node.type === "JSXElement" ? node : {
type: "JSXExpressionContainer",
expression: node
}]
};
}
//#endregion
//#region src/utils/generate.ts
const NEWLINE = Symbol(`newline`);
const INDENT_START = Symbol(`indent start`);
const INDENT_END = Symbol(`indent end`);
let NewlineType = /* @__PURE__ */ function(NewlineType$1) {
/** Start with `\n` */
NewlineType$1[NewlineType$1["Start"] = 0] = "Start";
/** Ends with `\n` */
NewlineType$1[NewlineType$1["End"] = -1] = "End";
/** No `\n` included */
NewlineType$1[NewlineType$1["None"] = -2] = "None";
/** Don't know, calc it */
NewlineType$1[NewlineType$1["Unknown"] = -3] = "Unknown";
return NewlineType$1;
}({});
function buildCodeFragment(...frag) {
const push = frag.push.bind(frag);
const unshift = frag.unshift.bind(frag);
return [
frag,
push,
unshift
];
}
function genMulti([left, right, seg, placeholder], ...frags) {
if (placeholder) {
while (frags.length > 0 && !frags.at(-1)) frags.pop();
frags = frags.map((frag$1) => frag$1 || placeholder);
} else frags = frags.filter(Boolean);
const frag = [];
push(left);
for (const [i, fn] of frags.entries()) {
push(fn);
if (i < frags.length - 1) push(seg);
}
push(right);
return frag;
function push(fn) {
if (!(0, __vue_shared.isArray)(fn)) fn = [fn];
frag.push(...fn);
}
}
const DELIMITERS_ARRAY = [
"[",
"]",
", "
];
const DELIMITERS_ARRAY_NEWLINE = [
[
"[",
INDENT_START,
NEWLINE
],
[
INDENT_END,
NEWLINE,
"]"
],
[", ", NEWLINE]
];
const DELIMITERS_OBJECT = [
"{ ",
" }",
", "
];
const DELIMITERS_OBJECT_NEWLINE = [
[
"{",
INDENT_START,
NEWLINE
],
[
INDENT_END,
NEWLINE,
"}"
],
[", ", NEWLINE]
];
function genCall(name, ...frags) {
const hasPlaceholder = (0, __vue_shared.isArray)(name);
const fnName = hasPlaceholder ? name[0] : name;
const placeholder = hasPlaceholder ? name[1] : "null";
return [fnName, ...genMulti([
"(",
")",
", ",
placeholder
], ...frags)];
}
function codeFragmentToString(code, context) {
const { options: { filename, sourceMap } } = context;
let map;
if (sourceMap) {
map = new source_map_js.SourceMapGenerator();
map.setSourceContent(filename, context.ir.source);
map._sources.add(filename);
}
let codegen = "";
const pos = {
line: 1,
column: 0,
index: 0
};
let indentLevel = 0;
for (let frag of code) {
if (!frag) continue;
if (frag === NEWLINE) frag = [`\n${` `.repeat(indentLevel)}`, NewlineType.Start];
else if (frag === INDENT_START) {
indentLevel++;
continue;
} else if (frag === INDENT_END) {
indentLevel--;
continue;
}
if ((0, __vue_shared.isString)(frag)) frag = [frag];
let [code$1, newlineIndex = NewlineType.None, loc, name] = frag;
codegen += code$1;
if (map) {
if (loc) addMapping(loc.start, name);
if (newlineIndex === NewlineType.Unknown) advancePositionWithMutation(pos, code$1);
else {
pos.index += code$1.length;
if (newlineIndex === NewlineType.None) pos.column += code$1.length;
else {
if (newlineIndex === NewlineType.End) newlineIndex = code$1.length - 1;
pos.line++;
pos.column = code$1.length - newlineIndex;
}
}
if (loc && loc !== locStub) addMapping(loc.end);
}
}
return [codegen, map];
function addMapping(loc, name = null) {
const { _names, _mappings } = map;
if (name !== null && !_names.has(name)) _names.add(name);
_mappings.add({
originalLine: loc.line,
originalColumn: loc.column,
generatedLine: pos.line,
generatedColumn: pos.column - 1,
source: filename,
name
});
}
}
function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {
let linesCount = 0;
let lastNewLinePos = -1;
for (let i = 0; i < numberOfCharacters; i++) if (source.charCodeAt(i) === 10) {
linesCount++;
lastNewLinePos = i;
}
pos.index += numberOfCharacters;
pos.line += linesCount;
pos.column = lastNewLinePos === -1 ? pos.column + numberOfCharacters : numberOfCharacters - lastNewLinePos;
return pos;
}
function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {
return advancePositionWithMutation({
index: pos.index,
line: pos.line,
column: pos.column
}, source, numberOfCharacters);
}
//#endregion
//#region src/utils/dom.ts
/**
* Copied from https://github.com/MananTank/validate-html-nesting
* with ISC license
*
* To avoid runtime dependency on validate-html-nesting
* This file should not change very often in the original repo
* but we may need to keep it up-to-date from time to time.
*/
/**
* returns true if given parent-child nesting is valid HTML
*/
function isValidHTMLNesting(parent, child) {
if (parent === "template") return true;
if (parent in onlyValidChildren) return onlyValidChildren[parent].has(child);
if (child in onlyValidParents) return onlyValidParents[child].has(parent);
if (parent in knownInvalidChildren && knownInvalidChildren[parent].has(child)) return false;
if (child in knownInvalidParents && knownInvalidParents[child].has(parent)) return false;
return true;
}
const headings = new Set([
"h1",
"h2",
"h3",
"h4",
"h5",
"h6"
]);
const emptySet = new Set([]);
/**
* maps element to set of elements that can be it's children, no other */
const onlyValidChildren = {
head: new Set([
"base",
"basefront",
"bgsound",
"link",
"meta",
"title",
"noscript",
"noframes",
"style",
"script",
"template"
]),
optgroup: new Set(["option"]),
select: new Set([
"optgroup",
"option",
"hr"
]),
table: new Set([
"caption",
"colgroup",
"tbody",
"tfoot",
"thead"
]),
tr: new Set(["td", "th"]),
colgroup: new Set(["col"]),
tbody: new Set(["tr"]),
thead: new Set(["tr"]),
tfoot: new Set(["tr"]),
script: emptySet,
iframe: emptySet,
option: emptySet,
textarea: emptySet,
style: emptySet,
title: emptySet
};
/** maps elements to set of elements which can be it's parent, no other */
const onlyValidParents = {
html: emptySet,
body: new Set(["html"]),
head: new Set(["html"]),
td: new Set(["tr"]),
colgroup: new Set(["table"]),
caption: new Set(["table"]),
tbody: new Set(["table"]),
tfoot: new Set(["table"]),
col: new Set(["colgroup"]),
th: new Set(["tr"]),
thead: new Set(["table"]),
tr: new Set([
"tbody",
"thead",
"tfoot"
]),
dd: new Set(["dl", "div"]),
dt: new Set(["dl", "div"]),
figcaption: new Set(["figure"]),
summary: new Set(["details"]),
area: new Set(["map"])
};
/** maps element to set of elements that can not be it's children, others can */
const knownInvalidChildren = {
p: new Set([
"address",
"article",
"aside",
"blockquote",
"center",
"details",
"dialog",
"dir",
"div",
"dl",
"fieldset",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"header",
"hgroup",
"hr",
"li",
"main",
"nav",
"menu",
"ol",
"p",
"pre",
"section",
"table",
"ul"
]),
svg: new Set([
"b",
"blockquote",
"br",
"code",
"dd",
"div",
"dl",
"dt",
"em",
"embed",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"hr",
"i",
"img",
"li",
"menu",
"meta",
"ol",
"p",
"pre",
"ruby",
"s",
"small",
"span",
"strong",
"sub",
"sup",
"table",
"u",
"ul",
"var"
])
};
/** maps element to set of elements that can not be it's parent, others can */
const knownInvalidParents = {
a: new Set(["a"]),
button: new Set(["button"]),
dd: new Set(["dd", "dt"]),
dt: new Set(["dd", "dt"]),
form: new Set(["form"]),
li: new Set(["li"]),
h1: headings,
h2: headings,
h3: headings,
h4: headings,
h5: headings,
h6: headings
};
function toValidAssetId(name, type) {
return `_${type}_${name.replaceAll(/\W/g, (searchValue, replaceValue) => {
return searchValue === "-" ? "_" : name.charCodeAt(replaceValue).toString();
})}`;
}
//#endregion
//#region src/generators/expression.ts
function genExpression(node, context, assignment, needWrap = false) {
let { content, ast, isStatic, loc } = node;
if (needWrap) content = `() => (${content})`;
if (isStatic) return [[
JSON.stringify(content),
NewlineType.None,
loc
]];
if (!node.content.trim() || isConstantExpression(node)) return [[
content,
NewlineType.None,
loc
], assignment && ` = ${assignment}`];
if (!ast) return genIdentifier(content, context, loc, assignment);
const ids = [];
const parentStackMap = /* @__PURE__ */ new Map();
const parentStack = [];
(0, ast_kit.walkIdentifiers)(ast, (id) => {
ids.push(id);
parentStackMap.set(id, parentStack.slice());
}, false, parentStack);
let hasMemberExpression = false;
if (ids.length) {
const [frag, push] = buildCodeFragment();
const isTSNode = ast && TS_NODE_TYPES.includes(ast.type);
const offset = (ast?.start ? ast.start - 1 : 0) - (needWrap ? 7 : 0);
ids.sort((a, b) => a.start - b.start).forEach((id, i) => {
const start = id.start - 1 - offset;
const end = id.end - 1 - offset;
const last = ids[i - 1];
if (!isTSNode || i !== 0) {
const leadingText = content.slice(last ? last.end - 1 - offset : 0, start);
if (leadingText.length) push([leadingText, NewlineType.Unknown]);
}
const source = content.slice(start, end);
const parentStack$1 = parentStackMap.get(id);
const parent = parentStack$1.at(-1);
hasMemberExpression ||= !!parent && (parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression");
push(...genIdentifier(source, context, {
start: advancePositionWithClone(node.loc.start, source, start),
end: advancePositionWithClone(node.loc.start, source, end),
filename: "",
identifierName: void 0
}, hasMemberExpression ? void 0 : assignment, parent));
if (i === ids.length - 1 && end < content.length && !isTSNode) push([content.slice(end), NewlineType.Unknown]);
});
if (assignment && hasMemberExpression) push(` = ${assignment}`);
return frag;
} else return [[
content,
NewlineType.Unknown,
loc
]];
}
function genIdentifier(raw, context, loc, assignment, parent) {
const { identifiers } = context;
const name = raw;
const idMap = identifiers[raw];
if (idMap && idMap.length) {
const replacement = idMap[0];
if ((0, __vue_shared.isString)(replacement)) if (parent && parent.type === "ObjectProperty" && parent.shorthand) return [[
`${name}: ${replacement}`,
NewlineType.None,
loc
]];
else return [[
replacement,
NewlineType.None,
loc
]];
else return genExpression(replacement, context, assignment);
}
let prefix;
if (isStaticProperty(parent) && parent.shorthand) prefix = `${raw}: `;
raw = withAssignment(raw);
return [prefix, [
raw,
NewlineType.None,
loc,
name
]];
function withAssignment(s) {
return assignment ? `${s} = ${assignment}` : s;
}
}
//#endregion
//#region src/generators/vModel.ts
const helperMap = {
text: "applyTextModel",
radio: "applyRadioModel",
checkbox: "applyCheckboxModel",
select: "applySelectModel",
dynamic: "applyDynamicModel"
};
function genVModel(oper, context) {
const { modelType, element, dir: { exp, modifiers } } = oper;
return [NEWLINE, ...genCall(context.helper(helperMap[modelType]), `n${element}`, [
`() => (`,
...genExpression(exp, context),
`)`
], genModelHandler(exp, context), modifiers.length ? `{ ${modifiers.map((e) => `${e.content}: true`).join(",")} }` : void 0)];
}
function genModelHandler(exp, context) {
return [
"_value => (",
...genExpression(exp, context, "_value"),
")"
];
}
//#endregion
//#region src/generators/vShow.ts
function genVShow(oper, context) {
return [NEWLINE, ...genCall(context.helper("applyVShow"), `n${oper.element}`, [
`() => (`,
...genExpression(oper.dir.exp, context),
`)`
])];
}
//#endregion
//#region src/generators/directive.ts
function genBuiltinDirective(oper, context) {
switch (oper.name) {
case "show": return genVShow(oper, context);
case "model": return genVModel(oper, context);
default: return [];
}
}
/**
* user directives via `withVaporDirectives`
* TODO the compiler side is implemented but no runtime support yet
* it was removed due to perf issues
*/
function genDirectivesForElement(id, context) {
const dirs = filterCustomDirectives(id, context.block.operation);
return dirs.length ? genCustomDirectives(dirs, context) : [];
}
function genCustomDirectives(opers, context) {
const { helper } = context;
const element = `n${opers[0].element}`;
const directiveItems = opers.map(genDirectiveItem);
const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems);
return [NEWLINE, ...genCall(helper("withVaporDirectives"), element, directives)];
function genDirectiveItem({ dir, name, asset }) {
const directiveVar = asset ? toValidAssetId(name, "directive") : genExpression(createSimpleExpression(name), context);
const value = dir.exp && ["() => ", ...genExpression(dir.exp, context)];
const argument = dir.arg && genExpression(dir.arg, context);
const modifiers = !!dir.modifiers.length && [
"{ ",
genDirectiveModifiers(dir.modifiers.map((m) => m.content)),
" }"
];
return genMulti(DELIMITERS_ARRAY.concat("void 0"), directiveVar, value, argument, modifiers);
}
}
function genDirectiveModifiers(modifiers) {
return modifiers.map((value) => `${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`).join(", ");
}
function filterCustomDirectives(id, operations) {
return operations.filter((oper) => oper.type === IRNodeTypes.DIRECTIVE && oper.element === id && !oper.builtin);
}
//#endregion
//#region src/generators/event.ts
function genSetEvent(oper, context) {
const { helper } = context;
const { element, key, keyOverride, value, modifiers, delegate, effect } = oper;
const name = genName();
const handler = genEventHandler(context, value, modifiers);
const eventOptions = genEventOptions();
if (delegate) {
context.delegates.add(key.content);
if (!context.block.operation.some(isSameDelegateEvent)) return [
NEWLINE,
`n${element}.$evt${key.content} = `,
...handler
];
}
return [NEWLINE, ...genCall(helper(delegate ? "delegate" : "on"), `n${element}`, name, handler, eventOptions)];
function genName() {
const expr = genExpression(key, context);
if (keyOverride) {
const find = JSON.stringify(keyOverride[0]);
const replacement = JSON.stringify(keyOverride[1]);
const wrapped = [
"(",
...expr,
")"
];
return [
...wrapped,
` === ${find} ? ${replacement} : `,
...wrapped
];
} else return genExpression(key, context);
}
function genEventOptions() {
const { options } = modifiers;
if (!options.length && !effect) return;
return genMulti(DELIMITERS_OBJECT_NEWLINE, effect && ["effect: true"], ...options.map((option) => [`${option}: true`]));
}
function isSameDelegateEvent(op) {
if (op.type === IRNodeTypes.SET_EVENT && op !== oper && op.delegate && op.element === oper.element && op.key.content === key.content) return true;
}
}
function genSetDynamicEvents(oper, context) {
const { helper } = context;
return [NEWLINE, ...genCall(helper("setDynamicEvents"), `n${oper.element}`, genExpression(oper.event, context))];
}
function genEventHandler(context, value, modifiers = {
nonKeys: [],
keys: []
}, extraWrap = false) {
let handlerExp = [`() => {}`];
if (value && value.content.trim()) if (isMemberExpression(value)) {
handlerExp = genExpression(value, context);
if (!extraWrap) handlerExp = [
`e => `,
...handlerExp,
`(e)`
];
} else if (isFnExpression(value)) handlerExp = genExpression(value, context);
else {
const hasMultipleStatements = value.content.includes(`;`);
handlerExp = [
"() => ",
hasMultipleStatements ? "{" : "(",
...genExpression(value, context),
hasMultipleStatements ? "}" : ")"
];
}
const { keys, nonKeys } = modifiers;
if (nonKeys.length) handlerExp = genWithModifiers(context, handlerExp, nonKeys);
if (keys.length) handlerExp = genWithKeys(context, handlerExp, keys);
if (extraWrap) handlerExp.unshift(`() => `);
return handlerExp;
}
function genWithModifiers(context, handler, nonKeys) {
return genCall(context.helper("withModifiers"), handler, JSON.stringify(nonKeys));
}
function genWithKeys(context, handler, keys) {
return genCall(context.helper("withKeys"), handler, JSON.stringify(keys));
}
//#endregion
//#region src/generators/prop.ts
const helpers = {
setText: { name: "setText" },
setHtml: { name: "setHtml" },
setClass: { name: "setClass" },
setStyle: { name: "setStyle" },
setValue: { name: "setValue" },
setAttr: {
name: "setAttr",
needKey: true
},
setProp: {
name: "setProp",
needKey: true
},
setDOMProp: {
name: "setDOMProp",
needKey: true
},
setDynamicProps: { name: "setDynamicProps" }
};
function genSetProp(oper, context) {
const { helper } = context;
const { prop: { key, values, modifier }, tag } = oper;
const resolvedHelper = getRuntimeHelper(tag, key.content, modifier);
const propValue = genPropValue(values, context);
return [NEWLINE, ...genCall([helper(resolvedHelper.name), null], `n${oper.element}`, resolvedHelper.needKey ? genExpression(key, context) : false, propValue)];
}
function genDynamicProps(oper, context) {
const { helper } = context;
const values = oper.props.map((props) => Array.isArray(props) ? genLiteralObjectProps(props, context) : props.kind === IRDynamicPropsKind.ATTRIBUTE ? genLiteralObjectProps([props], context) : genExpression(props.value, context));
return [NEWLINE, ...genCall(helper("setDynamicProps"), `n${oper.element}`, genMulti(DELIMITERS_ARRAY, ...values), oper.root && "true")];
}
function genLiteralObjectProps(props, context) {
return genMulti(DELIMITERS_OBJECT, ...props.map((prop) => [
...genPropKey(prop, context),
`: `,
...genPropValue(prop.values, context)
]));
}
function genPropKey({ key: node, modifier, runtimeCamelize, handler, handlerModifiers }, context) {
const { helper } = context;
const handlerModifierPostfix = handlerModifiers && handlerModifiers.options ? handlerModifiers.options.map(__vue_shared.capitalize).join("") : "";
if (node.isStatic) {
const keyName = (handler ? (0, __vue_shared.toHandlerKey)(node.content) : node.content) + handlerModifierPostfix;
return [[
isSimpleIdentifier(keyName) ? keyName : JSON.stringify(keyName),
NewlineType.None,
node.loc
]];
}
let key = genExpression(node, context);
if (runtimeCamelize) key = genCall(helper("camelize"), key);
if (handler) key = genCall(helper("toHandlerKey"), key);
return [
"[",
modifier && `${JSON.stringify(modifier)} + `,
...key,
handlerModifierPostfix ? ` + ${JSON.stringify(handlerModifierPostfix)}` : void 0,
"]"
];
}
function genPropValue(values, context) {
if (values.length === 1) return genExpression(values[0], context);
return genMulti(DELIMITERS_ARRAY, ...values.map((expr) => genExpression(expr, context)));
}
function getRuntimeHelper(tag, key, modifier) {
const tagName = tag.toUpperCase();
if (modifier) if (modifier === ".") return getSpecialHelper(key, tagName) || helpers.setDOMProp;
else return helpers.setAttr;
const helper = getSpecialHelper(key, tagName);
if (helper) return helper;
if (/aria[A-Z]/.test(key)) return helpers.setDOMProp;
if ((0, __vue_shared.isSVGTag)(tag)) return helpers.setAttr;
if ((0, __vue_shared.shouldSetAsAttr)(tagName, key) || key.includes("-")) return helpers.setAttr;
return helpers.setProp;
}
function getSpecialHelper(keyName, tagName) {
if (keyName === "value" && (0, __vue_shared.canSetValueDirectly)(tagName)) return helpers.setValue;
else if (keyName === "class") return helpers.setClass;
else if (keyName === "style") return helpers.setStyle;
else if (keyName === "innerHTML") return helpers.setHtml;
else if (keyName === "textContent") return helpers.setText;
}
//#endregion
//#region src/generators/component.ts
function genCreateComponent(operation, context) {
const { helper } = context;
const tag = genTag();
const { root, props, slots, once } = operation;
const rawProps = genRawProps(props, context);
const rawSlots = genRawSlots(slots, context);
return [
NEWLINE,
`const n${operation.id} = `,
...genCall(operation.dynamic && !operation.dynamic.isStatic ? helper("createDynamicComponent") : operation.asset ? helper("createComponentWithFallback") : helper("createComponent"), tag, rawProps, rawSlots, root ? "true" : false, once && "true"),
...genDirectivesForElement(operation.id, context)
];
function genTag() {
if (operation.dynamic) if (operation.dynamic.isStatic) return genCall(helper("resolveDynamicComponent"), genExpression(operation.dynamic, context));
else return [
"() => (",
...genExpression(operation.dynamic, context),
")"
];
else if (operation.asset) return toValidAssetId(operation.tag, "component");
else return genExpression(createSimpleExpression(operation.tag), context);
}
}
function genRawProps(props, context) {
const staticProps = props[0];
if ((0, __vue_shared.isArray)(staticProps)) {
if (!staticProps.length && props.length === 1) return;
return genStaticProps(staticProps, context, genDynamicProps$1(props.slice(1), context));
} else if (props.length) return genStaticProps([], context, genDynamicProps$1(props, context));
}
function genStaticProps(props, context, dynamicProps) {
const args = props.map((prop) => genProp(prop, context, true));
if (dynamicProps) args.push([`$: `, ...dynamicProps]);
return genMulti(args.length > 1 ? DELIMITERS_OBJECT_NEWLINE : DELIMITERS_OBJECT, ...args);
}
function genDynamicProps$1(props, context) {
const { helper } = context;
const frags = [];
for (const p of props) {
let expr;
if ((0, __vue_shared.isArray)(p)) {
if (p.length) frags.push(genStaticProps(p, context));
continue;
} else if (p.kind === IRDynamicPropsKind.ATTRIBUTE) expr = genMulti(DELIMITERS_OBJECT, genProp(p, context));
else {
expr = genExpression(p.value, context);
if (p.handler) expr = genCall(helper("toHandlers"), expr);
}
frags.push([
"() => (",
...expr,
")"
]);
}
if (frags.length) return genMulti(DELIMITERS_ARRAY_NEWLINE, ...frags);
}
function genProp(prop, context, isStatic) {
const values = genPropValue(prop.values, context);
return [
...genPropKey(prop, context),
": ",
...prop.handler ? genEventHandler(context, prop.values[0], prop.handlerModifiers, true) : isStatic ? [
"() => (",
...values,
")"
] : values,
...prop.model ? [...genModelEvent(prop, context), ...genModelModifiers(prop, context)] : []
];
}
function genModelEvent(prop, context) {
const name = prop.key.isStatic ? [JSON.stringify(`onUpdate:${(0, __vue_shared.camelize)(prop.key.content)}`)] : [
"[\"onUpdate:\" + ",
...genExpression(prop.key, context),
"]"
];
const handler = genModelHandler(prop.values[0], context);
return [
",",
NEWLINE,
...name,
": () => ",
...handler
];
}
function genModelModifiers(prop, context) {
const { key, modelModifiers } = prop;
if (!modelModifiers || !modelModifiers.length) return [];
const modifiersKey = key.isStatic ? [`${key.content}Modifiers`] : [
"[",
...genExpression(key, context),
" + \"Modifiers\"]"
];
const modifiersVal = genDirectiveModifiers(modelModifiers);
return [
",",
NEWLINE,
...modifiersKey,
`: () => ({ ${modifiersVal} })`
];
}
function genRawSlots(slots, context) {
if (!slots.length) return;
const staticSlots = slots[0];
if (staticSlots.slotType === IRSlotType.STATIC) return genStaticSlots(staticSlots, context, slots.length > 1 ? slots.slice(1) : void 0);
else return genStaticSlots({
slotType: IRSlotType.STATIC,
slots: {}
}, context, slots);
}
function genStaticSlots({ slots }, context, dynamicSlots) {
const args = Object.keys(slots).map((name) => [`${JSON.stringify(name)}: `, ...genSlotBlockWithProps(slots[name], context)]);
if (dynamicSlots) args.push([`$: `, ...genDynamicSlots(dynamicSlots, context)]);
return genMulti(DELIMITERS_OBJECT_NEWLINE, ...args);
}
function genDynamicSlots(slots, context) {
return genMulti(DELIMITERS_ARRAY_NEWLINE, ...slots.map((slot) => slot.slotType === IRSlotType.STATIC ? genStaticSlots(slot, context) : slot.slotType === IRSlotType.EXPRESSION ? slot.slots.content : genDynamicSlot(slot, context, true)));
}
function genDynamicSlot(slot, context, withFunction = false) {
let frag;
switch (slot.slotType) {
case IRSlotType.DYNAMIC:
frag = genBasicDynamicSlot(slot, context);
break;
case IRSlotType.LOOP:
frag = genLoopSlot(slot, context);
break;
case IRSlotType.CONDITIONAL:
frag = genConditionalSlot(slot, context);
break;
}
return withFunction ? [
"() => (",
...frag,
")"
] : frag;
}
function genBasicDynamicSlot(slot, context) {
const { name, fn } = slot;
return genMulti(DELIMITERS_OBJECT_NEWLINE, ["name: ", ...genExpression(name, context)], ["fn: ", ...genSlotBlockWithProps(fn, context)]);
}
function genLoopSlot(slot, context) {
const { name, fn, loop } = slot;
const { value, key, index, source } = loop;
const rawValue = value && value.content;
const rawKey = key && key.content;
const rawIndex = index && index.content;
const idMap = {};
if (rawValue) idMap[rawValue] = rawValue;
if (rawKey) idMap[rawKey] = rawKey;
if (rawIndex) idMap[rawIndex] = rawIndex;
const slotExpr = genMulti(DELIMITERS_OBJECT_NEWLINE, ["name: ", ...context.withId(() => genExpression(name, context), idMap)], ["fn: ", ...context.withId(() => genSlotBlockWithProps(fn, context), idMap)]);
return [...genCall(context.helper("createForSlots"), genExpression(source, context), [
...genMulti([
"(",
")",
", "
], rawValue ? rawValue : rawKey || rawIndex ? "_" : void 0, rawKey ? rawKey : rawIndex ? "__" : void 0, rawIndex),
" => (",
...slotExpr,
")"
])];
}
function genConditionalSlot(slot, context) {
const { condition, positive, negative } = slot;
return [
...genExpression(condition, context),
INDENT_START,
NEWLINE,
"? ",
...genDynamicSlot(positive, context),
NEWLINE,
": ",
...negative ? [...genDynamicSlot(negative, context)] : ["void 0"],
INDENT_END
];
}
function genSlotBlockWithProps(oper, context) {
let isDestructureAssignment = false;
let rawProps;
let propsName;
let exitScope;
let depth;
const { props } = oper;
const idsOfProps = /* @__PURE__ */ new Set();
if (props) {
rawProps = props.content;
if (isDestructureAssignment = !!props.ast) {
[depth, exitScope] = context.enterScope();
propsName = `_slotProps${depth}`;
(0, ast_kit.walkIdentifiers)(props.ast, (id, _, __, isReference, isLocal) => {
if (isReference && !isLocal) idsOfProps.add(id.name);
}, true);
} else idsOfProps.add(propsName = rawProps);
}
const idMap = {};
idsOfProps.forEach((id) => idMap[id] = isDestructureAssignment ? `${propsName}[${JSON.stringify(id)}]` : null);
const blockFn = context.withId(() => genBlock(oper, context, [propsName]), idMap);
exitScope && exitScope();
return blockFn;
}
//#endregion
//#region src/generators/dom.ts
function genInsertNode({ parent, elements, anchor }, { helper }) {
let element = elements.map((el) => `n${el}`).join(", ");
if (elements.length > 1) element = `[${element}]`;
return [NEWLINE, ...genCall(helper("insert"), element, `n${parent}`, anchor === void 0 ? void 0 : `n${anchor}`)];
}
function genPrependNode(oper, { helper }) {
return [NEWLINE, ...genCall(helper("prepend"), `n${oper.parent}`, ...oper.elements.map((el) => `n${el}`))];
}
//#endregion
//#region src/generators/for.ts
/**
* Flags to optimize vapor `createFor` runtime behavior, shared between the
* compiler and the runtime
*/
let VaporVForFlags = /* @__PURE__ */ function(VaporVForFlags$1) {
/**
* v-for is the only child of a parent container, so it can take the fast
* path with textContent = '' when the whole list is emptied
*/
VaporVForFlags$1[VaporVForFlags$1["FAST_REMOVE"] = 1] = "FAST_REMOVE";
/**
* v-for used on component - we can skip creating child scopes for each block
* because the component itself already has a scope.
*/
VaporVForFlags$1[VaporVForFlags$1["IS_COMPONENT"] = 2] = "IS_COMPONENT";
/**
* v-for inside v-ince
*/
VaporVForFlags$1[VaporVForFlags$1["ONCE"] = 4] = "ONCE";
return VaporVForFlags$1;
}({});
function genFor(oper, context) {
const { helper } = context;
const { source, value, key, index, render, keyProp, once, id, component, onlyChild } = oper;
let rawValue = null;
const rawKey = key && key.content;
const rawIndex = index && index.content;
const sourceExpr = [
"() => (",
...genExpression(source, context),
")"
];
const idToPathMap = parseValueDestructure();
const [depth, exitScope] = context.enterScope();
const idMap = {};
const itemVar = `_for_item${depth}`;
idMap[itemVar] = null;
idToPathMap.forEach((pathInfo, id$1) => {
let path = `${itemVar}.value${pathInfo ? pathInfo.path : ""}`;
if (pathInfo) {
if (pathInfo.helper) {
idMap[pathInfo.helper] = null;
path = `${pathInfo.helper}(${path}, ${pathInfo.helperArgs})`;
}
if (pathInfo.dynamic) {
const node = idMap[id$1] = createSimpleExpression(path);
node.ast = (0, __babel_parser.parseExpression)(`(${path})`, { plugins: context.options.expressionPlugins });
} else idMap[id$1] = path;
} else idMap[id$1] = path;
});
const args = [itemVar];
if (rawKey) {
const keyVar = `_for_key${depth}`;
args.push(`, ${keyVar}`);
idMap[rawKey] = `${keyVar}.value`;
idMap[keyVar] = null;
}
if (rawIndex) {
const indexVar = `_for_index${depth}`;
args.push(`, ${indexVar}`);
idMap[rawIndex] = `${indexVar}.value`;
idMap[indexVar] = null;
}
const { selectorPatterns, keyOnlyBindingPatterns } = matchPatterns(render, keyProp, idMap, context.ir.source);
const selectorDeclarations = [];
const selectorSetup = [];
for (const [i, { selector }] of selectorPatterns.entries()) {
const selectorName = `_selector${id}_${i}`;
selectorDeclarations.push(`let ${selectorName}`, NEWLINE);
if (i === 0) selectorSetup.push(`({ createSelector }) => {`, INDENT_START);
selectorSetup.push(NEWLINE, `${selectorName} = `, ...genCall(`createSelector`, [`() => `, ...genExpression(selector, context)]));
if (i === selectorPatterns.length - 1) selectorSetup.push(INDENT_END, NEWLINE, "}");
}
const blockFn = context.withId(() => {
const frag = [];
frag.push("(", ...args, ") => {", INDENT_START);
if (selectorPatterns.length || keyOnlyBindingPatterns.length) frag.push(...genBlockContent(render, context, false, () => {
const patternFrag = [];
for (const [i, { effect }] of selectorPatterns.entries()) {
patternFrag.push(NEWLINE, `_selector${id}_${i}(() => {`, INDENT_START);
for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
patternFrag.push(INDENT_END, NEWLINE, `})`);
}
for (const { effect } of keyOnlyBindingPatterns) for (const oper$1 of effect.operations) patternFrag.push(...genOperation(oper$1, context));
return patternFrag;
}));
else frag.push(...genBlockContent(render, context));
frag.push(INDENT_END, NEWLINE, "}");
return frag;
}, idMap);
exitScope();
let flags = 0;
if (onlyChild) flags |= VaporVForFlags.FAST_REMOVE;
if (component) flags |= VaporVForFlags.IS_COMPONENT;
if (once) flags |= VaporVForFlags.ONCE;
return [
NEWLINE,
...selectorDeclarations,
`const n${id} = `,
...genCall([helper("createFor"), "undefined"], sourceExpr, blockFn, genCallback(keyProp), flags ? String(flags) : void 0, selectorSetup.length ? selectorSetup : void 0)
];
function parseValueDestructure() {
const map = /* @__PURE__ */ new Map();
if (value) {
rawValue = value && value.content;
if (value.ast && value.ast.type !== "Identifier") (0, ast_kit.walkIdentifiers)(value.ast, (id$1, _, parentStack, isReference, isLocal) => {
if (isReference && !isLocal) {
let path = "";
let isDynamic = false;
let helper$1;
let helperArgs;
for (let i = 0; i < parentStack.length; i++) {
const parent = parentStack[i];
const child = parentStack[i + 1] || id$1;
if (parent.type === "ObjectProperty" && parent.value === child) if (parent.key.type === "StringLiteral") path += `[${JSON.stringify(parent.key.value)}]`;
else if (parent.computed) {
isDynamic = true;
path += `[${value.content.slice(parent.key.start - 1, parent.key.end - 1)}]`;
} else path += `.${parent.key.name}`;
else if (parent.type === "ArrayExpression") {
const index$1 = parent.elements.indexOf(child);
if (child.type === "SpreadElement") path += `.slice(${index$1})`;
else path += `[${index$1}]`;
} else if (parent.type === "ObjectExpression" && child.type === "SpreadElement") {
helper$1 = context.helper("getRestElement");
helperArgs = `[${parent.properties.filter((p) => p.type === "ObjectProperty").map((p) => {
if (p.key.type === "StringLiteral") return JSON.stringify(p.key.value);
else if (p.computed) {
isDynami